Obsługa kodów USSD w modemach LTE
Spis treści
Każdy, kto ma lub miał prepaid'a, prędzej czy później musiał nauczyć się obsługi kodów
USSD. To za ich pomocą
jesteśmy w stanie sprawdzić stan konta czy też aktywować poszczególne usługi. Co się jednak stanie,
gdy taki prepaid zostanie umieszczony w modemie LTE? Teoretycznie modem powinien nam zapewnić
połączenie LTE ale to jest nieco inna technologia niż GSM czy UMTS, a to za ich pomocą mogą być
przesyłane zarówno kody USSD i SMS. Niby modemy LTE potrafią operować również na UMTS i GSM ale pod
linux'em przesyłanie kodów USSD może być nieco problematyczne. Jedynym oprogramowaniem będącym w
stanie operować na tych kodach był modem-manager-gui
. Problem w tym, że zajmuje on praktycznie
cały modem dla siebie, co w pewnych sytuacjach może nie być pożądane. Zatem jakie alternatywy nam
pozostają? W jaki sposób operować na tych kodach USSD pod linux'em?
Interfejsy modemu
Modemy LTE mogą pracować w kilku trybach. Ja póki co spotkałem się z dwoma z nich: RAS (demon PPP i
wvdial) i NDIS
(NCM). Różnic między tymi
trybami jest kilka ale nas interesuje głównie jedna z nich. Chodzi o operowanie na interfejsach
/dev/ttyUSB*
. W przypadku trybu RAS, jedno z tych urządzeń jest wykorzystywane cały czas.
Natomiast jeśli chodzi o tryb NDIS (NCM), to jeden interfejs jest wykorzystywany tylko przy
nawiązywaniu połączenia, po czym jest zwalniany. W efekcie jeśli mamy do dyspozycji dwa interfejsy,
to po nawiązaniu połączenia w trybie RAS zostanie nam wolny jeden z nich, a w przypadku NDIS (NCM)
będą do dyspozycji dwa. Ma to znaczenie, tylko gdy korzystamy z jakichś egzotycznych usług, np.
gammu-smsd do odbierania i wysyłania
SMS'ów. Każda z takich usług
zajmuje sobie jeden z interfejsów i logiczne jest, że jeśli mamy do dyspozycji tylko dwa urządzenia
w katalogu /dev/
do obsługi modemu LTE, to ilość nasłuchujących demonów usług jest ograniczona do
dwóch lub jednego. Jeśli dwie usługi będą chciały korzystać z tego samego interfejsu, to tylko jedna
z nich będzie mogła to zrobić. Oczywiście nic nie stoi na przeszkodzie, by na chwilę dezaktywować
jedną usługę na czas korzystania z drugiej, choć nie jest to jakoś zbytnio wygodne.
W przypadku tego modemu, tj Huawei E3372s-153 w wersji NON-HiLink, mamy tryb NDIS (NCM) i przy
odpowiedniej konfiguracji możemy zestawić połączenie LTE i mieć do dyspozycji standardowo dwa
interfejsy /dev/ttyUSB0
oraz /dev/ttyUSB1
.
USSD-GUI
Szukając na sieci jakiegoś przyjaznego narzędzia do obsługi kodów USSD, natrafiłem na ussd-gui. Ten programik posiada w miarę prosty interfejs QT i wygląda mniej więcej tak:
W polu Input
wpisujemy kod USSD i wciskamy przycisk Send
. Po chwili powinna zostać nam zwrócona
odpowiedź z sieci, tak jak to widzimy wyżej. ussd-gui
potrafi też odbierać wiadomości SMS ale nie
potrafi ich wysyłać.
Niemniej jednak, wysyłanie i obieranie SMS lepiej zostawić wammu. On chyba najlepiej ma opanowaną tę kwestię.
Warto też wiedzieć, że ussd-gui
można sobie lekko skonfigurować w pliku
~/.config/ussd-gui/ussd-gui.conf
. Poniżej przykład konfiguracji:
[General]
autowaitInterval=2
decodeType=0
device=/dev/huawei-E3372-1
gsm7Encoded=true
history=*111*480*1#\n*105#\n*101#\n*107#\n*111#\n*121#\n*111*480*3#
initCommand="AT+CMGF=1;^CURC=0;^USSDMODE=0"
no_history=
source=internal
terminatorSequence=68
timeout=15
ussdInfo=*111# - RBM: zarzadzanie kontem\n*121# - RBM: wlasny numer\n*107# - RBM: stan internetu\n*101# - RBM: stan konta\n*111*480*1# - RBM: LTE FREE\n*111*480*3# - RBM: LTE FREE status\n
W FAQ zabrakło
wyjaśnienia opcji autowaitInterval
i na dobrą sprawę nie mam pojęcia za co ona odpowiada.
Podobnie sprawa ma się w przypadku gsm7Encoded
. W oparciu o parametry history
i no_history
generowana jest lista wpisanych kodów USSD w oknie aplikacji. Opcja to timeout
odpowiada za czas
przez jaki aplikacja oczekiwać będzie odpowiedzi na przesłany kod USSD. Standardowo ten czas jest
bardzo długi i waha się w granicach około 1-2 minut. Tu nie chodzi o to, że tyle czasu zajmuje
odpowiedź na żądanie, bo ona jest zwracana w kilka sekund ale z jakiegoś powodu szereg aplikacji
czeka ponad 1 minutę ze zwróceniem wyniku. W przypadku ussd-gui
odpowiedź jest zwracana prawie
natychmiastowo. Do wyboru mamy dwa backend'y, które możemy podać w opcji source
. Są to libgammu
oraz internal
. Pierwszy z nich wykorzystuje bibliotekę libgammu
, drugi zaś operuje na
poleceniach AT. Chodzi generalnie o to, że nie wszystkie urządzenia są wspierane w libgammu
, w
efekcie czego nie działają za dobrze z tym backend'em. W device
określamy interfejs modemu, z
którego ma korzystać ussd-gui
. W ussdInfo
zaś są przechowywane wszystkie ulubione kody USSD
wraz z ich opisami. Kody USSD jak i opisy można definiować bezpośrednio w oknie ussd-gui
, co
wygląda mniej więcej tak:
Mamy także dwie dość enigmatyczne opcje: initCommand
oraz terminatorSequence
. Obie z nich są
wykorzystywane, gdy w grę wchodzi backend source=internal
. W initCommand
podajemy sekwencję
poleceń AT, które mają zostać przesłane do modemu przed nawiązaniem z nim połączenia. Chodzi głównie
o ustawienie poprawnego trybu pracy modemu niezbędnego do prawidłowej pracy urządzenia. Z kolei
jeśli chodzi zaś o terminatorSequence
to wartość tego parametru trzeba ustalić w oparciu o
zwracane przez modem komunikaty. Przykładowo, przy przesyłaniu kodu USSD do modemu możemy otrzymać
poniższy wynik:
$ cat /dev/ttyUSB1
AT+CUSD=1,"*121#",15
OK
+CUSD: 0,"Twoj nr: 600123456",68
Wartość 68
na końcu komunikatu zwrotnego, to właśnie jest nasz terminatorSequence
i to tę
wartość musimy wpisać w pliku konfiguracyjnym. W przeciwnym razie mogą wystąpić problemy w
działaniu ussd-gui
.
Kody USSD w gammu
Jako, że ussd-gui
wykorzystuje gammu
, to możemy spróbować przesłać te kody również z wiersza
poleceń. Tak dla przykładu, by przesłać kod *111#
, wpisujemy gammu getussd '*111#'
. Poniżej
przykład:
Niestety czas oczekiwania na odpowiedź jest bardzo długi. Nie udało mi się także odpowiedzieć na
otrzymany komunikat i to pomimo faktu, że wyraźnie widnieje tam Action needed
. Być może było to
za sprawą zbyt długiego oczekiwanie na zwrócenie komunikatu przez aplikację. Nie mam pojęcia jak
dostosować timeout
w gammu
, dlatego też nie uśmiecha mi się korzystanie bezpośrednio z niego.
Przesyłanie kodów USSD przy pomocy poleceń AT
Ostatnia opcja, która nam zostaje, to przesyłanie kodów USSD bezpośrednio na interfejsy modemu przy
pomocy poleceń AT. Oczywiście, możemy to zrobić na dwa sposoby. Pierwszy z nich zakłada
wykorzystanie oprogramowania typu cu
lub minicom
. Drugi zaś przesyła kody przy pomocy echo
bezpośrednio na interfejsy modemu w katalogu /dev/
.
Czas reakcji na kody w obu przypadkach jest bardzo szybki. Niemniej jednak, trzeba nauczyć się poleceń AT i ręcznie je wpisywać za każdym razem do terminala, co jest bardzo niewygodne. Poniżej przykład:
Sposób z echo
jest nieco wygodniejszy, bo wykorzystywana jest historia shell'a. Jeśli mamy zsh
zamiast domyślnego bash
, to operowanie na tych kodach może być naprawdę proste. Wymagane będą też
dwa okna terminala. W jednym z nich będą wpisywane polecenia, w drugi będą zwracane wyniki. Poniżej
przykład w oparciu o multiplekser tmux
:
W górnym okienku przy pomocy echo
wpisaliśmy dwa polecenia:
$ echo -e "AT+CMGF=1;^CURC=0;^USSDMODE=0\r" > /dev/huawei-E3372-0
$ echo -e "AT+CUSD=1,\"*101#\",15\r" >/dev/huawei-E3372-0
Pierwsze z nich konfiguruje odpowiednio modem, drugie zaś wysyła faktyczny kod USSD. W tym przypadku
jest to *101#
. Ważne jest by kod ująć w " "
oraz by zakończyć polecenie za pomocą \r
.
Odpowiedzi są zwracane w przeciągu 2-3 sekund.
W ten sposób również jesteśmy w stanie odpowiadać na komunikaty, które się pojawiają w dolnym oknie.
Dla przykładu, w górnym oknie prześlijmy kod *111#
.
Widzimy, że pojawiło się kilka opcji do wyboru. Wybierzmy Kontro
w odpowiedzi wysyłając 1
:
Teraz sprawdźmy stan konta również przesyłając 1
:
Teraz możemy zakończyć pracę przesyłając 0
:
W ten sposób przy wykorzystaniu historii i możliwości shell'a ZSH oraz poleceń echo
i cat
możemy
komunikować się z siecią przesyłając jej kody USSD.