Ejemplo n.º 1
0
    def __init__(self):
        """Constructor."""
        threading.Thread.__init__(self, daemon=True) 
        self.__queue = queue.Queue()
        self.__cb = defcallback
        self.__subscriptions = set()
        self.__curov = None
        self.__deftopic = None
        self.__connected = False
        self.__connect_pending = False
        self.__host = None
        self.__qos = 0
        self.__doreconnect = True  # if host set, try to connect on startup

        # check system config for overrides
        if metarace.sysconf.has_option('telegraph', 'host'):
            self.__host = metarace.sysconf.get('telegraph', 'host')
        if metarace.sysconf.has_option('telegraph', 'deftopic'):
            # note: this may be overidden by application
            self.__deftopic = metarace.sysconf.get('telegraph', 'deftopic')
        if metarace.sysconf.has_option('telegraph', 'qos'):
            self.__qos = strops.confopt_posint(metarace.sysconf.get(
                                  'telegraph', 'qos'),0)
            if self.__qos > 2:
                LOG.info('Invalid QOS %r set to %r', self.__qos, 2)
                self.__qos = 2

        # create mqtt client
        self.__client = mqtt.Client()
        if metarace.sysconf.has_option('telegraph', 'debug'):
            if strops.confopt_bool(metarace.sysconf.get('telegraph',
                                                        'debug')):
                LOG.debug('Enabling mqtt/paho debug')
                mqlog = logging.getLogger('metarace.telegraph.mqtt')
                mqlog.setLevel(logging.DEBUG)
                self.__client.enable_logger(mqlog)
        if metarace.sysconf.has_option('telegraph', 'usetls'):
            if strops.confopt_bool(metarace.sysconf.get('telegraph',
                                                        'usetls')):
                LOG.debug('Enabling TLS connection')
                self.__client.tls_set()
        username = None
        password = None
        if metarace.sysconf.has_option('telegraph', 'username'):
            username = metarace.sysconf.get('telegraph', 'username')
        if metarace.sysconf.has_option('telegraph', 'password'):
            password = metarace.sysconf.get('telegraph', 'password')
        if username and password:
            self.__client.username_pw_set(username, password)
        self.__client.reconnect_delay_set(2, 16)
        self.__client.on_message = self.__on_message
        self.__client.on_connect = self.__on_connect
        self.__client.on_disconnect = self.__on_disconnect
        self.__running = False
Ejemplo n.º 2
0
    def loadconfig(self):
        """Load config from disk."""
        cr = jsonconfig.config({u'road_announce':{
                                    u'remoteport':u'',
                                    u'remoteuser':u'',
                                    u'remotechan':u'#agora',
                                    u'autoscroll':False,
                                    u'timetick':12,
                                    u'fontsize':20,
                                    u'fullscreen':False,
                                    u'groupcol':True,
                                    u'catcol':True,
                                    u'bunchmap':True,
                                    u'search':False,
                                    u'maxlaptime':'2:00',
                                    u'motd':MOTD}})
        cr.add_section(u'road_announce')
        cwfilename = metarace.default_file(CONFIGFILE)
        # read in sysdefaults before checking for config file
        cr.merge(metarace.sysconf, u'road_announce')

        # re-set log file
        if self.loghandler is not None:
            self.log.removeHandler(self.loghandler)
            self.loghandler.close()
            self.loghandler = None
        self.loghandler = logging.FileHandler(
                             os.path.join(self.configpath, LOGFILE))
        self.loghandler.setLevel(LOGHANDLER_LEVEL)
        self.loghandler.setFormatter(logging.Formatter(
                       '%(asctime)s %(levelname)s:%(name)s: %(message)s'))
        self.log.addHandler(self.loghandler)

        # check for config file
        try:
            with open(cwfilename, 'rb') as f:
                cr.read(f)
        except Exception as e:
            self.log.error(u'Reading app config: ' + repr(e))

        self.fontsize = strops.confopt_posint(cr.get(u'road_announce',
                                              u'fontsize'), FONTSIZE)

        fnszstr = str(self.fontsize)+'px'
        self.font = pango.FontDescription(FONTFACE + ' ' + fnszstr)

        self.motd = cr.get(u'road_announce', u'motd')
        if strops.confopt_bool(cr.get(u'road_announce', u'fullscreen')):
            self.window.fullscreen()

        self.remoteport = cr.get(u'road_announce', u'remoteport')
        self.remotechan = cr.get(u'road_announce', u'remotechan')
        self.remoteuser = cr.get(u'road_announce', u'remoteuser')
        self.io.set_portstr(portstr=self.remoteport,
                             channel=self.remotechan)
        if self.remoteuser:
            self.log.info(u'Enabled remote control by: '
                          + repr(self.remoteuser))
        else:
            self.log.info(u'Promiscuous remote control enabled.')

        self.lbl_header.modify_font(self.font)
        self.elap_lbl.modify_font(self.font)
        self.search_lbl.modify_font(self.font)
        self.search_entry.modify_font(self.font)
        self.view.modify_font(self.font)
        self.iview.modify_font(self.font)
        self.fin_rank.modify_font(self.font)
        self.fin_label.modify_font(self.font)
        self.fin_rider.modify_font(self.font)
        self.fin_time.modify_font(self.font)
        self.int_rank.modify_font(self.font)
        self.int_label.modify_font(self.font)
        self.int_rider.modify_font(self.font)
        self.int_time.modify_font(self.font)
