slotUI/SlotCli.py

changeset 77
cede78304992
parent 74
173d0863a804
child 78
d9126a55295c
equal deleted inserted replaced
76:1c8305764b3f 77:cede78304992
2 """ 2 """
3 Freeslot project 3 Freeslot project
4 Command line interface 4 Command line interface
5 """ 5 """
6 6
7 from freeslot import Blackbox 7 from freeslot import Blackbox, LOGLEVEL
8 from optparse import OptionParser 8 from optparse import OptionParser
9 from operator import itemgetter
9 import sys 10 import sys
10 from copy import copy 11 from copy import copy
11 import curses 12 import curses
12 13
13 VERSION = "1.2" 14 VERSION = "1.3"
14 MAXSLOTS = 6 15 MAXSLOTS = 6
15 TERM = { 16 TERM = {
16 "caption": "\033[1;37m\033[1;44m", 17 "caption": "\033[1;37m\033[1;44m",
17 "text": "\033[1;30m", 18 "text": "\033[1;30m",
18 } 19 }
20
21 # disable debug log output
22 LOGLEVEL = 10
19 23
20 class SlotCli(): 24 class SlotCli():
21 def __init__(self): 25 def __init__(self):
22 self.box = Blackbox() 26 self.box = Blackbox()
23 self.box.connect() 27 self.box.connect()
27 "last": 0.00, 31 "last": 0.00,
28 "best": 0.00, 32 "best": 0.00,
29 "fuel": 0, 33 "fuel": 0,
30 "position": 0, 34 "position": 0,
31 "drive": 0, 35 "drive": 0,
36 "status": "Idle",
37 "clk": 0,
38 "car": 0,
32 } 39 }
33 40
34 self.slot = [ 41 self.slot = [
35 copy(self.slot_dummy), copy(self.slot_dummy), 42 copy(self.slot_dummy), copy(self.slot_dummy),
36 copy(self.slot_dummy), copy(self.slot_dummy), 43 copy(self.slot_dummy), copy(self.slot_dummy),
37 copy(self.slot_dummy), copy(self.slot_dummy), 44 copy(self.slot_dummy), copy(self.slot_dummy),
38 ] 45 ]
46 self.reset_slots()
47 self.sysclk = 0.00
48
49 def reset_slots(self):
50 idx = 0
51 for slt in self.slot:
52 slt["laps"] = 0
53 slt["last"] = 0.00
54 slt["best"] = 0.00
55 slt["fuel"] = 0
56 slt["position"] = idx
57 slt["car"] = idx # used for sort order calculation
58 slt["status"] = self.slot_dummy["status"]
59 slt["clk"] = 0
60 idx += 1
39 61
40 def update_positions(self): 62 def update_positions(self):
41 for idx in range(MAXSLOTS): 63 order1 = sorted(self.slot, key=itemgetter(
42 self.slot[idx]["position"] = idx + 1 64 "clk"))
43 # TODO 65 order2 = sorted(self.slot, key=itemgetter(
66 "laps"), reverse=True)
67 idx = 1
68 for tst in order2:
69 self.slot[tst["car"]]["position"] = idx
70 idx += 1
44 71
45 def render_slots(self): 72 def render_slots(self):
46 self.update_positions() 73 self.update_positions()
47 self.scr.addstr(3,0, 74 self.scr.addstr(3,0,
48 "Pos | #/Name | Laps | Best | Last | Fuel |", 75 "Pos | #/Name | Laps | Best | Last | Fuel | Status ",
49 curses.color_pair(2)) 76 curses.color_pair(2))
50 for idx in range(MAXSLOTS): 77 for idx in range(MAXSLOTS):
51 self.scr.addstr((3 + self.slot[idx]["position"]), 0, 78 self.scr.addstr((3 + self.slot[idx]["position"]), 0,
52 "%3i | %15s | %4i | %5.2fs | %5.2fs | %3i%% |" % ( 79 "%3i | %i %15s | %4i | %7.2fs | %7.2fs | %3i%% | %10s" % (
53 self.slot[idx]["position"], 80 self.slot[idx]["position"],
54 self.slot[idx]["name"], 81 self.slot[idx]["car"] + 1, self.slot[idx]["name"],
55 self.slot[idx]["laps"], 82 self.slot[idx]["laps"],
56 self.slot[idx]["best"], 83 self.slot[idx]["best"],
57 self.slot[idx]["last"], 84 self.slot[idx]["last"],
58 self.slot[idx]["fuel"], 85 self.slot[idx]["fuel"],
86 self.slot[idx]["status"],
59 ) ) 87 ) )
60 88
61 def cleartop(self): 89 def cleartop(self):
62 self.scr.addstr(0,0, "%80s" % "Live monitor running, press keys to control or (q)uit") 90 self.scr.addstr(0,0, "%80s" % "Live monitor running, press keys to control or (q)uit")
63 self.scr.addstr(1,0, "%80s" % " ") 91 self.scr.addstr(1,0, "%80s" % " ")
88 def monitor(self): 116 def monitor(self):
89 """ 117 """
90 Live Monitor on the console 118 Live Monitor on the console
91 Keyboard loop to control it??? 119 Keyboard loop to control it???
92 """ 120 """
121 # clear garbage in UART rx buffer
122 while self.box.com.readline() != "": pass
123
93 self.monitor_init() 124 self.monitor_init()
94 self.scr = curses.initscr() 125 self.scr = curses.initscr()
95 curses.start_color() 126 curses.start_color()
96 curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_BLACK) # standard text 127 curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_BLACK) # standard text
97 curses.init_pair(2, curses.COLOR_WHITE, curses.COLOR_BLUE) # label 128 curses.init_pair(2, curses.COLOR_WHITE, curses.COLOR_BLUE) # label
130 161
131 162
132 # is there something in the rx buffer? 163 # is there something in the rx buffer?
133 rx = self.box.com.readline() 164 rx = self.box.com.readline()
134 if rx != "": 165 if rx != "":
166 self.scr.addstr(10,0,
167 "Last RX: %19s" % rx, curses.color_pair(2))
168 self.scr.refresh()
135 # we have received something 169 # we have received something
136 data = rx.split(":") 170 data = rx.split(":")
137 if rx[:2] == "L:": 171 if rx[:2] == "L:":
138 # update lap time info 172 # update lap time info
173 l = int(data[2], 16)
139 slot = int(data[3]) - 1 174 slot = int(data[3]) - 1
140 t = int(data[4], 16) 175 t = int(data[4], 16) / 2000.00
141 l = int(data[2], 16) 176 self.sysclk = int(data[5], 16) / 2000.00
142 t /= 2000.00
143 self.slot[slot]["laps"] = l 177 self.slot[slot]["laps"] = l
144 self.slot[slot]["last"] = t 178 self.slot[slot]["last"] = t
179 self.slot[slot]["clk"] = self.sysclk
145 if (self.slot[slot]["best"] > t) or (self.slot[slot]["best"] == 0): self.slot[slot]["best"] = t 180 if (self.slot[slot]["best"] > t) or (self.slot[slot]["best"] == 0): self.slot[slot]["best"] = t
181 self.slot[slot]["status"] = "IN-RACE"
146 self.render_slots() 182 self.render_slots()
147 183
148 if rx[:2] == "F:": 184 if rx[:2] == "F:":
149 # update fuel level 185 # update fuel level
150 slot = int(data[1]) 186 slot = int(data[1])
151 f = int(data[2], 16) 187 f = int(data[2], 16)
152 f = f / 100 # fuel in percent 188 f = f / 100 # fuel in percent
189 self.sysclk = int(data[3], 16) / 2000.00
153 self.slot[slot]["fuel"] = f 190 self.slot[slot]["fuel"] = f
154 self.render_slots() 191 self.render_slots()
192
193 if rx[:1] == "~":
194 # jumpstart occured
195 slot = int(rx[1:2])
196 t = int(data[1], 16) / 2000.00
197 self.slot[slot]["jumpstart"] = t
198 self.slot[slot]["status"] = "Jumpstart!"
199
200 if rx[:3] == "RW:":
201 # ResponseWire packet, do nothing at the moment, just decode
202 slot = int(data[1])
203 devtype = int(data[2])
204 sender = int(data[3], 16)
205 status = int(data[4], 16)
206 self.sysclk = int(data[5], 16)
207 if (devtype == 4):
208 # pitlane sent something
209 if (status == 5): self.slot[slot]["status"] = "PITLANE"
210 if (status == 6): self.slot[slot]["status"] = "IN-RACE"
211
212 self.render_slots()
213
214 if rx == "!RACE PREPARE":
215 # reset current race status
216 # and display PREPARE PHASE
217 for slot in range(MAXSLOTS):
218 self.slot[slot]["status"] = "Prepare"
219
220 if rx == "!RACE START":
221 for slot in range(MAXSLOTS):
222 if self.slot[slot]["status"] == "~~~~~~~~~~":
223 self.slot[slot]["status"] = "Idle"
224
225 if rx == "!COUNTDOWN":
226 # countdown initiated
227 for slot in range(MAXSLOTS):
228 self.slot[slot]["status"] = "~~~~~~~~~~"
229
230 self.scr.addstr(10,31,
231 "Race Timer: %7.3f min" % (self.sysclk / 60),
232 curses.color_pair(2))
155 233
156 self.scr.refresh() 234 self.scr.refresh()
157 235
158 # terminate 236 # terminate
159 curses.nocbreak() 237 curses.nocbreak()

mercurial