def BumpTemp(self, setpoint, degrees): debugprint(config.dbgscreenbuild, "Bump temp: ", setpoint, degrees) debugprint(config.dbgscreenbuild, "New: ", self.info[setpoint][0] + degrees) r = config.ISYrequestsession.get( config.ISYprefix + 'nodes/' + self.RealObj.address + '/set/' + setpoint + '/' + str( self.info[setpoint][0] + degrees))
def __init__(self, screensection, screenname): debugprint(config.dbgscreenbuild, "New WeatherScreenDesc ", screenname) screen.ScreenDesc.__init__(self, screensection, screenname, (('which', ('', )), )) utilities.LocalizeParams(self, screensection, WunderKey='', location='') self.scrlabel = screen.FlatenScreenLabel(self.label) # entries are (fontsize, centered, formatstring, values) self.conditions = [ (2, True, "{d}", self.scrlabel), (1, True, "{d[0]}", ('Location', )), (1, False, u"Now: {d[0]} {d[1]}\u00B0F", ('Sky', 'Temp')), (0, False, u" Feels like: {d[0]}\u00B0", ('Feels', )), (1, False, "Wind {d[0]}", ('WindStr', )), (1, False, "Sunrise: {d[0]:02d}:{d[1]:02d}", ('SunriseH', 'SunriseM')), (1, False, "Sunset: {d[0]:02d}:{d[1]:02d}", ('SunsetH', 'SunsetM')), (0, False, "Moon rise: {d[0]} set: {d[1]}", ('Moonrise', 'Moonset')), (0, False, " {d[0]}% illuminated", ('MoonPct', )), (0, False, "will be replaced", "") ] self.forecast = [ (1, False, u"{d[0]} {d[1]}\u00B0/{d[2]}\u00B0 {d[3]}", ('Day', 'High', 'Low', 'Sky')), (1, False, "Wind: {d[0]} at {d[1]}", ('WindDir', 'WindSpd')) ] self.Info = weatherinfo.WeatherInfo(self.WunderKey, self.location) utilities.register_example("WeatherScreenDesc", self)
def SendCommand(self, state, fast): selcmd = (('DOF', 'DFOF'), ('DON', 'DFON')) config.debugprint(ISYdebug, "OnOff sent: ", selcmd[state][fast], ' to ', self.name) url = 'http://' + config.ISYaddr + '/rest/nodes/' + self.address + '/cmd/' + selcmd[ state][fast] r = config.ISYrequestsession.get(url) return r
def event_feed(*arg): data = arg[0] if config.seq <> int(data["Event-seqnum"]): config.fromDaemon.put( ("Log", "Event mismatch - Expected: " + str(config.seq) + " Got: " + str(data["Event-seqnum"]), ConsoleWarning)) config.seq = int(data["Event-seqnum"]) + 1 else: config.seq += 1 if config.streamid <> data["Event-sid"]: config.fromDaemon.put( ("Log", "Now using event stream: " + str(data["Event-sid"]), ConsoleWarning)) config.streamid = data["Event-sid"] if time.time() < config.watchstarttime + 10: debugprint(config.dbgdaemon, time.time(), "Skipping item in stream: ", data["Event-seqnum"], ":", data["control"], " : ", data["node"], " : ", data["eventInfo"], " : ", data["action"]) return None while not config.toDaemon.empty(): msg = config.toDaemon.get() if len(msg) == 0: config.watchlist = ["empty"] else: config.watchlist = msg debugprint(config.dbgdaemon, time.time(), "New watchlist: ", config.watchlist) data = arg[0] # data["Event-seqnum"],":",prcode," : ",data["node"]," : ",data["eventInfo"]," : ",data["action"]," : ",data["Event-sid"]) eventcode = data["control"] if eventcode in EVENT_CTRL: prcode = EVENT_CTRL[eventcode] # print "Orig EC", eventcode, prcode else: prcode = "**" + eventcode + "**" # print "Ugly EC", eventcode, prcode if (prcode == "Status" or config.watchlist[0] == "") and data["node"] in config.watchlist: debugprint(config.dbgdaemon, time.time(), "Status update in stream: ", data["Event-seqnum"], ":", prcode, " : ", data["node"], " : ", data["eventInfo"], " : ", data["action"]) config.fromDaemon.put(("Node", data["node"], data["action"])) debugprint(config.dbgdaemon, "Qsize at daemon ", config.fromDaemon.qsize()) else: debugprint(config.dbgdaemon, time.time(), "Other update in stream: ", data["Event-seqnum"], ":", prcode, " : ", data["node"], " : ", data["eventInfo"], " : ", data["action"])
def __init__(self, screensection, screenname): debugprint(config.dbgscreenbuild, "Build Clock Screen") screen.ScreenDesc.__init__(self, screensection, screenname) utilities.LocalizeParams(self, screensection, CharSize=[20], Font='droidsansmono', OutFormat=[]) for i in range(len(self.CharSize), len(self.OutFormat)): self.CharSize.append(self.CharSize[-1]) utilities.register_example("ClockScreen", self)
def Watcher(): config.watchstarttime = time.time() config.watchlist = ['init'] debugprint(config.dbgdaemon, "Watcher: ", config.watchstarttime, os.getpid()) server = ISYEvent() server.subscribe(addr=config.ISYaddr, userl=config.ISYuser, userp=config.ISYpassword) server.set_process_func(event_feed, "") server.events_loop()
def __init__(self, screensection, screenname): debugprint(config.dbgscreenbuild, "Build House Status Screen") screen.ScreenDesc.__init__(self, screensection, screenname, ()) # no extra cmd keys utilities.LocalizeParams(self, screensection, NormalOn=[], NormalOff=[]) checklist = [ nm for nm in config.ISY.NodesByName if ((nm in self.NormalOn) or (nm in self.NormalOff)) ] # addr -> name utilities.register_example("HouseStatusScreenDesc", self)
def __init__(self, screensection, screenname): debugprint(config.dbgscreenbuild, "New KeyScreenDesc ", screenname) screen.BaseKeyScreenDesc.__init__(self, screensection, screenname) self.subscriptionlist = {} # Build the Key objects for keyname in screensection: if isinstance(screensection[keyname], Section): NewKey = keydesc.KeyDesc(screensection[keyname], keyname) self.keysbyord.append(NewKey) self.LayoutKeys() utilities.register_example("KeyScreenDesc", self)
def __init__(self, screensection, screenname): debugprint(config.dbgscreenbuild, "New ThermostatScreenDesc ", screenname) screen.BaseKeyScreenDesc.__init__(self, screensection, screenname) utilities.LocalizeParams(self, screensection, 'KeyColor', 'KeyOffOutlineColor', 'KeyOnOutlineColor') self.info = {} self.fsize = (30, 50, 80, 160) if screenname in config.ISY.NodesByName: self.RealObj = config.ISY.NodesByName[screenname] else: self.RealObj = None config.Logs.Log("No Thermostat: " + screenname, severity=logsupport.ConsoleWarning) self.TitleRen = config.fonts.Font(self.fsize[1]).render(screen.FlatenScreenLabel(self.label), 0, wc(self.CharColor)) self.TitlePos = ((config.screenwidth - self.TitleRen.get_width())/2, config.topborder) self.TempPos = config.topborder + self.TitleRen.get_height() self.StatePos = self.TempPos + config.fonts.Font(self.fsize[3]).get_linesize() - scaleH(20) self.SPPos = self.StatePos + scaleH(25) self.AdjButSurf = pygame.Surface((config.screenwidth, scaleH(40))) self.AdjButTops = self.SPPos + config.fonts.Font(self.fsize[2]).get_linesize() - scaleH(5) centerspacing = config.screenwidth/5 self.AdjButSurf.fill(wc(self.BackgroundColor)) arrowsize = scaleH(40) # pixel for i in range(4): gfxdraw.filled_trigon(self.AdjButSurf, *trifromtop(centerspacing, arrowsize/2, i + 1, arrowsize, wc(("red", "blue", "red", "blue")[i]), i%2 <> 0)) self.keysbyord.append(toucharea.TouchPoint((centerspacing*(i + 1), self.AdjButTops + arrowsize/2), (arrowsize*1.2, arrowsize*1.2))) self.ModeButPos = self.AdjButTops + scaleH(85) # pixel bsize = (scaleW(100), scaleH(50)) # pixel self.keysbyord.append(toucharea.ManualKeyDesc("Mode", ["Mode"], self.KeyColor, self.CharColor, self.CharColor, center=(config.screenwidth/4, self.ModeButPos), size=bsize, KOn=config.KeyOffOutlineColor)) # todo clean up self.keysbyord.append(toucharea.ManualKeyDesc("Fan", ["Fan"], self.KeyColor, self.CharColor, self.CharColor, center=(3*config.screenwidth/4, self.ModeButPos), size=bsize, KOn=config.KeyOffOutlineColor)) self.keysbyord[4].FinishKey((0,0),(0,0)) self.keysbyord[5].FinishKey((0,0),(0,0)) self.ModesPos = self.ModeButPos + bsize[1]/2 + scaleH(5) utilities.register_example("ThermostatScreenDesc", self)
def HandleScreen(self, newscr=True): # stop any watching for device stream config.toDaemon.put(["", self.RealObj.address]) self.ShowScreen() while 1: choice = config.DS.NewWaitPress(self) if choice[0] == WAITEXIT: return choice[1] elif (choice[0] == WAITNORMALBUTTON) or (choice[0] == WAITNORMALBUTTONFAST): if choice[1] < 4: self.BumpTemp(('CLISPH', 'CLISPH', 'CLISPC', 'CLISPC')[choice[1]], (2, -2, 2, -2)[choice[1]]) else: self.BumpMode(('CLIMD', 'CLIFS')[choice[1] - 4], (range(8), (7, 8))[choice[1] - 4]) elif choice[0] == WAITISYCHANGE: debugprint(config.dbgscreenbuild, "Thermo change", choice) self.ShowScreen()
def __init__(self, keys): debugprint(config.dbgscreenbuild, "Build Maintenance Screen") screen.BaseKeyScreenDesc.__init__(self, fixedoverrides, 'Maint', withnav=False) utilities.LocalizeParams(self, None, TitleFontSize=40, SubFontSize=25) self.keysbyord = [] for k, kt in keys.iteritems(): self.keysbyord.append( toucharea.ManualKeyDesc(k, [kt[0]], 'gold', 'black', 'black', KOn='black', KOff='black', proc=kt[1])) topoff = self.TitleFontSize + self.SubFontSize self.LayoutKeys(topoff, config.screenheight - 2 * config.topborder - topoff) utilities.register_example("MaintScreenDesc", self)
def BumpMode(self, mode, vals): debugprint(config.dbgscreenbuild, "Bump mode: ", mode, vals) cv = vals.index(self.info[mode][0]) debugprint(config.dbgscreenbuild, cv, vals[cv]) cv = (cv + 1)%len(vals) debugprint(config.dbgscreenbuild, "new cv: ", cv) r = config.ISYrequestsession.get( config.ISYprefix + 'nodes/' + self.RealObj.address + '/set/' + mode + '/' + str(vals[cv]))
def __init__(self, screensection, screenname): debugprint(config.dbgscreenbuild, "New TimeTempDesc ", screenname) screen.ScreenDesc.__init__(self, screensection, screenname) utilities.LocalizeParams(self, screensection, WunderKey='', location='', CharSize=[20], Font='droidsansmono', TimeFormat=[], ConditionFields=[], ConditionFormat=[], ForecastFields=[], ForecastFormat=[], ForecastDays=1) self.scrlabel = screen.FlatenScreenLabel(self.label) self.WInfo = weatherinfo.WeatherInfo(self.WunderKey, self.location) for i in range( len(self.CharSize), len(self.TimeFormat) + len(self.ConditionFormat) + len(self.ForecastFormat)): self.CharSize.append(self.CharSize[-1])
def ShowScreen(self): self.PaintBase() r = config.ISYrequestsession.get('http://' + config.ISYaddr + '/rest/nodes/' + self.RealObj.address, verify=False) tstatdict = xmltodict.parse(r.text) props = tstatdict["nodeInfo"]["properties"]["property"] self.info = {} for item in props: debugprint(config.dbgscreenbuild, item["@id"], ":", item["@value"], ":", item["@formatted"]) self.info[item["@id"]] = (int(item['@value']), item['@formatted']) config.screen.blit(self.TitleRen, self.TitlePos) r = config.fonts.Font(self.fsize[3], bold=True).render(u"{:4.1f}".format(self.info["ST"][0]/2), 0, wc(self.CharColor)) config.screen.blit(r, ((config.screenwidth - r.get_width())/2, self.TempPos)) if isinstance(self.info["CLIHCS"][0], int): r = config.fonts.Font(self.fsize[0]).render(("Idle", "Heating", "Cooling")[self.info["CLIHCS"][0]], 0, wc(self.CharColor)) else: r = config.fonts.Font(self.fsize[0]).render("n/a", 0, wc(self.CharColor)) config.screen.blit(r, ((config.screenwidth - r.get_width())/2, self.StatePos)) r = config.fonts.Font(self.fsize[2]).render( "{:2d} {:2d}".format(self.info["CLISPH"][0]/2, self.info["CLISPC"][0]/2), 0, wc(self.CharColor)) config.screen.blit(r, ((config.screenwidth - r.get_width())/2, self.SPPos)) config.screen.blit(self.AdjButSurf, (0, self.AdjButTops)) self.keysbyord[4].PaintKey() self.keysbyord[5].PaintKey() r1 = config.fonts.Font(self.fsize[1]).render( ('Off', 'Heat', 'Cool', 'Auto', 'Fan', 'Prog Auto', 'Prog Heat', 'Prog Cool')[self.info["CLIMD"][0]], 0, wc(self.CharColor)) r2 = config.fonts.Font(self.fsize[1]).render(('On', 'Auto')[self.info["CLIFS"][0] - 7], 0, wc(self.CharColor)) config.screen.blit(r1, (self.keysbyord[4].Center[0] - r1.get_width()/2, self.ModesPos)) config.screen.blit(r2, (self.keysbyord[5].Center[0] - r2.get_width()/2, self.ModesPos)) pygame.display.update()
def NewWaitPress(self, ActiveScreen, callbackint=0, callbackproc=None, callbackcount=0): self.AS = ActiveScreen cycle = 0 if callbackint <> 0: # todo needs a better structural fix for posted actions that persist across Waitpress calls pygame.time.set_timer(self.INTERVALHIT.type, int(callbackint * 1000)) cycle = callbackcount if callbackcount <> 0 else 100000000 # essentially infinite if self.isDim and self.AS == config.DimHomeScreenCover: pygame.time.set_timer( self.GOHOMEHIT.type, 0) # in final quiet state so cancel gohome until a touch else: pygame.time.set_timer( self.MAXTIMEHIT.type, self.AS.DimTO * 1000) # if not in final quiet state set dim timer while True: rtn = (0, 0) event = pygame.fastevent.poll() if event.type == pygame.NOEVENT: time.sleep(.01) pass elif event.type == pygame.MOUSEBUTTONDOWN: pos = (pygame.mouse.get_pos()[0], pygame.mouse.get_pos()[1]) # if self.presscount < 10: # this is debug code for a weird/unreproducible RPi behavior where touch is off # print pos # self.presscount += 1 tapcount = 1 pygame.time.delay(config.MultiTapTime) while True: eventx = pygame.fastevent.poll() if eventx.type == pygame.NOEVENT: break elif eventx.type == pygame.MOUSEBUTTONDOWN: tapcount += 1 pygame.time.delay(config.MultiTapTime) else: continue if tapcount > 2: self.GoDim(False) rtn = (WAITEXIT, tapcount) break # on any touch reset return to home screen pygame.time.set_timer(self.GOHOMEHIT.type, int(config.HomeScreenTO) * 1000) # on any touch restart dim timer and reset to bright if dim pygame.time.set_timer(self.MAXTIMEHIT.type, self.AS.DimTO * 1000) dimscr = self.GoDim(False) if dimscr is not None: rtn = (WAITEXIT, config.HomeScreen) break for i in range(len(self.AS.keysbyord)): K = self.AS.keysbyord[i] if toucharea.InBut(pos, K): if tapcount == 1: rtn = (WAITNORMALBUTTON, i) else: rtn = (WAITNORMALBUTTONFAST, i) if self.AS.PrevScreen is not None: if toucharea.InBut(pos, self.AS.PrevScreenKey): rtn = (WAITEXIT, self.AS.PrevScreen) elif toucharea.InBut(pos, self.AS.NextScreenKey): rtn = (WAITEXIT, self.AS.NextScreen) for K in self.AS.ExtraCmdKeys: if toucharea.InBut(pos, K): rtn = (WAITEXTRACONTROLBUTTON, K.name) if rtn[0] <> 0: break continue elif event.type == self.MAXTIMEHIT.type: dimscr = self.GoDim(True) if dimscr is not None: rtn = (WAITEXIT, dimscr) break continue elif event.type == self.INTERVALHIT.type: if (callbackproc is not None) and (cycle > 0): callbackproc(cycle) cycle -= 1 continue elif event.type == self.GOHOMEHIT.type: rtn = (WAITEXIT, config.HomeScreen) break else: pass # ignore and flush other events if (not config.fromDaemon.empty()) and ( cycle == 0): # todo don't process daemon reports while cycling debugprint(config.dbgMain, "Q size at main loop ", config.fromDaemon.qsize()) item = config.fromDaemon.get() debugprint(config.dbgMain, time.time(), "ISY reports change: ", "Key: ", str(item)) if item[0] == "Log": config.Logs.Log(item[1], severity=item[2]) continue elif item[0] == "Node": rtn = (WAITISYCHANGE, (item[1], item[2])) break else: config.Logs.Log("Bad msg from watcher: " + str(item), Severity=ConsoleWarning) pygame.time.set_timer(self.INTERVALHIT.type, 0) pygame.time.set_timer(self.MAXTIMEHIT.type, 0) return rtn
def runThen(self): config.debugprint(ISYdebug, "runThen sent to ", self.name) url = config.ISYprefix + 'programs/' + self.address + '/runThen' r = config.ISYrequestsession.get(url) return r
def __init__(self, keysection, keyname): debugprint(config.dbgscreenbuild, " New Key Desc ", keyname) toucharea.ManualKeyDesc.__init__(self, keysection, keyname) utilities.LocalizeParams(self, keysection, SceneProxy='', KeyRunThenName='', type='ONOFF') self.MonitorObj = None # ISY Object monitored to reflect state in the key (generally a device within a Scene) # for ONOFF keys (and others later) map the real and monitored nodes in the ISY # map the key to a scene or device - prefer to map to a scene so check that first # Obj is the representation of the ISY Object itself, addr is the address of the ISY device/scene if self.type in ('ONOFF'): if keyname in config.ISY.ScenesByName: self.RealObj = config.ISY.ScenesByName[keyname] if self.SceneProxy <> '': # explicit proxy assigned if self.SceneProxy in config.ISY.NodesByAddr: # address given self.MonitorObj = config.ISY.NodesByAddr[ self.SceneProxy] elif self.SceneProxy in config.ISY.NodesByName: self.MonitorObj = config.ISY.NodesByName[ self.SceneProxy] else: config.Logs.Log('Bad explicit scene proxy:' + self.name, severity=ConsoleWarning) else: for i in self.RealObj.members: device = i[1] if device.enabled and device.hasstatus: self.MonitorObj = device break else: config.Logs.Log( 'Skipping disabled/nonstatus device: ' + device.name, severity=ConsoleWarning) if self.MonitorObj is None: config.Logs.Log("No proxy for scene: " + keyname, severity=ConsoleError) #debugprint(config.dbgscreenbuild, "Scene ", keyname, " default proxying with ", # self.MonitorObj.name) elif keyname in config.ISY.NodesByName: self.RealObj = config.ISY.NodesByName[keyname] self.MonitorObj = self.RealObj else: debugprint(config.dbgscreenbuild, "Screen", keyname, "unbound") config.Logs.Log('Key Binding missing: ' + self.name, severity=ConsoleWarning) elif self.type in ("ONBLINKRUNTHEN"): self.State = False try: self.RealObj = config.ISY.ProgramsByName[self.KeyRunThenName] except: self.RealObj = None debugprint(config.dbgscreenbuild, "Unbound program key: ", self.label) config.Logs.Log("Missing Prog binding: " + self.name, severity=ConsoleWarning) else: debugprint(config.dbgscreenbuild, "Unknown key type: ", self.label) config.Logs.Log("Bad keytype: " + self.name, severity=ConsoleWarning) utilities.register_example("KeyDesc", self) debugprint(config.dbgscreenbuild, repr(self))
def __init__(self): thisconfig = config.ParsedConfigFile debugprint(config.dbgscreenbuild, "Process Configuration File") mainlist = {} secondlist = {} extralist = {} for screenitem in thisconfig: NewScreen = None if isinstance(thisconfig[screenitem], Section): thisScreen = thisconfig[screenitem] # its a screen tempscreentype = thisScreen.get("type", "unspec") debugprint(config.dbgscreenbuild, "Screen of type ", tempscreentype) if tempscreentype in config.screentypes: NewScreen = config.screentypes[tempscreentype](thisScreen, screenitem) config.Logs.Log(tempscreentype + " screen " + screenitem) else: config.Logs.Log("Screentype error" + screenitem + " type " + tempscreentype, severity=ConsoleWarning) pass if NewScreen is not None: # set the standard navigation keys and navigation linkages if NewScreen.name in config.MainChain: mainlist[NewScreen.name] = NewScreen elif NewScreen.name in config.SecondaryChain: secondlist[NewScreen.name] = NewScreen else: extralist[NewScreen.name] = NewScreen config.ExtraChain.append(NewScreen.name) if len(secondlist) == 0: secondlist = extralist config.SecondaryChain = config.ExtraChain config.ExtraChain = [] config.Logs.Log("Main Screen List:") for scr in config.MainChain: if not scr in mainlist: config.Logs.Log("-- Undefined Screen:", scr, severity=ConsoleWarning) config.MainChain.remove(scr) for scr in config.MainChain: if scr in mainlist: S = mainlist[scr] S.PrevScreen = mainlist[config.MainChain[ config.MainChain.index(scr) - 1]] S.NextScreen = mainlist[config.MainChain[ (config.MainChain.index(scr) + 1) % len(config.MainChain)]] config.Logs.Log("---" + scr) config.Logs.Log("Secondary Screen List:") for scr in config.SecondaryChain: if not scr in secondlist: config.Logs.Log("-- Undefined Screen:", scr, severity=ConsoleWarning) config.SecondaryChain.remove(scr) for scr in config.SecondaryChain: if scr in secondlist: S = secondlist[scr] S.PrevScreen = secondlist[config.SecondaryChain[ config.SecondaryChain.index(scr) - 1]] S.NextScreen = secondlist[config.SecondaryChain[ (config.SecondaryChain.index(scr) + 1) % len(config.SecondaryChain)]] config.Logs.Log("---" + scr) config.Logs.Log("Not on a screen list (unavailable)", severity=ConsoleWarning) for scr in config.ExtraChain: config.Logs.Log("---" + scr, severity=ConsoleWarning) for S in mainlist.itervalues(): S.FinishScreen() for S in secondlist.itervalues(): S.FinishScreen() if config.HomeScreenName in config.MainChain: config.HomeScreen = mainlist[config.HomeScreenName] else: config.Logs.Log("Error in Home Screen Name", severity=ConsoleWarning) config.HomeScreen = mainlist[config.MainChain[0]] config.HomeScreen2 = secondlist[config.SecondaryChain[0]] config.Logs.Log("Home Screen: " + config.HomeScreen.name) if config.DimHomeScreenCoverName in config.MainChain: # todo why must it be on MainChain? config.DimHomeScreenCover = mainlist[config.DimHomeScreenCoverName] config.Logs.Log("Dim Home Screen: " + config.DimHomeScreenCover.name) else: config.DimHomeScreenCover = config.HomeScreen config.Logs.Log("No Dim Home Screen Cover Set") config.Logs.Log("First Secondary Screen: " + config.HomeScreen2.name)
config.Logs.Log("Enumerated ISY Structure") """ Build the ISY object structure and connect the configured screens to it """ configobjects.MyScreens() config.Logs.Log("Linked config to ISY") """ Set up the watcher daemon and its communications """ config.toDaemon = Queue(300) config.fromDaemon = Queue(300) p = Process(target=watchdaemon.Watcher, name="Watcher") p.daemon = True p.start() config.DaemonProcess = p debugprint(config.dbgMain, "Spawned watcher as: ", p.pid) config.Logs.Log("Watcher pid: " + str(p.pid)) config.Logs.livelog = False # turn off logging to the screen and give user a moment to scan time.sleep(2) # config.backlight.ChangeDutyCycle(config.BrightLevel) """ Set up the Maintenance Screen """ config.Logs.Log("Built Maintenance Screen") maintscreen.SetUpMaintScreens() """ Dump documentation """ utilities.DumpDocumentation()
def HandleScreen(self, newscr=True): def BlinkKey(scr, key, cycle): # thistime = finalstate if cycle % 2 <> 0 else not finalstate key.State = not key.State key.PaintKey() if newscr: # key screen change actually occurred self.PaintBase() self.subscriptionlist = {} debugprint(config.dbgMain, "Switching to screen: ", self.name) for K in self.keysbyord: if K.MonitorObj is not None: # skip program buttons self.subscriptionlist[K.MonitorObj.address] = K states = isy.get_real_time_status(self.subscriptionlist.keys()) for K in self.keysbyord: if K.MonitorObj is not None: K.State = not (states[K.MonitorObj.address] == 0 ) # K is off (false) only if state is 0 debugprint(config.dbgMain, "Active Subscription List will be:") addressestoscanfor = ["Status"] for i in self.subscriptionlist: debugprint(config.dbgMain, " Subscribe: ", i, self.subscriptionlist[i].name, " : ", self.subscriptionlist[i].RealObj.name, ' via ', self.subscriptionlist[i].MonitorObj.name) addressestoscanfor.append(i) config.toDaemon.put(addressestoscanfor) self.PaintKeys() else: debugprint(config.dbgMain, "Skipping screen recreation: ", self.name) blinkproc = None blinktime = 0 blinks = 0 while 1: choice = config.DS.NewWaitPress(self, callbackint=blinktime, callbackproc=blinkproc, callbackcount=blinks) blinkproc = None blinktime = 0 blinks = 0 if (choice[0] == WAITNORMALBUTTON) or (choice[0] == WAITNORMALBUTTONFAST): # handle various keytype cases K = self.keysbyord[choice[1]] if K.type == "ONOFF": K.State = not K.State if K.RealObj is not None: K.RealObj.SendCommand(K.State, choice[0] <> WAITNORMALBUTTON) # config.Logs.Log("Sent command to " + K.RealObj.name) else: config.Logs.Log("Screen: " + self.name + " press unbound key: " + K.name, severity=logsupport.ConsoleWarning) K.PaintKey() elif K.type == "ONBLINKRUNTHEN": # force double tap for programs for safety - too easy to accidentally single tap with touchscreen if choice[0] == WAITNORMALBUTTONFAST: K.RealObj.runThen() blinkproc = functools.partial(BlinkKey, config.screen, K) blinktime = .5 blinks = 8 # even number leaves final state of key same as initial state K.PaintKey() # leave K.State as is - key will return to off at end elif K.type == "ONOFFRUN": pass elif choice[0] == WAITEXIT: return choice[1] elif choice[0] == WAITISYCHANGE: K = self.subscriptionlist[choice[1][0]] ActState = int(choice[1][1]) <> 0 if ActState <> K.State: K.State = ActState K.PaintKey()