104 lines
3.4 KiB
Python
Executable File
104 lines
3.4 KiB
Python
Executable File
import sys, os, select, re, time
|
|
|
|
def quit(r):
|
|
sys.stdout.flush()
|
|
os._exit(r)
|
|
|
|
class ModemResponse:
|
|
def __init__(self, retcode, retstring):
|
|
self.ret = retcode
|
|
self.data = retstring
|
|
|
|
class Modem:
|
|
def open(self):
|
|
self.i = os.open(self.devname, os.O_RDONLY)
|
|
self.o = os.open(self.devname, os.O_WRONLY)
|
|
#clear output of modem, if any is pending (not sure of this)
|
|
while True:
|
|
(ri, ro, re) = select.select([self.i], [], [self.i], 0)
|
|
if len(ri) == 0:
|
|
break
|
|
l = os.read(self.i, 65536)
|
|
print "WARNING: modem had unread data: '" + \
|
|
l.replace('\r', '\\r') + "'"
|
|
|
|
def __init__(self, devname):
|
|
self.devname = devname
|
|
self.i = -1
|
|
self.o = -1
|
|
self.open()
|
|
|
|
def send(self, s):
|
|
print "DEBUG: SEND TO MODEM: '" + s + "'"
|
|
os.write(self.o, s+"\r")
|
|
|
|
def recv(self):
|
|
return os.read(self.i, 65536)
|
|
|
|
def wait(self):
|
|
ok = '\r\nOK\r\n'
|
|
error = '\r\nERROR\r\n'
|
|
cme_error = '\r\nCME ERROR:[^\r]*\r\n'
|
|
no_carrier = '\r\nNO CARRIER\r\n'
|
|
l = ''
|
|
while True:
|
|
l = l + self.recv()
|
|
print "DEBUG: CURRENT MODEM RESPONSE: '" + \
|
|
l.replace('\r','\\r').replace('\n','\\n') + "'"
|
|
|
|
#AT returned 'things' are "\r\nXXXX\r\n", look for that.
|
|
#Check if last one matches 'ok', 'error' or 'cme_error'.
|
|
#(Hopefully this is enough and no other reply is possible.)
|
|
#This code accepts invalid responses from modem, ie. all
|
|
#that does not fit in the 'findall' is thrashed away, maybe
|
|
#we want to do something in this case?
|
|
|
|
res = re.findall('\r\n[^\r]*\r\n', l)
|
|
if len(res) == 0:
|
|
print "DEBUG: NO MATCH: wait for more input from modem"
|
|
continue
|
|
last_res = res[len(res)-1]
|
|
print "DEBUG: CURRENT LAST LINE: '" + \
|
|
last_res.replace('\r','\\r').replace('\n','\\n')+"'"
|
|
if re.match(ok, last_res) != None:
|
|
return ModemResponse(True, l)
|
|
if ( re.match(error, last_res) != None or
|
|
re.match(cme_error, last_res) != None or
|
|
re.match(no_carrier, last_res) != None):
|
|
return ModemResponse(False, l)
|
|
#TODO purge?
|
|
#re.purge()
|
|
|
|
def modem_reset_cycle(self):
|
|
#close all
|
|
os.close(self.i)
|
|
os.close(self.o)
|
|
self.i = -1
|
|
self.o = -1
|
|
|
|
print "DEBUG: RESET CYCLE: wait for modem to go away"
|
|
#wait for file descriptor to go away
|
|
while True:
|
|
try:
|
|
test = os.open(self.devname, os.O_RDONLY)
|
|
os.close(test)
|
|
time.sleep(0.1)
|
|
except BaseException, e:
|
|
break
|
|
print "DEBUG: RESET CYCLE: modem has gone away"
|
|
|
|
print "DEBUG: RESET CYCLE: wait for modem to come back"
|
|
#wait for file descriptor to be back, try to open it over and over
|
|
#TODO: use inotify here? (it's not in basic python as it seems)
|
|
while True:
|
|
try:
|
|
test = os.open(self.devname, os.O_RDONLY)
|
|
os.close(test)
|
|
break
|
|
except BaseException, e:
|
|
time.sleep(0.1)
|
|
print "DEBUG: RESET CYCLE: modem is back"
|
|
|
|
#back to business
|
|
self.open()
|