Ejemplo n.º 3
0
    def loadconfig(self):
        """Load app config from disk."""
        cr = jsonconfig.config({
            u'voladisp': {
                u'id': '',
                u'port': u'',
                u'brightness': u'1',
                u'remoteport': u'',
                u'remotechan': u'',
                u'remoteuser': u'',
                u'loglevel': unicode(logging.INFO),
                u'maxlaptime': u'4:00'
            }
        })
        cr.add_section(u'voladisp')
        cwfilename = metarace.default_file(CONFIGFILE)
        cr.merge(metarace.sysconf, u'voladisp')

        # re-set log file
        if self.loghandler is not None:
            self.log.removeHandler(self.loghandler)
            self.loghandler.close()
            self.loghandler = None
        self.loghandler = logging.FileHandler(
            os.path.join(self.configpath, LOGFILE))
        self.loghandler.setLevel(LOGHANDLER_LEVEL)
        self.loghandler.setFormatter(
            logging.Formatter(
                '%(asctime)s %(levelname)s:%(name)s: %(message)s'))
        self.log.addHandler(self.loghandler)

        # check for config file
        try:
            with open(cwfilename, 'rb') as f:
                cr.read(f)
        except Exception as e:
            self.log.error(u'Reading app config: ' + repr(e))

        # set uSCBsrv connection
        self.remoteuser = cr.get(u'voladisp', u'remoteuser')
        self.remotechan = cr.get(u'voladisp', u'remotechan')
        self.remoteport = cr.get(u'voladisp', u'remoteport')
        self.remote.set_portstr(portstr=self.remoteport,
                                channel=self.remotechan)
        if self.remoteuser:
            self.log.info(u'Enabled remote control by: ' +
                          repr(self.remoteuser))
        else:
            self.log.info(u'Promiscuous remote control enabled.')

        # set display serial port
        self.port = cr.get(u'voladisp', u'port')
        self.reconnect_display()

        # check the maximum lap time field
        mlap = tod.str2tod(cr.get(u'voladisp', u'maxlaptime'))
        if mlap is not None:
            self.maxlaptime = mlap

        # set display birightness
        self.set_brightness(
            strops.confopt_posint(cr.get(u'voladisp', u'brightness'), 1))

        cid = cr.get(u'voladisp', u'id')
        if cid and cid != APP_ID:
            self.log.error(u'Meet configuration mismatch: ' + repr(cid) +
                           u' != ' + repr(APP_ID))
