slotUI/SlotCli.py

Sat, 10 Dec 2011 17:12:47 +0100

author
Malte Bayer <mbayer@neo-soft.org>
date
Sat, 10 Dec 2011 17:12:47 +0100
changeset 75
0b38de31ad5d
parent 74
173d0863a804
child 77
cede78304992
permissions
-rwxr-xr-x

made fuel divisor configurable

#!/usr/bin/env python
"""
Freeslot project
Command line interface
"""

from freeslot import Blackbox
from optparse import OptionParser
import sys
from copy import copy
import curses

VERSION = "1.2"
MAXSLOTS = 6
TERM = {
    "caption": "\033[1;37m\033[1;44m",
    "text": "\033[1;30m",
    }

class SlotCli():
    def __init__(self):
        self.box = Blackbox()
        self.box.connect()
        self.slot_dummy = {
            "name": "Unnamed",
            "laps": 0,
            "last": 0.00,
            "best": 0.00,
            "fuel": 0,
            "position": 0,
            "drive": 0,
            }

        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),
            ]

    def update_positions(self):
        for idx in range(MAXSLOTS):
            self.slot[idx]["position"] = idx + 1
        # TODO

    def render_slots(self):
        self.update_positions()
        self.scr.addstr(3,0,
            "Pos | #/Name          | Laps | Best   | Last   | Fuel |",
            curses.color_pair(2))
        for idx in range(MAXSLOTS):
            self.scr.addstr((3 + self.slot[idx]["position"]), 0,
                "%3i | %15s | %4i | %5.2fs | %5.2fs | %3i%% |" % (
                self.slot[idx]["position"],
                self.slot[idx]["name"],
                self.slot[idx]["laps"],
                self.slot[idx]["best"],
                self.slot[idx]["last"],
                self.slot[idx]["fuel"],
                ) )

    def cleartop(self):
        self.scr.addstr(0,0, "%80s" % "Live monitor running, press keys to control or (q)uit")
        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 monitor_init(self):
        """
        Send initializing commands for live monitoring
        """
        self.box.com.query("F1\n") # set fuel logic enabled
        self.box.com.query("*1\n") # set live fuel info

    def monitor(self):
        """
        Live Monitor on the console
        Keyboard loop to control it???
        """
        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.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.cyclemode()
            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('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[4]["drive"])


            # is there something in the rx buffer?
            rx = self.box.com.readline()
            if rx != "":
                # we have received something
                data = rx.split(":")
                if rx[:2] == "L:":
                    # update lap time info
                    slot = int(data[3]) - 1
                    t = int(data[4], 16)
                    l = int(data[2], 16)
                    t /= 2000.00
                    self.slot[slot]["laps"] = l
                    self.slot[slot]["last"] = t
                    if (self.slot[slot]["best"] > t) or (self.slot[slot]["best"] == 0): self.slot[slot]["best"] = t
                    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.slot[slot]["fuel"] = f
                    self.render_slots()

                self.scr.refresh()

        # 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("--carid", dest="carid",
        help="Required for programming a car directly", metavar="[0-5]")
    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("--speed", dest="speed",
        help="Set maximum CAR speed", metavar="[0-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]")

    (options, args) = parser.parse_args()
    cli = SlotCli()
    # 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 --carid is required for all car programming commands!\nUse --help to get a list of available commands"
        sys.exit(1)

    if options.fuel:
        print "setFuel: " + cli.box.progcar(int(options.carid), "fuel", int(options.fuel))

    if options.speed:
        print "setSpeed: " + cli.box.progcar(int(options.carid), "speed", int(options.speed))

    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