^Вверх

foto1 foto2 foto3 foto4 foto5


3G 4G LTE

CDMA

Wi-Fi

Антенны своими руками

3G-Aerial

Поиск на сайте

Сейчас на сайте

На сайте один гость и ни одного пользователя

Вход

Войти Регистрация

Войти в аккаунт

Логин *
Пароль *
Запомнить меня

Создать аккаунт

Обязательные поля помечены звездочкой (*).
Максимальная длина имени и логина 16 символов
Имя *
Логин *
Пароль *
Подтверждение пароля *
Email *
Подтверждение email *
Защита от ботов *
5 1 1 1 1 1 Рейтинг 100% [2 Голоса (ов)]

HUAWEI E153Эта статья адресована прежде всего пользователям Linux имеющим 3G модем HUAWEI от Киевстар, но может быть полезна и клиентам других сотовых операторов - MTS, BeeLine, Megafon, Life...

Дело в том, что при переходе на Linux, теряется возможность проконтролировать денежный баланс, остаток пакетных мегабайт, наличие СМС от оператора и ряд других необходимых функций. В Windows этот сервис доступен в программе Mobile partner, которая поставляется вместе с модемом. 

Linux-версию этой программы предоставляет только Megafon, остальные же операторы игнорируют тот факт, что кроме Windows существуют и другие операционные системы. Давайте устраним этот пробел...

Восполнить этот пробел призван скрипт на GTK2+Python. Он не заменяет собой Mobile Partner, а просто предоставляет наиболее востребованные функции управления модемом. Скрипт работал на машине автора с UBUNTU 12.04LTS и модемом HUAWEI E153. При желании скрипт легко модифицируется под других операторов, достаточно поменять в нем USSD коды запроса баланса и т.п.

 

#!/usr/bin/python
# vim:fileencoding=utf-8
# author Kustarev Valery
import gtk
import glib
import sys
import serial
import time
import datetime

Port = "/dev/ttyUSB2"

# Functions for PDU en-/decoding
def pduDecode(text):
pad = lambda number: number + "0" * (8 - len(number))
data = "".join([ pad("".join(reversed(bin(ord(c))[2:]))) for c in text.decode("hex") ])
output = ""
while len(data) >= 7:
output += chr(int("".join(reversed(data[:7])), 2))
data = data[7:]
return output
def pduDecodeSMS(text):
text = text[2 + int(text[:2], 16) * 2:]# Skip SMSC
text = text[2:]# Skip info
#text = text[2:] # Skip reference
text = text[2 + (int(text[:2], 16) + int(text[:2], 16) % 2) + 2:]# Skip telephone number
text = text[2:]# Skip protocol
text = text[2:]# Skip data coding scheme
text = text[14:]# Skip date
text = text[2:]# Skip content length
return pduDecode(text)
def pduEncode(text):
pad = lambda number: number + "0" * (7 - len(number))binrep = ""
while text:
binrep += pad("".join(reversed(bin(ord(text[0]) & ~(1<<7))[2:])))
text = text[1:]
output = ""
while len(binrep) >= 8:
output += chr(int("".join(reversed(binrep[:8])), 2)).encode("hex")
binrep = binrep[8:]
if binrep:
binrep = "".join(reversed(binrep))
output += chr(int(binrep, 2)).encode("hex")
return output.upper()
#Convert telephone number
def convertPhone(number):
pdu_number = ''
for i in range(0,len(number)):
if i%2==0:
continue
pdu_number += number[i] + number[i-1]
return pdu_number
def dectobin(i):
b = ''
while i > 0:
j = i & 1
b = str(j) + b
i >>= 1
return b
def TextToSMS(text):
#'''Convert text to binary format'''
pdu_text_bin = []
for i in text:
dec_s=ord(i)
if dec_s == 95: dec_s = 17
if dec_s == 94: dec_s = 1
if dec_s == 64: dec_s = 0
if dec_s == 36: dec_s = 2
if dec_s == 123: dec_s = 40
if dec_s == 125: dec_s = 41
if dec_s == 124: dec_s = 64
if dec_s == 126: dec_s = 61
if dec_s == 92: dec_s = 47
if dec_s == 91: dec_s = 60
if dec_s == 93: dec_s = 62
bin = dectobin(dec_s)
le = len(bin)
while le<7:
bin='0'+bin
le = len(bin)
pdu_text_bin.append(bin)
#'''Encode binary to PDU format'''
pdu_text_bin_cp = []
n=0
for i in range(0,len(text)):
if (i>0) & ((i+1)%8==0):
continue
n+=1
if n==8:
n=1
if i==len(text)-1:
cp = pdu_text_bin[i][0:8-n]
else:
cp = str(pdu_text_bin[i+1][7-n:7] + pdu_text_bin[i])[0:8]
pdu_text_bin_cp.append(cp)
#'''Convert PDU to hex'''
pdu_text=''
for i in pdu_text_bin_cp:
hexi = str(hex(int(i,2)))[2:4].upper()
if len(hexi) == 1:
hexi = '0' + str(hexi)
pdu_text += hexi
return pdu_text
def CreateSMS(data):
number = data[0:10]
text = data[10:97]
pdu_data = '00'#СМС центр (default)
pdu_data += '11'#SMS-SUBMIT
pdu_data += '00'#TP-Message-Reference
pdu_data += '0A'#Phone number-Length
pdu_data += '81'#81 - национальный формат, 91 - международный
pdu_data += convertPhone(number)
pdu_data += '00'#TP-Protocol identifier
pdu_data += '00'#TP-Data coding scheme
pdu_data += 'AA'#TP-Validity-Period
len_hex = hex(len(text))[2:4].upper()#Calculate text length
if len(len_hex) == 1:
len_hex = '0' + str(len_hex)
pdu_text = pduEncode(text)
pdu_data+=len_hex
pdu_data+=pdu_text
return pdu_data