Ejemplo n.º 4
0
    def loadconfig(self):
        """Load config from disk."""
        cr = jsonconfig.config({u'irtt_start':{
                                    u'uscbsrv':'',
                                    u'channel':USCBSRV_CHANNEL, 
                                    u'fullscreen':False,
                                    u'timer':'',
                                    u'backlightlow':0.25,
                                    u'backlighthigh':1.0,
                                    u'backlightdev':None,
                                    u'syncthresh':DEFAUDIOSYNCTHRESH,
                                    u'startlist':u'startlist.csv'}})
        cr.add_section(u'irtt_start')
        # check for config file
        cfile = metarace.default_file(CONFIGFILE)
        # read in sysdefaults before checking for config file
        cr.merge(metarace.sysconf, u'irtt_start')

        try:
            self.log.info(u'Reading config from: ' +repr(cfile))
            with open(cfile, 'rb') as f:
                cr.read(f)
        except Exception as e:
            self.log.error(u'Reading config: ' + unicode(e))

        if strops.confopt_bool(cr.get(u'irtt_start', u'fullscreen')):
            self.window.fullscreen()

        # set timer port
        tport = cr.get(u'irtt_start', u'timer')
        self.timer.setport(tport)
        self.timer.sane()
        self.timer.keylock()
        self.timer.setcb(self.starttrig)
        self.timer.armlock(True)	# always re-armlock
        self.timer.arm(timy.CHAN_START)

        # load backlight parameters
        self.backlightdev = cr.get(u'irtt_start', u'backlightdev')
        self.backlightlow = strops.confopt_float(cr.get(u'irtt_start',
                                                 u'backlightlow'),0.25)
        self.backlighthigh = strops.confopt_float(cr.get(u'irtt_start',
                                                 u'backlighthigh'),1.0)
        if os.path.exists(self.backlightdev):
            try:
                with open(os.path.join(self.backlightdev,u'max_brightness'),
                                       'rb') as bf:
                    mbstr = bf.read()
                    self.backlightmax = strops.confopt_posint(mbstr,20)
                    self.backlightdev = os.path.join(self.backlightdev,
                                                     u'brightness')
                    self.log.info(u'Using backlight dev '
                                    + repr(self.backlightdev) 
                                    + u'; Max={0}, Low={1}%, High={2}%'.format(
                                        self.backlightmax,
                                        int(100.0*self.backlightlow),
                                        int(100.0*self.backlighthigh)))
            except Exception as e:
                self.log.error(u'Reading from backlight device: ' + repr(e))
                self.backlightdev = None
        else:
            self.log.info(u'Backlight control not configured.')
            self.backlightdev = None

        # audio sync thresh
        self.syncthresh = strops.confopt_posint(
                                   cr.get(u'irtt_start', u'syncthresh'),
                                   DEFAUDIOSYNCTHRESH)
        self.log.info(u'Sync threshold set to: {0:0.3f}s'.format(
                                            float(self.syncthresh)*1e-9))
              
        # set sender port
        nhost = cr.get(u'irtt_start', u'uscbsrv')
        nchannel = cr.get(u'irtt_start', u'channel')
        self.scb.set_portstr(nhost, nchannel)

        # load riders
        datafile = cr.get(u'irtt_start', u'startlist')
        try:
            rlist = []
            with open(datafile,'rb') as f:
                cr = ucsv.UnicodeReader(f)
                for r in cr:
                    key = None
                    st = None
                    bib = u''
                    series = u''
                    name = u''
                    next = None
                    # load rider info
                    # start, no, series, name, cat
                    if len(r) > 0 and r[0] not in NOHDR: # time & no provided
                        st = tod.str2tod(r[0])
                        if len(r) > 1:	# got bib
                            bib = r[1]
                        if len(r) > 2:	# got series
                            series = r[2]
                        if len(r) > 3:  # got name
                            name = u' '.join([r[1],r[3]])
                        if st is not None:
                            # enough data to add a starter
                            key = tod2key(st)
                            nr = [st, bib, series, name, next]
                            self.ridermap[key] = nr
                            rlist.append(key)
            # sort startlist and build list linkages
            curoft = tod2key(tod.tod(u'now'))
            self.currider = None
            rlist.sort()
            prev = None
            for r in rlist:
                if prev is not None:
                    self.ridermap[prev][4] = r	# prev -> next
                prev = r
                if self.currider is None and r > curoft:
                    self.currider = r
                    rvec  = self.ridermap[r]
                    stxt = tod.tod(r).meridian()
                    sno = rvec[1]
                    sname = rvec[3]
                    self.log.info(u'Setting first rider to: '
                          + u','.join([sno, sname]) + u' @ ' + stxt)
            # last link will be None

        except Exception as e:
            # always an error - there must be startlist to continue
            self.log.error(u'Error loading from startlist: '
                             + unicode(e))
