Если вы используете USB модемы для совершения звонков через asterisk, то приходится время от времени проверять счёт. Можно вынимать симки, вставлять в телефон и проверять счёт. Но! Можно это делать программно.
Тестовый стенд: USB модем Huawei E1550.
Будет рассмотрено 2 способа. Лично у меня заработал только 1-ый.
Способ1
Можно использовать встроенные функции asterisk’a. Для этого выполним команду:
datacard ussd datacard7 *100#
прямо в консоле астериска, где *100# – номер для проверки счёта, а datacard7 – имя вашего модема. Иногда USSD код нужно заключать в двойные кавычки.
После этого в файле /var/log/asterisk/ussd.log появится вот такая запись:
2011-11-10 10:05:22 - datacard7: Ваш баланс составляет 32419 рублей.
или в консоли:
boom-ats*CLI> datacard ussd datacard7 *100#
[datacard7] Got USSD response: 'Ваш баланс составляет 32419 рублей.'
-- Executing [ussd@datacard-incoming:1] Set("Local/ussd@datacard-incoming-a372;1", "USSD_ML=Ваш баланс составляет 32419 рублей.") in new stack
-- Executing [ussd@datacard-incoming:2] Verbose("Local/ussd@datacard-incoming-a372;1", "Incoming USSD: Ваш баланс составляет 32419 рублей.") in new stack
Incoming USSD: Ваш баланс составляет 32419 рублей.
-- Executing [ussd@datacard-incoming:3] System("Local/ussd@datacard-incoming-a372;1", "echo '2011-11-10 11:33:50 - datacard7: Ваш баланс составляет 32419 рублей.' >> /var/log/asterisk/ussd.txt") in new stack
-- Executing [ussd@datacard-incoming:4] Hangup("Local/ussd@datacard-incoming-a372;1", "") in new stack
== Spawn extension (datacard-incoming, ussd, 4) exited non-zero on 'Local/ussd@datacard-incoming-a372;1'
-- Executing [h@datacard-incoming:1] Hangup("Local/ussd@datacard-incoming-a372;1", "") in new stack
== Spawn extension (datacard-incoming, h, 1) exited non-zero on 'Local/ussd@datacard-incoming-a372;1'
Способ2
Использовать скрипт, написанный Юрием Куринковым. Вот текст скрипта:
#!/usr/bin/perl use Getopt::Std; use Device::Gsm::Pdu; # defaults $opt_r = "/dev/ttyUSB2"; $opt_s = "/dev/ttyUSB0"; my $USAGE = <<__EOU; Usage: $0 [-i input_port] [-o output_port] [-n] [-h] [-v] ussd_msg Description: Send and receive 7-bit PDU-encoded USSD messages. Written and tested for Huawei E1550 GSM/UMTS USB modem. Options: -r port Port to receive data from. Default: $opt_r -s port Port to send AT commands to. Default: $opt_s -n Do not send any data to port. Useful with -v. -h Print this help. -v Be verbose. __EOU sub HELP_MESSAGE {print "$USAGE\n"; exit;} sub VERSION_MESSAGE {}; getopts ('i:o:hnv'); HELP_MESSAGE() and exit if (! $ARGV[0]) or defined($opt_h); print "USSD MSG: $ARGV[0]\n" if $opt_v; my $ussd_req = Device::Gsm::Pdu::encode_text7($ARGV[0]); $ussd_req =~ s/^..//; print "PDU ENCODED: $ussd_req\n" if $opt_v; my $ussd_reply; if (! $opt_n) { open (SENDPORT, '+<', $opt_s) or die "Can't open '$opt_s': $!\n"; print SENDPORT 'AT+CUSD=1,',$ussd_req,",15\r\n"; close SENDPORT; open (RCVPORT, $opt_r) or die "Can't open '$opt_r': $!\n"; print "Waiting for USSD reply...\n" if $opt_v; while (<RCVPORT>) { chomp; die "USSD ERROR\n" if $_ eq "+CUSD: 2"; if (/^\+CUSD: 0,\"([A-F0-9]+)\"/) { $ussd_reply = $1; print "PDU USSD REPLY: $ussd_reply\n" if $opt_v; last; } print "Got unknown USSD message: $_\n" if /^\+CUSD:/ and $opt_v; } } if ($ussd_reply) { $decoded_ussd_reply = Device::Gsm::Pdu::decode_text7('00'.$ussd_reply); print STDOUT "USSD REPLY: $decoded_ussd_reply\n"; } else {print "No USSD reply!\n";}
Для скрипта нужны два перловых модуля. Getopt::Std устанавливается вместе с PERLом, а второй необходимо установить. На нетбуке в Ubuntu надо сказать:
%sudo perl -MCPAN -e ‘install Device::Gsm::Pdu’
Во FreeBSD необходимо установить comms/p5-Device-Gsm
А вот ещё один скрипт для Huawei E219/E220
#!/usr/bin/env python # # This script send 'get balance' request to the Beeline # from Huawei E219/E220 USB-GPRS modem. # # IDima (c) 2008 # import serial import string import os # # Decode string from Beeline to current charset # def str2byte(a): b='' for i in range(len(a)/4): b+=chr(eval('0x'+a[i*4+2:i*4+4]))+chr(eval('0x'+a[i*4:i*4+2])) return unicode(b, 'utf16') # # Definitions # KDIALOG='/usr/bin/kdialog' USBPORT='/dev/ttyUSB1' USBSPEED=460800 MAXSTRINGLENGTH=300 print "Wait a while ... " s=serial.Serial(USBPORT,USBSPEED,timeout=5) s.write('ATZ \015') s.write('AT+CUSD=1,AA184C3602,15 \015') line='' while line[0:6] != '+CUSD:': line=s.readline(MAXSTRINGLENGTH) s.close() line2=line.split(',')[1] line3=string.replace(line2,'"','') line4=str2byte(line3) result=line4.encode('utf8') if KDIALOG and os.path.isfile(KDIALOG): os.system(KDIALOG + ' --title "Beeline_Internet@Home" --msgbox "' + result + '"') else: print result
А вот пример проверки счёт для модемов Киевстар. Ну и на всякий случай пример для работы с USSD-запросами
4 коментарі “Узнаем счёт на модеме”
Скоро как раз будет нужно. Спасибо 🙂
Спасибо
А на другие модемы есть?
Понимаете, здесь вы отправляете команды непосредственно из астериска, соответственно, если ваш модем опознался астериском как datacard*, то вы смело можете проверять состояние счёта. Другое дело – модем должен поддерживать USSD запросы.