wnd = gtk.Window()

def aboutDialog():
about = gtk.AboutDialog()
about.set_modal(gtk.DIALOG_MODAL)
about.set_program_name("gKyivStarModemTool")
about.set_version("0.0.5-2")
about.set_copyright("2013 © Valery Kustarev")
about.set_comments("gKyivStarModemTool - программа управления модемом Киевстар для GTK+")
about.run()
about.destroy()

# Function to show „action pending“ message
def doPendingDialog():
dlg = gtk.MessageDialog(wnd, 0, gtk.MESSAGE_OTHER, gtk.BUTTONS_NONE, None)
dlg.set_markup("Ждите ответа от модема...")
sp = gtk.Spinner()
sp.set_size_request(50, 50)
dlg.vbox.add(sp)
sp.start()
dlg.set_modal(True)
dlg.show_all()
return dlg

# Function to show error dialog
def doError(message):
dlg = gtk.MessageDialog(wnd, 0, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, None)
dlg.set_markup(message)
dlg.set_title("USB GPRS 3G modem tool - Ошибка")
dlg.run()
dlg.destroy()
sys.exit(1)
# Function to ask for sth
def doAsk(question):
dlg = gtk.MessageDialog(wnd, 0, gtk.MESSAGE_QUESTION, gtk.BUTTONS_OK_CANCEL, None)
dlg.set_markup(question)
dlg.set_title("Modem tool - Запрос")
entry = gtk.Entry()
dlg.vbox.add(entry)
entry.show()
if dlg.run() == gtk.RESPONSE_CANCEL:
dlg.destroy()
return False
retVal = entry.get_text()
dlg.destroy()
return retVal
def dialogSMS(question):
dlg = gtk.MessageDialog(wnd, 0, gtk.MESSAGE_QUESTION, gtk.BUTTONS_OK_CANCEL, None)
dlg.set_markup(question)
dlg.set_title("Modem tool - Запрос")
Label1 = gtk.Label()
dlg.vbox.add(Label1)
Label1.set_text('Номер телефона: \n (в национальном формате, например 0661234567)')
Label1.show()
entry = gtk.Entry()
dlg.vbox.add(entry)
entry.show()
Label2 = gtk.Label()
dlg.vbox.add(Label2)
Label2.set_text('Текст сообщения:')
Label2.show()
textView = gtk.TextView()
textView.set_editable(True)
textView.set_cursor_visible(True)
textView.set_size_request(240, 120)
textView.set_wrap_mode(gtk.WRAP_WORD)
dlg.vbox.add(textView)
textView.show()
if dlg.run() == gtk.RESPONSE_CANCEL:
dlg.destroy()
return False
buffer = textView.get_buffer()
txt = buffer.get_text(buffer.get_start_iter(),buffer.get_end_iter())
retVal = entry.get_text()+unicode(txt)
dlg.destroy()
return retVal
def sendNWait(send):
usbTTY.write(send + "\r\n")
usbTTY.flush()
globals()["pending"] = doPendingDialog()
def ttyReceivedCallback(source, condition):
if condition != glib.IO_IN:
doError("Потеряна связь с модемом")
textInput = usbTTY.readline().strip()
print textInput
if "cmglMode" in globals():
if textInput[0:2] == "AT": return True
if textInput == "": return True
if textInput[:5] == "+CMGL":
msgNo = textInput[7:textInput.find(",")]
appendText("==============================")
appendText("Сообщение №. " + msgNo + " следующее:")
appendText("-------------------------------------------------------------------")
return True
if textInput == "OK":
del globals()["cmglMode"]
if "pending" in globals():
globals()["pending"].destroy()
del globals()["pending"]
appendText("Нет новых сообщений")
appendText("")
else:
try:
appendText(" * " + pduDecodeSMS(textInput))
except:
appendText("Не понято " + textInput)
return True
if textInput[:9] == "^SYSINFO:":
data = textInput[20:21]
if data == "0":
outputText = "Нет доступа к сети"
if data == "1":
outputText = "GSM mode"
if data == "2":
outputText = "GPRS"
if data == "3":
outputText = "EDGE mode"
if data == "4":
outputText = "WCDMA mode"
if data == "5":
outputText = "HSDPA mode "
if data == "6":
outputText = "HSUPA mode"
if data == "7":
outputText = "HSPA mode"
if data == "8":
outputText = "HSPA + mode"
setStatus1Mes('Режим сети: "'+outputText+'"')
return True
if len(textInput) == 0 or textInput[0] != "+":
# Not of interest for us
return True
if"pending" in globals():
globals()["pending"].destroy()
del globals()["pending"]
if textInput[0:5] == "+COPS":
textInput = textInput[textInput.find('"') + 1:]
textInput = textInput[:textInput.find('"')]
if textInput == "25001": textInput = "MTS RUS"
elif textInput == "25002": textInput = "MegaFon"
elif textInput == "25099": textInput = "BeeLine RUS"
elif textInput == "25020": textInput = "Tele2"
elif textInput == "25039": textInput = "Utel (Пермский край)"
elif textInput == "25501": textInput = "MTS-UA"
elif textInput == "25502": textInput = "Beeline-UA"
elif textInput == "25503": textInput = "UA-KYIVSTAR"
elif textInput == "25505": textInput = "UA-GOLDEN TELECOM"
elif textInput == "25506": textInput = "Life:)"
elif textInput == "25507": textInput = "Utel (Ukrtelecom)"
else: textInput = "Unknown"
setStatus3Mes("Оператор: " + '"'+textInput+'"')
if textInput[0:5] == "+CPIN":
result = textInput[7:]
if result != 'READY':
pin = doAsk("Карточка просит " + result)
if pin == False:
sys.exit(1)
sendNWait('AT+CPIN="' + pin + '"')
usbTTY.flush()
def send_ask_pin(*w):
usbTTY.write("AT+CPIN?\r\n")
return False
glib.timeout_add(300, send_ask_pin)
else:
appendText("Pin ok; модем доступен")
appendText("")
usbTTY.write("AT+CNUM\r\n")
usbTTY.flush()
usbTTY.write("AT+CSQ\r\n")
usbTTY.flush()
usbTTY.write("AT^SYSINFO\r\n")
usbTTY.flush()
usbTTY.write("AT+CMGF=0\r\n")
usbTTY.flush()
usbTTY.write("AT+COPS?\r\n")
usbTTY.flush()
usbTTY.write("AT+CNMI=1,1,0,0,0\r\n")
usbTTY.flush()
return True
if textInput[0:5] == "+CUSD":
textInput = textInput[textInput.find('"') + 1:textInput.rfind('"')]
s = pduDecode(textInput)
appendText(s)
try:
Mb = s[s.index('Bonusy:')+7:s.index('Mb')]
# print Mb
# print s[-4:]
# print s[-7:-5]
# print s[-10:-8]
nowDay = datetime.date.today()
finish = datetime.date(int(s[-4:]),int(s[-7:-5]),int(s[-10:-8]))
delta = finish - nowDay
mb_per_day = int(Mb)/(delta.days+1)
appendText("")
appendText("Осталось "+unicode(delta.days+1)+" дней (включая сегодняшний)")
appendText ('В день можно тратить: ' + unicode(mb_per_day) + ' Mb')
except:
appendText("")
appendText("")
if textInput[:5] == "+CNUM":
textInput = textInput[10:]
textInput = textInput[textInput.find('"') + 1:textInput.rfind('"')]
setStatus4Mes("Номер телефона модема: " + textInput)
if textInput[:5] == "+CMTI":
appendText("Получено новое СМС!")
if textInput[:5] == "+CSQ:":
print textInput
data = textInput[6:8]
print data
sig_str = -113 + int(data)*2
sig_per = int(data)*100 / 30
pbar.set_text("Уровень сигнала сети: "+unicode(sig_str)+"dBm / "+unicode(sig_per)+"%")
pbar.set_fraction(float(sig_per)/100)
return True

