betment_6


Мудак и член партии Справедливый Хохлосрач


Previous Entry Share Next Entry
huawei e1550 и linux: отправить USSD-запрос
betment_6
Вот например тут обсуждалась проблема с этим устройством. Там написано, что USSD-запрос нужно отправлять кодированным в "GSM 7 bit default alphabet (3GPP 23.038)". Предложенный там скрипт на php не торт. Не горя желанием вдаваться в детали и писать кодер-декодер для этого я поискал в CPAN по слову pdu, и кое-что нашел. Это модуль Device::Gsm::Pdu. Вот мой скрипт на perl:

#!/usr/bin/perl


use Getopt::Std;
use Device::Gsm::Pdu;


# defaults
$opt_i = "/dev/ttyUSB2";
$opt_o = "/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 to work for (just mine) Huawei E1550 GSM/UMTS USB modem.


Options:
  -i port   Port to receive data from. Default: $opt_i
  -o port   Port to send AT commands to. Default: $opt_o
  -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_o) or die "Can't open '$opt_o': $!\n";
    print SENDPORT 'AT+CUSD=1,',$ussd_req,",15\r\n";
    close SENDPORT;
    open (RCVPORT, $opt_i) or die "Can't open '$opt_i': $!\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";}






ussd_msg пишется привычным способом:
# script.pl "*111#"
USSD REPLY: Na Vashomu rahunku 6.66 grn.



upd: если не расшифровывается USSD-ответ, замените вызов функции decode_text7('00'.$ussd_reply) на pdu_to_latin1($ussd_reply)
(без нолей)
Tags: ,

Я не пойму зачем вы пишите эти скрипты, один фиг же не работает. Как он вообще работать может а? напиши уже подробней тогда как вы им пользуетесь. может и видео снимите заодно? начинай с момента загрузки ОС и вставке в порт USB модема? А то чувствую вы в статье ох как много чего не договариваете.

Здраствуйте. Спасибо за скрипт.
У меня возникла проблема - PDU код не расшифровуется.

sudo ./perl.pl -v *121#
USSD MSG: *121#
PDU ENCODED: AA982C3602
Waiting for USSD reply...
PDU USSD REPLY: 4937BD2C7797E9BAD91114ABD56A38980BB714B3AAEEB4BD2C9F87D9EE7C1A348BC572B49ACBB614B39C61BA4BFEAEB7D3EE3308E6822DC53B980B366D4E41F037A8BA9687D3EEF40E6607B5CB7A74180DAAAEE5E1B43BBF83B9C3A0B47B8E4E83DA6F719AED4E83AA6B7938EDCE03
USSD REPLY:

Дайте совет.

Замените функцию decode_text7 на pdu_to_latin1
А так, подсмотреть можно, например, на странице модуля: http://search.cpan.org/~cosimo/Device-Gsm-1.58/lib/Device/Gsm/Pdu.pm

Кстати, нашёл у себя ошибки, вместо $opt_r и $opt_s должны быть $opt_i и $opt_o соответственно.

Выдаёт ошибку:

root@debian-laptop:/# /home/nn/Desktop/ussd -v "*100#"
USSD MSG: *100#
Undefined subroutine &Device::Gsm::Pdu::encode_text7 called at /home/nn/Desktop/ussd line 32

Как сделать чтоб заработало?

Ээ.. у вас какой-то не такой Device::Gsm::Pdu? Не знаю, сравните содержимое вашего Pdu.pm и того, что в CPAN.

Зддравствуйте, в perl и linux неофит, потихоньку пытаюсь разбираться. нашёл Ваш скрипт, хочу попробовать его запустить, терминал выводит:

baktus@brasus:~$ perl huawei-ussd.pl
Can't locate Device/Gsm/Pdu.pm in @INC (@INC contains: /etc/perl /usr/local/lib/perl/5.10.1 /usr/local/share/perl/5.10.1 /usr/lib/perl5 /usr/share/perl5 /usr/lib/perl/5.10 /usr/share/perl/5.10 /usr/local/lib/site_perl .) at huawei-ussd.pl line 4.
BEGIN failed--compilation aborted at huawei-ussd.pl line 4.

ubuntu 11.04 kernel 2.6.38-10

спасибо заранее



Вам надо поставить модуль. Например, так:
perl -MCPAN -e 'install Device::Gsm::Pdu'

скрипт не работает для gobi 2000

(Anonymous)

2011-09-09 11:58 am (UTC)

Установил
perl -MCPAN -e 'install Device::Gsm::Pdu'

Appending installation info to /usr/lib/perl5/i386-linux/perllocal.pod
COSIMO/Device-Gsm-1.58.tar.gz
/usr/bin/make install -- OK
Warning (usually harmless): 'YAML' not installed, will not store persistent state

Затем запустил скрипт. И он завис для модема gobi 2000 /dev/ttyUSB2:
$ ./script.pl -v "*100#"
USSD MSG: *100#
PDU ENCODED: AA180C3602
Waiting for USSD reply...

Как подправить скрипт для этого модема?

Re: скрипт не работает для gobi 2000

betment_6

2011-09-09 03:03 pm (UTC)

Не знаю, у меня нет такого модема чтобы проверить что-либо. Пообщайтесь с модемом через что-нибудь наподобие minicom.

Спасибо за скрипт!

Я поправил кое-что, иначе у меня не работало. Вот исправленная версия.

(Кстати, у вас в тексте куда-то делись все знаки + и *.)

