def doDiscoverFound( self, action, inEvent ):
     # verify webbrick is in the address list
     od = inEvent.getPayload()
     if od.has_key("version") and od["version"] >= 6 :
         adrs = od["ipAdr"]
         if adrs == WbDefs.DEFAULT_SP_ADR:
             resetSitePlayer(adrs)
         elif not self._webbrickConfigs.has_key( adrs ):
             self._webbrickConfigs[adrs] = None
    def handleMinute( self, inEvent ):
        """
        """
        #_log.debug( "handleMinute %s" % (self._SpCounters) )

        # if entry goes positive then clock needs resetting as getting SS or ST meddages with clock more 
        # then a configurable number of seconds out of step.
        od = inEvent.getPayload()
        for tgt in self._SpCounters:
            self._SpCounters[tgt] = self._SpCounters[tgt] + 1
            if self._SpCounters[tgt] > self._resetWebIfTimer:
                self._SpCounters[tgt] = 0
                # webbrick has not sent any UDP events for a period of time
                resetSitePlayer( tgt )

        for tgt in self._ClockCounters.keys():
            if self._ClockCounters[tgt] > self._resetClocktimer:
                # webbrick has not picked up time from RTC or RTC is too far out of step.
                self._log.info( "SetTime on node %s " % tgt )
                cmd = Wb6Commands(tgt)
                cmd.Login( "password" )
                cmd.SetTime( od["day"], od["hour"], od["minute"] )
                del self._ClockCounters[tgt]
    def handleTimeSignal( self, inEvent ):
        # If time from webbrick is more than x away from Gateway reset it.
        od = inEvent.getPayload()

        if od and od.has_key("ipAdr"):
            tgt = od["ipAdr"]

            self._SpCounters[tgt] = 0  # reset site player monitor

            if od["uptime"] < 5:    # minutes
                _log.info( "Webbrick %s rebooted reason %u" % (tgt, od["resetCode"]) )

            if tgt == WbDefs.DEFAULT_IP_ADR:
                # on default IP address
                _log.info( "Webbrick %s on default IP address" % (tgt) )
                if self._resetOnDefault:
                    resetSitePlayer( tgt )

            if tgt == WbDefs.DEFAULT_SP_ADR:
                # on default Siteplayer IP address
                _log.info( "Webbrick %s on default siteplayer IP address" % (tgt) )
                resetSitePlayer( tgt )

            # add to monitor list
            if od.has_key("hour") and od.has_key("minute") and od.has_key("second"):
                now = time.time() % 86400   # in seconds today.
                wbNow = od["second"] + (60 * od["minute"]) + (3600 * od["hour"])
                if ( abs(now-wbNow) > self._clockMaxError ):
                    # let the minute handle and system started code handle this.
                    if self._ClockCounters.has_key(tgt):
                        self._ClockCounters[tgt] = self._ClockCounters[tgt] + 1
                    else:
                        self._ClockCounters[tgt] = 1
                    _log.info( "Webbrick %s clock error(%i) - %s" % (tgt, self._ClockCounters[tgt], od) )
                else:
                    if self._ClockCounters.has_key(tgt):
                        del self._ClockCounters[tgt]
    def run(self):
        # stay in loop reading packets while socket open.
        self._log.debug( 'enter run' )
        seqNrs = dict()
        try:
            # bind socket
            self.WbSkt = getWebBrickSocket()
            while ( self.running ):
                # read packet
                try:
                    data = self.WbSkt.recvfrom(32)
                    if data and self.running:
                        evnt = None
                        adr = str(data[1][0])
                        if adr == WbDefs.DEFAULT_SP_ADR:
                            resetSitePlayer( adr )  # then events do not get beyond here.
                        else:
                            self._log.debug( 'Receive %s' % str(data) )
                            # create WbUdpEvents
                            # Wb 6 UDP packets have a length byte in the first position, use to decide on 5 or 6.
                            len = ord(data[0][0])
                            if  len < 32 :
                                if ( ord(data[0][1]) >= 32 ):
                                    # lets filter out duplicates
                                    # simple approach that only handles duplicates when
                                    # appear immediatly.
                                    if len >= 13:    # contains sequenece number
                                        sn = ord(data[0][12])
                                        if (not seqNrs.has_key(adr)) or seqNrs[adr] <> sn:
                                            seqNrs[adr] = sn
                                            evnt = Wb6Event( data[1], data[0] )
                                        else:
                                            self._log.debug( 'Duplicate %i' % sn  )
                                    else:
                                        evnt = Wb6Event( data[1], data[0] )
                                else:
                                    # len, type, from, seq, 
                                    sn = ord(data[0][3])
                                    if (not seqNrs.has_key(adr)) or seqNrs[adr] <> sn:
                                        seqNrs[adr] = sn
                                        evnt = WB6BinaryEvent( data[1], data[0] )
                                    else:
                                        self._log.debug( 'Duplicate %i' % sn  )
                            else:
                                evnt = Wb5Event( data[1], data[0] )

                        # call eventTgt method.
                        if (evnt):
                            self._log.debug( evnt )
                            self.sendEvent( evnt )

                    # end if data
                except socket.error, err:
                    if err[0] == errno.EINTR:
                        continue    # ignore error
                    if err[0] == errno.EAGAIN:
                        continue    # ignore error
                    if (str(err) != "timed out") and not self.running:
                        self._log.exception( err )
                except Exception, ex:
                    self._log.exception( ex )
    def updateStatus( self, adrs, newSts ):
        # now look for changes in all values and generate correct events.
        if newSts.getOperationalState() == 255: # this is site-player reset value.
            # siteplayer has been reset, so data not valid.
            self._log.error( "read from webbrick %s with invalid status data %s" % (adrs, newSts.xmlstr) )
            # reset siteplayer.
            resetSitePlayer( adrs )
            return  # short circuit out of here

        oldSts = None
        if self._webbrickStati.has_key( adrs ) :
            oldSts = self._webbrickStati[adrs]

        nnr = self._webbrickConfigs[adrs][0]
        curCfg = self._webbrickConfigs[adrs][2]
        typeRoot = "http://id.webbrick.co.uk/events/webbrick/"
        srcRoot = "webbrick/%s" % nnr

        if not oldSts or ( oldSts.getLoginState() != newSts.getLoginState() ):