# Create main window

wnd.set_title("USB GPRS EDGE 3G KyivStar modem tool")
wnd.set_size_request(640, 420)
gbox = gtk.VBox()
hbox = gtk.HBox()
vbox = gtk.VBox()

textView = gtk.TextView()
textView.set_editable(True)
textView.set_cursor_visible(False)
textView.set_size_request(320, 64)
textView.set_wrap_mode(gtk.WRAP_WORD)
textView.get_vadjustment ()
buffer = textView.get_buffer()
sw = gtk.ScrolledWindow()
sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)

# Create the menu items
menu = gtk.Menu()
menu_item1 = gtk.MenuItem('О программе')
menu_item2 = gtk.MenuItem('Выход')
menu.append(menu_item1)
menu.append(menu_item2)
menu_item1.connect_object("activate", lambda *f: aboutDialog(),"О программе")
menu_item2.connect_object("activate", lambda *f: wnd.hide(),"Выход")
menu_item1.show()
menu_item2.show()
root_menu = gtk.MenuItem("Меню")
root_menu.show()
root_menu.set_submenu(menu)
menu_bar = gtk.MenuBar()
gbox.pack_start(menu_bar, False, False, 2)
menu_bar.show()
menu_bar.append (root_menu)
# Create the menu items

def appendText(text):
buffer.insert(buffer.get_end_iter(), text.strip() + "\n")
textView.scroll_to_iter(buffer.get_end_iter(), 0.25)
checkButton = gtk.Button("Проверить баланс")
def checkAction(widget):
sendNWait('AT+CUSD=1,"' + pduEncode("*111#") + '",15')
checkButton.connect("clicked", checkAction)
mbButton = gtk.Button("Проверить остаток Мб")
def mbAction(widget):
sendNWait('AT+CUSD=1,"' + pduEncode("*221#") + '",15')
mbButton.connect("clicked", mbAction)
rechargeButton = gtk.Button("Пополнить счет")
def rechargeAction(widget):
code = doAsk("Введите код пополнения:")
if code == False: return
appendText("Код послан-ответ оператора:")
sendNWait('AT+CUSD=1,"' + pduEncode("*123*" + code + "#") + '",15')
rechargeButton.connect("clicked", rechargeAction)
readTextButton = gtk.Button("Прочитать новые СМС")
def readTextAction(widget):
sendNWait("AT+CMGL")
globals()["cmglMode"] = True
readTextButton.connect("clicked", readTextAction)
readAllTextButton = gtk.Button("Прочитать все СМС")
def readAllTextAction(widget):
appendText("Текст полученных сообщений: ")
sendNWait("AT+CMGL=4")
globals()["cmglMode"] = True
readAllTextButton.connect("clicked", readAllTextAction)
deleteTextButton = gtk.Button("Удалить СМС")
def deleteTextAction(widget):
delw = doAsk("Введите № удаляемого СМС")
if delw == False: return True
usbTTY.write("AT+CMGD=" + delw + "\r\n")
deleteTextButton.connect("clicked", deleteTextAction)
sendTextButton = gtk.Button("Отправить СМС")
def sendTextAction(widget):
sendText = dialogSMS("Введите номер телефона и текст сообщения \n Только для украинских операторов!")
print sendText
if sendText == False: return True
usbTTY.write("AT+CMGF=0 \015")
time.sleep(1)
pdu_data = CreateSMS(sendText)
print pdu_data
pdu_len = str(len(pdu_data)/2-1)
usbTTY.write("AT+CMGS=" + pdu_len + "\015")
time.sleep(1)
usbTTY.write(pdu_data + "\032")
sendTextButton.connect("clicked", sendTextAction)
sendCusdButton = gtk.Button("Послать USSD запрос")
def sendCusdAction(widget):
cusd = doAsk("USSD запрос: (например *101#)")
if cusd == False:
return
sendNWait('AT+CUSD=1,"' + pduEncode(cusd) + '",15')
sendCusdButton.connect("clicked", sendCusdAction)
sep1 = gtk.HSeparator()
sep2 = gtk.HSeparator()
stBar1 = gtk.Statusbar()

