#!/usr/bin/python import sys sys.path.append('./pyserial-2.0/build/lib') from sys import stdin, stdout, stderr, argv from time import sleep import time import getopt import serial import re class MaxStreamTalk: def __init__(self, port=0, baud=9600): ser = serial.Serial() ser.port = port ser.baud = baud ser.rtscts = False ser.xonxoff = False ser.timeout = .1 ser.open() self.ser = ser self.atresponse = .2 # time required to get in/out of AT mode self.esc = {'cmd': '+'} self.escc = '\\' def fileno(self): return self.ser.fd def ser_readline(self): '''Be careful: this routine does not time out''' ser = self.ser str = '' c = ser.read(1) while c != '\r': if c: str += c c = ser.read(1) #print 'read', str return str def sendCommand(self, cmd): '''Assume that we are already in AT command mode.''' ser = self.ser cmd2 = cmd.rstrip() ser.write(cmd2 + '\r') ret = self.ser_readline().rstrip() if ret == cmd2 or ret == self.esc['cmd'] * 3 + cmd2: # we must be in ATE1 mode ret = self.ser_readline().rstrip() ret = ret.split('\r')[-1] #print (cmd2, ret) return ret def sendCommands(self, cmds): assert(self.commandModeOn().endswith('OK')) responses = [self.sendCommand(c) for c in cmds if c.lower() != 'atcn'] atcnret = self.sendCommand('ATCN') #print 'atcnret', atcnret assert(atcnret.startswith('OK')) return responses def commandModeOn(self): '''This assumes we are not in command mode...?''' # sleepiness is a smudge factor to account for ATAT, ATBT, # and somewhat to account for delays in the serial buffer # processing (if you happen to be using a crappy serial # wrapper or something like that): sleepiness = self.atresponse ser = self.ser ret = '' for i in range(5): #print 'sending +++' t = 2**i * sleepiness # adaptive guard time sleep(.11) ser.write(self.esc['cmd'] * 3) sleep(t) ret = '' while ser.inWaiting(): ret += ser.readline(eol='\r').rstrip() if ret.endswith('OK'): break #print 'break' return ret def ensureCommandModeOff(self): '''This is intended to be run at initialization only.''' ser = self.ser self.commandModeOn() assert(self.sendCommand('ATCN') == 'OK') def write(self, str): str2 = str.replace(self.escc, self.escc * 2) for ch in self.esc.itervalues(): str2 = str2.replace(ch, self.escc + ch) self.ser.write(str2) def read(self, size=1): str = '' while len(str) < size: str2 = self.ser.read(size - len(str)) if not str2: break # str2 must not end with an odd number of self.escc: while str2[-1] == self.escc: ch = self.ser.read(1) str2 += ch assert(ch) # eliminate any characters that are not escaped but should be: for ch in self.esc.itervalues(): # example: # re.subn(r'([^%s])\%s+' % ('F', '+'), r'\1', 'foo+++F+ba+r') if ch in ['+']: str2 = re.sub(r'([^\%s])\%s+' % (self.escc, ch), r'\1', str2) else: str2 = re.sub(r'([^\%s])%s+' % (self.escc, ch), r'\1', str2) # replace escaped characters with their real value: # example: # 'FFrFenFcFh'.replace('FF', 'F').replace('Fe', 'e') str2 = str2.replace(self.escc * 2, self.escc) for ch in self.esc.itervalues(): str2 = str2.replace(self.escc + ch, ch) str += str2 return str def readline(self, size=1): # This is kinda nasty, assuming we can't put characters # back where they came from. str = '' while len(str) < size and (not str or str[-1] not in ['\n', '\r']): str += self.read(1) if not str: break return str if __name__ == '__main__': max = MaxStreamTalk(0, 9600) print 'Getting out of command mode...' max.ensureCommandModeOff() print '...okay, out of command mode.' print max.sendCommands(['ATAT0', 'ATBT0', 'ATAT', 'ATBT']) max.atresponse = .11 print max.sendCommands(['ATRS', 'ATER', 'ATGD']) print max.sendCommands(['ATDT1234', 'ATMK0fff', 'ATDT', 'ATMK', 'ATHP1']) version, = max.sendCommands(['ATVR']) print 'version', version def profile(max, command, mult): # Profile rapidness: for x in mult: t0 = time.time() print '%dx:' % x for i in range(4): max.sendCommands([command]*x) t = time.time() print t-t0 t0 = t if len(argv) > 1: str = '\\Hello \\+++ \\world' if argv[1] == 'tx': print 'Sending', str response = '' while response.strip() != 'ACK': print >>max, str sleep(1) response = max.readline(20) print response while 1: response = 'ACK' while response.strip() == 'ACK': print >>max, str sleep(1) response = max.readline(20) RS, ER, GD = max.sendCommands(['ATRS', 'ATER', 'ATGD']) print response.strip(), 'RS=%s, ER=%s, GD=%s' % (RS, ER, GD) print 'break' if argv[1] == 'rx': print 'Waiting for some text' message = '' while 1: while message.strip() != str: sleep(.5) message = max.readline(20) if message: RS, ER, GD = max.sendCommands(['ATRS', 'ATER', 'ATGD']) print message.strip(), \ 'RS=%s, ER=%s, GD=%s' % (RS, ER, GD) message = '' print >>max, 'ACK' else: profile(max, 'ATRS', [1,1,1,1,1,8]) max.write('foo') max.read(10)