def updateCheck (self, onlyNewer = False, force = True): return try: try: if self.pluginUrl == "": if force: indigo.server.log ("This plugin currently does not check for newer versions", isError = True) return except: # Normal if pluginUrl hasn't been defined if force: indigo.server.log ("This plugin currently does not check for newer versions", isError = True) return d = indigo.server.getTime() if eps.valueValid (self.pluginPrefs, "latestVersion") == False: self.pluginPrefs["latestVersion"] = False if force == False and eps.valueValid (self.pluginPrefs, "lastUpdateCheck", True): last = datetime.datetime.strptime (self.pluginPrefs["lastUpdateCheck"], "%Y-%m-%d %H:%M:%S") lastCheck = dtutil.DateDiff ("hours", d, last) if self.pluginPrefs["latestVersion"]: if lastCheck < 72: return # if last check has us at the latest then only check once every 3 days else: if lastCheck < 2: return # only check every four hours in case they don't see it in the log self.debugLog("Checking for updates") page = urllib2.urlopen(self.pluginUrl) soup = BeautifulSoup(page) versions = soup.find(string=re.compile("\#Version\|")) versionData = unicode(versions) versionInfo = versionData.split("#Version|") newVersion = float(versionInfo[1][:-1]) if newVersion > float(self.pluginVersion): self.pluginPrefs["latestVersion"] = False indigo.server.log ("Version %s of %s is available, you are currently using %s." % (str(round(newVersion,2)), self.pluginDisplayName, str(round(float(self.pluginVersion), 2))), isError=True) else: self.pluginPrefs["latestVersion"] = True if onlyNewer == False: indigo.server.log("%s version %s is the most current version of the plugin" % (self.pluginDisplayName, str(round(float(self.pluginVersion), 2)))) self.pluginPrefs["lastUpdateCheck"] = d.strftime("%Y-%m-%d %H:%M:%S") except Exception as e: eps.printException(e)
def sendCharacter_Sprinkler (self, dev, devAction): try: cache = dev.states["keyCache"] + devAction.props["key"] # Catch special phrases so we don't error out for i in range (1, 9): deviceNum = 0 zoneNum = 0 if cache.lower() == "#dev" + str(i): deviceNum = i if cache.lower() == "#zone" + str(i): deviceNum = i if deviceNum <> 0: self.setSprinklerDevice (dev, deviceNum) return if zoneNum <> 0: for y in range (1, 9): if y != i: dev.updateStateOnServer ("onZone" + str(i), False) dev.updateStateOnServer ("onZone" + str(i), True) self.setStatusMessage (dev, "zone" + str(i) + "SelectedUI") return # If we got here then we got an entry, determine if it's for a device, a zone or a duration isDevice = True for i in range (1, 4): if dev.states["onDevice" + str(i)]: isDevice = False break # If no device then our entry is a device selection if isDevice: self.debugLog("No device is currently active, setting device") if int(cache) > 3: cache = "3" # can't select more than device 3 self.setSprinklerDevice (dev, int(cache)) return if eps.valueValid (dev.pluginProps, "device2", True) == False and eps.valueValid (dev.pluginProps, "device3", True) == False: # If only a single device then we need to set the timeout for two minutes like when we select a device self.setDeviceTimeout(dev, 120) # Since when we select a device it automatically selects zone 1 it's a duration ui = cache dev.updateStateOnServer ("keyCache", cache, uiValue=ui) except Exception as e: eps.printException(e)
def validateDeviceConfigUi(self, valuesDict, typeId, devId): try: dev = indigo.devices[devId] self.logger.debug(u"%s is validating device configuration UI" % dev.name) if len(valuesDict["devicelist"]) == 0: errorDict = indigo.Dict() errorDict["devicelist"] = "You must select at least one device" errorDict["showAlertText"] = "You must select at least one device for this plugin to work!" return (False, valuesDict, errorDict) # Make sure they aren't choosing a device that is already on another auto off device for deviceId in valuesDict["devicelist"]: for dev in indigo.devices.iter(self.pluginId): if str(dev.id) != str(devId): if eps.valueValid (dev.pluginProps, "devicelist", True): for d in dev.pluginProps["devicelist"]: if d == deviceId and valuesDict["allowSave"] == False: errorDict = indigo.Dict() errorDict["devicelist"] = "One or more devices are already managed by other Powermiser auto-off devices" errorDict["showAlertText"] = "You are already managing %s in another Powermiser auto-off device, the conditions could overlap and cause problems.\n\nBe sure that your conditions are different enough not to collide with the other Powermiser device.\n\nThis is only a warning, hit save again to ignore this warning." % indigo.devices[int(deviceId)].name valuesDict["allowSave"] = True return (False, valuesDict, errorDict) # All is good, set the allowSave back to false for the next round valuesDict["allowSave"] = False # If we get here all is good so far, return from conditions in case there are problems there return self.cond.validateDeviceConfigUi(valuesDict, typeId, devId) except Exception as e: eps.printException(e) return True
def zwaveCommandSent(self, cmd): byteList = cmd['bytes'] byteListStr = ' '.join(["%02X" % byte for byte in byteList]) nodeId = 0 dev = False if eps.valueValid (cmd, "nodeId", True): nodeId = cmd['nodeId'] dev = self.cache.deviceForAddress (nodeId) if dev: self.logger.debug ("Found monitored Z-Wave from command: %s" % unicode(dev)) else: return self.logger.debug("Detected sent Z-Wave command %s for node %s" % (byteListStr, unicode(nodeId))) self.logger.debug("Assuming that this device is a switch and that command group 4 is our command") cmdFunc = "Unknown" cmdF = int(cmd['bytes'][8]) if cmdF == 0: cmdFunc = "off" if cmdF == 255: cmdFunc = "on" if dev: if cmdFunc != "Unknown": for devId in dev: self.processRawCommand (indigo.devices[devId], cmdFunc, "Indigo") else: self.logger.info("Can't seem to figure out what command %s sent so auto-off won't work" % unicode(nodeId))
def deviceStartComm(self, dev): self.logger.debug(u"%s starting communication" % dev.name) try: dev.stateListOrDisplayStateIdChanged() # Make sure any device.xml changes are incorporated if self.cache is None: return if "lastreset" in dev.states: d = indigo.server.getTime() if dev.states["lastreset"] == "": dev.updateStateOnServer("lastreset", d.strftime("%Y-%m-%d")) if eps.valueValid (dev.states, "autoOffTimes", True) == False: dev.updateStateOnServer("autoOffTimes", "{}") if self.cache.deviceInCache (dev.id) == False: self.logger.debug(u"%s not in cache, appears to be a new device or plugin was just started" % dev.name) self.cache.cacheDevices() # Failsafe self.addWatchedStates("*", dev.deviceTypeId, dev.id) # Failsafe #self.cache.dictDump (self.cache.devices[dev.id]) self.setStateDisplay(dev) except Exception as e: eps.printException(e) return
def onRunConcurrentThread (self): try: self.updateCheck(True, False) for dev in indigo.devices.iter(self.pluginId): if eps.valueValid (dev.states, "autoOffTimes", True): if dev.states["autoOffTimes"] != "{}": autoOffTimes = ast.literal_eval (dev.states["autoOffTimes"]) for devId, offDict in autoOffTimes.iteritems(): d = datetime.datetime.strptime (offDict["offTime"], "%Y-%m-%d %H:%M:%S") diff = dtutil.DateDiff ("seconds", d, indigo.server.getTime()) if diff < 0: self.logger.info("Turning off device %s" % indigo.devices[int(devId)].name) indigo.device.turnOff(devId) if dev.states["autoOffTimes"] == "{}" and dev.states["statedisplay"] != "off": dev.updateStateImageOnServer(indigo.kStateImageSel.PowerOff) dev.updateStateOnServer("statedisplay", "off") if dev.states["autoOffTimes"] != "{}" and dev.states["statedisplay"] == "off": dev.updateStateImageOnServer(indigo.kStateImageSel.PowerOn) dev.updateStateOnServer("statedisplay", "on") except Exception as e: eps.printException(e) return
def nextField (self, devAction): try: dev = indigo.devices[devAction.deviceId] # In case they use this command on a non-compatible device, redirect if dev.deviceTypeId == "securityKeypad": self.sendCharacter (devAction) if dev.deviceTypeId == "dimmerKeypad": self.sendCharacter (devAction) if dev.deviceTypeId == "sprinklerKeypad": # Next indicates they are switching zones zoneNum = 0 for i in range (1, 9): if dev.states["onZone" + str(i)]: zoneNum = i break if zoneNum == 1 and eps.valueValid (dev.pluginProps, "device2", True) == False and eps.valueValid (dev.pluginProps, "device3", True) == False: # Failsafe in case they didn't enter a duration for zone 1 and cause the timer to start for 2 minutes self.setDeviceTimeout(dev, 120) self.saveSchedule (dev) if zoneNum > 0: zoneNum = zoneNum + 1 if zoneNum > 8: zoneNum = 1 self.debugLog("Change to zone %i" % zoneNum) self.setSprinklerZone (dev, zoneNum) except Exception as e: eps.printException(e)
def sendCharacter_Dimmer (self, dev, devAction): try: if eps.valueValid (devAction.props, "devicelist", True): self.debugLog ("Setting action based devices on %s" % dev.name) devlist = [] for s in devAction.props["devicelist"]: devlist.append(s) dev.updateStateOnServer ("deviceList", unicode(devlist)) return cache = dev.states["keyCache"] + devAction.props["key"] if int(cache) > 100: cache = "100" ui = cache n = int(eps.getDictValue(dev.pluginProps, "resetTime", 10)) self.setDeviceTimeout (dev, n) dev.updateStateOnServer ("keyCache", cache, uiValue=ui) if len(cache) == 3: self.processCache (dev) # 3 characters is the most except Exception as e: eps.printException(e)
def turnDeviceOn (self, devParent, devChild, autoOffTimes): try: d = indigo.server.getTime() if self.cond.conditionsPass (devParent.pluginProps) == False: self.logger.debug ("\tDevice doesn't pass conditions, ignoring command") return if devChild.id in autoOffTimes: if devParent.pluginProps["tapDuration"]: if eps.valueValid (devParent.pluginProps, "extendTime", True): self.logger.info ("Extending %s time on by %s minutes" % (devChild.name, devParent.pluginProps["extendTime"])) offDict = autoOffTimes[devChild.id] offDict["repeats"] = offDict["repeats"] + 1 if eps.valueValid (devParent.pluginProps, "turnOn", True): if int(devParent.pluginProps["turnOn"]) > 0: if offDict["repeats"] >= int(devParent.pluginProps["turnOn"]): self.logger.info ("\t%s maximum repeats reached, cancelling auto off" % devChild.name) del autoOffTimes[devChild.id] devParent.updateStateOnServer("autoOffTimes", unicode(autoOffTimes)) return autoOff = datetime.datetime.strptime (offDict["offTime"], "%Y-%m-%d %H:%M:%S") autoOff = dtutil.DateAdd ("minutes", int(devParent.pluginProps["extendTime"]), autoOff) offDict["offTime"] = autoOff.strftime("%Y-%m-%d %H:%M:%S") autoOffTimes[devChild.id] = offDict devParent.updateStateOnServer("autoOffTimes", unicode(autoOffTimes)) self.logger.info ("%s will turn off automatically at %s" % (devChild.name, autoOff.strftime("%Y-%m-%d %H:%M:%S"))) else: self.logger.debug ("\tSetting the initial auto off time") if eps.valueValid (devParent.pluginProps, "timeOut", True): offDict = {} offDict["repeats"] = 1 autoOff = dtutil.DateAdd ("minutes", int(devParent.pluginProps["timeOut"]), d) offDict ["offTime"] = autoOff.strftime("%Y-%m-%d %H:%M:%S") autoOffTimes[devChild.id] = offDict devParent.updateStateOnServer("autoOffTimes", unicode(autoOffTimes)) self.logger.info ("%s will turn off automatically at %s" % (devChild.name, autoOff.strftime("%Y-%m-%d %H:%M:%S"))) except Exception as e: eps.printException(e)
def updateDateTime (self): d = indigo.server.getTime() for dev in indigo.devices.iter(self.pluginId + ".epslcddt"): if dev.pluginProps["systemdate"] == False: continue # they are watching states / variables if eps.valueValid(dev.states, "storeddate", True): if dev.states["storeddate"] == d.strftime("%Y-%m-%d %H:%M:00"): continue # we don't calculate seconds, only update if Y-M-D or H:M updated else: dev.updateStateOnServer("storeddate", d.strftime("%Y-%m-%d %H:%M:00")) if eps.valueValid (dev.pluginProps, "dateformat", True): value = d.strftime(dev.pluginProps["dateformat"]) value = self.lcd.stringToLCD (value, 20, dev.pluginProps["textspaces"]) self.lcd.stringToGraphics (dev, "currentDate", value) dev.updateStateOnServer("storeddate", d.strftime("%Y-%m-%d %H:%M:00"))
def variableUpdated (self, origVariable, newVariable): # Since we don't use variable caching find any date/time devices using variables for dev in indigo.devices.iter(self.pluginId + ".epslcddt"): if dev.pluginProps["usevariable"] and eps.valueValid(dev.pluginProps, "variable", True): if str(origVariable.id) == dev.pluginProps["variable"]: # Our watched variable changed, update self.debugLog(u"The monitored variable %s changed" % newVariable.name) self.dateTimeDeviceUpdate (dev, newVariable.value)
def deviceReset (self, dev): try: self.debugLog ("Resetting %s" % dev.name) if dev.deviceTypeId == "securityKeypad": dev.updateStateOnServer ("keyCache", "", uiValue=" ") # Clear the code dev.updateStateOnServer ("currentAttempts", 0) # Clear attempts if dev.states["lockOutActive"] == False: dev.updateStateOnServer ("statedisplay", "Ready") if dev.deviceTypeId == "dimmerKeypad": ui = eps.getDictValue (dev.pluginProps, "brightnessUI", " ") dev.updateStateOnServer ("keyCache", "", uiValue=ui) # Clear the code #dev.updateStateOnServer ("deviceList", "[]") # Clear the additional devices dev.updateStateOnServer ("statedisplay", "Ready") if dev.deviceTypeId == "sprinklerKeypad": # Reset devices 2-3 since 1 has already been handled for i in range (2, 4): dev.updateStateOnServer ("onDevice" + str(i), False) dev.updateStateOnServer ("device" + str(i) + "Schedule", "[0,0,0,0,0,0,0,0]") for i in range (1, 9): dev.updateStateOnServer ("onZone" + str(i), False) ui = eps.getDictValue (dev.pluginProps, "deviceUI", " ") # If only one device, always reset for device 1 if eps.valueValid (dev.pluginProps, "device2", True) == False and eps.valueValid (dev.pluginProps, "device3", True) == False: ui = eps.getDictValue (dev.pluginProps, "zone1SelectedUI", " ") dev.updateStateOnServer ("onDevice1", True) dev.updateStateOnServer ("onZone1", True) # since there is no device selection that will auto select it else: dev.updateStateOnServer ("onDevice1", False) dev.updateStateOnServer ("keyCache", "", uiValue=ui) # Clear the code dev.updateStateOnServer ("device1Schedule", "[0,0,0,0,0,0,0,0]") dev.updateStateOnServer ("statedisplay", "Ready") except Exception as e: eps.printException(e)
def checkDeviceTimeout (self): try: for dev in indigo.devices.iter(self.pluginId): if eps.valueValid (dev.states, "resetTime", True): d = datetime.datetime.strptime (dev.states["resetTime"], "%Y-%m-%d %H:%M:%S") diff = dtutil.DateDiff ("seconds", d, indigo.server.getTime()) if diff < 0: # Don't waste processing time if it's already cleared ui = " " if dev.deviceTypeId == "dimmerKeypad": ui = eps.getDictValue (dev.pluginProps, "brightnessUI", " ") if dev.deviceTypeId == "sprinklerKeypad": ui = eps.getDictValue (dev.pluginProps, "deviceUI", " ") # If only one device, don't ever prompt for a device if eps.valueValid (dev.pluginProps, "device2", True) == False and eps.valueValid (dev.pluginProps, "device3", True) == False: ui = eps.getDictValue (dev.pluginProps, "zone1SelectedUI", " ") if ui == "": ui = " " if dev.states["keyCache"] != "" or dev.states["keyCache.ui"] != ui: self.debugLog("Device '%s' timeout reached, resetting device" % dev.name) self.deviceReset (dev) else: # It's blank, set it now dev.updateStateOnServer ("resetTime", indigo.server.getTime().strftime("%Y-%m-%d %H:%M:%S")) if dev.deviceTypeId == "securityKeypad" and dev.states["lockOutActive"]: d = datetime.datetime.strptime (dev.states["lockOut"], "%Y-%m-%d %H:%M:%S") diff = dtutil.DateDiff ("seconds", d, indigo.server.getTime()) if diff >= 0: ui = dtutil.secondsToClock (diff, "mm:ss") dev.updateStateOnServer ("statedisplay", "LOCKED " + ui) else: dev.updateStateOnServer ("lockOutActive", False) dev.updateStateOnServer ("statedisplay", "Ready") except Exception as e: eps.printException(e) return
def dateTimeDeviceUpdate (self, dev, value): try: value = unicode(value) d = datetime.datetime.strptime (value, dev.pluginProps["valueformat"]) if eps.valueValid (dev.pluginProps, "dateformat", True): value = d.strftime(dev.pluginProps["dateformat"]) value = self.lcd.stringToLCD (value, 20, dev.pluginProps["textspaces"]) self.lcd.stringToGraphics (dev, "currentDate", value) except Exception as e: eps.printException(e)
def sendCharacter_Security (self, dev, key): try: # Make sure we aren't locked out if eps.valueValid (dev.states, "lockOut", True): d = datetime.datetime.strptime (dev.states["lockOut"], "%Y-%m-%d %H:%M:%S") diff = dtutil.DateDiff ("seconds", d, indigo.server.getTime()) if diff >= 0: indigo.server.log("Attempted to enter code on device %s but that device is in failed code lockout for %i more seconds" % (dev.name, diff), isError=True) msg = "L.OUT" secs = 5 if secs > diff: secs = diff ui = eps.getDictValue (dev.pluginProps, "lockoutUI", "L.OUT") dev.updateStateOnServer ("keyCache", dev.states["keyCache"], uiValue=ui) self.setDeviceTimeout (dev, secs) return else: dev.updateStateOnServer ("lockOutActive", False) self.debugLog ("Keypad button %s pressed, adding to characters" % key) cache = dev.states["keyCache"] + key ui = "" n = int(eps.getDictValue(dev.pluginProps, "resetTime", 10)) if dev.pluginProps["codeCharacter"] != "" and dev.pluginProps["codeCharacter"] != " ": for s in cache: ui += dev.pluginProps["codeCharacter"] self.setDeviceTimeout (dev, n) else: self.setDeviceTimeout (dev, n) ui = cache dev.updateStateOnServer ("keyCache", cache, uiValue=ui) self.processCache (dev) except Exception as e: eps.printException(e) return
def setAlarmEndTime (self, dev, startTime): origEndTime = "" # 1.1.1 if eps.valueValid(dev.states, "endTime", True): # 1.1.1 origEndTime = datetime.datetime.strptime (dev.states["endTime"], "%Y-%m-%d %H:%M:%S") if dev.states["durationMinutes"] == 0: # Save our default duration to the duration state dev.updateStateOnServer("durationMinutes", int(dev.pluginProps["defaultDuration"])) endTime = dtutil.DateAdd("minutes", int(dev.states["durationMinutes"]), startTime) if origEndTime != endTime: self.debugLog(u"\t\tend time recalculated, new alarm time is %s to %s" % (unicode(startTime), unicode(endTime))) return endTime
def setBrightness (self, devlist, dev, currentCode): for devId in devlist: devChild = indigo.devices[int(devId)] if eps.valueValid (devChild.states, "brightnessLevel") == False: indigo.server.log ("Cannot set the brightness on %s because it is not a dimmer" % devChild.name, isError=True) continue cur = devChild.states["brightnessLevel"] new = int(currentCode) if new == 0: indigo.dimmer.turnOff(devChild.id) elif new == 100: indigo.dimmer.turnOn(devChild.id) else: indigo.dimmer.setBrightness(devChild.id, value=new)
def epsInit (self): try: # Set any missing prefs self.pluginPrefs = eps.validateDictValue (self.pluginPrefs, "logLevel", "20", True) self.pluginPrefs = eps.validateDictValue (self.pluginPrefs, "pollingMode", "realTime", True) self.pluginPrefs = eps.validateDictValue (self.pluginPrefs, "pollingInterval", 1, True) self.pluginPrefs = eps.validateDictValue (self.pluginPrefs, "pollingFrequency", "s", True) # Change this to true if we are watching devices self.pluginPrefs = eps.validateDictValue (self.pluginPrefs, "monitorChanges", False, True) # EPS common startup self.logger.setLevel(int(self.pluginPrefs["logLevel"])) if int(self.pluginPrefs["logLevel"]) < 20: self.debug = True else: self.debug = False pollingMode = self.pluginPrefs["pollingMode"] pollingInterval = int(self.pluginPrefs["pollingInterval"]) pollingFrequency = self.pluginPrefs["pollingFrequency"] self.monitor = self.pluginPrefs["monitorChanges"] # Legacy cleanup (Indigo 7 removes need for debug mode and may eliminate it entirely at some point) if eps.valueValid (self.pluginPrefs, "debugMode"): self.logger.info(u"Upgraded plugin preferences from pre-Indigo 7, depreciated preferences removed") del self.pluginPrefs["debugMode"] # EPS common variables and classes self.pluginUrl = "http://forums.indigodomo.com/viewtopic.php?f=196&t=16343" eps.parent = self self.reload = False self.cache = cache (self, self.pluginId, pollingMode, pollingInterval, pollingFrequency) self.cond = conditions (self) except Exception as e: msg = eps.debugHeader ("Plugin intialization had an error, restart required!") self.logger.critical(msg) eps.printException(e) raise
def addWatchedStates (self, subDevId = "*", deviceTypeId = "*", mainDevId = "*"): # The only device we currently watch is sprinklers so we know what zone came on and for how long if deviceTypeId == "*" or deviceTypeId == "sprinklerKeypad": dev = indigo.devices[int(mainDevId)] if eps.valueValid (dev.pluginProps, "device", True): devChild = indigo.devices[int(dev.pluginProps["device"])] subDevId = devChild.id # Must be specific for multiple choice self.cache.addWatchState ("activeZone", subDevId, "sprinklerKeypad", dev.id) #self.cache.addWatchState ("onOffState", subDevId, "epsCustomDev") #self.cache.addWatchState (848833485, "onOffState", 1089978714) #self.cache.addWatchState ("onOffState", subDevId, deviceTypeId, mainDevId) # All devices, pass vars #self.cache.addWatchState ("onOffState") # All devices, all subdevices, all types #self.cache.addWatchState ("onOffState", 848833485) # All devices, this subdevice, all types #self.cache.addWatchState ("onOffState", subDevId, "epslcdth") # All devices, all subdevices of this type #self.cache.addWatchState ("onOffState", 848833485, "*", 1089978714) # This device, this subdevice of all types return
def processRawCommand (self, devChild, cmd, method = "Physical"): try: self.logger.debug(u"A monitored device '%s' processed a raw command '%s'" % (devChild.name, cmd)) dev = False for d in indigo.devices.iter(self.pluginId): if eps.valueValid (d.pluginProps, "devicelist", True): for devId in d.pluginProps["devicelist"]: if devId == str(devChild.id): devParent = d self.logger.debug ("\tProcessing auto off group '%s' managing this device" % devParent.name) autoOffTimes = ast.literal_eval (devParent.states["autoOffTimes"]) if devParent.pluginProps["physicalOnly"] and cmd == "on" and method != "Physical": self.logger.debug("\t%s is configured for physical only, this on command was sent from Insteon so it will be ignored" % devParent.name) continue # so we can see if it's in another Powermiser device if devChild.id in autoOffTimes: self.logger.debug ("\tThe device is currently in an on state in the plugin") if cmd == "off": self.logger.debug ("\tThe command is to turn it off") del autoOffTimes[devChild.id] devParent.updateStateOnServer("autoOffTimes", unicode(autoOffTimes)) else: self.logger.debug ("\tThe command is to turn it on") self.turnDeviceOn (devParent, devChild, autoOffTimes) else: self.logger.debug ("\tThe device is currently in an off state in the plugin") if cmd == "off": self.logger.debug ("\tThe command is to turn it off and it's not in cache, nothing to do") else: self.logger.debug ("\tThe command is to turn it on") self.turnDeviceOn (devParent, devChild, autoOffTimes) except Exception as e: eps.printException(e)
def addWatchedStates (self, subDevId = "*", deviceTypeId = "*", mainDevId = "*"): dev = False if mainDevId != "*": dev = indigo.devices[int(mainDevId)] if deviceTypeId == "*" or deviceTypeId == "epsdecon": # Conversion if dev.pluginProps["chdevice"]: # It's a device and not a variable devChild = indigo.devices[int(dev.pluginProps["device"])] subDevId = devChild.id # Must be specific for multiple choice if dev.pluginProps["states"] == "lastChanged": self.cache.addWatchProperty ("lastChanged", subDevId, "epsdecon", dev.id) else: self.cache.addWatchState (dev.pluginProps["states"], subDevId, "epsdecon", dev.id) else: # We are watching a variable if eps.valueValid (dev.pluginProps, "variable", True): self.varCache.append (dev.pluginProps["variable"]) return
def deviceStartComm(self, dev): self.debugLog(u"%s starting communication" % dev.name) dev.stateListOrDisplayStateIdChanged() # Force plugin to refresh states from devices.xml if self.cache is None: return if "lastreset" in dev.states: d = indigo.server.getTime() if dev.states["lastreset"] == "": dev.updateStateOnServer("lastreset", d.strftime("%Y-%m-%d ")) if "lastCalc" in dev.states: d = indigo.server.getTime() if dev.states["lastCalc"] == "": dev.updateStateOnServer("lastCalc", d.strftime("%Y-%m-%d %H:%M:%S")) if eps.valueValid (dev.states, "statedisplay", True): self.debugLog("Device doesn't have a valid device state, setting the state now") # There is no state display, set it now - 1.1.1 if dev.states["isOn"]: dev.updateStateOnServer("statedisplay", "On") dev.updateStateImageOnServer(indigo.kStateImageSel.TimerOn) else: dev.updateStateOnServer("statedisplay", "Off") dev.updateStateImageOnServer(indigo.kStateImageSel.TimerOff) if eps.stateValid (dev, "startTime", True) == False: self.debugLog("Device doesn't have a start time, creating a default alarm for 8:00 AM") # added in 1.1.1 or creating the start date will fail because there are no days self.auditDays (dev) resetday = dev.states["isSaturday"] dev.updateStateOnServer ("isSaturday", True) # failsafe d = indigo.server.getTime() t = datetime.datetime.strptime(d.strftime("%Y-%m-%d") + " 08:00:00", "%Y-%m-%d %H:%M:%S") #t = self.proposedFutureTime (t, dev) t = self.getNextStartTime (dev, t) # 1.1.1 dev.updateStateOnServer("startTime", t.strftime ("%Y-%m-%d %H:%M:%S"), uiValue=self.dtToString(t, dev.pluginProps["militaryTime"])) dev.updateStateOnServer ("isSaturday", resetday) # failsafe if eps.stateValid (dev, "endTime", True) == False: self.debugLog("Device doesn't have an end time, calculating the next available end time from the start time") d = datetime.datetime.strptime (dev.states["startTime"], "%Y-%m-%d %H:%M:%S") #t = dtutil.DateAdd("minutes", int(dev.pluginProps["defaultDuration"]), d) #t = self.proposedFutureTime (t, dev, t.strftime("%Y-%m-%d %H:%M:%S")) t = self.setAlarmEndTime (dev, d) # 1.1.1 dev.updateStateOnServer("endTime", t.strftime ("%Y-%m-%d %H:%M:%S"), uiValue=self.dtToString(t, dev.pluginProps["militaryTime"])) if "durationMinutes" in dev.states: if dev.states["durationMinutes"] == 0: dev.updateStateOnServer("durationMinutes", int(dev.pluginProps["defaultDuration"])) if self.cache.deviceInCache (dev.id) == False: self.debugLog(u"%s not in cache, appears to be a new device or plugin was just started" % dev.name) self.cache.cacheDevices() # Failsafe #dev.updateStateOnServer("startTime", "2016-06-08 17:00:00") # Debug testing self.validateAlarmTimes(dev) self.addWatchedStates("*", dev.deviceTypeId, dev.id) # Failsafe #self.cache.dictDump (self.cache.devices[dev.id]) #indigo.server.log(unicode(dev.states)) X = 1 # placeholder return
def convertDeviceAction (self, devEx): if devEx.pluginProps["chdevice"]: dev = indigo.devices[int(devEx.pluginProps["device"])] # Added condition to check if it's in states, it will be if it's a state because we already verified this in the config (1.5.0) if devEx.pluginProps["states"] in dev.states: value = dev.states[devEx.pluginProps["states"]] else: # It's a special device property added in 1.5.0 if devEx.pluginProps["states"] == "lastChanged": value = dev.lastChanged else: dev = "" value = indigo.variables[int(devEx.pluginProps["variable"])] if devEx.pluginProps["action"] == "strtocase": # 1.52 value = unicode(value) if devEx.pluginProps["strcase"] == "title": value = value.title() if devEx.pluginProps["strcase"] == "initial": value = value.capitalize() if devEx.pluginProps["strcase"] == "upper": value = value.upper() if devEx.pluginProps["strcase"] == "lower": value = value.lower() devEx.updateStateOnServer("convertedValue", str(value)) devEx.updateStateOnServer(key="statedisplay", value=value, uiValue=value) if devEx.pluginProps["action"] == "strtonum": # 1.52 # CONVERTED value = unicode(value) if eps.valueValid (devEx.pluginProps, "trimstart", True): if devEx.pluginProps["trimstart"] != "0" and len(value) > int(devEx.pluginProps["trimstart"]): self.debugLog("Removing %i characters from beginning of string" % int(devEx.pluginProps["trimstart"])) diff = int(devEx.pluginProps["trimstart"]) value = value[diff:len(value)] if eps.valueValid (devEx.pluginProps, "trimend", True): if devEx.pluginProps["trimend"] != "0" and len(value) > int(devEx.pluginProps["trimend"]): self.debugLog("Removing %i characters from end of string" % int(devEx.pluginProps["trimend"])) diff = int(devEx.pluginProps["trimend"]) diff = diff * -1 value = value[:diff] try: dec = string.find (value, '.') numtype = devEx.pluginProps["numtype"] if dec > -1 and numtype == "int": indigo.server.log("Input value of %s on %s contains a decimal, forcing value to be a float. Change the preferences for this device to get rid of this error." % (value, devEx.name), isError=True) numtype = "float" if numtype == "int": value = int(value) devEx.updateStateOnServer("statedisplay", value, uiValue=unicode(value)) devEx.updateStateOnServer("convertedValue", unicode(value)) devEx.updateStateOnServer("convertedNumber", value) if numtype == "float": value = float(value) devEx.updateStateOnServer("statedisplay", value, uiValue=unicode(value)) devEx.updateStateOnServer("convertedValue", unicode(value)) devEx.updateStateOnServer("convertedNumber", value) except Exception as e: eps.printException(e) devEx.updateStateOnServer(key="statedisplay", value="Error", uiValue="Error") return if devEx.pluginProps["action"] == "dtformat": # 1.52 if eps.valueValid (devEx.pluginProps, "inputdtformat", True) and eps.valueValid (devEx.pluginProps, "outputdtformat", True): value = unicode(value) value = dtutil.DateStringFormat (value, devEx.pluginProps["inputdtformat"], devEx.pluginProps["outputdtformat"]) devEx.updateStateOnServer("convertedValue", str(value)) devEx.updateStateOnServer(key="statedisplay", value=value, uiValue=value) if devEx.pluginProps["action"] == "string": # 1.52 value = unicode(value) if eps.valueValid (devEx.pluginProps, "maxlength", True): if devEx.pluginProps["maxlength"] != "0" and len(value) > int(devEx.pluginProps["maxlength"]): self.debugLog("Shortening string to %i characters" % int(devEx.pluginProps["maxlength"])) diff = len(value) - int(devEx.pluginProps["maxlength"]) diff = diff * -1 value = value[:diff] if eps.valueValid (devEx.pluginProps, "trimstart", True): if devEx.pluginProps["trimstart"] != "0" and len(value) > int(devEx.pluginProps["trimstart"]): self.debugLog("Removing %i characters from beginning of string" % int(devEx.pluginProps["trimstart"])) diff = int(devEx.pluginProps["trimstart"]) value = value[diff:len(value)] if eps.valueValid (devEx.pluginProps, "trimend", True): if devEx.pluginProps["trimend"] != "0" and len(value) > int(devEx.pluginProps["trimend"]): self.debugLog("Removing %i characters from end of string" % int(devEx.pluginProps["trimend"])) diff = int(devEx.pluginProps["trimend"]) diff = diff * -1 value = value[:diff] devEx.updateStateOnServer("convertedValue", str(value)) devEx.updateStateOnServer(key="statedisplay", value=value, uiValue=value) if devEx.pluginProps["action"] == "ctof": # 1.2 added precision if "precision" in devEx.pluginProps: #value = self.cache.convertTemperature (value, False, int(devEx.pluginProps["precision"])) value = conv.temperature (value, False, int(devEx.pluginProps["precision"])) # 1.52 else: #value = self.cache.convertTemperature (value, False) value = conv.temperature (value, False) # 1.52 stateSuffix = u" °F" devEx.updateStateOnServer("convertedValue", str(value)) devEx.updateStateImageOnServer(indigo.kStateImageSel.TemperatureSensor) devEx.updateStateOnServer(key="statedisplay", value=value, decimalPlaces=1, uiValue=str(value) + stateSuffix) if devEx.pluginProps["action"] == "ftoc": # 1.2 added precision if "precision" in devEx.pluginProps: #value = self.cache.convertTemperature (value, True, int(devEx.pluginProps["precision"])) value = conv.temperature (value, True, int(devEx.pluginProps["precision"])) # 1.52 else: #value = self.cache.convertTemperature (value, True) value = conv.temperature (value, True) # 1.52 stateSuffix = u" °C" devEx.updateStateOnServer("convertedValue", str(value)) devEx.updateStateImageOnServer(indigo.kStateImageSel.TemperatureSensor) devEx.updateStateOnServer(key="statedisplay", value=value, decimalPlaces=1, uiValue=str(value) + stateSuffix) if devEx.pluginProps["action"] == "lux": value = int(value) term = "Direct Sunlight" if value < 100001: term = "Direct Sunlight" if value < 30001: term = "Cloudy Outdoors" if value < 10001: term = "Dim Outdoors" if value < 5001: term = "Bright Indoors" if value < 1001: term = "Normal Indoors" if value < 401: term = "Dim Indoors" if value < 201: term = "Dark Indoors" if value < 51: term = "Very Dark" if value < 11: term = "Pitch Black" if value < 1001: devEx.updateStateImageOnServer(indigo.kStateImageSel.LightSensor) else: devEx.updateStateImageOnServer(indigo.kStateImageSel.LightSensorOn) devEx.updateStateOnServer("convertedValue", term) devEx.updateStateOnServer("statedisplay", term) if devEx.pluginProps["action"] == "boolstr": # CONVERTED value = unicode(value).lower() truevalue = unicode(devEx.pluginProps["truewhen"]) falsevalue = unicode(devEx.pluginProps["falsewhen"]) statevalue = falsevalue if value == "true": statevalue = truevalue devEx.updateStateImageOnServer(indigo.kStateImageSel.None) devEx.updateStateOnServer("statedisplay", unicode(statevalue)) devEx.updateStateOnServer("convertedValue", unicode(statevalue)) if devEx.pluginProps["action"] == "booltype": value = unicode(value).lower() statevalue = "na" statebool = False truevalue = "na" falsevalue = "na" if devEx.pluginProps["booltype"] == "tf": truevalue = "true" falsevalue = "false" elif devEx.pluginProps["booltype"] == "yesno": truevalue = "yes" falsevalue = "no" elif devEx.pluginProps["booltype"] == "onoff": truevalue = "on" falsevalue = "off" elif devEx.pluginProps["booltype"] == "oz": truevalue = "1" falsevalue = "0" elif devEx.pluginProps["booltype"] == "oc": truevalue = "open" falsevalue = "closed" elif devEx.pluginProps["booltype"] == "rdy": truevalue = "ready" falsevalue = "not ready" elif devEx.pluginProps["booltype"] == "avail": truevalue = "available" falsevalue = "not available" elif devEx.pluginProps["booltype"] == "gbad": truevalue = "good" falsevalue = "bad" elif devEx.pluginProps["booltype"] == "lock": truevalue = "locked" falsevalue = "unlocked" if value == "true": statebool = True if devEx.pluginProps["reverse"]: statebool = False else: statebool = False if devEx.pluginProps["reverse"]: statebool = True if statebool: statevalue = truevalue else: statevalue = falsevalue devEx.updateStateImageOnServer(indigo.kStateImageSel.None) devEx.updateStateOnServer("statedisplay", unicode(statevalue).lower()) devEx.updateStateOnServer("convertedValue", unicode(statevalue).lower()) devEx.updateStateOnServer("convertedBoolean", statebool) if devEx.pluginProps["booltype"] == "oz": devEx.updateStateOnServer("convertedNumber", int(statevalue)) if devEx.pluginProps["action"] == "true": # CONVERTED devEx.updateStateImageOnServer(indigo.kStateImageSel.None) devEx.updateStateOnServer("statedisplay", "true") devEx.updateStateOnServer("convertedValue", "true") devEx.updateStateOnServer("convertedBoolean", True) if devEx.pluginProps["action"] == "false": # CONVERTED devEx.updateStateImageOnServer(indigo.kStateImageSel.None) devEx.updateStateOnServer("statedisplay", "false") devEx.updateStateOnServer("convertedValue", "false") devEx.updateStateOnServer("convertedBoolean", False) if devEx.pluginProps["action"] == "bool": # CONVERTED value = unicode(value).lower() #if devEx.pluginProps["booleanstatetype"] == "float": value = float(value) truevalue = unicode(devEx.pluginProps["truewhen"]).lower() falsevalue = unicode(devEx.pluginProps["falsewhen"]).lower() statevalue = False if truevalue != "*else*": if value == truevalue: statevalue = True else: if falsevalue == "*else*": statevalue = False if falsevalue != "*else*": if value == falsevalue: statevalue = False else: if truevalue == "*else*": statevalue = True devEx.updateStateImageOnServer(indigo.kStateImageSel.None) devEx.updateStateOnServer("statedisplay", unicode(statevalue).lower()) devEx.updateStateOnServer("convertedValue", unicode(statevalue).lower()) devEx.updateStateOnServer("convertedBoolean", statevalue) if devEx.pluginProps["action"] == "dtmin": self.calcMinutes (devEx, value)
def processCache (self, dev, force = False): try: currentCode = dev.states["keyCache"] if currentCode == " ": currentCode = "" if dev.deviceTypeId == "securityKeypad": if dev.pluginProps["actionCode1"] != "" and currentCode == dev.pluginProps["actionCode1"]: self.debugLog("Automatically executing action 1") self.setStatusMessage (dev, "action1UI") self.runAction (dev, "action1") elif dev.pluginProps["actionCode2"] != "" and currentCode == dev.pluginProps["actionCode2"]: self.debugLog("Automatically executing action 2") self.setStatusMessage (dev, "action2UI") self.runAction (dev, "action2") elif dev.pluginProps["autoAcceptChars"] != "" and dev.pluginProps["autoAcceptChars"] != "0" and len(currentCode) >= int(dev.pluginProps["autoAcceptChars"]): self.processCode(dev, currentCode) return elif force: self.processCode(dev, currentCode) return elif dev.deviceTypeId == "dimmerKeypad": indigo.server.log("Setting brightness now") if eps.valueValid (dev.states, "deviceList", True): if dev.states["deviceList"] != "[]": # They sent devices devs = ast.literal_eval(dev.states["deviceList"]) if dev.pluginProps["deviceMethod"] == "replace": self.setBrightness (devs, dev, currentCode) elif dev.pluginProps["deviceMethod"] == "append": self.setBrightness (devs, dev, currentCode) self.setBrightness (dev.pluginProps["devicelist"], dev, currentCode) elif dev.pluginProps["deviceMethod"] == "ignore": self.setBrightness (dev.pluginProps["devicelist"], dev, currentCode) else: # Use the devices configure in props self.debugLog("Device list is empty") self.setBrightness (dev.pluginProps["devicelist"], dev, currentCode) self.setStatusMessage (dev, "completedUI") return elif dev.deviceTypeId == "sprinklerKeypad": self.saveSchedule (dev) for i in range (1, 4): idx = str(i) if i == 1: idx = "" if eps.valueValid (dev.pluginProps, "device" + idx, True): devEx = indigo.devices[int(dev.pluginProps["device" + idx])] if idx == "": idx = "1" schedule = ast.literal_eval(dev.states["device" + idx + "Schedule"]) self.runSprinklerSchedule (dev, devEx, schedule, i) self.setStatusMessage (dev, "completedUI") return except Exception as e: eps.printException(e)