stBar3 = gtk.Statusbar()
stBar4 = gtk.Statusbar()
pbar = gtk.ProgressBar()
pbar.show()
table = gtk.Table(2, 2, False)
table.attach(stBar1, 0, 1, 0, 1)
table.attach(pbar, 1, 2, 0, 1)
table.attach(stBar3, 0, 1, 1, 2)
table.attach(stBar4, 1, 2, 1, 2)
table.show()
def setStatus1Mes(mess):
stBar1.push(0,mess)
return
def setStatus3Mes(mess):
stBar3.push(0,mess)
return
def setStatus4Mes(mess):
stBar4.push(0,mess)
return
wnd.connect("hide", lambda *f: gtk.main_quit())
hbox.add(vbox)
sw.add(textView)
hbox.pack_end(sw, padding=5)
vbox.pack_start(checkButton, False, padding=3)
vbox.pack_start(mbButton, False, padding=3)
vbox.pack_start(rechargeButton, False, padding=3)
vbox.pack_start(sep1, False, padding=8)
vbox.pack_start(readTextButton, False, padding=3)
vbox.pack_start(readAllTextButton, False, padding=3)
vbox.pack_start(deleteTextButton, False, padding=3)
vbox.pack_start(sendTextButton, False, padding=3)
vbox.pack_start(sep2, False, padding=8)
vbox.pack_start(sendCusdButton, False, padding=3)
gbox.add(hbox)
gbox.pack_end(table, False, padding=5)
wnd.add(gbox)
wnd.show_all()