Ejemplo n.º 5
0
    def __init__(self, linelen=28):
        """Constructor."""
        threading.Thread.__init__(self)
        self.running = False
        self.debug = False
        self.il = None
        self.localsrv = False
        self.rdbuf = {}  # source -> dest -> buf[]
        self.pub_cb = None
        self.iohandle = {}
        self.addchans = set()

        ## HACK
        self.linelen = linelen
        self.pagelen = 7
        self.encoding = 'utf-8'

        self.log = logging.getLogger('telegraph')
        self.log.setLevel(logging.DEBUG)

        try:
            import irclib
            # CHECK: 16.2.9. "all import attempts must be completed
            # before the interpreter starts shutting itself down."
            self.ih = irclib.IRC(fn_to_add_socket=self._addsock,
                                 fn_to_remove_socket=self._delsock)
            self.il = irclib
        except ImportError:
            self.log.warn(u'irclib not present: Telegraph will not function.')
            self.ih = fakeirc()
        self.ic = self.ih.server()
        self.ping_interval = PING_INTERVAL
        self.np = tod.tod('now') + self.ping_interval

        self.name = 'telegraph'
        self.chanstatus = False
        self.nick = TELEGRAPH_USER + unicode(random.randint(1000, 9999))
        self.host = TELEGRAPH_HOST
        self.port = TELEGRAPH_PORT
        self.username = TELEGRAPH_USERNAME
        self.fullname = TELEGRAPH_FULLNAME
        self.channel = TELEGRAPH_CHANNEL
        self.srvid = TELEGRAPH_FAKEHOST
        self.privateservers = TELEGRAPH_PRIVATESERVERS
        self.opername = TELEGRAPH_OPERNAME
        self.operpass = TELEGRAPH_OPERPASS
        self.doreconnect = False
        self.connect_pending = False
        self.dumbcnt = 0
        self.curov = None  # allow use as a sender
        #self.linelen = linelen
        self.queue = Queue.Queue()
        # check system config for overrides
        if metarace.sysconf.has_option(u'telegraph', u'username'):
            self.username = metarace.sysconf.get(u'telegraph', u'username')
        if metarace.sysconf.has_option(u'telegraph', u'fullname'):
            self.fullname = metarace.sysconf.get(u'telegraph', u'fullname')
        if metarace.sysconf.has_option(u'telegraph', u'channel'):
            self.channel = metarace.sysconf.get(u'telegraph', u'channel')
        if metarace.sysconf.has_option(u'telegraph', u'privateservers'):
            self.privateservers = metarace.sysconf.get(u'telegraph',
                                                       u'privateservers')
        if metarace.sysconf.has_option(u'telegraph', u'opername'):
            self.opername = metarace.sysconf.get(u'telegraph', u'opername')
        if metarace.sysconf.has_option(u'telegraph', u'operpass'):
            self.operpass = metarace.sysconf.get(u'telegraph', u'operpass')
        if metarace.sysconf.has_option(u'sender', u'pagelen'):
            self.pagelen = strops.confopt_posint(
                metarace.sysconf.get(u'sender', u'pagelen'), self.pagelen)
        if metarace.sysconf.has_option(u'telegraph', u'ping_interval'):
            ck = tod.str2tod(
                metarace.sysconf.get(u'telegraph', u'ping_interval'))
            if ck is not None:
                self.ping_interval = ck
Ejemplo n.º 6
0
 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
