Пример #1
0
 def __init__( self ):
     self._logger = logging.getLogger( "WebBrickGateway.LocalData" )
     self.sunRise = Sun()
     self._timeFormat_12h = "%I:%M%p"   # 12 hour clock
     self._timeFormat_24h = "%H:%M"   # 24 hour clock
         #self._timeFormat = "%X"   # locale clock, includes seconds
     self._insertMessages( Message( "Started", "Started" ) )
 def __init__ (self, localRouter ):
     self._log = _log
     super(TimeEventGenerator,self).__init__( localRouter )
     self._thread = None
     self.running = False
     self.sunRise = Sun()
     self._nextSunRise = (0,0)
     self._nextSunSet = (0,0)
     # london england
     self._lat = 51.5086
     self._long = -0.1264
     self._doSeconds = False
     self._runtimeStop = 900    # seconds, 15 minutes
     self.startup_delay = 30     # wait before sending any time events
Пример #3
0
class LocalData:
    """
    Local class to handle queries for local data to the gateway, e.g. time of day.
    """

    def __init__( self ):
        self._logger = logging.getLogger( "WebBrickGateway.LocalData" )
        self.sunRise = Sun()
        self._timeFormat_12h = "%I:%M%p"   # 12 hour clock
        self._timeFormat_24h = "%H:%M"   # 24 hour clock
            #self._timeFormat = "%X"   # locale clock, includes seconds
        self._insertMessages( Message( "Started", "Started" ) )

    def _clearOldMessages(self):
        """
        Check for obsolete messages in the _currentMessages
        """
        cherrypy.response.headerMap["cache-control"] = "no-cache"
        global _currentMesages
        now = time.time()
        idx = len(_currentMesages)
        while idx > 0:
            idx -= 1
            msg = _currentMesages[idx]
            if msg._expires and ( msg._expires < now ):
                # remove from list
                self._logger.debug( "_clearOldMessages(delete) %i %s %s" % (msg._pri, msg._txt, msg._expires ) )
                del _currentMesages[idx]

    def _insertMessages(self, msg):
        """
        Adds message to _currentMesages based on priority. Lowest values come first.
        """
        self._logger.debug( "_insertMessages %i:%s %s %s" % (msg._pri, msg._tag, msg._txt, msg._expires ) )
        global _currentMesages
        _currentMesages.append( msg )
        _currentMesages.sort( _cmpMessage )

    @turbogears.expose(template="WebBrickGateway.templates.singleValue", format="xml", content_type="text/xml")
    def time(self, *args):
        """
        Return time at Gateway as string value in form HH:MM
        """
        cherrypy.response.headerMap["cache-control"] = "no-cache"
        
        len_args = len(args) 
        if len_args >= 1:
            
            # the below is left for backward compatibility
            if args[0] == "sunrise":
                riseSet = self.sunRise.sunRiseSetDST()
                # convert values, they are 
                if (len_args == 2) and (args[1] == "24h"):
                    res = time.strftime( self._timeFormat_24h, time.gmtime(riseSet[0] * 3600))   # 24 hour clock
                else:
                    res = time.strftime( self._timeFormat_12h, time.gmtime(riseSet[0] * 3600))   # 12 hour clock

            elif args[0] == "sunset":
                riseSet = self.sunRise.sunRiseSetDST()
                if (len_args == 2) and (args[1] == "24h"):
                    res = time.strftime( self._timeFormat_24h, time.gmtime(riseSet[1] * 3600))   # 24 hour clock
                else:
                    res = time.strftime( self._timeFormat_12h, time.gmtime(riseSet[1] * 3600))   # 12 hour clock
            
            elif args[0] == "24h":
                res = time.strftime( self._timeFormat_24h)   # 24 hour clock
                
            elif args[0] == "12h":
                res = time.strftime( self._timeFormat_12h)   # 12 hour clock
        else:
            res = time.strftime( self._timeFormat_12h)   # 12 hour clock

        return { 'stserr': None, 'stsval': res }

    @turbogears.expose(template="WebBrickGateway.templates.singleValue", format="xml", content_type="text/xml")
    def messages(self):
        """
        return a string containing recent messages. With CR between messages.
        """
        self._clearOldMessages()

        global _currentMesages
        nr = 0
        s = ""
        for msg in _currentMesages:
            s = s + "\n"+ msg._txt
            nr += 1
            if nr > 5:
                break   # stop at 5 messages

        return { 'stserr': None, 'stsval': s }

    @turbogears.expose()
    def removemessage(self, tag ):
        """
        update the messages list
        """
        self._clearOldMessages()
        # if no tag then do not attempt delete
        if tag:
            global _currentMesages
            idx = len(_currentMesages)
            while idx > 0:
                idx -= 1
                msg = _currentMesages[idx]
                if ( msg._tag == tag ):
                    # remove from list
                    self._logger.debug( "removemessage(delete) %i:%s %s" % (msg._pri, msg._tag, msg._txt ) )
                    del _currentMesages[idx]
        return ""

    @turbogears.expose()
    def postmessage(self, msg, tag="", priority=4, validFor=300 ):
        """
        update the messages list
        """
		# tag may be blank and this will be suppressed in removemessage
        self.removemessage(tag)

        self._insertMessages( Message( msg, tag, priority, validFor ) )
        return ""
