def set_elapsed(self): """Update elapsed time in race ui and announcer.""" self.curelap = None if self.start is not None and self.finish is not None: et = self.finish - self.start self.time_lbl.set_text(et.timestr(2)) self.curelap = et msg = unt4.unt4(header=unichr(unt4.DC3) + u'N F$', xx=0, yy=0, text=et.timestr(2)[0:12]) self.meet.udptimer.sendto(msg.pack(), (self.meet.udpaddr, 6789)) elif self.start is not None: # Note: uses 'local start' for RT runtm = (tod.tod('now') - self.lstart).timestr(1) ## UDP hack msg = unt4.unt4(header=unichr(unt4.DC3) + u'R F$', xx=0, yy=0, text=runtm[0:12]) self.meet.udptimer.sendto(msg.pack(), (self.meet.udpaddr, 6789)) self.time_lbl.set_text(runtm) elif self.timerstat == 'armstart': self.time_lbl.set_text(tod.tod(0).timestr(1)) else: self.time_lbl.set_text('')
def postxt(self, line, oft, msg, chan=None): """Position msg at oft on line in DHI database.""" # TODO: Handle negative offsets? From right? if oft < self.linelen: msg = msg[0:(self.linelen - oft)] umsg = unt4.unt4(xx=int(oft), yy=int(line), text=msg) self.sendmsg(umsg)
def set_time(self, tstr=' '): """Set timer string.""" if self.uport is not None and tstr != self.ulast: msg = unt4.unt4(xx=0, yy=self.urow, header=unichr(unt4.DC3) + u'R F$', text=tstr[0:12]) self.uport.sendto(msg.pack(), (self.uaddr,6789)) self.ulast = tstr self.ck.set_text(tstr)
def gfx_add_row(self, rvec, chan=None): """Update graphic channel title.""" ovec = [] for c in rvec: # replace nulls and empties nc = u'' if c: # but assume strings? nc = c ovec.append(nc) self.queue.put_nowait( ('MSG', unt4.unt4(header=u'add_row', text=chr(unt4.US).join(ovec)).pack(), chan))
def run(self): """Called via threading.Thread.start().""" self.running = True so = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) so.bind(('', RECEIVER_PORT)) so.settimeout(1.0) lbmsg = None while self.running: try: (buf, ad) = so.recvfrom(1024) bv = buf.decode(self.encoding, 'ignore') #.split() msg = unt4.unt4(bv) if self.pub_cb is not None: glib.idle_add(self.pub_cb, msg) except socket.timeout: pass except Exception as e: self.log.error(u'Exception: ' + str(type(e)) + str(e)) self.log.info('Exiting')
def send_cmd(self, hdr=None, txt=None, chan=None): """Send the provided new style command.""" self.sendmsg(unt4.unt4(header=hdr, text=txt), chan)
def gfx_set_title(self, title, chan=None): """Update graphic channel title.""" self.queue.put_nowait(('MSG', unt4.unt4(header=u'set_title', text=title).pack(), chan))
def gfx_overlay(self, newov, chan=None): """Update graphic channel overlay.""" self.queue.put_nowait( ('MSG', unt4.unt4(header=u'overlay', text=unicode(newov)).pack(), chan))
def add_rider(self, rvec, header_txt='rider', chan=None): """Send a rider vector to the announcer.""" self.sendmsg( unt4.unt4(header=header_txt, text=chr(unt4.US).join(rvec)), chan)
def set_avg(self, tstr, chan=None): """Update the announcer's average speed.""" self.sendmsg(unt4.unt4(header='average', text=tstr), chan)
def set_gap(self, tstr, chan=None): """Update the announcer's gap time (if relevant).""" self.sendmsg(unt4.unt4(header='gap', text=tstr), chan)
def linefill(self, line, char=u'_', chan=None): """Use char to fill the specified line.""" #msg = char * self.linelen msg = char * 100 self.sendmsg(unt4.unt4(xx=0, yy=int(line), text=msg))
def linefill(self, line, char=u'_'): """Use char to fill the specified line.""" msg = char * self.linelen umsg = unt4.unt4(xx=0, yy=int(line), text=msg) self.sendmsg(umsg)
def postxt(self, line, oft, msg, chan=None): """Position msg at oft on line in DHI database.""" if oft >= 0: self.sendmsg(unt4.unt4(xx=int(oft), yy=int(line), text=msg), chan)
def setline(self, line, msg, chan=None): """Set the specified DHI database line to msg.""" msg = msg[0:self.linelen].ljust(self.linelen) self.sendmsg(unt4.unt4(xx=0, yy=int(line), text=msg), chan)
def clrline(self, line, chan=None): """Clear the specified line in DHI database.""" self.sendmsg(unt4.unt4(xx=0, yy=int(line), erl=True), chan)
def intro(self): m = unt4.unt4() m.yy = SCB_H - 1 m.text = 'metarace track announce ' + metarace.VERSION m.xx = SCB_W - len(m.text) self.msg_cb(m)
def showmotd(self): """Draw 'welcome'.""" if self.motd != '': m = unt4.unt4(yy=0, xx=0, text=self.motd, erl=True) self.msg_cb(m)
def clrline(self, line, chan=None): """Clear the specified line in DHI database.""" umsg = unt4.unt4(xx=0, yy=int(line), text=u' ' * self.linelen) self.sendmsg(umsg)
def linefill(self, line, char='_', chan=None): """Use char to fill the specified line.""" ## Why was this set to 100? #msg = char * 100 msg = char * self.linelen self.sendmsg(unt4.unt4(xx=0, yy=int(line), text=msg), chan)
def set_title(self, line, chan=None): """Update the announcer's title line.""" self.sendmsg(unt4.unt4(header='title', text=line), chan)
def msg_cb(self, c, e): """Handle privmsg.""" source = self.il.nm_to_n(e.source()).lower() dest = e.target().lower() body = ''.join(e.arguments()) # RCV bytes! # determine receive stream and append to appropriate buffer if self.pub_cb is not None: # add buffer if required if source not in self.rdbuf: self.rdbuf[source] = {} sbuf = self.rdbuf[source] if dest not in sbuf: sbuf[dest] = '' sbuf[dest] += body # append payload to relevant buffer while len(sbuf[dest]) > 0: # attempt to process current buffer content if sbuf[dest][0] == 'J': # process the buffer as a JSON report joft = sbuf[dest].find('{') blen = len(sbuf[dest]) if joft > 6: # implies blen > 0 # enough length for sig and buflen, start decode mvec = sbuf[dest].split(None, 3) if len(mvec) == 4: dlen = strops.confopt_posint(mvec[2]) if len(mvec[3]) >= dlen: data = mvec[3][0:dlen] dsig = self.message_sig(data) if dsig == mvec[1]: try: o = json.loads(data) glib.idle_add(self.pub_cb, o, source, dest) except Exception as e: self.log.error(u'Error reading ob: ' + repr(e)) else: self.log.info(u'Invalid signature: ' + repr(sbuf[dest])) nstart = joft + dlen sbuf[dest] = sbuf[dest][nstart:] else: # awaiting more data break else: self.log.info( u'Skipping malformed report packet: ' + repr(sbuf[dest])) sbuf[dest] = sbuf[dest][1:] # chop off marker # terminal else: if len(sbuf[dest]) > 40: self.log.info( u'Skipping malformed report packet: ' + repr(sbuf[dest])) sbuf[dest] = sbuf[dest][1:] # chop off marker elif sbuf[dest][0] == '<': data = unt4.decode(sbuf[dest]) # attempt to decode as UNT4 encoded list oidx = data.find(chr(unt4.SOH)) eidx = data.find(chr(unt4.EOT)) # process one chunk and then unravel if oidx >= 0 and eidx >= 0 and eidx > oidx: msgtxt = data[oidx:eidx + 1] glib.idle_add( self.pub_cb, unt4.unt4( unt4str=msgtxt.decode('utf-8', 'replace')), source, dest) datlen = len(unt4.encode(data[0:eidx + 1])) sbuf[dest] = sbuf[dest][datlen:] elif eidx >= 0: # discard partial msg (not yet complete) datlen = len(unt4.encode(data[0:eidx + 1])) sbuf[dest] = sbuf[dest][datlen:] else: # awaiting more data break else: # assume buffer contains a complete utf8 command list glib.idle_add(self.pub_cb, sbuf[dest].decode('utf-8', 'ignore').split(), source, dest) sbuf[dest] = '' # truncate buffer
def set_time(self, tstr, chan=None): """Update the announcer's time.""" self.sendmsg(unt4.unt4(header='time', text=tstr), chan)
def set_start(self, stod, chan=None): """Update the announcer's relative start time.""" self.sendmsg(unt4.unt4(header='start', text=stod.rawtime()), chan)
def setline(self, line, msg, chan=None): """Set the specified DHI database line to msg.""" # set line should also clear, used to have ERL, but not now? msg = strops.truncpad(msg, self.linelen, 'l', False) #msg = msg[0:self.linelen].ljust(self.linelen) self.sendmsg(unt4.unt4(xx=0, yy=int(line), text=msg))