# Open TTY
try:
usbTTY = serial.Serial(Port)
glib.io_add_watch(usbTTY.fileno(), glib.IO_IN | glib.IO_ERR, ttyReceivedCallback)
except:
doError('Ошибка открытия порта USB-tty. Убедитесь, что подключение "/dev/ttyUSB2" доступно '+
'(возможно его заняло другое приложение, работающее с модемом, например NetworkManager). ' +
'Убедитесь, что "usbserial" модуль загружен и модем подключен к порту USB')
usbTTY.write("ATZ\r\n")
sendNWait("AT+CPIN?")

gtk.main()# Run

Скрипт можно скачать одним файлом - ussd.zip. Распаковав и сохранив его в домашней папке, нужно дать ему права на выполнение. После запуска скрипта появится следующее окно.mobile partner for Linux

Ну а дальше все понятно... Можно проверить баланс, пополнить счет, проверить наличие входящих СМС или послать СМС с модема. При отсылке СМС, следует иметь ввиду, что текст сообщения надо написать транслитом, иначе корреспондент получит его абракадаброй. Есть возможность послать любой USSD запрос и получить любую информацию от оператора. Предлагаю также deb-пакет этого скрипта для установки в Linux-системы на основе Debian.

Network manager обычно забирает себе все ресурсы модема и скрипт не работает, если модем подключен к интернет через NM. После этого приходится перезагружать модем. Приходится мирится с этим, но зато теперь уже можно не ходить в Windows, чтобы просто посмотреть баланс и не нужно искать Mobile Partner, который заработал бы с вашим модемом в Linux...

Последние коммы


Яндекс.Метрика Рейтинг@Mail.ru