slotUI/slotCli.py

Fri, 27 Dec 2013 12:16:58 +0100

author
mbayer
date
Fri, 27 Dec 2013 12:16:58 +0100
changeset 155
9e27eb837d3f
parent 146
a1eb2dc83819
permissions
-rwxr-xr-x

timing finetune

#!/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
from logger import eventLogger
import sys, os
from copy import copy
import curses
from time import sleep, time
import ConfigParser

import SimpleXMLRPCServer
import xmlrpclib
import threading


VERSION = "1.8.2"
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"),
#        "first_position":  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()
        self.nofuel = False
        self.pitfinish = False
        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 # best lap time
        self.test = test
        self.laplimit = 999 # race laplimit
        self.timelimit = 0 # race timelimit
        self.firstpos = -1 # first position slot
        self.freerun = True # freerun mode = sort order by best lap
        self.raceName = "Freestyle"
        self.log = eventLogger("events.log")

    def reset_slots(self):
        idx = 0
        for slt in self.slot:
            slt["laps"] = 0
            slt["laps_last"] = 0
            slt["last"] = 999.00
            slt["best"] = 999.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")
            idx += 1
        self.bestlap = 99999.00
        self.raceactive = False

    def update_positions(self):
        order1 = sorted(self.slot, key=itemgetter(
            "clk"))
        if self.freerun:
            order2 = sorted(self.slot, key=itemgetter(
                "best"))
        else:
            order2 = sorted(self.slot, key=itemgetter(
                "laps"), reverse=True)
        idx = 1
        for tst in order2:
            self.slot[tst["car"]]["position"] = idx
            # check if first position changed
            if (self.firstpos != tst["car"]) and (idx == 1):
                self.firstpos = tst["car"]
                trigger_event("first_position", tst["car"] + 1)
            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.scr.addstr(1,0, "%70s" % "Writing settings for %s to car %i, PLEASE WAIT...          " % (
            self.slot[slot]["name"],
            slot + 1),
            curses.color_pair(9))
        self.scr.refresh()
        if not self.nofuel:
            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)
        if self.slot[slot]["profile"].getint("Settings", "Fuel") == 0:
            self.box.unlimitedfuel(slot, True)
        else:
            self.box.unlimitedfuel(slot, False)
        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:
                # load default profile
                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 readRaceName(self):
        self.scr.nodelay(0) # enable delay on readkey
        curses.echo()
        self.scr.addstr(0,0, "Enter Race Name [%s]:" % (
            self.raceName),
            curses.color_pair(1))
        self.scr.refresh()
        name = self.scr.getstr(1,0, 15)
        if name != "":
            self.raceName = 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
        """
        if self.nofuel:
            #print cli.box.fueldivisor(0)
            self.box.query("F0\n") # set fuel logic disabled
        else:
            #print cli.box.fueldivisor(25)
            self.box.query("F1\n") # set fuel logic enabled

        if self.pitfinish:
            self.box.query("X1\n") # set pitlane finish function
        else:
            #print cli.box.fueldivisor(25)
            self.box.query("X0\n")

        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(9, curses.COLOR_WHITE, curses.COLOR_RED) # ATTENTION
        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('q'): break
            elif key == ord(' '): self.box.query("+") # panic / resume
            elif key == 10: 
                self.freerun = False
                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('n'): self.readRaceName()
            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)
            elif key == ord('f'):
                # set freerun mode manually (abort race)
                self.freerun = not self.freerun


            # is there something in the rx buffer?
            rx = self.box.readline()
            if (rx != "") or self.test:
                self.scr.addstr(17,3,
                    "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:
                            if self.freerun:
                                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

                        tmpname = "n/a"
                        if not self.freerun:
                            tmpname = self.raceName
                        self.log.push([
                            time(),
                            self.sysclk,
                            tmpname,
                            slot,
                            self.slot[slot]["name"],
                            l,
                            t,
                            self.slot[slot]["best"],
                            self.laplimit,
                            self.timelimit
                            ])


                        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 == "!PRE":
                        # 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 == "!GO":
                        # 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 == "!SET":
                        # countdown initiated
                        for slot in range(MAXSLOTS):
                            self.slot[slot]["status"] = "~~~~~~~~~~"
                        trigger_event("countdown_start")

                    if rx == "!STOP":
                        # panic mode, race stopped
                        trigger_event("panic")

                    if rx == "!OC":
                        # panic mode, overcurrent
                        trigger_event("panic_shortcut")

                    if rx == "!RESUME":
                        # panic mode reset - race goes on normally
                        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))

                    tmpmode = "RACE MODE (LAPS)"
                    if self.freerun:
                        tmpmode = "FREERUN (BEST)"
                    self.scr.addstr(18,31,
                        "%19s" % tmpmode, 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("--nofuel", dest="nofuel", action="store_true", default=False,
        help="Disable Freeslot fuel management", metavar="[0-5]")
    parser.add_option("--pit", dest="pitfinish", action="store_true", default=False,
        help="Pitlane entry acts as finish line too", 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.nofuel = options.nofuel
        cli.pitfinish = options.pitfinish
        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