#            self.sendEvent( Event( typeRoot, srcRoot, {} ) )
            pass

        if not oldSts or ( oldSts.getDate() != newSts.getDate() ):
#            self.sendEvent( Event( typeRoot, srcRoot, {} ) )
            pass

        ow = newSts.getOneWireBus()
        for idx in range(WbDefs.TEMPCOUNT):
            if (ow & (0x01 << idx)) == 0:
                # sensor not there
                pass
            else:
                if not oldSts or ( oldSts.getTemp( idx ) != newSts.getTemp( idx ) ):

                    if newSts.getTemp( idx ) == -1000.0:
                        self._log.error( "Erroneous Temperature Reading %s %s" % (adrs, newSts.xmlstr) )
                        self.sendEvent( Event( typeRoot+"ET", 
                                "%s/ET/%i" % (srcRoot,idx) , 
                                { "fromNode": nnr, "srcChannel": idx, 
                                        "val": newSts.getTemp( idx ), 
                                        "curlo": newSts.getTempLowThresh( idx ),
                                        "curhi": newSts.getTempHighThresh( idx ),
                                        "deflo": curCfg.getTempTriggerLow( idx )["threshold"],
                                        "defhi": curCfg.getTempTriggerHigh( idx )["threshold"],
                                } ) )
                    else:
                        self.sendEvent( Event( typeRoot+"CT", 
                                "%s/CT/%i" % (srcRoot,idx) , 
                                { "fromNode": nnr, "srcChannel": idx, 
                                        "val": newSts.getTemp( idx ), 
                                        "curlo": newSts.getTempLowThresh( idx ),
                                        "curhi": newSts.getTempHighThresh( idx ),
                                        "deflo": curCfg.getTempTriggerLow( idx )["threshold"],
                                        "defhi": curCfg.getTempTriggerHigh( idx )["threshold"],
                                } ) )

        for idx in range(WbDefs.AOCOUNT):
            if not oldSts or ( oldSts.getAnOut( idx ) != newSts.getAnOut( idx ) ):
                self.sendEvent( Event( typeRoot+"AO", 
                        "%s/AO/%i" % (srcRoot,idx), 
                        { "fromNode": nnr, "srcChannel": idx, "val": newSts.getAnOut( idx ) } ) )

        for idx in range(WbDefs.AICOUNT):
            if not oldSts or ( oldSts.getAnIn( idx ) != newSts.getAnIn( idx ) ):
                self.sendEvent( Event( typeRoot+"AI", 
                        "%s/AI/%i" % (srcRoot,idx), 
                        { "fromNode": nnr, "srcChannel": idx, 
                                "val": newSts.getAnIn( idx ),
                                    "curlo": newSts.getAnInLowThresh( idx ),
                                    "curhi": newSts.getAnInHighThresh( idx ),
                                    "deflo": curCfg.getAnalogTriggerLow( idx )["threshold"],
                                    "defhi": curCfg.getAnalogTriggerHigh( idx )["threshold"],
                        } ) )

        for idx in range(WbDefs.DICOUNT):
            if not oldSts or ( oldSts.getDigIn( idx ) != newSts.getDigIn( idx ) ):
                state = 0
                if newSts.getDigIn( idx ):
                    state = 1
                self.sendEvent( Event( typeRoot+"DI", 
                        "%s/DI/%i" % (srcRoot,idx), 
                        { "fromNode": nnr, "srcChannel": idx, "state": state } ) )

        for idx in range(WbDefs.DOCOUNT+WbDefs.MIMICCOUNT):   # dig out 8-15 are the mimics.
            if not oldSts or ( oldSts.getDigOut( idx ) != newSts.getDigOut( idx ) ):
                state = 0
                if newSts.getDigOut( idx ):
                    state = 1
                self.sendEvent( Event( typeRoot+"DO", 
                        "%s/DO/%i" % (srcRoot,idx), 
                        { "fromNode": nnr, "srcChannel": idx, "state": state } ) )

        self._webbrickStati[adrs] = newSts
        return None