def Command(alert): if not isinstance(alert.trigger, alerttasks.VarChangeTrigger): logsupport.Logs.Log('Net Command not triggered by variable', severity=ConsoleWarning) varval = valuestore.GetVal(alert.trigger.var) valuestore.SetVal(alert.trigger.var, 0) if varval == 1: logsupport.Logs.Log('Remote restart') exitutils.Exit_Screen_Message('Remote restart requested', 'Remote Restart') config.terminationreason = 'remote restart' exitutils.Exit(exitutils.REMOTERESTART) elif varval == 2: logsupport.Logs.Log('Remote reboot') exitutils.Exit_Screen_Message('Remote reboot requested', 'Remote Reboot') config.terminationreason = 'remote reboot' exitutils.Exit(exitutils.REMOTEREBOOT) elif varval == 3: logsupport.Logs.Log('Remote download stable') maintscreen.fetch_stable() elif varval == 4: logsupport.Logs.Log('Remote download beta') maintscreen.fetch_beta() elif varval == 5: logsupport.Logs.Log('Remote set stable') subprocess.Popen('sudo rm /home/pi/usebeta', shell=True) elif varval == 6: logsupport.Logs.Log('Remote set beta') subprocess.Popen('sudo touch /home/pi/usebeta', shell=True) elif varval == 7: logsupport.Logs.Log('Remote history buffer dump') entrytime = time.strftime('%m-%d-%y %H:%M:%S') historybuffer.DumpAll('Command Dump', entrytime) elif varval == 8: logsupport.Logs.Log('Remote error indicator cleared') config.sysStore.ErrorNotice = -1 elif varval in range(100, 100 + len(debug.DbgFlags)): flg = debug.DbgFlags[varval - 100] valuestore.SetVal(('Debug', flg), True) logsupport.Logs.Log('Remote set debug ', flg) elif varval in range(200, 200 + len(debug.DbgFlags)): flg = debug.DbgFlags[varval - 200] valuestore.SetVal(('Debug', flg), False) logsupport.Logs.Log('Remote clear debug ', flg) elif varval in range(300, 310): valuestore.SetVal(('Debug', 'LogLevel'), varval - 300) logsupport.Logs.Log('Remote set LogLevel to ', varval - 300) else: logsupport.Logs.Log('Unknown remote command: ', varval)
def DoRestart(): if self.fetcher is not None and self.fetcher.is_alive(): logsupport.Logs.Log('Delaying restart until fetch completes') dly = timers.OnceTimer(10,start=True,name='RestartDelay',proc=DoDelayedRestart) ReportStatus('wait restart', hold=1) return ReportStatus('rmt restart', hold=1) exitutils.Exit_Screen_Message('Remote restart requested', 'Remote Restart') config.terminationreason = 'mqtt restart' exitutils.Exit(exitutils.REMOTERESTART)
def MainControlLoop(self, InitScreen): TimerName = 0 config.sysStore.ErrorNotice = -1 # don't pester for errors during startup threadmanager.StartThreads() config.sysStore.LogStartTime = time.time( ) # MQTT will start tracking other console errors now # so we can start broadcasting our errors logsupport.LocalOnly = False self.ScreensDict = screens.SecondaryDict.copy() self.ScreensDict.update(screens.MainDict) for a in alerttasks.AlertItems.AlertsList.values(): a.state = 'Armed' logsupport.Logs.Log("Arming " + a.type + " alert " + a.name) logsupport.Logs.Log("->" + str(a), severity=ConsoleDetail) if a.type == 'Periodic': alerttasks.SchedulePeriodicEvent(a) elif a.type == 'NodeChange': a.trigger.node.Hub.SetAlertWatch(a.trigger.node, a) if a.trigger.IsTrue(): # noinspection PyArgumentList PostEvent( ConsoleEvent(CEvent.ISYAlert, hub='DS-NodeChange', alert=a)) elif a.type == 'VarChange': a.state = 'Init' # Note: VarChange alerts don't need setup because the store has an alert proc pass elif a.type == 'Init': a.Invoke() else: logsupport.Logs.Log("Internal error - unknown alert type: ", a.type, ' for ', a.name, severity=ConsoleError, tb=False) logsupport.Logs.livelog = False # turn off logging to the screen with open("{}/.ConsoleStart".format(config.sysStore.HomeDir), "a") as f: f.write(str(time.time()) + '\n') if config.Running: # allow for a very early restart request from things like autoversion self.SwitchScreen(InitScreen, 'Bright', 'Startup', newstate='Home') statusperiod = time.time() prevstatus = '' if config.sysStore.versionname in ('development'): TempThdList = threading.Thread(target=failsafe.TempThreadList, name='ThreadLister') TempThdList.daemon = True TempThdList.start() Injector = threading.Thread(target=failsafe.NoEventInjector, name='Injector') Injector.daemon = True Injector.start() Failsafe = multiprocessing.Process(target=failsafe.MasterWatchDog, name='Failsafe') Failsafe.daemon = True Failsafe.start() config.sysStore.SetVal('Watchdog_pid', Failsafe.pid) #if config.sysStore.versionname in ('development', 'homerelease'): topper.inittop() logsupport.Logs.Log('Starting master watchdog {} for {}'.format( config.sysStore.Watchdog_pid, config.sysStore.Console_pid)) event = None pcslist = '' for pcs in ('Console', 'Watchdog', 'AsyncLogger', 'Topper'): try: if config.sysStore.GetVal(pcs + '_pid') != 0: pcslist = pcslist + '{}: {} '.format( pcs, config.sysStore.GetVal(pcs + '_pid')) except: pass logsupport.Logs.Log('Console Up: {}'.format(pcslist)) perfdump = time.time() ckperf = time.time() dayord = time.localtime().tm_yday try: while config.Running: # Operational Control Loop logsupport.maincyclecnt += 1 if logsupport.maincyclecnt == 4: logsupport.NewDay(Report=False) # ignore startup delays if dayord != time.localtime().tm_yday: dayord = time.localtime().tm_yday logsupport.NewDay(Report=True) self.HBEvents.Entry('Start event loop iteration') StackCheck = traceback.format_stack() if len(StackCheck) != 4 and config.sysStore.versionname in ( 'development', 'homerelease'): logsupport.Logs.Log('Stack growth error', severity=ConsoleWarning, hb=True) for L in StackCheck: logsupport.Logs.Log(L.strip()) if time.time() - ckperf > 900: # todo 900: ckperf = time.time() if config.sysStore.versionname in ( 'development', 'homerelease') and (logsupport.queuedepthmax > 4 or logsupport.queuetimemax > 1): logsupport.Logs.Log( 'Console performance({}): maxq: {} maxwait: {}'. format(time.time() - perfdump, logsupport.queuedepthmax, logsupport.queuetimemax), severity=ConsoleWarning, hb=True, localonly=True) logsupport.queuetimemax = 0 logsupport.queuedepthmax = 0 perfdump = time.time() if not Failsafe.is_alive(): logsupport.DevPrint('Watchdog died') logsupport.Logs.Log('Watchdog died - restarting console', severity=ConsoleError, hb=True) config.terminationreason = 'watchdog died' exitutils.Exit(exitutils.ERRORRESTART) failsafe.KeepAlive.set() nowtime = time.time() if statusperiod <= nowtime or prevstatus != config.sysStore.consolestatus: ReportStatus(config.sysStore.consolestatus) prevstatus = config.sysStore.consolestatus statusperiod = nowtime + 60 if not threadmanager.Watcher.is_alive(): logsupport.Logs.Log("Threadmanager Failure", severity=ConsoleError, tb=False) config.terminationreason = 'watcher died' exitutils.Exit(exitutils.ERRORRESTART) logsupport.LoggerQueue.put( (logsupport.Command.Touch, "{}/.ConsoleStart".format(config.sysStore.HomeDir))) if debug.dbgStore.GetVal('StatesDump'): debug.dbgStore.SetVal('StatesDump', False) for h, hub in hubs.hubs.Hubs.items(): print('States dump for hub: ', h) hub.StatesDump() debug.dbgStore.SetVal('StatesDump', False) if self.Deferrals: # an event was deferred mid screen touches - handle now event = self.Deferrals.pop(0) self.HBEvents.Entry('Got deferred event: {} {}'.format( time.time(), repr(event))) debug.debugPrint('EventList', 'Deferred Event Pop', event) elif debug.dbgStore.GetVal('QDump'): # todo QDump with new event mechanism '''if events: debug.debugPrint('QDump', 'Time: ', time.time()) for e in events: self.Deferrals.append(e) debug.debugPrint('QDump', e, e.type) else: debug.debugPrint('QDump', "Empty queue") time.sleep(0.01) event = pygame.event.Event(NOEVENT, dict={'inject':time.time(),'defer':True}) #eventfix ''' pass else: needvalidevent = True while needvalidevent: event = GetEvent() self.HBEvents.Entry('Got event: {} {}'.format( time.time(), repr(event))) if event.type == CEvent.ACTIVITYTIMER: if event.seq == self.activityseq: needvalidevent = False else: if config.sysStore.versionname == 'development': logsupport.Logs.Log( 'Outdated activity {} {}'.format( event.seq, self.activityseq)) self.HBEvents.Entry( 'outdated activity {} {}'.format( event.seq, self.activityseq)) logsupport.DevPrint( 'outdated activity {} {}'.format( event.seq, self.activityseq)) else: needvalidevent = False self.HBEvents.Entry('Process at {} {}'.format( time.time(), repr(event))) postwaittime = time.time() if event.type == CEvent.FailSafePing: self.HBEvents.Entry( 'Saw NOEVENT {} after injection at {}'.format( time.time() - event.inject, event.inject)) pass # these appear to make sure loop is running elif event.type == CEvent.MouseDown: # pygame.MOUSEBUTTONDOWN: self.HBEvents.Entry('MouseDown' + str(event.pos)) debug.debugPrint( 'Touch', 'MouseDown' + str(event.pos) + repr(event)) # screen touch events; this includes touches to non-sensitive area of screen self.SetActivityTimer(self.AS.DimTO, 'Screen touch') # refresh non-dimming in all cases including non=sensitive areas # this refresh is redundant in some cases where the touch causes other activities if self.dim == 'Dim': # wake up the screen and if in a cover state go home config.sysStore.consolestatus = 'active' if self.state == 'Cover': self.SwitchScreen(screens.HomeScreen, 'Bright', 'Wake up from cover', newstate='Home') else: self.Brighten( ) # if any other screen just brighten continue # wakeup touches are otherwise ignored # Screen was not Dim so the touch was meaningful pos = event.pos tapcount = 1 pygame.time.delay(config.sysStore.MultiTapTime) while True: eventx = GetEventNoWait() if eventx is None: break elif eventx.type == CEvent.MouseDown: self.HBEvents.Entry('Follow MouseDown: {}'.format( repr(eventx))) debug.debugPrint( 'Touch', 'Follow MouseDown' + str(event.pos) + repr(event)) tapcount += 1 pygame.time.delay(config.sysStore.MultiTapTime ) # todo make general time call? else: if eventx.type in (CEvent.MouseUp, CEvent.MouseMotion): debug.debugPrint( 'Touch', 'Other event: {}'.format(repr(eventx))) self.HBEvents.Entry('Mouse Other: {}'.format( repr(eventx))) else: self.HBEvents.Entry('Defer' + repr(eventx)) self.Deferrals.append( eventx ) # defer the event until after the clicks are sorted out # Future add handling for hold here with checking for MOUSE UP etc. if tapcount == 3: # Switch screen chains if screens.HomeScreen != screens.HomeScreen2: # only do if there is a real secondary chain if self.Chain == 0: self.Chain = 1 self.SwitchScreen(screens.HomeScreen2, 'Bright', 'Chain switch to secondary', newstate='NonHome') else: self.Chain = 0 self.SwitchScreen(screens.HomeScreen, 'Bright', 'Chain switch to main', newstate='Home') continue elif tapcount > 3: # Go to maintenance # timers.StartLongOp( # 'maintenance') # todo a bit ugly - start long op here but end in gohome in maint screen self.SwitchScreen(maintscreen.MaintScreen, 'Bright', 'Tap to maintenance', newstate='Maint') continue if self.AS.Keys is not None: for K in self.AS.Keys.values(): if K.touched(pos): K.Pressed(tapcount) for K in self.AS.NavKeys.values(): if K.touched(pos): K.Proc() # todo make a goto key elif event.type in (CEvent.MouseUp, CEvent.MouseMotion): debug.debugPrint('Touch', 'Other mouse event {}'.format(event)) # ignore for now - handle more complex gestures here if ever needed elif event.type == CEvent.ACTIVITYTIMER: # ACTIVITYTIMER: debug.debugPrint('Dispatch', 'Activity timer fired State=', self.state, '/', self.dim) if self.dim == 'Bright': self.HBEvents.Entry( 'ActivityTimer(Bright) state: {}'.format( self.state)) config.sysStore.consolestatus = 'idle' self.Dim() self.SetActivityTimer(self.AS.PersistTO, 'Go dim and wait persist') else: self.HBEvents.Entry( 'ActivityTimer(non-Bright) state: {}'.format( self.state)) if self.state == 'NonHome': self.SwitchScreen(screens.HomeScreen, 'Dim', 'Dim nonhome to dim home', newstate='Home', clear=True) elif self.state == 'Home': self.SwitchScreen(screens.DimIdleList[0], 'Dim', 'Go to cover', newstate='Cover', AsCover=True, clear=True) # rotate covers - save even if only 1 cover screens.DimIdleList = screens.DimIdleList[1:] + [ screens.DimIdleList[0] ] screens.DimIdleTimes = screens.DimIdleTimes[1:] + [ screens.DimIdleTimes[0] ] elif self.state == 'Cover': if len(screens.DimIdleList) > 1: self.SwitchScreen(screens.DimIdleList[0], 'Dim', 'Go to next cover', newstate='Cover', AsCover=True, clear=True) screens.DimIdleList = screens.DimIdleList[ 1:] + [screens.DimIdleList[0]] screens.DimIdleTimes = screens.DimIdleTimes[ 1:] + [screens.DimIdleTimes[0]] else: # Maint or Alert - just ignore the activity action # logsupport.Logs.Log('Activity timer fired while in state: {}'.format(self.state),severity=ConsoleWarning) debug.debugPrint('Dispatch', 'TO while in: ', self.state) elif event.type == CEvent.GeneralRepaint: self.HBEvents.Entry('General Repaint: {}'.format( repr(event))) debug.debugPrint('Dispatch', 'General Repaint Event', event) self.AS.ReInitDisplay() elif event.type == CEvent.HubNodeChange: self.HBEvents.Entry('Hub Change: {}'.format(repr(event))) debug.debugPrint('Dispatch', 'Hub Change Event', event) if hasattr(event, 'node'): self.AS.NodeEvent(hub=event.hub, node=event.node, value=event.value) elif hasattr(event, 'varinfo'): self.AS.NodeEvent(hub=event.hub, varinfo=event.varinfo) else: debug.debugPrint('Dispatch', 'Bad Node Change Event: ', event) logsupport.Logs.Log('Bad Node Change Event ', event, severity=ConsoleWarning) elif event.type in (CEvent.ISYVar, CEvent.ISYAlert): self.HBEvents.Entry('Var or Alert' + repr(event)) evtype = 'variable' if event.type == CEvent.ISYVar else 'node' debug.debugPrint('Dispatch', 'ISY ', evtype, ' change', event) alert = event.alert if alert.state in ('Armed', 'Init'): if alert.trigger.IsTrue(): # alert condition holds if alert.trigger.delay != 0: # delay invocation alert.state = 'Delayed' debug.debugPrint('Dispatch', "Post with delay:", alert.name, alert.trigger.delay) TimerName += 1 alert.timer = timers.OnceTimer( alert.trigger.delay, start=True, name='MainLoop' + str(TimerName), proc=alerttasks.HandleDeferredAlert, param=alert) else: # invoke now alert.state = 'FiredNoDelay' debug.debugPrint('Dispatch', "Invoke: ", alert.name) alert.Invoke( ) # either calls a proc or enters a screen and adjusts alert state appropriately else: if alert.state == 'Armed': # condition cleared after alert rearmed - timing in the queue? logsupport.Logs.Log( 'Anomolous Trigger clearing while armed: ', repr(alert), severity=ConsoleDetail, hb=True) else: alert.state = 'Armed' logsupport.Logs.Log( 'Initial var value for trigger is benign: ', repr(alert), severity=ConsoleDetail) elif alert.state == 'Active' and not alert.trigger.IsTrue( ): # alert condition has cleared and screen is up debug.debugPrint('Dispatch', 'Active alert cleared', alert.name) alert.state = 'Armed' # just rearm the alert self.SwitchScreen(screens.HomeScreen, 'Dim', 'Cleared alert', newstate='Home') elif ((alert.state == 'Delayed') or (alert.state == 'Deferred')) and not alert.trigger.IsTrue(): # condition changed under a pending action (screen or proc) so just cancel and rearm if alert.timer is not None: alert.timer.cancel() alert.timer = None else: logsupport.DevPrint( 'Clear with no timer?? {}'.format(repr(alert))) debug.debugPrint( 'Dispatch', 'Delayed event cleared before invoke', alert.name) alert.state = 'Armed' # todo - verify this is correct. Issue is that the alert might have gotten here from a delay or from the # alert screen deferring. The screen uses it's own id for this alert to might be either. Probably should # distinguish based on if delay or defer but doing both should be same id(alert.actiontarget)) originally this was id-alert for some # reason I changed it to id-actiontarget don't know why but it was done while adding HASS this screwed up clearing deferred alerts # so switched it back in hopes to remember why the change todo else: logsupport.Logs.Log( "Anomolous change situation State: ", alert.state, " Alert: ", repr(alert), " Trigger IsTue: ", alert.trigger.IsTrue(), severity=ConsoleWarning, hb=True) debug.debugPrint('Dispatch', 'ISYVar/ISYAlert passing: ', alert.state, alert.trigger.IsTrue(), event, alert) # Armed and false: irrelevant report # Active and true: extaneous report # Delayed or deferred and true: redundant report elif event.type == CEvent.SchedEvent: self.HBEvents.Entry('Sched event {}'.format(repr(event))) eventnow = time.time() diff = eventnow - event.TargetTime if abs(diff) > controlevents.latencynotification: logsupport.Logs.Log( 'Timer late by {} seconds. Event: {}'.format( diff, repr(event)), severity=ConsoleWarning, hb=True, localonly=True, homeonly=True) self.HBEvents.Entry( 'Event late by {} target: {} now: {}'.format( diff, event.TargetTime, eventnow)) event.proc(event) elif event.type == CEvent.RunProc: self.HBEvents.Entry('Run procedure {}'.format(event.name)) event.proc() else: logsupport.Logs.Log("Unknown main event {}".format( repr(event)), severity=ConsoleError, hb=True, tb=False) if time.time( ) - postwaittime > controlevents.latencynotification and not timers.LongOpInProgress: # this loop took a long time logsupport.Logs.Log( "Slow loop at {} took {} for {}".format( time.time(), time.time() - postwaittime, event), severity=ConsoleWarning, hb=True, localonly=True, homeonly=True) self.HBEvents.Entry( 'End Event Loop took: {}'.format(time.time() - postwaittime)) except Exception as E: logsupport.Logs.Log('Main display loop had exception: {}'.format( repr(E))) traceback.print_exc() config.ecode = exitutils.ERRORRESTART print('Display Screen Exception: {}'.format(repr(E))) logsupport.Logs.Log('Main GUI loop exiting')
del ParsedConfigFile[i] for hubtyp, pkg in hubs.hubs.hubtypes.items(): if stype == hubtyp: # noinspection PyBroadException try: hubs.hubs.Hubs[i] = pkg(i, v.get('address', ''), v.get('user', ''), v.get('password', '')) except BaseException as e: logsupport.Logs.Log( "Fatal console error - fix config file: ", e, severity=ConsoleError, tb=False) exitutils.Exit( exitutils.ERRORDIE, immediate=True) # shutdown and don't try restart del ParsedConfigFile[i] from stores import genericweatherstore for i, v in ParsedConfigFile.items(): if isinstance(v, Section): # noinspection PyArgumentList stype = v.get('type', '', delkey=False) #todo check no type param loccode = '*unset*' for wptyp, info in WeathProvs.items(): if stype == wptyp: try: desc = i loccode = v.get('location', desc)
def ForceRestart(): logsupport.Logs.Log('Autoversion Restart Event') config.terminationreason = 'autoversion' exitutils.Exit(exitutils.AUTORESTART)
def AlertProc1(self, alert): logsupport.DevPrint("---------------------VC invocation" + str(self.ct1) + str(alert) + str(id(alert))) logsupport.Logs.Log('Alert proc test exiting') logsupport.Logs.Log('Restart for new version') exitutils.Exit(66)