#!/usr/bin/python import serial import time import sys import re modem_device = "/dev/ttyACM1" apn = "web.vodafone.de" # TODO: AT*EGNCI (gsm-only) # AT*EWNCI (umts-only) # AT+COPS (operator select) # # *EGNCI: "26202","026E","00000000",6,50,24 # # *EWNCI: # UARFCN,PSC,RSCP,ECNO,PathLoss # 10588 ,287,36 ,14 ,158 # # UARFCN = Channel, RSCP = RSSI, CID = PSC # RNCid = CID_lang / 65536 (sometimes(?) == LAC) # CID = CID_lang % 65536 # def send_command(modem, cmd, text): modem.write(cmd) if text != None: print text + ": ", response = modem.readlines() if text != None: print ('ERROR\r\n' in response and "Error" or "OK") return response def get_pin_state(modem): modem.write('AT+CPIN?\r') response = modem.readlines() if "+CPIN: SIM PIN\r\n" in response: return False elif "+CPIN: READY\r\n" in response: return True else: print "[get_pin_state] Unknown response", print response return False # determine whether there is a gsm or umts connection # -1: unknown # 0: gsm # 2: umts def connection_mode(modem): response = send_command(modem, 'AT+COPS?\r', None) for line in response: if line.startswith('+COPS: '): values = line[7:].strip().split(',') if len(values) == 1: return -1 else: return int(values[-1]) return -1 def cell_info(modem): cells = set() # get GSM cell information send_command(modem, 'AT+CFUN=5\r', None) while connection_mode(modem) != 0: time.sleep(1) # get connected station modem.write('AT+CREG=2\r') modem.readlines() modem.write('AT+CREG?\r') response = modem.readlines() modem.write('AT+CREG=0\r') modem.readlines() for line in response: if line.startswith('+CREG: '): results = line.rstrip()[7:].split(',') if len(results) == 4: lac = int(results[2].strip('"'), 16) cid = int(results[3].strip('"'), 16) break modem.write('AT*EHNET=2\r') response = modem.readlines() for line in response: if line.startswith('*EHNET: '): mcc = int(line[8:].rstrip().strip('"')[:3]) mnc = int(line[8:].rstrip().strip('"')[3:]) cells.add((mcc, mnc, lac, cid)) # check stations until all are known (i.e. no '???' in response) retry = True while retry: retry = False response = send_command(modem, 'AT*EGNCI\r', None) if 'ERROR\r\n' in response: print "error" retry = True time.sleep(1) continue for line in response: if line.startswith('*EGNCI: '): values = line[8:].rstrip().split(',') try: mcc = int(values[0].strip('"')[:3]) mnc = int(values[0].strip('"')[3:]) lac = int(values[1].strip('"'), 16) cid = int(values[2].strip('"'), 16) if cid == 0: continue cells.add((mcc, mnc, lac, cid)) except: retry = True print "retrying" time.sleep(2) break for (mcc, mnc, lac, cid) in cells: print "MCC: " + str(mcc) + ", MNC: " + str(mnc) + ", LAC: " + str(lac) + ", CellID: " + str(cid) # # get UMTS cell information # send_command(modem, 'AT+CFUN=6\r', None) # time.sleep(10) # response = send_command(modem, 'AT*EWNCI\r', None) # for line in response: # if line.startswith('*EWNCI: '): # print line.rstrip() # # switch back to default mode # send_command(modem, 'AT+CFUN=1\r', None) def print_state(modem): modem.timeout = 0.1 modem.write('AT+CSQ\r') response = modem.readlines() for line in response: if line.startswith('+CSQ: '): signal = line.rstrip()[6:].split(',')[0] print "Signal: " + signal + "/31" break mcc, mnc, lac, cid = -1, -1, -1, -1 modem.write('AT*EHNET=2\r') response = modem.readlines() for line in response: if line.startswith('*EHNET: '): mcc = line[8:].rstrip().strip('"')[:3] mnc = line[8:].rstrip().strip('"')[3:] break modem.write('AT+CREG=2\r') modem.readlines() modem.write('AT+CREG?\r') response = modem.readlines() modem.write('AT+CREG=0\r') modem.readlines() for line in response: if line.startswith('+CREG: '): results = line.rstrip()[7:].split(',') if len(results) == 4: lac = int(results[2].strip('"'), 16) cid = int(results[3].strip('"'), 16) % 65536 # last 2 bytes for umts break print "MCC: " + str(mcc) + ", MNC: " + str(mnc) + ", LAC: " + str(lac) + ", CellID: " + str(cid) def start_modem(modem): if not get_pin_state(modem): pin = raw_input("Please enter PIN: ") send_command(modem, 'AT+CPIN="' + pin + '"\r', "Sending PIN") send_command(modem, 'AT+CFUN=1\r', "Starting modem") def connect(modem): send_command(modem, 'AT+CGDCONT=1,"IP","' + apn + '"\r', "Setting up") send_command(modem, 'AT*ENAP=1,1\r', "Connecting") def disconnect(modem): send_command(modem, 'AT*ENAP=0\r', "Disconnecting") def stop_modem(modem): send_command(modem, 'AT+CFUN=4\r', "Stopping") def show_usage(): print "Usage: " + sys.argv[0] + " " print "\tstart: switch on modem and unlock sim" print "\tstop: switch modem to powersave state" print "\tconnect: connect to internet" print "\tdisconnect: disconnect from internet" print "\tstate: show signal/base station info" print "\tcellinfo: show info about all received cells" if len(sys.argv) != 2: show_usage() sys.exit(0) modem = serial.Serial(modem_device, timeout=0.5) modem.readlines() if sys.argv[1] == "start": start_modem(modem) elif sys.argv[1] == "stop": stop_modem(modem) elif sys.argv[1] == "connect": start_modem(modem) connect(modem) elif sys.argv[1] == "disconnect": disconnect(modem) stop_modem(modem) elif sys.argv[1] == "state": print_state(modem) elif sys.argv[1] == "cellinfo": # start_modem(modem) cell_info(modem) else: show_usage() modem.close()