Скрипт проверки баланса для 3G модема Huawey/ZTE
Создано: 19-06-2011 21:44:25 изменено: 16-06-2012 20:47:16  Метки: linux tcl
Была поставлена задача проверять баланс 3G модема Huawey без использования Mobile Partner. После прочесывания инета было выяснено:
1) АТ команду нужно посылать в закодированном виде
2) Ответ модем также присылает в закодированном виде

АТ команда имеет общий вид AT+CUSD=1,*102#,15 . Вот в ней USSD-запрос *102# и надо кодировать в вид понятный модему.
Примерно так:
perl -e '@a=split(//,unpack("b*","*102#")); for ($i=7; $i < $#a; $i+=8) { $a[$i]="" } print uc(unpack("H*", pack("b*", join("", @a))))."\n"'
AA184C3602

Ответ от модема приходит примерно такой:
AT+CUSD=1,AA184C3602,15
OK

+CUSD: 0,"04110430043B0430043D04410020003500370039002E003600300440002E00200422044004300
4440438043A002000300020041A0431002E0414043504420430043B0438003A002000680074007400700073
003A002F002F00750073006C007500670069002E006200650065006C0069006E0065002E00720075",72

Декодировать его можно так:
echo "04110430043B0430043D04410020003500370039002E003600300440002E0
02004220440043004440438043A002000300020041A0431002E0414043504420430043B0438003A0020
00680074007400700073003A002F002F00750073006C007500670069002E006200650065006C0069006
E0065002E00720075" \
| perl -ne '@a = m/([0-9A-F]{4})/g; map { eval "print \"\\x{$_}\""; } @a;' 2>/dev/null

Баланс 579.60р. Трафик 0 Кб.Детали: https://uslugi.beeline.ru

Поскольку с перлом у меня туго, а тут попался скрипт на питоне, я слегка адаптировал его под себя:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# 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
#
USBPORT='/dev/ttyUSB2'
USBSPEED=460800
MAXSTRINGLENGTH=300

#print "Wait a USSD request ... "
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')
#result=line3
# вывод в консоль
print result
# вывод в нотификатор
os.system('echo "message:' + result + '" | /usr/bin/zenity --notification --listen --timeout 5')
#os.system('notify-send -i info -t 5000 "Запрос баланса" "' + result +'"')

У меня запрос и ответ пересылаются через /dev/ttyUSB2, в некоторых случаях порты ввода и вывода как я понял могут отличаться. Вызов скрипта повесил на горячую клавишу, поскольку стоит unity нотификатором служит zenity, в случае другого DE возможно нужно будет поменять последнюю строчку.
Update:
Для сравнения написал почти тоже самое на tcl:
#! /usr/bin/tclsh
# порт
set port /dev/ttyUSB2
# запрос баланса
set req AT+CUSD=1,AA184C3602,15

# вывод в нотификатор
#proc mess m {
#    puts $m
#}

proc mess m {
    exec notify-send -i info -t 5000 "Запрос баланса" $m
}


if {![file exists $port]} {
    mess "Модем не подключен?"
    exit 1
}
if [catch {set f [open $port w+]}] {
    mess "Нет прав на открытие $port"
    exit 1
}
fconfigure $f -mode 19200,n,8,1 -blocking 0 -buffering none
# сброс модема
puts $f ATZ
after 100
puts $f $req
set a ""
set timeout 300
# читаем из порта до ответа
while {![regexp {\+CUSD\:} $a]} {
    after 100
    set a [read $f]
    incr timeout -1
    if {!$timeout} {
        mess "Нет ответа от модема"
        exit 1
    }
}
close $f
# вырезаем ответ
regexp {"([[:xdigit:]]*)"} $a => a
set c 0 ; set str ""
# декодируем ответ
while {$c < [string length $a]} {
    set str $str[format "%c" "0x[string range $a $c [expr $c+3]]"]
    incr c 4
}
mess $str

UPDATE:Для модема ZTE MF100 строчки конфигурации выглядят так:
# порт
set port /dev/ttyUSB1
# запрос баланса
set req AT+CUSD=1,#102#,15

Сюда же вставлю:

AT-команды ZTE:
disable/enable flashdrive 
AT+ZCDRUN=8       enable
AT+ZCDRUN=9       disable (включает AutoRUN для CD-ROM модема).

AT+ZCDRUN=E       удалить NODOWNLOAD.FLG
AT+ZCDRUN=F       восстановить NODOWNLOAD.FLG

Set Operational Mode 
AT+ZSNT=0,0,0      (Auto) - Default
AT+ZSNT=1,0,0      только GPRS
AT+ZSNT=2,0,0      только 3G
AT+ZSNT=0,0,1      предпочтение GPRS
AT+ZSNT=0,0,2      предпочтение 3G

stay online 
AT+ZOPRT=5

check net-/SIMlock 
AT+ZSEC?
answer: <SEC_STATUE>,<SEC_ITEMS>

< SEC_STATUE >:
0 Initializing the encryption (Insignificant SEC_ITEMS)
1 Network Lock error. (Insignificant SEC_ITEMS)
2 Network Locked
3 Unlocked or correct MCC/MNC

<SEC_ITEMS>:
0 No action
1 Network lock
2 (U)SIM card lock
3 Network Lock and (U)SIM card Lock

Unlock
+ZNCK="unlock-code"
+ZNCK?
Unlock residual time 0-5
Set Band Status 
+ZBANDI
at+zbandi=0 • Automatic (Auto) - Default
at+zbandi=1 • UMTS 850 + GSM 900/1800
at+zbandi=2 • UMTS 2100 + GSM 900/1800 (Europe)
at+zbandi=3 • UMTS 850/2100 + GSM 900/1800
at+zbandi=4 • UMTS 850/1900 + GSM 850/1900

Notice! the command is used only in platform 6290 and 6246. 
Подробнее: http://give-all.ru/faq/show/7/1/at-komandy-zte/
3240 просмотров комментировать