class TimeEventGenerator(BaseHandler):
    """
    Generate time based events.
    """

    def __init__ (self, localRouter ):
        self._log = _log
        super(TimeEventGenerator,self).__init__( localRouter )
        self._thread = None
        self.running = False
        self.sunRise = Sun()
        self._nextSunRise = (0,0)
        self._nextSunSet = (0,0)
        # london england
        self._lat = 51.5086
        self._long = -0.1264
        self._doSeconds = False
        self._runtimeStop = 900    # seconds, 15 minutes
        self.startup_delay = 30     # wait before sending any time events

    def configure( self, cfgDict ):
        """
        called with an XmlDom that contains the configuration for self
        """
        # save latitude and longitude
        if cfgDict.has_key("latitude"):
            valStr = cfgDict["latitude"]
            if ( valStr and (len(valStr) > 0 ) ):
                self._lat = float( valStr )
        if cfgDict.has_key("longitude"):
            valStr = cfgDict["longitude"]
            if ( valStr and (len(valStr) > 0 ) ):
                self._long = float( valStr )
        if cfgDict.has_key("interval"):
            valStr = cfgDict["interval"]
            if ( valStr ):
                self._doSeconds = (valStr == 'seconds')
        if cfgDict.has_key("runtime"):
            valStr = cfgDict["runtime"]
            if ( valStr and (len(valStr) > 0 ) ):
                self._runtimeStop = int( valStr )
        if cfgDict.has_key("startup_delay"):
            valStr = cfgDict["startup_delay"]
            if ( valStr and (len(valStr) > 0 ) ):
                self.startup_delay = int( valStr )

    # Terminate interface
    def stop(self):
        _log.debug( 'stop' )
        self.running = False

    def alive(self):
        return self._thread and self._thread.isAlive()

    def start(self):
        _log.debug( 'start' )
        self.running = True
        self._thread = threading.Thread( target=self.run )
        self._thread.setDaemon(True)
        self._thread.start()

    def _nextSunRiseSunSet(self):
        # get todays values, returned as Daylight saving time values.
        riseSet = self.sunRise.sunRiseSetDST( self._long, self._lat )
        _log.debug( 'next Sun Rise/Sun Set %s' % (riseSet,) )
        # convert values, they are 
        self._nextSunRise = time.gmtime(riseSet[0] * 3600)
        self._nextSunSet = time.gmtime(riseSet[1] * 3600)
        _log.debug( 'next Sun Rise %s' % (self._nextSunRise,) )
        _log.debug( 'next Sun Set %s' % (self._nextSunSet,) )

    def sendIsDark(self, nowSplit):
        # between sunset and midnight
        if ( nowSplit[3] > self._nextSunSet[3] ) or ( ( nowSplit[3] == self._nextSunSet[3] ) and ( nowSplit[4] >= self._nextSunSet[4] ) ):
            self.sendEvent( Wb6TimeEventIsDark( 1 ) )
        # between midnight and sunrise
        elif ( nowSplit[3] < self._nextSunRise[3] ) or ( ( nowSplit[3] == self._nextSunRise[3] ) and ( nowSplit[4] <= self._nextSunRise[4] ) ):
            self.sendEvent( Wb6TimeEventIsDark( 1 ) )
        else:
            # daytime
            self.sendEvent( Wb6TimeEventIsDark( 0 ) )
    
    def run(self):
        # stay in loop reading packets while socket open.
        _log.debug( 'enter run' )

        # let system settle a bit before we cause lots of work.
        if self.startup_delay > 0:
            # sleep may get terminated by signals.
            to = time.time() + self.startup_delay
            while to > time.time():
                time.sleep(1)   

        startTime = time.time()
        lastSend = startTime
        nowTime = startTime
        elapsed = 0
        self._nextSunRiseSunSet()

        nowSplit = time.localtime( lastSend )
        self.sendIsDark( nowSplit )

        while ( self.running == True ):

            try:
                # wait for next second or minute
                if self._doSeconds :
                    # rounded up to timer tick resolution to ensure not back until 
                    # next second.
                    st = (1015000.0 - float(datetime.now().microsecond) ) / 1000000.0
                else:
                    st = 60-time.localtime()[5]
                    if ( st > 10 ):
                        st = 10 # faster shutdown otherwise wait a long time.

                # throws occasional error 514 as sleep using select. google Errno 514 python
                # http://mail.python.org/pipermail/python-dev/2007-January/070626.html
                time.sleep(st)

                # generate events.
                nowTime = time.time()
                # we may of been shutdown in the meantime.
                while self.running == True and lastSend < nowTime:
                    # this while is in case ione of the time event loops takes too long.
                    lastSend = lastSend + 1
                    nowSplit = time.localtime( lastSend )

                    if self._doSeconds :
                        self.sendEvent( Wb6TimeEvent('second',nowSplit) )

                    # There is an issue that this could miss seconds.
                    if ( nowSplit[5] == 0 ): # seconds in case we change the above wait..
                        self.sendEvent( Wb6TimeEvent('minute',nowSplit) )
                        if ( nowSplit[4] == 0 ):   # new hour
                            self.sendEvent( Wb6TimeEvent('hour',nowSplit) )
                            if ( nowSplit[3] == 0 ): # new day
                                self._nextSunRiseSunSet()  # get next pair.
                                self.sendEvent( Wb6TimeEvent('day',nowSplit) )
                                self.sendEvent( Wb6TimeEvent('date',nowSplit) )
                                if ( nowSplit[2] == 1 ): # new month
                                    self.sendEvent( Wb6TimeEvent('month',nowSplit) )
                                    if ( nowSplit[1] == 1 ): # new year
                                        self.sendEvent( Wb6TimeEvent('year',nowSplit) )

                        # sunrise/sunset.
                        if ( nowSplit[3] == self._nextSunRise[3] ) and ( nowSplit[4] == self._nextSunRise[4] ):
                            self.sendEvent( Wb6TimeEvent('sunrise',nowSplit) )
                            self.sendEvent( Wb6TimeEventIsDark( 0 ) )  # not dark
                        if ( nowSplit[3] == self._nextSunSet[3] ) and ( nowSplit[4] == self._nextSunSet[4] ):
                            self.sendEvent( Wb6TimeEvent('sunset',nowSplit) )
                            self.sendEvent( Wb6TimeEventIsDark( 1 ) )  # is dark

                        # lightingupstart/lightingupend.
                        # daystart/dayend.

                    # This is unlikely to generate events if running using minute ticks.
                    elapsed = int(lastSend-startTime)
                    # generate events at 5 second intervals
                    if ( elapsed < self._runtimeStop ) and (( elapsed % 5 ) == 0):
                        self.sendEvent( Wb6TimeEventRunTime(elapsed) )

                    if ( elapsed < 120 ) and (( elapsed % 10 ) == 0):
                        # Every 10 seconds for 2 minutes.
                        # Need to send these for a while at startup otherwise sent before some sub systems have subscribed.
                        # TODO have this event generator subscribe to subscribe events so it can resend some of them
                        self.sendIsDark( nowSplit )

                # decide on 
                #<li>http://id.webbrick.co.uk/events/time/lightingupstart</li>
                #<li>http://id.webbrick.co.uk/events/time/lightingupend</li>
                #<li>http://id.webbrick.co.uk/events/time/daystart</li>
                #<li>http://id.webbrick.co.uk/events/time/dayend</li>
            except Exception, ex:
                _log.exception( ex )

        _log.debug( 'exit run' )