#!/usr/bin/python # vim:fileencoding=utf-8 # # Hacked by Phillip Berndt, www.pberndt.com # import gtk import glib import sys import serial import time # 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() # Function to show „action pending“ message def doPendingDialog(): dlg = gtk.MessageDialog(wnd) dlg.set_markup("Waiting for response from the dongle") progress = gtk.ProgressBar() dlg.vbox.add(progress) def do_pulse(*w): if progress.get_window() is None: return False progress.pulse() return True glib.timeout_add(100, do_pulse) dlg.set_modal(True) dlg.show_all() return dlg # Function to show error dialog def doError(message): dlg = gtk.MessageDialog() dlg.set_markup(message) dlg.set_title("Error") dlg.add_button("Ok", gtk.RESPONSE_OK) dlg.run() sys.exit(1) # Function to ask for sth def doAsk(question): dlg = gtk.MessageDialog() dlg.set_markup(question) dlg.set_title("Question") entry = gtk.Entry() dlg.vbox.add(entry) entry.show() dlg.add_button("Ok", gtk.RESPONSE_OK) dlg.add_button("Cancel", gtk.RESPONSE_CANCEL) if dlg.run() == gtk.RESPONSE_CANCEL: dlg.destroy() return False retVal = entry.get_text() 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("Connection to dongle lost") 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("Message no. " + msgNo + " follows:") return True if textInput == "OK": del globals()["cmglMode"] if "pending" in globals(): globals()["pending"].destroy() del globals()["pending"] appendText("No further messages") appendText("") else: try: appendText(" * " + pduDecodeSMS(textInput)) except: appendText("Did not understand " + textInput) 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] == "+CPIN": result = textInput[7:] if result != 'READY': pin = doAsk("The card asks for " + 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; dongle accessible") usbTTY.write("AT+CNUM\r\n") usbTTY.flush() usbTTY.write("AT+CMGF=0\r\n") usbTTY.flush() usbTTY.write("AT+CNMI=1,1,0,0,0\r\n") return True if textInput[0:5] == "+CUSD": textInput = textInput[textInput.find('"') + 1:textInput.rfind('"')] appendText(pduDecode(textInput)) appendText("") if textInput[:5] == "+CNUM": textInput = textInput[10:] textInput = textInput[textInput.find('"') + 1:textInput.rfind('"')] appendText("Own phone number is " + textInput) appendText("") if textInput[:5] == "+CMTI": appendText("A new text message has arrived!") return True # Open TTY try: usbTTY = serial.Serial("/dev/ttyUSB3") glib.io_add_watch(usbTTY.fileno(), glib.IO_IN | glib.IO_ERR, ttyReceivedCallback) except: doError("Failed to upen USB-tty. Make sure to have the dongle attached, /dev/ttyUSB3 accessible " + "and the usbserial module loaded") # Create main window wnd = gtk.Window() wnd.set_title("USB UMTS dongle recharge tool") wnd.set_size_request(640, 240) hbox = gtk.HBox() vbox = gtk.VBox() textView = gtk.TextView() textView.set_editable(False) textView.set_cursor_visible(False) textView.set_size_request(440, 240) textView.set_wrap_mode(gtk.WRAP_WORD) buffer = textView.get_buffer() 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("Check balance") def checkAction(widget): appendText("Sending request for balance check") sendNWait('AT+CUSD=1,"' + pduEncode("*101#") + '",15') checkButton.connect("clicked", checkAction) rechargeButton = gtk.Button("Recharge") def rechargeAction(widget): code = doAsk("Enter recharge code:") if code == False: return appendText("Sending recharge-request") sendNWait('AT+CUSD=1,"' + pduEncode("*103*" + code + "#") + '",15') rechargeButton.connect("clicked", rechargeAction) readTextButton = gtk.Button("Read new text messages") def readTextAction(widget): appendText("Receiving text messages") sendNWait("AT+CMGL") globals()["cmglMode"] = True readTextButton.connect("clicked", readTextAction) readAllTextButton = gtk.Button("Read all text messages") def readAllTextAction(widget): appendText("Receiving text messages") sendNWait("AT+CMGL=4") globals()["cmglMode"] = True readAllTextButton.connect("clicked", readAllTextAction) deleteTextButton = gtk.Button("Delete a text message") def deleteTextAction(widget): delw = doAsk("Enter message no. to be deleted") if delw == False: return True usbTTY.write("AT+CMGD=" + delw + "\r\n") deleteTextButton.connect("clicked", deleteTextAction) sendCusdButton = gtk.Button("Send CUSD") def sendCusdAction(widget): cusd = doAsk("CUSD to send: (e.g. *101#)") if cusd == False: return sendNWait('AT+CUSD=1,"' + pduEncode(cusd) + '",15') sendCusdButton.connect("clicked", sendCusdAction) wnd.connect("hide", lambda *f: gtk.main_quit()) hbox.add(vbox) hbox.pack_end(textView, padding=5) vbox.pack_start(checkButton, False, padding=3) vbox.pack_start(rechargeButton, False, padding=3) vbox.pack_start(readTextButton, False, padding=3) vbox.pack_start(readAllTextButton, False, padding=3) vbox.pack_start(deleteTextButton, False, padding=3) vbox.pack_start(sendCusdButton, False, padding=3) wnd.add(hbox) wnd.show_all() usbTTY.write("ATZ\r\n") sendNWait("AT+CPIN?") # Run gtk.main()