slotUI/slotCli.py

changeset 115
bb150048d329
parent 113
b2d91fd5d926
child 116
c2fc650cc48f
--- /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