#!/usr/bin/perl

use Getopt::Std;
use Device::Gsm::Pdu;
use Fcntl;

# defaults
$opt_i = "/dev/ttyUSB2";
$opt_o = "/dev/ttyUSB2";

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.
  Edited for Huavei E173 modem (Megafon)

Options:
  -i port   Port to receive data from. Default: $opt_i
  -o port   Port to send AT commands to. Default: $opt_o
  -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) {
    sysopen(SENDPORT, $opt_o, O_NONBLOCK|O_RDWR) or die "Can't open '$opt_o': $!\n";
    print SENDPORT 'AT+CUSD=1,',$ussd_req,",15\r\n";
    close SENDPORT;
    open (RCVPORT, $opt_i) or die "Can't open '$opt_i': $!\n";
    print "Waiting for USSD reply...\n" if $opt_v;
    while () {
        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_text_UCS2('00'.$ussd_reply);
    print STDOUT "USSD REPLY: $decoded_ussd_reply\n";
}
else {print "No USSD reply!\n";}


Что-то да, пропали символы. Спасибо, поправил.

а вот с такой концовкой работает и с русскими и с английскими ответами:

if (! $opt_n) {
open (SENDPORT, '+<', $opt_o) or die "Can't open '$opt_o': $!\n";
print SENDPORT 'AT+CUSD=1,',$ussd_req,",15\r\n";
close SENDPORT;
open (RCVPORT, $opt_i) or die "Can't open '$opt_i': $!\n";
print "Waiting for USSD reply...\n" if $opt_v;
while () {
chomp;
die "USSD ERROR\n" if $_ eq "+CUSD: 2";
if (/^\+CUSD: 0,\"([A-F0-9]+)\",([0-9]*)/) {
$ussd_reply = $1;
$ussd_coding = $2;
print "PDU USSD REPLY: $ussd_reply\n" if $opt_v;
print "USSD encoding ID is $ussd_coding\n" if $opt_v;
last;
}
print "Got unknown USSD message: $_\n" if /^\+CUSD:/ and $opt_v;
}
}

if ($ussd_reply) {
if($ussd_coding=='15') {
$decoded_ussd_reply = Device::Gsm::Pdu::pdu_to_latin1($ussd_reply);
}
if($ussd_coding=='72'){
$decoded_ussd_reply = Device::Gsm::Pdu::decode_text_UCS2('00'.$ussd_reply);
}
print STDOUT "USSD REPLY: $decoded_ussd_reply\n";
}
else {print "No USSD reply!\n";}

Огромное спасибо за скрипт! После нескольких манипуляций заработало с модемом Huawei E153

извините, чт откапываю стюардессу

snow_irbis

2014-09-19 09:48 am (UTC)

не знаю, актуально ли, но вот моя версия без Device::Gsm::Pdu и с одним портом чтения/записи (актуально для FreeBSD), за исходник огромное спасибо!

#!/usr/bin/perl

use Getopt::Std;

# defaults
$opt_i = "/dev/cuaU0.2";

my $USAGE = <
[Error: Irreparable invalid markup ('<__eou;>') in entry. Owner must fix manually. Raw contents below.]

не знаю, актуально ли, но вот моя версия без Device::Gsm::Pdu и с одним портом чтения/записи (актуально для FreeBSD), за исходник огромное спасибо!

#!/usr/bin/perl

use Getopt::Std;

# defaults
$opt_i = "/dev/cuaU0.2";

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 to work for (just mine) Huawei E1550 GSM/UMTS USB modem.


Options:
-i port Port to send and receive data from. Default: $opt_i
-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:hnv');
HELP_MESSAGE() and exit if (! $ARGV[0]) or defined($opt);


print "USSD MSG: $ARGV[0]\n" if $opt_v;

my $ussd_req = encode_text($ARGV[0]);

print "PDU ENCODED: $ussd_req\n" if $opt_v;

my $ussd_reply;
if (! $opt_n) {
open (PORT, '+<', $opt_i) or die "Can't open '$opt_o': $!\n";
print PORT 'AT+CUSD=1,',$ussd_req,",15\r\n";
print "Waiting for USSD reply...\n" if $opt_v;
while (<PORT>) {
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;
}
close(PORT);
}


if ($ussd_reply) {
$decoded_ussd_reply = decode_text($ussd_reply);
print STDOUT "USSD REPLY: $decoded_ussd_reply\n";
}
else {print "No USSD reply!\n";}

sub encode_text {
my $text = shift;
my $i;
my @a = split(//,unpack("b*",$text));
for ($i=7; $i < $#a; $i+=8) {
$a[$i]="";
}
my $return = uc(unpack("H*", pack("b*", join("", @a))));
return $return;
}

sub decode_text {
my $text = shift;
my $i;
my @a = split(//,unpack("b*", pack("H*",$text)));
for ($i=6; $i < $#a; $i+=7) {
$a[$i].="0";
}
my $return = pack("b*", join("", @a));
return $return;
}




Re: извините, чт откапываю стюардессу

betment_6

2014-09-23 09:00 am (UTC)

Однако и вам спасибо :)
Сам уже не пользуюсь скриптом, после покупки телефона на android модем пылится в ящике шкафа :)

Re: извините, чт откапываю стюардессу

snow_irbis

2014-09-23 09:30 am (UTC)

у меня он к тазу с мониторингом прикручен

пс: парсер - мудак

You are viewing betment_6