Если вы используете 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 запросы.