added player profiles

Sun, 02 Dec 2012 19:19:23 +0100

author
Malte Bayer <mbayer@neo-soft.org>
date
Sun, 02 Dec 2012 19:19:23 +0100
changeset 115
bb150048d329
parent 114
313aad7435a8
child 116
c2fc650cc48f

added player profiles

slotUI/SlotCli.py file | annotate | diff | comparison | revisions
slotUI/SlotUi.py file | annotate | diff | comparison | revisions
slotUI/profiles/default file | annotate | diff | comparison | revisions
slotUI/slotCli.py file | annotate | diff | comparison | revisions
--- a/slotUI/SlotCli.py	Sun Dec 02 18:03:06 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,651 +0,0 @@
-#!/usr/bin/env python
-"""
-Freeslot project
-Command line interface
-"""
-
-from freeslot import Blackbox, LOGLEVEL
-from optparse import OptionParser
-from operator import itemgetter
-from subprocess import Popen, PIPE
-import sys, os
-from copy import copy
-import curses
-from time import sleep
-
-import SimpleXMLRPCServer
-import xmlrpclib
-import threading
-
-
-VERSION = "1.7"
-MAXSLOTS = 6
-TERM = {
-    "caption": "\033[1;37m\033[1;44m",
-    "text": "\033[1;30m",
-    }
-
-# disable debug log output
-LOGLEVEL = 10
-
-SOUNDPREFIX = "quake-"
-EVENTPREFIX = "event/"
-SOUNDS = {
-        "countdown_start": os.path.abspath(SOUNDPREFIX + "sound/countdown.mp3"),
-        "race_start":      os.path.abspath(SOUNDPREFIX + "sound/racestart.mp3"),
-        "race_prepare":    os.path.abspath(SOUNDPREFIX + "sound/prepare.mp3"),
-        "lap_record":      os.path.abspath(SOUNDPREFIX + "sound/laprecord.mp3"),
-        "fuel_warning1":   os.path.abspath(SOUNDPREFIX + "sound/fuel1.mp3"),
-        "fuel_warning2":   os.path.abspath(SOUNDPREFIX + "sound/fuel2.mp3"),
-        "fuel_full":       os.path.abspath(SOUNDPREFIX + "sound/fuel_full.mp3"),
-        "pitlane_enter":   os.path.abspath(SOUNDPREFIX + "sound/pitlane_enter.mp3"),
-        "pitlane_exit":    os.path.abspath(SOUNDPREFIX + "sound/pitlane_exit.mp3"),
-        "data_error":      os.path.abspath(SOUNDPREFIX + "sound/data_error.mp3"),
-        "panic":           os.path.abspath(SOUNDPREFIX + "sound/panic.mp3"),
-        "panic_shortcut":  os.path.abspath(SOUNDPREFIX + "sound/panic_shortcut.mp3"),
-        "resume":          os.path.abspath(SOUNDPREFIX + "sound/resume.mp3"),
-        "win":             os.path.abspath(SOUNDPREFIX + "sound/win.mp3"),
-
-    }
-
-def trigger_sound(what):
-    if what in SOUNDS:
-        Popen(["/usr/bin/mpg123", "-q", SOUNDS[what]])
-        #os.spawnlp(os.P_NOWAIT, "/usr/bin/mpg123", "mpg123", SOUNDS[what])
-        #Popen(["/usr/bin/mpg123", SOUNDS[what]]).pid
-
-def trigger_event(what, slot = 0):
-    trigger_sound(what)
-    Popen(["/bin/sh", os.path.abspath(EVENTPREFIX + what), str(slot)])
-
-class SlotServer(threading.Thread):
-    def __init__(self, blackbox):
-        threading.Thread.__init__(self)
-        self.server = SimpleXMLRPCServer.SimpleXMLRPCServer(("localhost", 8000))
-        self.server.register_instance(blackbox)
-        #self.server.register_function(lambda astr: '_' + astr, '_string')
-        self.daemon = True
-
-    def run(self):
-        self.server.serve_forever()
-
-class SlotClient():
-    def __init__(self, url):
-        self.box = xmlrpclib.Server(url)
-
-class SlotCli():
-    def __init__(self, test = None, dev=""):
-        self.box = Blackbox()
-        if (not test):
-            self.box.connect(dev)
-            self.rpcserver = SlotServer(self.box)
-            self.rpcserver.start()
-        self.slot_dummy = {
-            "name": "Unnamed",
-            "laps": 0,
-            "laps_last": 0,
-            "last": 0.00,
-            "best": 0.00,
-            "fuel": 0,
-            "fuel_last": 0,
-            "position": 0,
-            "drive": 0,
-            "status": "Idle",
-            "clk": 0,
-            "car": 0,
-            "limit": 15,
-            }
-
-        self.slot = [
-            copy(self.slot_dummy), copy(self.slot_dummy),
-            copy(self.slot_dummy), copy(self.slot_dummy),
-            copy(self.slot_dummy), copy(self.slot_dummy),
-            ]
-        self.reset_slots()
-        self.sysclk = 0.00
-        self.sysclk_last = 0.00
-        self.bestlap = 9999999.00
-        self.test = test
-        self.laplimit = 999;
-        self.timelimit = 0;
-
-    def reset_slots(self):
-        idx = 0
-        for slt in self.slot:
-            slt["laps"] = 0
-            slt["laps_last"] = 0
-            slt["last"] = 0.00
-            slt["best"] = 0.00
-            slt["fuel"] = 100
-            slt["fuel_last"] = 0
-            slt["position"] = idx
-            slt["car"] = idx # used for sort order calculation
-            slt["status"] = self.slot_dummy["status"]
-            slt["clk"] = 0
-            slt["limit"] = 15
-            idx += 1
-        self.bestlap = 99999.00
-        self.raceactive = False
-
-    def update_positions(self):
-        order1 = sorted(self.slot, key=itemgetter(
-            "clk"))
-        order2 = sorted(self.slot, key=itemgetter(
-            "laps"), reverse=True)
-        idx = 1
-        for tst in order2:
-            self.slot[tst["car"]]["position"] = idx
-            idx += 1
-
-    def render_slots(self):
-        self.update_positions()
-        self.scr.addstr(3,0,
-            #"Pos | #/Name            | Laps | Best     | Last     | Fuel | Status    ",
-            "Pos | #/Name                                                            ",
-            curses.color_pair(2))
-        self.scr.addstr(4,4,
-            "  Laps | Best     | Last     | Fuel | Status                        ",
-            curses.color_pair(2))
-        for idx in range(MAXSLOTS):
-            """
-            self.scr.addstr((3 + (self.slot[idx]["position"] * 2)), 0,
-                "%3i | %i %15s | %4i | %7.2fs | %7.2fs | %3i%% | %10s" % (
-                self.slot[idx]["position"],
-                self.slot[idx]["car"] + 1, self.slot[idx]["name"],
-                self.slot[idx]["laps"],
-                self.slot[idx]["best"],
-                self.slot[idx]["last"],
-                self.slot[idx]["fuel"],
-                self.slot[idx]["status"],
-                ),
-                curses.color_pair(11 + idx) )
-            """
-            if idx > 3:
-                namesuffix = " (%i)" % self.slot[idx]["drive"]
-            else:
-                namesuffix = ""
-
-            self.scr.addstr((3 + (self.slot[idx]["position"] * 2)), 0,
-                "%3i | %i %15s %48s" % (
-                self.slot[idx]["position"],
-                self.slot[idx]["car"] + 1, (self.slot[idx]["name"] + namesuffix),
-                "",
-                ),
-                curses.color_pair(11 + idx) )
-            self.scr.addstr((4 + (self.slot[idx]["position"] * 2)), 4,
-                "  %4i | %7.2fs | %7.2fs | %3i%% | %10s | %2i% 15s" % (
-                self.slot[idx]["laps"],
-                self.slot[idx]["best"],
-                self.slot[idx]["last"],
-                self.slot[idx]["fuel"],
-                self.slot[idx]["status"],
-                self.slot[idx]["limit"],
-                ""
-                ),
-                curses.color_pair(11 + idx) )
-
-    def cleartop(self):
-        self.scr.addstr(0,0, "%60s" % "Race Limits: %i Laps / %i Minutes" % (self.laplimit, self.timelimit))
-        self.scr.addstr(1,0, "%80s" % " ")
-
-    def readName(self, slot):
-        self.scr.nodelay(0) # enable delay on readkey
-        curses.echo()
-        self.scr.addstr(0,0, "Enter Name for Controller %i [%s]:" % (
-            slot + 1,
-            self.slot[slot]["name"]),
-            curses.color_pair(1))
-        self.scr.refresh()
-        name = self.scr.getstr(1,0, 15)
-        if name != "":
-            self.slot[slot]["name"] = name
-        self.cleartop()
-        self.scr.refresh()
-        curses.noecho()
-        self.scr.nodelay(1) # disable delay on readkey
-
-    def readLimit(self, slot):
-        limit = self.readInt("SPEEDLIMIT for %s (%i)" % (
-            self.slot[slot]["name"],
-            slot + 1),
-            self.slot[slot]["limit"], 15)
-        if limit:
-            self.slot[slot]["limit"] = limit
-            self.cleartop()
-            self.box.speedlimit(slot, limit)
-
-
-    def readInt(self, msg, default, maximum = 999999):
-        self.scr.nodelay(0) # enable delay on readkey
-        curses.echo()
-        self.scr.addstr(0,0, "%s [%i]:" % (
-            msg,
-            default),
-            curses.color_pair(1))
-        self.scr.refresh()
-        inp = self.scr.getstr(1,0, 4)
-        if inp != "":
-            try:
-                inp = int(inp)
-                if inp > maximum: inp = maximum
-            except Exception:
-                inp = None
-        else:
-            inp = None
-        self.cleartop()
-        self.scr.refresh()
-        curses.noecho()
-        self.scr.nodelay(1) # disable delay on readkey
-        return inp
-
-
-    def monitor_init(self, live = 1):
-        """
-        Send initializing commands for live monitoring
-        """
-        self.box.query("F1\n") # set fuel logic enabled
-        self.box.query("*%i\n" % live) # set live fuel info
-
-    def monitor_learn(self, slot):
-        # clear garbage in UART rx buffer
-        self.box.query("*0\n") # set live fuel info
-        self.box.query("*0\n") # set live fuel info
-        while self.box.readline() != "": pass
-
-        trk = False
-        spd = 0
-        trk_old = False
-        spd_old = 0
-        clock = -1
-
-        self.monitor_init(slot + 2)
-        while 1:
-            #key = self.scr.getch()
-            #if key == ord('c'): break
-
-            # is there something in the rx buffer?
-            rx = self.box.readline()
-            if (rx != ""):
-                try:
-                    data = rx.split(":")
-                    if rx[:3] == "LN:":
-                        if clock >= 0:
-                            clock += 1
-                        spd = int(data[1], 16)
-                        trk = (data[2] != 'X')
-                        if (spd != spd_old) or (trk != trk_old):
-                            if clock < 0:
-                                clock = 0
-                            print "%i,%i,%s" % (clock, spd, trk)
-                        trk_old = trk
-                        spd_old = spd * 1
-                    if rx[:2] == "L:":
-                        # update lap time info
-                        l = int(data[2], 16)
-                        s = int(data[3]) - 1
-                        t = int(data[4], 16) / 2000.00
-                        if (slot == s):
-                            print "# lap %i complete: %3.2f seconds" % (l, t)
-                            clock = 0
-                            print "%i,%i,%s" % (clock, spd, trk)
-                except:
-                    print "RX ERROR: " % rx
-
-    def monitor_playback(self, slot, filename):
-        # clear garbage in UART rx buffer
-        self.box.query("*0\n") # set live fuel info
-        self.box.query("*0\n") # set live fuel info
-        sleep(1)
-        cli.box.speedminimum(slot, 0 )
-        while self.box.readline() != "": pass
-
-        clock = -5
-        trkfile = open(filename, "r").readlines()
-        print "Loading %s..." % filename
-
-        while 1:
-            try:
-                for l in trkfile:
-                    l = l.strip()
-                    if (l != "") and (l[:1] != "#"):
-                        print "Line: %s" % repr(l)
-                        data = l.split(",")
-                        speed = int(data[1])
-                        while (clock < int(data[0]) and (int(data[0]) > 0)):
-                            clock += 1
-                            sleep(0.07)
-                        print "CLK %i/%i -> set: %i" % (clock, int(data[0]), speed)
-                        cli.box.speedminimum(slot, speed )
-                # now wait for lap sync :)
-                while self.box.readline() != "": pass
-                rx = ""
-                while rx[:2] != "L:":
-                    rx = self.box.readline()
-                data = rx.split(":")
-                l = int(data[2], 16)
-                s = int(data[3]) - 1
-                t = int(data[4], 16) / 2000.00
-                print "# lap %i complete: %3.2f seconds" % (l, t)
-                clock = -3
-            except Exception, e:
-                print repr(e)
-                sys.exit(1)
-            except KeyboardInterrupt:
-                print "resetting"
-                cli.box.speedminimum(slot, 0 )
-                cli.box.speedminimum(slot, 0 )
-                sys.exit(0)
-                
-
-
-    def monitor(self):
-        """
-        Live Monitor on the console
-        Keyboard loop to control it???
-        """
-        # clear garbage in UART rx buffer
-        while self.box.readline() != "": pass
-
-        self.monitor_init()
-        self.scr = curses.initscr()
-        curses.start_color()
-        curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_BLACK) # standard text
-        curses.init_pair(2, curses.COLOR_WHITE, curses.COLOR_BLUE) # label
-        curses.init_pair(11, curses.COLOR_BLACK, curses.COLOR_YELLOW) # player 1 slot
-        curses.init_pair(12, curses.COLOR_BLACK, curses.COLOR_GREEN) # player 2 slot
-        curses.init_pair(13, curses.COLOR_BLACK, curses.COLOR_RED) # player 3 slot
-        curses.init_pair(14, curses.COLOR_BLACK, curses.COLOR_MAGENTA) # player 4 slot
-        curses.init_pair(15, curses.COLOR_WHITE, curses.COLOR_BLACK) # player 5 slot
-        curses.init_pair(16, curses.COLOR_WHITE, curses.COLOR_BLACK) # player 6 slot
-        curses.noecho() # disable key echo
-        curses.cbreak() # do not buffer keypresses
-        self.scr.keypad(1) # enable special keys
-        self.scr.nodelay(1) # disable delay on readkey
-
-        self.cleartop()
-        self.render_slots()
-        self.scr.refresh()
-
-
-        while 1:
-            key = self.scr.getch()
-            if key == ord('c'): break
-            elif key == ord(' '): self.box.query("+") # panic / resume
-            elif key == 10: self.box.query("#") # remote start button press
-            elif key == ord('1'): self.readName(0)
-            elif key == ord('2'): self.readName(1)
-            elif key == ord('3'): self.readName(2)
-            elif key == ord('4'): self.readName(3)
-            elif key == ord('5'): self.readName(4)
-            elif key == ord('6'): self.readName(5)
-            elif key == ord('q'): self.readLimit(0)
-            elif key == ord('w'): self.readLimit(1)
-            elif key == ord('e'): self.readLimit(2)
-            elif key == ord('r'): self.readLimit(3)
-            elif key == ord('t'): self.readLimit(4)
-            elif key == ord('z'): self.readLimit(5)
-            elif key == ord('a'):
-                if self.slot[4]["drive"] > 0: self.slot[4]["drive"] -= 1
-                cli.box.speedminimum(4, self.slot[4]["drive"])
-            elif key == ord('s'):
-                if self.slot[4]["drive"] < 16: self.slot[4]["drive"] += 1
-                cli.box.speedminimum(4, self.slot[4]["drive"])
-            elif key == ord('y'):
-                if self.slot[5]["drive"] > 0: self.slot[5]["drive"] -= 1
-                cli.box.speedminimum(5, self.slot[5]["drive"])
-            elif key == ord('x'):
-                if self.slot[5]["drive"] < 16: self.slot[5]["drive"] += 1
-                cli.box.speedminimum(5, self.slot[5]["drive"])
-            elif key == ord('t'):
-                tmp = self.readInt("Set new Race TIME limit", self.timelimit)
-                if tmp: self.timelimit = tmp
-            elif key == ord('l'):
-                tmp = self.readInt("Set new Race LAP limit", self.laplimit)
-                if tmp: self.laplimit = tmp
-
-
-            # is there something in the rx buffer?
-            rx = self.box.readline()
-            if (rx != "") or self.test:
-                self.scr.addstr(17,0,
-                    "Last RX: %19s" % rx, curses.color_pair(2))
-                self.scr.redrawwin()
-                self.scr.refresh()
-                # we have received something
-                try:
-                    data = rx.split(":")
-                    if rx[:2] == "L:":
-                        # update lap time info
-                        l = int(data[2], 16)
-                        slot = int(data[3]) - 1
-                        t = int(data[4], 16) / 2000.00
-                        self.sysclk = int(data[5], 16) / 2000.00
-                        self.slot[slot]["laps_last"] = self.slot[slot]["laps"]
-                        self.slot[slot]["laps"] = l
-                        self.slot[slot]["last"] = t
-                        self.slot[slot]["clk"] = self.sysclk
-                        if (self.slot[slot]["best"] > t) or (self.slot[slot]["best"] == 0):
-                            self.slot[slot]["best"] = t
-                        if self.bestlap > t:
-                            trigger_event("lap_record", slot + 1)
-                            self.bestlap = t
-
-                        self.slot[slot]["status"] = "IN-RACE"
-                        if (self.slot[slot]["laps_last"] != l) and (l == self.laplimit):
-                            # we have lap limit reached!
-                            trigger_event("win", slot + 1)
-                            self.raceactive = False
-                            self.slot[slot]["status"] = "WINNER!"
-                            self.box.query("+") # stop race
-
-                        self.render_slots()
-
-                    if rx[:2] == "F:":
-                        # update fuel level
-                        slot = int(data[1])
-                        f = int(data[2], 16)
-                        f = f / 100 # fuel in percent
-                        self.sysclk = int(data[3], 16) / 2000.00
-                        self.slot[slot]["fuel_last"] = self.slot[slot]["fuel"]
-                        self.slot[slot]["fuel"] = f
-                        if self.slot[slot]["fuel_last"] != f:
-                            if (self.slot[slot]["fuel_last"] == 16) and (f == 15):
-                                # 15 percent fuel, set speed limit for car to 8
-                                # warning sound
-                                trigger_event("fuel_warning1", slot + 1)
-                                cli.box.speedlimit(slot, 8)
-                            if (self.slot[slot]["fuel_last"] == 6) and (f == 5):
-                                # 5 percent, set speed limit for car to 6
-                                # warning sound
-                                trigger_event("fuel_warning2", slot + 1)
-                                cli.box.speedlimit(slot, 6)
-                            if (self.slot[slot]["fuel_last"] == 1) and (f == 0):
-                                # fuel empty
-                                # set speedlimit to 4
-                                cli.box.speedlimit(slot, 4)
-                            if (self.slot[slot]["fuel_last"] < f) and (f >= 11) and (f < 20):
-                                cli.box.speedlimit(slot, 15)
-                            if (self.slot[slot]["fuel_last"] < f) and (f == 100):
-                                trigger_event("fuel_full", slot + 1)
-                        self.render_slots()
-
-                    if rx[:1] == "~":
-                        # jumpstart occured
-                        slot = int(rx[1:2])
-                        t = int(data[1], 16) / 2000.00
-                        self.slot[slot]["jumpstart"] = t
-                        self.slot[slot]["status"] = "Jumpstart!"
-
-                    if rx[:3] == "RW:":
-                        # ResponseWire packet, do nothing at the moment, just decode
-                        slot = int(data[1])
-                        devtype = int(data[2])
-                        sender = int(data[3], 16)
-                        status = int(data[4], 16)
-                        self.sysclk = int(data[5], 16)
-                        if (devtype == 4):
-                            # pitlane sent something
-                            if (status == 5):
-                                self.slot[slot]["status"] = "PITLANE"
-                                trigger_event("pitlane_enter", slot + 1)
-                            if (status == 7):
-                                self.slot[slot]["status"] = "IN-RACE"
-                                trigger_event("pitlane_exit", slot + 1)
-
-                        self.render_slots()
-
-                    if rx == "!RACE PREPARE":
-                        # reset current race status
-                        # and display PREPARE PHASE
-                        self.reset_slots()
-                        for slot in range(MAXSLOTS):
-                            self.slot[slot]["status"] = "Prepare"
-                        trigger_event("race_prepare")
-
-                    if rx == "!RACE START":
-                        for slot in range(MAXSLOTS):
-                            if self.slot[slot]["status"] == "~~~~~~~~~~":
-                                self.slot[slot]["status"] = "Idle"
-                        trigger_event("race_start")
-                        self.raceactive = True
-
-                    if rx == "!COUNTDOWN":
-                        # countdown initiated
-                        for slot in range(MAXSLOTS):
-                            self.slot[slot]["status"] = "~~~~~~~~~~"
-                        trigger_event("countdown_start")
-
-                    if rx == "!PANIC":
-                        # panic mode
-                        trigger_event("panic")
-
-                    if rx == "!SHORTCUT":
-                        # panic mode
-                        trigger_event("panic_shortcut")
-
-                    if rx == "!RESUME":
-                        # panic mode
-                        trigger_event("resume")
-
-
-                    if ((self.timelimit > 0) and (self.raceactive) and 
-                        (self.sysclk_last != self.sysclk) and 
-                        ((self.sysclk / 60) >= self.timelimit)):
-                        self.sysclk_last = self.sysclk
-                        self.raceactive = False
-                        # we have time limit reached!
-                        self.box.query("+") # stop race
-                        trigger_event("win")
-                        # get the one with position 1
-                        for slot in self.slots:
-                            if slot["position"] == 1:
-                                slot["status"] = "WINNER!"
-                	self.render_slots()
-                    self.sysclk_last = self.sysclk
-    
-
-
-                    self.scr.addstr(17,31,
-                        "Race Timer: %7.3f min" % (self.sysclk / 60),
-                        curses.color_pair(2))
-
-                    self.scr.refresh()
-
-                except Exception:
-                    trigger_event("data_error")
-                    pass
-
-        # terminate
-        curses.nocbreak()
-        self.scr.keypad(0)
-        curses.echo()
-        curses.endwin()
-        return None
-
-    def cyclemode(self):
-        pass
-
-if __name__ == "__main__":
-    parser = OptionParser(version="%prog " + VERSION)
-    parser.add_option("--live", dest="live", action="store_true", default=False,
-        help="Run Live monitor on console", metavar="[0-5]")
-    parser.add_option("--learn", dest="learn", action="store_true", default=False,
-        help="Run Learning mode for [slot]", metavar="[0-5]")
-    parser.add_option("--teach", dest="playback", 
-        help="Playback teach file", metavar="[filename]")
-
-    parser.add_option("--slot", dest="carid",
-        help="Required for programming a car directly", metavar="[1-6]")
-    parser.add_option("--fuel", dest="fuel",
-        help="Set maximum CAR fuel level", metavar="[0-15]")
-    parser.add_option("--brake", dest="brake",
-        help="Set CAR brake strength", metavar="[0-15]")
-    parser.add_option("--accel", dest="accel",
-        help="Set CAR acceleration ", metavar="[6-15]")
-    parser.add_option("--blink", dest="blink",
-        help="Set car lights blinking state", metavar="[on|off]")
-    parser.add_option("--limit", dest="limit",
-        help="Controlled SPEED LIMIT (15 = no limit)", metavar="[0-15]")
-    parser.add_option("--drive", dest="drive",
-        help="Controlled SPEED MINIMUM (0 = disabled)", metavar="[0-15]")
-    parser.add_option("--test", dest="test", action="store_true", default=False,
-        help="", metavar="")
-    parser.add_option("--dev", dest="dev", default="/dev/ttyUSB0",
-        help="Communication port", metavar="[/dev/ttyUSB0]")
-
-    (options, args) = parser.parse_args()
-    #if not options.dev:
-    #    options.dev = "/dev/ttyUSB0"
-
-    if options.live or options.learn or options.playback:
-        cli = SlotCli(options.test, options.dev)
-    else:
-        cli = SlotClient('http://localhost:8000')
-    # should a CLI function be started?
-
-    if options.live:
-        # start the live monitor
-        cli.monitor()
-        sys.exit(0)
-
-    # check commandline if we have to program something
-    if not options.carid:
-        print "Option --slot is required for all car programming commands!\nUse --help to get a list of available commands"
-        sys.exit(1)
-    else:
-        options.carid = int(options.carid) - 1
-        if (options.carid < 0) or (options.carid > 6):
-            print "Error: Invalid slot selected"
-            sys.exit(1)
-
-    if options.learn:
-        # start the learn monitor
-        cli.monitor_learn(options.carid)
-        sys.exit(0)
-
-    if options.playback:
-        # start the playback monitor
-        cli.monitor_playback(options.carid, options.playback)
-        sys.exit(0)
-
-    if options.fuel:
-        print "setFuel: " + cli.box.progcar(int(options.carid), "fuel", int(options.fuel))
-
-    if options.accel:
-        print "setAccel: " + cli.box.progcar(int(options.carid), "accel", int(options.accel))
-
-    if options.brake:
-        print "setBrake: " + cli.box.progcar(int(options.carid), "brake", int(options.brake))
-
-    if options.blink:
-        state = False
-        if options.blink == "on":
-            state = True
-        print "setBlink: " + cli.box.blinkcar(int(options.carid), state)
-
-    if options.limit:
-        print "Change Speed Limit: " + cli.box.speedlimit(int(options.carid), int(options.limit))
-
-    if options.drive:
-        print "Change minimum Speed drive: " + cli.box.speedminimum(int(options.carid), int(options.drive))
-
--- a/slotUI/SlotUi.py	Sun Dec 02 18:03:06 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +0,0 @@
-#!/usr/bin/env python
-
-import pygtk
-pygtk.require('2.0')
-import gtk
-
-class Window:
-    """
-    Base Window Class
-    """
-    def delete_event(self, widget, event, data=None):
-        return False
-
-    def __init__(self, title="unnamed window"):
-        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
-        self.window.connect("delete_event", self.delete_event)
-        self.window.set_title(title)
-
-class SlotCars(Window):
-    """
-    Car configuration window
-    """
-    def __init__(self):
-        Window.__init__(self, "Car configuration")
-        #self.slot = gtk.ComboBox("Select car")
-        #self.slot.show()
-        #window.add(self.slot)
-
-class SlotUi(Window):
-    """
-    Graphical User Interface
-    using GTK
-    """
-    def delete_event(self, widget, event, data=None):
-        if widget == self.window:
-            self.destroy(widget, data)
-        Window.delete_event(self, widget, event, data)
-        return False
-
-    def destroy(self, widget, data=None):
-        gtk.main_quit()
-
-    def __init__(self):
-        Window.__init__(self, "FreeSlot UI")
-
-        # define toolbar buttons
-        self.buttons = {
-                "config":       gtk.Button("Settings"),
-                "cars":         gtk.Button("Car Config"),
-            }
-        self.buttons["config"].connect("clicked", self.openwindow, "config")
-        self.buttons["cars"].connect("clicked", self.openwindow, "cars")
-        #setup the toolbar box
-        self.toolbar = gtk.HBox(False, 0)
-        self.toolbar.show()
-        for btn in self.buttons:
-            self.toolbar.add(self.buttons[btn])
-            self.buttons[btn].show()
-
-        # create subwindow objects
-        self.cars = SlotCars()
-        self.windows = {
-            "config": None,
-            "cars": self.cars.window,
-            }
-
-        self.window.add(self.toolbar)
-        self.window.show()
-
-    def openwindow(self, widget, name):
-        self.windows[name].show()
-
-    def main(self):
-        gtk.main()
-
-if __name__ == "__main__":
-    print "FreeSlot UI starting..."
-    print "Note: this will be part of paepke development, no function at the moment :)"
-    app = SlotUi()
-    app.main()
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/slotUI/profiles/default	Sun Dec 02 19:19:23 2012 +0100
@@ -0,0 +1,9 @@
+[Settings]
+Name=unnamed
+Fuel=100
+Accel=10
+Limit=10
+Brake=15
+
+[Stats]
+Disabled=1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/slotUI/slotCli.py	Sun Dec 02 19:19:23 2012 +0100
@@ -0,0 +1,696 @@
+#!/usr/bin/env python
+"""
+Freeslot project
+Command line interface
+"""
+
+from freeslot import Blackbox, LOGLEVEL
+from optparse import OptionParser
+from operator import itemgetter
+from subprocess import Popen, PIPE
+import sys, os
+from copy import copy
+import curses
+from time import sleep
+import ConfigParser
+
+import SimpleXMLRPCServer
+import xmlrpclib
+import threading
+
+
+VERSION = "1.8"
+MAXSLOTS = 6
+TERM = {
+    "caption": "\033[1;37m\033[1;44m",
+    "text": "\033[1;30m",
+    }
+
+# disable debug log output
+LOGLEVEL = 10
+
+SOUNDPREFIX = "quake-"
+EVENTPREFIX = "event/"
+SOUNDS = {
+        "countdown_start": os.path.abspath(SOUNDPREFIX + "sound/countdown.mp3"),
+        "race_start":      os.path.abspath(SOUNDPREFIX + "sound/racestart.mp3"),
+        "race_prepare":    os.path.abspath(SOUNDPREFIX + "sound/prepare.mp3"),
+        "lap_record":      os.path.abspath(SOUNDPREFIX + "sound/laprecord.mp3"),
+        "fuel_warning1":   os.path.abspath(SOUNDPREFIX + "sound/fuel1.mp3"),
+        "fuel_warning2":   os.path.abspath(SOUNDPREFIX + "sound/fuel2.mp3"),
+        "fuel_full":       os.path.abspath(SOUNDPREFIX + "sound/fuel_full.mp3"),
+        "pitlane_enter":   os.path.abspath(SOUNDPREFIX + "sound/pitlane_enter.mp3"),
+        "pitlane_exit":    os.path.abspath(SOUNDPREFIX + "sound/pitlane_exit.mp3"),
+        "data_error":      os.path.abspath(SOUNDPREFIX + "sound/data_error.mp3"),
+        "panic":           os.path.abspath(SOUNDPREFIX + "sound/panic.mp3"),
+        "panic_shortcut":  os.path.abspath(SOUNDPREFIX + "sound/panic_shortcut.mp3"),
+        "resume":          os.path.abspath(SOUNDPREFIX + "sound/resume.mp3"),
+        "win":             os.path.abspath(SOUNDPREFIX + "sound/win.mp3"),
+
+    }
+
+def trigger_sound(what):
+    if what in SOUNDS:
+        Popen(["/usr/bin/mpg123", "-q", SOUNDS[what]])
+        #os.spawnlp(os.P_NOWAIT, "/usr/bin/mpg123", "mpg123", SOUNDS[what])
+        #Popen(["/usr/bin/mpg123", SOUNDS[what]]).pid
+
+def trigger_event(what, slot = 0):
+    trigger_sound(what)
+    Popen(["/bin/sh", os.path.abspath(EVENTPREFIX + what), str(slot)])
+
+class SlotServer(threading.Thread):
+    def __init__(self, blackbox):
+        threading.Thread.__init__(self)
+        self.server = SimpleXMLRPCServer.SimpleXMLRPCServer(("localhost", 8000))
+        self.server.register_instance(blackbox)
+        #self.server.register_function(lambda astr: '_' + astr, '_string')
+        self.daemon = True
+
+    def run(self):
+        self.server.serve_forever()
+
+class SlotClient():
+    def __init__(self, url):
+        self.box = xmlrpclib.Server(url)
+
+class SlotCli():
+    def __init__(self, test = None, dev=""):
+        self.box = Blackbox()
+        if (not test):
+            self.box.connect(dev)
+            self.rpcserver = SlotServer(self.box)
+            self.rpcserver.start()
+        self.slot_dummy = {
+            "name": "uninitialized",
+            "laps": 0,
+            "laps_last": 0,
+            "last": 0.00,
+            "best": 0.00,
+            "fuel": 0,
+            "fuel_last": 0,
+            "position": 0,
+            "drive": 0,
+            "status": "Idle",
+            "clk": 0,
+            "car": 0,
+            "limit": 15,
+            "profilename": "default",
+            "profile": ConfigParser.RawConfigParser(),
+            }
+        self.slot_dummy["profile"].read("profiles/" + self.slot_dummy["profilename"])
+        self.slot_dummy["name"] = self.slot_dummy["profile"].get("Settings", "Name")
+        self.slot_dummy["limit"] = self.slot_dummy["profile"].getint("Settings", "Limit")
+
+        self.slot = [
+            copy(self.slot_dummy), copy(self.slot_dummy),
+            copy(self.slot_dummy), copy(self.slot_dummy),
+            copy(self.slot_dummy), copy(self.slot_dummy),
+            ]
+        self.reset_slots()
+        self.sysclk = 0.00
+        self.sysclk_last = 0.00
+        self.bestlap = 9999999.00
+        self.test = test
+        self.laplimit = 999;
+        self.timelimit = 0;
+
+    def reset_slots(self):
+        idx = 0
+        for slt in self.slot:
+            slt["laps"] = 0
+            slt["laps_last"] = 0
+            slt["last"] = 0.00
+            slt["best"] = 0.00
+            slt["fuel"] = 100
+            slt["fuel_last"] = 0
+            slt["position"] = idx
+            slt["car"] = idx # used for sort order calculation
+            slt["status"] = self.slot_dummy["status"]
+            slt["clk"] = 0
+            slt["limit"] = slt["profile"].getint("Settings", "Limit")
+            #slt["limit"] = 15
+            idx += 1
+        self.bestlap = 99999.00
+        self.raceactive = False
+
+    def update_positions(self):
+        order1 = sorted(self.slot, key=itemgetter(
+            "clk"))
+        order2 = sorted(self.slot, key=itemgetter(
+            "laps"), reverse=True)
+        idx = 1
+        for tst in order2:
+            self.slot[tst["car"]]["position"] = idx
+            idx += 1
+
+    def render_slots(self):
+        self.update_positions()
+        self.scr.addstr(3,0,
+            #"Pos | #/Name            | Laps | Best     | Last     | Fuel | Status    ",
+            "Pos | #/Name                                                            ",
+            curses.color_pair(2))
+        self.scr.addstr(4,4,
+            "  Laps | Best     | Last     | Fuel | Status                        ",
+            curses.color_pair(2))
+        for idx in range(MAXSLOTS):
+            """
+            self.scr.addstr((3 + (self.slot[idx]["position"] * 2)), 0,
+                "%3i | %i %15s | %4i | %7.2fs | %7.2fs | %3i%% | %10s" % (
+                self.slot[idx]["position"],
+                self.slot[idx]["car"] + 1, self.slot[idx]["name"],
+                self.slot[idx]["laps"],
+                self.slot[idx]["best"],
+                self.slot[idx]["last"],
+                self.slot[idx]["fuel"],
+                self.slot[idx]["status"],
+                ),
+                curses.color_pair(11 + idx) )
+            """
+            if idx > 3:
+                namesuffix = " (%i)" % self.slot[idx]["drive"]
+            else:
+                namesuffix = ""
+
+            self.scr.addstr((3 + (self.slot[idx]["position"] * 2)), 0,
+                "%3i | %i %15s %48s" % (
+                self.slot[idx]["position"],
+                self.slot[idx]["car"] + 1, (self.slot[idx]["name"] + namesuffix),
+                "",
+                ),
+                curses.color_pair(11 + idx) )
+            self.scr.addstr((4 + (self.slot[idx]["position"] * 2)), 4,
+                "  %4i | %7.2fs | %7.2fs | %3i%% | %10s | %2i% 15s" % (
+                self.slot[idx]["laps"],
+                self.slot[idx]["best"],
+                self.slot[idx]["last"],
+                self.slot[idx]["fuel"],
+                self.slot[idx]["status"],
+                self.slot[idx]["limit"],
+                ""
+                ),
+                curses.color_pair(11 + idx) )
+
+    def cleartop(self):
+        self.scr.addstr(0,0, "%60s" % "Race Limits: %i Laps / %i Minutes" % (self.laplimit, self.timelimit))
+        self.scr.addstr(1,0, "%80s" % " ")
+
+    def flash_car_settings(self, slot):
+        # write current settings to car firmware
+        self.box.setmode(0)
+        self.cleartop()
+        self.scr.addstr(0,0, "Writing settings for %s to car %i..." % (
+            self.slot[slot]["name"],
+            slot + 1),
+            curses.color_pair(1))
+        self.scr.refresh()
+        self.box.progcar(slot, "fuel", 0)
+        sleep(0.5)
+        self.box.progcar(slot, "accel", self.slot[slot]["profile"].getint("Settings", "Accel"))
+        sleep(0.5)
+        self.box.progcar(slot, "brake", self.slot[slot]["profile"].getint("Settings", "Brake"))
+        sleep(0.5)
+        self.box.speedlimit(slot, self.slot[slot]["limit"])
+        sleep(0.5)
+        self.cleartop()
+        self.box.setmode(1)
+
+    def readName(self, slot):
+        self.scr.nodelay(0) # enable delay on readkey
+        curses.echo()
+        self.scr.addstr(0,0, "Enter Name for Controller %i [%s]:" % (
+            slot + 1,
+            self.slot[slot]["name"]),
+            curses.color_pair(1))
+        self.scr.refresh()
+        name = self.scr.getstr(1,0, 15)
+        if name != "":
+            # look if profile with that name found
+            try:
+                with open("profiles/" + name) as f: pass
+                self.slot[slot]["profilename"] = name
+                self.slot[slot]["profile"].read("profiles/" + name)
+                self.slot[slot]["name"] = self.slot[slot]["profile"].get("Settings", "Name")
+                self.slot[slot]["limit"] = self.slot[slot]["profile"].getint("Settings", "Limit")
+                self.flash_car_settings(slot)
+            except IOError, err:
+                self.slot[slot]["profilename"] = "default"
+                self.slot[slot]["profile"].read("profiles/default")
+                self.slot[slot]["limit"] = self.slot[slot]["profile"].getint("Settings", "Limit")
+                self.slot[slot]["name"] = name
+                self.flash_car_settings(slot)
+        self.cleartop()
+        self.scr.refresh()
+        curses.noecho()
+        self.scr.nodelay(1) # disable delay on readkey
+
+    def readLimit(self, slot):
+        limit = self.readInt("SPEEDLIMIT for %s (%i)" % (
+            self.slot[slot]["name"],
+            slot + 1),
+            self.slot[slot]["limit"], 15)
+        if limit:
+            self.slot[slot]["limit"] = limit
+            self.cleartop()
+            self.box.speedlimit(slot, limit)
+
+
+    def readInt(self, msg, default, maximum = 999999):
+        self.scr.nodelay(0) # enable delay on readkey
+        curses.echo()
+        self.scr.addstr(0,0, "%s [%i]:" % (
+            msg,
+            default),
+            curses.color_pair(1))
+        self.scr.refresh()
+        inp = self.scr.getstr(1,0, 4)
+        if inp != "":
+            try:
+                inp = int(inp)
+                if inp > maximum: inp = maximum
+            except Exception:
+                inp = None
+        else:
+            inp = None
+        self.cleartop()
+        self.scr.refresh()
+        curses.noecho()
+        self.scr.nodelay(1) # disable delay on readkey
+        return inp
+
+
+    def monitor_init(self, live = 1):
+        """
+        Send initializing commands for live monitoring
+        """
+        self.box.query("F1\n") # set fuel logic enabled
+        self.box.query("*%i\n" % live) # set live fuel info
+
+    def monitor_learn(self, slot):
+        # clear garbage in UART rx buffer
+        self.box.query("*0\n") # set live fuel info
+        self.box.query("*0\n") # set live fuel info
+        while self.box.readline() != "": pass
+
+        trk = False
+        spd = 0
+        trk_old = False
+        spd_old = 0
+        clock = -1
+
+        self.monitor_init(slot + 2)
+        while 1:
+            #key = self.scr.getch()
+            #if key == ord('c'): break
+
+            # is there something in the rx buffer?
+            rx = self.box.readline()
+            if (rx != ""):
+                try:
+                    data = rx.split(":")
+                    if rx[:3] == "LN:":
+                        if clock >= 0:
+                            clock += 1
+                        spd = int(data[1], 16)
+                        trk = (data[2] != 'X')
+                        if (spd != spd_old) or (trk != trk_old):
+                            if clock < 0:
+                                clock = 0
+                            print "%i,%i,%s" % (clock, spd, trk)
+                        trk_old = trk
+                        spd_old = spd * 1
+                    if rx[:2] == "L:":
+                        # update lap time info
+                        l = int(data[2], 16)
+                        s = int(data[3]) - 1
+                        t = int(data[4], 16) / 2000.00
+                        if (slot == s):
+                            print "# lap %i complete: %3.2f seconds" % (l, t)
+                            clock = 0
+                            print "%i,%i,%s" % (clock, spd, trk)
+                except:
+                    print "RX ERROR: " % rx
+
+    def monitor_playback(self, slot, filename):
+        # clear garbage in UART rx buffer
+        self.box.query("*0\n") # set live fuel info
+        self.box.query("*0\n") # set live fuel info
+        sleep(1)
+        cli.box.speedminimum(slot, 0 )
+        while self.box.readline() != "": pass
+
+        clock = -5
+        trkfile = open(filename, "r").readlines()
+        print "Loading %s..." % filename
+
+        while 1:
+            try:
+                for l in trkfile:
+                    l = l.strip()
+                    if (l != "") and (l[:1] != "#"):
+                        print "Line: %s" % repr(l)
+                        data = l.split(",")
+                        speed = int(data[1])
+                        while (clock < int(data[0]) and (int(data[0]) > 0)):
+                            clock += 1
+                            sleep(0.07)
+                        print "CLK %i/%i -> set: %i" % (clock, int(data[0]), speed)
+                        cli.box.speedminimum(slot, speed )
+                # now wait for lap sync :)
+                while self.box.readline() != "": pass
+                rx = ""
+                while rx[:2] != "L:":
+                    rx = self.box.readline()
+                data = rx.split(":")
+                l = int(data[2], 16)
+                s = int(data[3]) - 1
+                t = int(data[4], 16) / 2000.00
+                print "# lap %i complete: %3.2f seconds" % (l, t)
+                clock = -3
+            except Exception, e:
+                print repr(e)
+                sys.exit(1)
+            except KeyboardInterrupt:
+                print "resetting"
+                cli.box.speedminimum(slot, 0 )
+                cli.box.speedminimum(slot, 0 )
+                sys.exit(0)
+                
+
+
+    def monitor(self):
+        """
+        Live Monitor on the console
+        Keyboard loop to control it???
+        """
+        # clear garbage in UART rx buffer
+        while self.box.readline() != "": pass
+
+        self.monitor_init()
+        self.scr = curses.initscr()
+        curses.start_color()
+        curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_BLACK) # standard text
+        curses.init_pair(2, curses.COLOR_WHITE, curses.COLOR_BLUE) # label
+        curses.init_pair(11, curses.COLOR_BLACK, curses.COLOR_YELLOW) # player 1 slot
+        curses.init_pair(12, curses.COLOR_BLACK, curses.COLOR_GREEN) # player 2 slot
+        curses.init_pair(13, curses.COLOR_BLACK, curses.COLOR_RED) # player 3 slot
+        curses.init_pair(14, curses.COLOR_BLACK, curses.COLOR_MAGENTA) # player 4 slot
+        curses.init_pair(15, curses.COLOR_WHITE, curses.COLOR_BLACK) # player 5 slot
+        curses.init_pair(16, curses.COLOR_WHITE, curses.COLOR_BLACK) # player 6 slot
+        curses.noecho() # disable key echo
+        curses.cbreak() # do not buffer keypresses
+        self.scr.keypad(1) # enable special keys
+        self.scr.nodelay(1) # disable delay on readkey
+
+        self.cleartop()
+        self.render_slots()
+        self.scr.refresh()
+
+
+        while 1:
+            key = self.scr.getch()
+            if key == ord('c'): break
+            elif key == ord(' '): self.box.query("+") # panic / resume
+            elif key == 10: self.box.query("#") # remote start button press
+            elif key == ord('1'): self.readName(0)
+            elif key == ord('2'): self.readName(1)
+            elif key == ord('3'): self.readName(2)
+            elif key == ord('4'): self.readName(3)
+            elif key == ord('5'): self.readName(4)
+            elif key == ord('6'): self.readName(5)
+            #elif key == ord('q'): self.readLimit(0)
+            #elif key == ord('w'): self.readLimit(1)
+            #elif key == ord('e'): self.readLimit(2)
+            #elif key == ord('r'): self.readLimit(3)
+            #elif key == ord('t'): self.readLimit(4)
+            #elif key == ord('z'): self.readLimit(5)
+            elif key == ord('a'):
+                if self.slot[4]["drive"] > 0: self.slot[4]["drive"] -= 1
+                cli.box.speedminimum(4, self.slot[4]["drive"])
+            elif key == ord('s'):
+                if self.slot[4]["drive"] < 16: self.slot[4]["drive"] += 1
+                cli.box.speedminimum(4, self.slot[4]["drive"])
+            elif key == ord('y'):
+                if self.slot[5]["drive"] > 0: self.slot[5]["drive"] -= 1
+                cli.box.speedminimum(5, self.slot[5]["drive"])
+            elif key == ord('x'):
+                if self.slot[5]["drive"] < 16: self.slot[5]["drive"] += 1
+                cli.box.speedminimum(5, self.slot[5]["drive"])
+            elif key == ord('t'):
+                tmp = self.readInt("Set new Race TIME limit", self.timelimit)
+                if tmp: self.timelimit = tmp
+                self.cleartop()
+            elif key == ord('l'):
+                tmp = self.readInt("Set new Race LAP limit", self.laplimit)
+                if tmp: self.laplimit = tmp
+                self.cleartop()
+            elif key == ord('/'):
+                for slot in range(5):
+                    self.flash_car_settings(slot)
+
+
+            # is there something in the rx buffer?
+            rx = self.box.readline()
+            if (rx != "") or self.test:
+                self.scr.addstr(17,0,
+                    "Last RX: %19s" % rx, curses.color_pair(2))
+                self.scr.redrawwin()
+                self.scr.refresh()
+                # we have received something
+                try:
+                    data = rx.split(":")
+                    if rx[:2] == "L:":
+                        # update lap time info
+                        l = int(data[2], 16)
+                        slot = int(data[3]) - 1
+                        t = int(data[4], 16) / 2000.00
+                        self.sysclk = int(data[5], 16) / 2000.00
+                        self.slot[slot]["laps_last"] = self.slot[slot]["laps"]
+                        self.slot[slot]["laps"] = l
+                        self.slot[slot]["last"] = t
+                        self.slot[slot]["clk"] = self.sysclk
+                        if (self.slot[slot]["best"] > t) or (self.slot[slot]["best"] == 0):
+                            self.slot[slot]["best"] = t
+                        if self.bestlap > t:
+                            trigger_event("lap_record", slot + 1)
+                            self.bestlap = t
+
+                        self.slot[slot]["status"] = "IN-RACE"
+                        if (self.slot[slot]["laps_last"] != l) and (l == self.laplimit):
+                            # we have lap limit reached!
+                            trigger_event("win", slot + 1)
+                            self.raceactive = False
+                            self.slot[slot]["status"] = "WINNER!"
+                            self.box.query("+") # stop race
+
+                        self.render_slots()
+
+                    if rx[:2] == "F:":
+                        # update fuel level
+                        slot = int(data[1])
+                        f = int(data[2], 16)
+                        f = f / 100 # fuel in percent
+                        self.sysclk = int(data[3], 16) / 2000.00
+                        self.slot[slot]["fuel_last"] = self.slot[slot]["fuel"]
+                        self.slot[slot]["fuel"] = f
+                        if self.slot[slot]["fuel_last"] != f:
+                            if (self.slot[slot]["fuel_last"] == 16) and (f == 15):
+                                # 15 percent fuel, set speed limit for car to 8
+                                # warning sound
+                                trigger_event("fuel_warning1", slot + 1)
+                                cli.box.speedlimit(slot, 8)
+                            if (self.slot[slot]["fuel_last"] == 6) and (f == 5):
+                                # 5 percent, set speed limit for car to 6
+                                # warning sound
+                                trigger_event("fuel_warning2", slot + 1)
+                                cli.box.speedlimit(slot, 6)
+                            if (self.slot[slot]["fuel_last"] == 1) and (f == 0):
+                                # fuel empty
+                                # set speedlimit to 4
+                                cli.box.speedlimit(slot, 4)
+                            if (self.slot[slot]["fuel_last"] < f) and (f >= 11) and (f < 20):
+                                cli.box.speedlimit(slot, 15)
+                            if (self.slot[slot]["fuel_last"] < f) and (f == 100):
+                                trigger_event("fuel_full", slot + 1)
+                        self.render_slots()
+
+                    if rx[:1] == "~":
+                        # jumpstart occured
+                        slot = int(rx[1:2])
+                        t = int(data[1], 16) / 2000.00
+                        self.slot[slot]["jumpstart"] = t
+                        self.slot[slot]["status"] = "Jumpstart!"
+
+                    if rx[:3] == "RW:":
+                        # ResponseWire packet, do nothing at the moment, just decode
+                        slot = int(data[1])
+                        devtype = int(data[2])
+                        sender = int(data[3], 16)
+                        status = int(data[4], 16)
+                        self.sysclk = int(data[5], 16)
+                        if (devtype == 4):
+                            # pitlane sent something
+                            if (status == 5):
+                                self.slot[slot]["status"] = "PITLANE"
+                                trigger_event("pitlane_enter", slot + 1)
+                            if (status == 7):
+                                self.slot[slot]["status"] = "IN-RACE"
+                                trigger_event("pitlane_exit", slot + 1)
+
+                        self.render_slots()
+
+                    if rx == "!RACE PREPARE":
+                        # reset current race status
+                        # and display PREPARE PHASE
+                        self.reset_slots()
+                        for slot in range(MAXSLOTS):
+                            self.slot[slot]["status"] = "Prepare"
+                        trigger_event("race_prepare")
+
+                    if rx == "!RACE START":
+                        for slot in range(MAXSLOTS):
+                            if self.slot[slot]["status"] == "~~~~~~~~~~":
+                                self.slot[slot]["status"] = "Idle"
+                        trigger_event("race_start")
+                        self.raceactive = True
+
+                    if rx == "!COUNTDOWN":
+                        # countdown initiated
+                        for slot in range(MAXSLOTS):
+                            self.slot[slot]["status"] = "~~~~~~~~~~"
+                        trigger_event("countdown_start")
+
+                    if rx == "!PANIC":
+                        # panic mode
+                        trigger_event("panic")
+
+                    if rx == "!SHORTCUT":
+                        # panic mode
+                        trigger_event("panic_shortcut")
+
+                    if rx == "!RESUME":
+                        # panic mode
+                        trigger_event("resume")
+
+
+                    if ((self.timelimit > 0) and (self.raceactive) and 
+                        (self.sysclk_last != self.sysclk) and 
+                        ((self.sysclk / 60) >= self.timelimit)):
+                        self.sysclk_last = self.sysclk
+                        self.raceactive = False
+                        # we have time limit reached!
+                        self.box.query("+") # stop race
+                        trigger_event("win")
+                        # get the one with position 1
+                        for slot in self.slots:
+                            if slot["position"] == 1:
+                                slot["status"] = "WINNER!"
+                	self.render_slots()
+                    self.sysclk_last = self.sysclk
+    
+
+
+                    self.scr.addstr(17,31,
+                        "Race Timer: %7.3f min" % (self.sysclk / 60),
+                        curses.color_pair(2))
+
+                    self.scr.refresh()
+
+                except Exception:
+                    trigger_event("data_error")
+                    pass
+
+        # terminate
+        curses.nocbreak()
+        self.scr.keypad(0)
+        curses.echo()
+        curses.endwin()
+        return None
+
+    def cyclemode(self):
+        pass
+
+if __name__ == "__main__":
+    parser = OptionParser(version="%prog " + VERSION)
+    parser.add_option("--live", dest="live", action="store_true", default=False,
+        help="Run Live monitor on console", metavar="[0-5]")
+    parser.add_option("--learn", dest="learn", action="store_true", default=False,
+        help="Run Learning mode for [slot]", metavar="[0-5]")
+    parser.add_option("--teach", dest="playback", 
+        help="Playback teach file", metavar="[filename]")
+
+    parser.add_option("--slot", dest="carid",
+        help="Required for programming a car directly", metavar="[1-6]")
+    parser.add_option("--fuel", dest="fuel",
+        help="Set maximum CAR fuel level", metavar="[0-15]")
+    parser.add_option("--brake", dest="brake",
+        help="Set CAR brake strength", metavar="[0-15]")
+    parser.add_option("--accel", dest="accel",
+        help="Set CAR acceleration ", metavar="[6-15]")
+    parser.add_option("--blink", dest="blink",
+        help="Set car lights blinking state", metavar="[on|off]")
+    parser.add_option("--limit", dest="limit",
+        help="Controlled SPEED LIMIT (15 = no limit)", metavar="[0-15]")
+    parser.add_option("--drive", dest="drive",
+        help="Controlled SPEED MINIMUM (0 = disabled)", metavar="[0-15]")
+    parser.add_option("--test", dest="test", action="store_true", default=False,
+        help="", metavar="")
+    parser.add_option("--dev", dest="dev", default="/dev/ttyUSB0",
+        help="Communication port", metavar="[/dev/ttyUSB0]")
+
+    (options, args) = parser.parse_args()
+    #if not options.dev:
+    #    options.dev = "/dev/ttyUSB0"
+
+    if options.live or options.learn or options.playback:
+        cli = SlotCli(options.test, options.dev)
+    else:
+        cli = SlotClient('http://localhost:8000')
+    # should a CLI function be started?
+
+    if options.live:
+        # start the live monitor
+        cli.monitor()
+        sys.exit(0)
+
+    # check commandline if we have to program something
+    if not options.carid:
+        print "Option --slot is required for all car programming commands!\nUse --help to get a list of available commands"
+        sys.exit(1)
+    else:
+        options.carid = int(options.carid) - 1
+        if (options.carid < 0) or (options.carid > 6):
+            print "Error: Invalid slot selected"
+            sys.exit(1)
+
+    if options.learn:
+        # start the learn monitor
+        cli.monitor_learn(options.carid)
+        sys.exit(0)
+
+    if options.playback:
+        # start the playback monitor
+        cli.monitor_playback(options.carid, options.playback)
+        sys.exit(0)
+
+    if options.fuel:
+        print "setFuel: " + cli.box.progcar(int(options.carid), "fuel", int(options.fuel))
+
+    if options.accel:
+        print "setAccel: " + cli.box.progcar(int(options.carid), "accel", int(options.accel))
+
+    if options.brake:
+        print "setBrake: " + cli.box.progcar(int(options.carid), "brake", int(options.brake))
+
+    if options.blink:
+        state = False
+        if options.blink == "on":
+            state = True
+        print "setBlink: " + cli.box.blinkcar(int(options.carid), state)
+
+    if options.limit:
+        print "Change Speed Limit: " + cli.box.speedlimit(int(options.carid), int(options.limit))
+
+    if options.drive:
+        print "Change minimum Speed drive: " + cli.box.speedminimum(int(options.carid), int(options.drive))
+

mercurial