Ejemplo n.º 7
0
    def loadconfig(self):
        """Load config from disk."""
        cr = jsonconfig.config({
            u'road_announce': {
                u'remoteport': u'',
                u'remoteuser': u'',
                u'remotechan': u'#agora',
                u'autoscroll': False,
                u'timetick': 12,
                u'fontsize': 20,
                u'minelevrange': 300.0,
                u'fullscreen': False,
                u'groupcol': True,
                u'catcol': True,
                u'bunchmap': True,
                u'showtrack': False,
                u'search': False,
                u'maxlaptime': '2:00',
                u'motd': MOTD
            }
        })
        cr.add_section(u'road_announce')
        cwfilename = metarace.default_file(CONFIGFILE)
        # read in sysdefaults before checking for config file
        cr.merge(metarace.sysconf, u'road_announce')

        # re-set log file
        if self.loghandler is not None:
            self.log.removeHandler(self.loghandler)
            self.loghandler.close()
            self.loghandler = None
        self.loghandler = logging.FileHandler(
            os.path.join(self.configpath, LOGFILE))
        self.loghandler.setLevel(LOGHANDLER_LEVEL)
        self.loghandler.setFormatter(
            logging.Formatter(
                '%(asctime)s %(levelname)s:%(name)s: %(message)s'))
        self.log.addHandler(self.loghandler)

        # check for config file
        try:
            with open(cwfilename, 'rb') as f:
                cr.read(f)
        except Exception as e:
            self.log.error(u'Reading app config: ' + repr(e))

        self.timetick = strops.confopt_posint(
            cr.get(u'road_announce', u'timetick'), TIMETICK)
        self.fontsize = strops.confopt_posint(
            cr.get(u'road_announce', u'fontsize'), FONTSIZE)
        maxlap = tod.str2tod(cr.get(u'road_announce', u'maxlaptime'))
        if maxlap is not None:
            self.maxlaptime = maxlap
        self.motd = cr.get(u'road_announce', u'motd')
        if strops.confopt_bool(cr.get(u'road_announce', u'fullscreen')):
            self.window.fullscreen()
        if strops.confopt_bool(cr.get(u'road_announce', u'search')):
            self.search_ent.show()
            self.search_ent.set_sensitive(True)
        self.showtrack = strops.confopt_bool(
            cr.get(u'road_announce', u'showtrack'))
        if self.showtrack:
            self.track_area.show()
        autoscroll = strops.confopt_bool(
            cr.get(u'road_announce', u'autoscroll'))
        if autoscroll != self.autoscroll:
            self.autoscroll = True
            self.scrollcnt = 0
            glib.timeout_add(SCROLLDELAY, self.doautoscroll)

        self.remoteport = cr.get(u'road_announce', u'remoteport')
        self.remotechan = cr.get(u'road_announce', u'remotechan')
        self.remoteuser = cr.get(u'road_announce', u'remoteuser')
        self.io.set_portstr(portstr=self.remoteport, channel=self.remotechan)
        if self.remoteuser:
            self.log.info(u'Enabled remote control by: ' +
                          repr(self.remoteuser))
        else:
            self.log.info(u'Promiscuous remote control enabled.')

        if not strops.confopt_bool(cr.get(u'road_announce', 'groupcol')):
            self.view.get_column(5).set_visible(False)
        if not strops.confopt_bool(cr.get(u'road_announce', 'catcol')):
            self.view.get_column(3).set_visible(False)
        if not strops.confopt_bool(cr.get(u'road_announce', 'bunchmap')):
            self.map_area.hide()

        fnszstr = str(self.fontsize) + 'px'
        self.lbl_header.modify_font(
            pango.FontDescription(FONTFACE + ' ' + fnszstr))
        self.elap_lbl.modify_font(
            pango.FontDescription(FONTFACE + ' ' + fnszstr))
        self.gap_lbl.modify_font(
            pango.FontDescription(FONTFACE + ' ' + fnszstr))
        self.search_entry.modify_font(
            pango.FontDescription(FONTFACE + ' ' + fnszstr))
        self.lbl_resultmsg.modify_font(
            pango.FontDescription(FONTFACE + ' ' + fnszstr))
        self.view.modify_font(pango.FontDescription(FONTFACE + ' ' + fnszstr))
        zrangemin = strops.confopt_float(
            cr.get(u'road_announce', u'minelevrange'), 200.0)
        routefile = metarace.default_file(u'route.dat')
        self.profile = None
        self.zmin = None
        self.zmax = None
        self.dmax = None
        if os.path.exists(routefile):
            print(u'loading profile...')
            self.profile = []
            with open(routefile, 'rb') as f:
                dmax = 0.0
                xmin = -1.0
                xmax = 1.0
                ymin = -1.0
                ymax = 1.0
                zmin = 90000.0
                zmax = -100.0
                for l in f:
                    r = l.split()
                    t = strops.confopt_float(r[1])
                    x = strops.confopt_float(r[2])
                    y = strops.confopt_float(r[3])
                    z = strops.confopt_float(r[4])
                    d = strops.confopt_float(r[6])
                    if z < zmin:
                        zmin = z
                    if z > zmax:
                        zmax = z
                    if x < xmin:
                        xmin = x
                    if x > xmax:
                        xmax = x
                    if y < ymin:
                        ymin = y
                    if y > ymax:
                        ymax = y
                    if d > dmax:
                        dmax = d
                    self.profile.append([t, z, d, x, y])
                self.zmin = zmin
                self.zmax = zmax
                self.xmin = xmin
                self.xmax = xmax
                self.ymin = ymin
                self.ymax = ymax
                self.dmax = dmax
                erange = zmax - zmin  # profile min elevation range
                if erange < zrangemin:
                    self.zmin -= 0.5 * (zrangemin - erange)
                    self.zmax = self.zmin + zrangemin
                #print(repr([zmin,zmax,dmax]))
                routemeta = metarace.default_file(u'route.json')
                rjdat = jsonconfig.config()
                if os.path.exists(routemeta):
                    with open(routemeta, 'rb') as g:
                        rjdat.read(g)
                    bbmin = rjdat.get(u'route', u'mapmin')
                    bbmax = rjdat.get(u'route', u'mapmax')
                    self.track_bbox = [[bbmin[u'x'], bbmin[u'y']],
                                       [bbmax[u'x'], bbmax[u'y']]]