Узнаем счёт на модеме

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

    1. skeletor Автор записи

      Понимаете, здесь вы отправляете команды непосредственно из астериска, соответственно, если ваш модем опознался астериском как datacard*, то вы смело можете проверять состояние счёта. Другое дело — модем должен поддерживать USSD запросы.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *