Sat, 03 Dec 2011 16:42:53 +0100
implemented race prepare phase, countdown and jumpstart detection
""" FreeSlot project Blackbox communication library """ import serial, sys, string, time # how often should a command retried when busy? RETRIES = 10 # define loglevels DEBUG = 20 def log(level, msg): """ Logging output function """ print msg class SerialCommunicator(): def __init__(self, device, speed): self.device = device self.speed = speed self.com = None self.connected = False def connect(self): if self.connected: return True try: self.com = serial.Serial(self.device, baudrate=self.speed, xonxoff=0, timeout=1) except serial.SerialException, err: print err sys.exit(1) self.connected = True return True def disconnect(self): self.com = None return True def write(self, msg, getanswer=False): self.com.write(msg + "\n") if getanswer: return self.readline() return None def readline(self): answer = self.com.readline() return string.strip(answer, "\n") def query(self, msg): retry = 0 response = self.write(msg, True) while (retry < RETRIES) and (response == "BUSY"): time.sleep(0.1) response = self.write(msg, True) retry += 1 log( DEBUG, "%i> %s\n< %s" % (retry, msg, response) ) return response class Blackbox(): def __init__(self): self.com = None self.info = None def connect(self, device="/dev/ttyUSB0", speed=57600): if self.com == None: self.com = SerialCommunicator(device, speed) if self.com.connected: self.com.disconnect() self.com.connect() self.info = self.readinfo() def disconnect(self): self.com.disconnect() def readinfo(self): """ Read complete Information from connected box This does not include race+car status! """ return None def progcar(self, carid, command, value): """ Send program packets to specified car id valid command: speed, brake, fuel valid value: 4 bit integer (0..15) valid carid: 0..5 """ if (carid < 0) or (carid > 5): return "ERR - invalid carid" cmd = -1 if command == "speed": cmd = 0 if command == "brake": cmd = 1 if command == "fuel": cmd = 2 if (cmd == -1): return "ERR - invalid command" if (value<0) or (value>15): return "ERR - invalid value" # transform value 10..15 to A..F if (value>9): value = chr(ord("A") + (value-10)) command = "P%i%s%i" % (cmd, value, carid) response = self.com.query( command ) return response def blinkcar(self, carid, blink): """ Set car blinking state """ if (carid < 0) or (carid > 5): return "ERR - invalid carid" if blink: return self.com.query( "P48%i" % carid ) else: return self.com.query( "P40%i" % carid ) def speedlimit(self, carid, value): """ Set the maximum controller speed for a car Attention: this is software limited, this does not affect car acceleration! """ if (carid < 0) or (carid > 5): return "ERR - invalid carid" if (value<0) or (value>15): return "ERR - invalid value" # transform value 10..15 to A..F if (value>9): value = chr(ord("A") + (value-10)) return self.com.query( "L%i%s" % (carid, value) ) def setmode(self, mode): """ Switch the Blackbox mode Valid modes are: idle, prepare, race note: box will permanently send status info in race mode, so no polling is required """ return True def getmode(self): self.readinfo() return self.info["mode"]