def pluginMenuSupportInfo (self, returnString = False): try: ret = "" ret += self.factory.ui.debugHeader (self.factory.plugin.pluginDisplayName) ret += self.factory.ui.debugLine (" ") ret += self.factory.ui.debugLine ("Plugin Version : {0}".format(self.factory.plugin.pluginVersion)) ret += self.factory.ui.debugLine ("Template Version : {0}".format(self.factory.plugin.TVERSION)) ret += self.factory.ui.debugLine ("Core Engine Version : {0}".format(self.factory.VERSION)) ret += self.factory.ui.debugLine ("Indigo Version : {0}".format(indigo.server.version)) ret += self.factory.ui.debugLine ("Indigo API Version : {0}".format(indigo.server.apiVersion)) ret += self.factory.ui.debugLine (" ") if returnString: return ret ret += self.factory.ui.debugLine ("Alphas, Betas and Pre-Releases can be downloaded from:") ret += self.factory.ui.debugLine (" https://github.com/Colorado4Wheeler") ret += self.factory.ui.debugLine (" ") ret += self.factory.ui.debugLine ("All support inquiries, questions or comments go to:") ret += self.factory.ui.debugLine (" http://forums.indigodomo.com/viewforum.php?f=192") ret += self.factory.ui.debugLine (" ") ret += self.factory.ui.debugLine ("Copyright (c) 2017 - Colorado4Wheeler & EPS") ret += self.factory.ui.debugLine (" ") ret += self.factory.ui.debugHeaderEx () self.logger.info (ret) except Exception as e: self.logger.error (ext.getException(e))
def getDetailsByObject (self, obj): try: # Determine if we are reading a plugin device or Indigo device objtype = str(type(obj)).replace("<class '", "").replace("'>", "") #indigo.server.log(objtype) # Filter out objects we do not yet support if objtype == "indigo.ActionGroup": self.logger.error ("Plugdetail beta doesn't currently process Action Groups, cannot get actions for '{0}'".format(obj.name)) return None elif objtype == "indigo.ControlPage": self.logger.error ("Plugdetail beta doesn't currently process Control Pages, cannot get actions for '{0}'".format(obj.name)) return None elif "Trigger" in objtype: self.logger.error ("Plugdetail beta doesn't currently process Triggers, cannot get actions for '{0}'".format(obj.name)) return None elif objtype == "indigo.Schedule": self.logger.error ("Plugdetail beta doesn't currently process Schedules, cannot get actions for '{0}'".format(obj.name)) return None elif objtype == "indigo.Variable": self.logger.error ("Plugdetail beta doesn't currently process Variables, cannot get actions for '{0}'".format(obj.name)) return None return self.getDetailsByPluginId (obj.pluginId, obj.deviceTypeId) except Exception as e: #raise self.logger.error (ext.getException(e))
def cachePluginInformation (self): try: base = indigo.server.getInstallFolderPath() + "/Plugins" plugins = glob.glob(base + "/*.indigoPlugin") for plugin in plugins: try: plugInfo = self._parsePlist (plugin) self.pluginCache[plugInfo["id"]] = plugInfo except Exception as ex: self.logger.error (ext.getException(ex)) except Exception as e: self.logger.error (ext.getException(e))
def getPluginCacheItem (self, pluginId): try: #indigo.server.log(pluginId) if pluginId in self.pluginCache: plugInfo = self.pluginCache[pluginId] if "xml" not in plugInfo: # Retrieve it return self.getDetailsByPluginId (pluginId) else: return plugInfo else: # This should never get called since we cache basics when the library is loaded #indigo.server.log(unicode(self.pluginCache)) self.cachePluginInformation() return self.getDetailsByPluginId (pluginId) except Exception as e: self.logger.error (ext.getException(e)) return None
def closedActionConfigUi(self, valuesDict, userCancelled, typeId, deviceId): try: # We don't get the action information here, only the device ID if a device was selected if deviceId != 0: dev = indigo.devices[deviceId] if userCancelled: self.logger.threaddebug ("Action group referencing '{0}' dialog cancelled".format(dev.name)) else: self.logger.threaddebug ("Action group referencing '{0}' dialog closed".format(dev.name)) else: if userCancelled: self.logger.threaddebug ("Action group configuration dialog cancelled") else: self.logger.threaddebug ("Action group configuration dialog closed") self._callBack (BEFORE, [valuesDict, userCancelled, typeId, deviceId]) # Make sure we've flushed the cache for this device self.factory.ui.flushCache (deviceId) if ext.valueValid (valuesDict, "uniqueIdentifier", True): self.factory.ui.flushCache (int(valuesDict["uniqueIdentifier"])) self._callBack (AFTER, [valuesDict, userCancelled, typeId, deviceId]) except Exception as e: self.logger.error (ext.getException(e))
def _refreshRunningState(self, dev): try: if dev.activeZone is None and dev.pausedScheduleZone is None: self.isPaused = False self.pausedZone = 0 self.isRunning = False self.activeZone = 0 elif dev.activeZone is not None: self.isPaused = False self.pausedZone = 0 # Strange things can happen if we started up the plugin mid-schedule, we need to make sure we are ok if self.scheduleEndTime is None: self._updateFromSchedule() self.isRunning = True self.activeZone = dev.activeZone elif dev.pausedScheduleZone is not None: self.isPaused = True self.pausedZone = dev.pausedScheduleZone if self.scheduleEndTime is None: self._updateFromSchedule() self.isRunning = False self.activeZone = 0 except Exception as e: self.logger.error(ext.getException(e))
def removeDevice (self, obj): try: self.logger.threaddebug ("Removing '{0}' and any references from cache".format(obj.name)) self.items.remove(obj) except Exception as e: self.logger.error (ext.getException(e))
def deviceUpdated (self, origDev, newDev): try: if self.isFinishedLoading(): pass else: return if newDev.pluginId == self.factory.plugin.pluginId: if len(origDev.pluginProps) > 0: self.pluginDeviceUpdated (origDev, newDev) elif len(origDev.pluginProps) == 0 and len(newDev.pluginProps) == 0 and newDev.deviceTypeId != "": self.pluginDeviceBegun (newDev) elif len(origDev.pluginProps) == 0 and len(newDev.pluginProps) > 0: self.pluginDeviceCreated (newDev) else: # It's not a plugin device, see if it's a cache device if "cache" in dir(self.factory): ret = self.factory.cache.watchedItemChanges (origDev, newDev) for change in ret: self.logger.debug ("'{0}' {1} '{2}' has changed".format(newDev.name, change.type, change.name)) if change.itemType == "Device": if change.type == "state": self._callBack (NOTHING, [origDev, newDev, change], "onWatchedStateChanged") if change.type == "property": self._callBack (NOTHING, [origDev, newDev, change], "onWatchedPropertyChanged") if change.type == "attribute": self._callBack (NOTHING, [origDev, newDev, change], "onWatchedAttributeChanged") except Exception as e: self.logger.error (ext.getException(e))
def deviceStartComm (self, dev): try: self.logger.threaddebug ("Starting communications on '{0}'".format(dev.name)) self._callBack (BEFORE, [dev]) self.deviceStateUpgrade (dev) # Do this before committing state changes in case we need to upgrade or migrate dev.stateListOrDisplayStateIdChanged() # Commit any state changes if ext.valueValid (dev.states, "lastreset"): if ext.valueValid (dev.states, "lastreset", True) == False: dev.updateStateOnServer("lastreset", indigo.server.getTime().strftime("%Y-%m-%d")) self.addPluginDeviceToCache (dev) # If the name has "copy" as the last word in the name, check if this might have been copied from another device, # but this can only happen after we are already up and running #i = string.find (dev.name, "copy") #if i > -1: # if self.isFinishedLoading(): # indigo.server.log("copy") self._callBack (AFTER, [dev]) if self.lastDeviceLoaded: self.lastDeviceLoaded = indigo.server.getTime().strftime("%Y-%m-%d %H:%M:%S") except Exception as e: self.logger.error (ext.getException(e))
def getActionUIList (self, obj, showUIConfig = False): ret = [] try: data = self._resolveObject (obj) if len(data[0]) == 0: return ret plugInfo = data[0] deviceTypeId = data[1] if "xml" in plugInfo == False: return ret #if "actions" in plugInfo["xml"] == False: return ret if "actions" in plugInfo["xml"]: pass else: return ret if deviceTypeId[0:7] == "indigo.": ret = self._getActionUIList (plugInfo, deviceTypeId, showUIConfig, "indigo_") else: ret = self._getActionUIList (plugInfo, deviceTypeId, showUIConfig) # Add Indigo actions as long as this was not already done above if deviceTypeId[0:7] != "indigo.": data = self._resolveIndigoDevice (obj) retEx = self._getActionUIList (data[0], data[1], showUIConfig, "indigo_") retEx.append (("-line-", self.factory.ui.getSeparator())) ret = retEx + ret except Exception as e: self.logger.error (ext.getException(e)) return self._cleanReturnList (ret)
def _getActionUIList (self, plugInfo, deviceTypeId, showUIConfig, prefix = "plugin_"): ret = [] try: # Run through every device action and add a placeholder, we'll clean up after for id, action in plugInfo["xml"]["actions"].iteritems(): ret.append ("") for id, action in plugInfo["xml"]["actions"].iteritems(): isOk = True if "DeviceFilter" in action: isOk = self._isForDevice (plugInfo, deviceTypeId, action["DeviceFilter"]) if "ConfigUI" in action: if showUIConfig == False and len(action["ConfigUI"]) > 0: isOk = False if isOk: if action["Name"] == " - ": option = ("-line-", self.factory.ui.getSeparator()) ret[action["SortOrder"]] = option else: option = (prefix + id, action["Name"]) ret[action["SortOrder"]] = option except Exception as e: self.logger.error (ext.getException(e)) return ret
def getWatchList (self): ret = {} ret["states"] = [] ret["attribs"] = [] try: ret["states"].append ("activeZone") ret["states"].append ("zone1") ret["states"].append ("zone2") ret["states"].append ("zone3") ret["states"].append ("zone4") ret["states"].append ("zone5") ret["states"].append ("zone6") ret["states"].append ("zone7") ret["states"].append ("zone8") ret["attribs"].append ("displayStateValRaw") ret["attribs"].append ("displayStateValUi") ret["attribs"].append ("enabled") ret["attribs"].append ("pausedScheduleRemainingZoneDuration") ret["attribs"].append ("pausedScheduleZone") ret["attribs"].append ("zoneCount") ret["attribs"].append ("zoneEnableList") ret["attribs"].append ("zoneMaxDurations") ret["attribs"].append ("zoneNames") ret["attribs"].append ("zoneScheduledDurations") except Exception as e: self.logger.error (ext.getException(e)) return ret
def _refreshRunningState (self, dev): try: if dev.activeZone is None and dev.pausedScheduleZone is None: self.isPaused = False self.pausedZone = 0 self.isRunning = False self.activeZone = 0 elif dev.activeZone is not None: self.isPaused = False self.pausedZone = 0 # Strange things can happen if we started up the plugin mid-schedule, we need to make sure we are ok if self.scheduleEndTime is None: self._updateFromSchedule() self.isRunning = True self.activeZone = dev.activeZone elif dev.pausedScheduleZone is not None: self.isPaused = True self.pausedZone = dev.pausedScheduleZone if self.scheduleEndTime is None: self._updateFromSchedule() self.isRunning = False self.activeZone = 0 except Exception as e: self.logger.error (ext.getException(e))
def startServer(self, port, username=None, password=None): try: if self.stopped: return # It can try starting again after we stopped, causing an error on the except below port = int(port) if username is None: self.authKey = "" else: self.authKey = base64.b64encode("api:api") # Single Threaded #self.httpd = MyHTTPServer(("", port), AuthHandler) # Multi Threaded self.httpd = ThreadedHTTPServer(('', port), AuthHandler) self.httpd.serve_forever() except Exception as e: self.logger.error(ext.getException(e)) self.logger.error("Unable to open port {} for HTTP Server".format( str(port))) self.httpd = None else: self.httpd.timeout = 1.0 self.httpd.setKey(self.authKey)
def runConcurrentThread(self): try: if self.isRunning or self.isPaused: update = None self._refresh() # Do our calculations self.scheduleMinutesRemaining = round (dtutil.dateDiff ("minutes", self.scheduleEndTime, indigo.server.getTime()), 2) self.zoneMinutesRemaining = round (dtutil.dateDiff ("minutes", self.zoneEndTime, indigo.server.getTime()), 2) self.scheduleMinutesComplete = round (self.scheduleRunTime - self.scheduleMinutesRemaining, 2) self.zoneMinutesComplete = round (self.zoneRunTime - self.zoneMinutesRemaining, 2) self.schedulePercentRemaining = int(round(self.scheduleMinutesRemaining / self.scheduleRunTime, 2) * 100) if self.zoneRunTime > 0: self.zonePercentRemaining = int(round(self.zoneMinutesRemaining / self.zoneRunTime, 2) * 100) else: self.logger.info ("The zone run time is zero, unable to calculate time remaining. This is not a critical problem and may only indicate that you stopped a sprinkler that wasn't running.") self.schedulePercentComplete = 100 - self.schedulePercentRemaining self.zonePercentComplete = 100 - self.zonePercentRemaining # Raise the event on the plugin update = self.parent.factory.raiseEvent ("onSprinklerProgressChanged", [self, self.SprinklerDeviceExUpdate()]) update = self.parent.factory.raiseEvent ("onZoneProgressChanged", [self, self.SprinklerDeviceExUpdate()]) self._processUpdateRecord (update) except Exception as e: self.logger.error (ext.getException(e))
def validatePrefsConfigUi(self, valuesDict): errorDict = indigo.Dict() success = True try: self.logger.threaddebug ("Validating plugin configuration") retval = self._callBack (BEFORE, [valuesDict]) if retval is not None: if "success" in retval: success = retval["success"] if "valuesDict" in retval: valuesDict = retval["valuesDict"] if "errorDict" in retval: errorDict = retval["errorDict"] retval = self._callBack (AFTER, [valuesDict]) if retval is not None: if "success" in retval: success = retval["success"] if "valuesDict" in retval: valuesDict = retval["valuesDict"] if "errorDict" in retval: errorDict = retval["errorDict"] except Exception as e: self.logger.error (ext.getException(e)) return (success, valuesDict, errorDict)
def _callBack (self, type, args, funcname = None): retval = None try: caller = sys._getframe(1).f_code.co_name if funcname is None: prefix = "onBefore_" if type == AFTER: prefix = "onAfter_" funcname = prefix + caller if funcname in dir(self.factory.plugin): if caller != "runConcurrentThread": self.logger.threaddebug ("Raising {0} in plugin.py from call to {1}".format(funcname, caller)) func = getattr(self.factory.plugin, funcname) if len(args) > 0: retval = func(*args) else: retval = func() return retval except Exception as e: self.logger.error (ext.getException(e)) return retval
def __init__(self, devId = 0, characterDict = {}, deviceActions = [], loadOptional = False): try: self.type = "Switch" self.desc = "Switch" self.native = True # Functions can map directly to Indigo or a plugin (see requiresPlugin) natively without any customization self.requiresPlugin = [] # For this device to work Indigo must have one or more plugins installed self.required = ["On"] self.optional = [] self.actions = [] self.loadOptional = loadOptional # Create attributes for the optional fields # We have to append from here, if we were to set self.actions equal an outside list it would share among all instances of this class for d in deviceActions: self.actions.append (d) self.characterDict = characterDict self.devId = 0 #indigo.server.log(unicode(devId)) deviceInitialize (self, devId, characterDict) setAttributesForDevice (self) except Exception as e: indigo.server.log (ext.getException(e), isError=True)
def subscribeToChanges(self, obj): try: if type( obj ) is indigo.Variable and self.factory.plug.isSubscribedVariables == False: self.logger.threaddebug( "Variable is being watched, automatically subscribing to variable changes" ) indigo.variables.subscribeToChanges() self.factory.plug.isSubscribedVariables = True if type( obj ) is indigo.ActionGroup and self.factory.plug.isSubscribedActionGroups == False: self.logger.threaddebug( "Action group is being watched, automatically subscribing to action group changes" ) indigo.actionGroups.subscribeToChanges() self.factory.plug.isSubscribedActionGroups = True else: if self.factory.plug.isSubscribedDevices == False: self.logger.threaddebug( "Device is being watched, automatically subscribing to device changes" ) indigo.devices.subscribeToChanges() self.factory.plug.isSubscribedDevices = True except Exception as e: self.logger.error(ext.getException(e))
def updateFromIndigoObject (self, characterDict): try: definedActions = [] for a in self.actions: definedActions.append (a["name"]) self.characterDict = characterDict # Always overwrite if self.devId != 0 and self.devId in indigo.devices: dev = indigo.devices[self.devId] if "onState" in dir(dev) and "On" not in characterDict: characterDict["On"] = dev.onState if "brightness" in dir(dev) and "Brightness" not in characterDict: characterDict["Brightness"] = dev.brightness if "On" not in definedActions: self.actions.append (HomeKitAction("On", "equal", False, "device.turnOff", [self.devId], 0, {self.devId: "attr_onState"})) self.actions.append (HomeKitAction("On", "equal", True, "device.turnOn", [self.devId], 0, {self.devId: "attr_brightness"})) if "Brightness" not in definedActions: self.actions.append (HomeKitAction("Brightness", "between", 0, "dimmer.setBrightness", [self.devId, "=value="], 100, {self.devId: "attr_brightness"})) #self.actions.append (HomeKitAction("Brightness", "equal", 0, "device.turnOff", [self.devId], 0, {self.devId: "attr_onState"})) #self.actions.append (HomeKitAction("Brightness", "equal", 100, "device.turnOn", [self.devId], 0, {self.devId: "attr_onState"})) elif self.devId != 0 and self.devId in indigo.actionGroups: dev = indigo.actionGroups[self.devId] if "On" not in characterDict: characterDict["On"] = False if "On" not in definedActions: self.actions.append (HomeKitAction("On", "equal", True, "actionGroup.execute", [self.devId], 0, {})) except Exception as e: indigo.server.log (ext.getException(e), isError=True)
def updateFromIndigoObject (self, characterDict): try: definedActions = [] for a in self.actions: definedActions.append (a["name"]) self.characterDict = characterDict # Always overwrite if self.devId != 0 and self.devId in indigo.devices: dev = indigo.devices[self.devId] curval = 0 # Unsecure if "onState" in dir(dev): if dev.onState: curval = 1 else: curval = 0 if "onState" in dir(dev) and "LockCurrentState" not in characterDict: characterDict["LockCurrentState"] = curval if "onState" in dir(dev) and "LockTargetState" not in characterDict: characterDict["LockTargetState"] = curval if "LockTargetState" not in definedActions: self.actions.append (HomeKitAction("LockTargetState", "equal", 0, "device.turnOff", [self.devId], 0, {self.devId: "attr_onState"})) self.actions.append (HomeKitAction("LockTargetState", "equal", 1, "device.turnOn", [self.devId], 0, {self.devId: "attr_onState"})) elif self.devId != 0 and self.devId in indigo.actionGroups: dev = indigo.actionGroups[self.devId] if "On" not in characterDict: characterDict["On"] = False if "On" not in definedActions: self.actions.append (HomeKitAction("On", "equal", True, "actionGroup.execute", [self.devId], 0, {})) except Exception as e: indigo.server.log (ext.getException(e), isError=True)
def convertFromBoolean (dev, attribute, value, atype, vtype, obj): try: newvalue = None # Convert to integer if atype == "int": if value: newvalue = 1 if not value: newvalue = 0 if atype == "str": if value: newvalue = "true" if not value: newvalue = "false" if "validValues" in dir(obj) and newvalue in obj.validValues: obj.value = newvalue return True elif "validValues" in dir(obj) and newvalue not in obj.validValues: indigo.server.log("Converted {} for {} from {} to {} but the coverted value of {} was not a valid value for this attribute and will not be accepted by HomeKit, it will remain at the current value of {}".format(attribute, dev.Alias.value, vtype, atype, unicode(newvalue), unicode(obj.value))) return False except Exception as e: indigo.server.log (ext.getException(e), isError=True) return False
def getStr (dev): try: ret = "" proplist = [a for a in dir(dev) if not a.startswith('__') and not callable(getattr(dev, a))] for p in proplist: if p == "required": continue if p == "optional": continue if p == "devId": ret += "Indigo Id : " + str(dev.devId) + "\n" if dev.devId in indigo.devices: ret += "Indigo Type : Device\n" ret += "URL : /devices/" + str(dev.devId) + ".json\n" elif dev.devId in indigo.actionGroups: ret += "Indigo Type : Action Group\n" ret += "URL : /actiongroups/" + str(dev.devId) + ".json\n" elif dev.devId in indigo.variables: ret += "Indigo Type : Variable\n" ret += "URL : /variables/" + str(dev.devId) + ".json\n" continue if p == "type": ret += "Type : " + dev.type + "\n" continue if p == "desc": ret += "Description : " + dev.desc + "\n" continue if p == "characterDict": ret += "Characteristic Values : (Dict)\n" for k, v in dev.characterDict.iteritems(): ret += "\tCharacteristic :\n" ret += "\t\tCharacteristic : {0}\n".format(k) ret += "\t\tValue : {0} ({1})\n".format(unicode(v), str(type(v)).replace("<type '", "").replace("'>", "") ) continue if p == "actions": ret += "Actions : (List)\n" for action in dev.actions: ret += "\tAction : (HomeKitAction)\n" ret += "\t\tCharacteristic : {0}\n".format(action.characteristic) ret += "\t\tWhen : {0}\n".format(action.whenvalueis) ret += "\t\tValue : {0} ({1})\n".format(unicode(action.whenvalue), str(type(action.whenvalue)).replace("<type '", "").replace("'>", "") ) ret += "\t\tValue2 : {0} ({1})\n".format(unicode(action.whenvalue2), str(type(action.whenvalue)).replace("<type '", "").replace("'>", "")) ret += "\t\tCommand : {0}\n".format(unicode(action.command)) ret += "\t\tArguments : {0}\n".format(unicode(action.arguments)) continue requirement = "" if "required" in dir(dev) and p in dev.required: requirement = " (required)" val = getattr(dev, p) ret += p + " : " + unicode(val.value) + requirement + "\n" except Exception as e: indigo.server.log (ext.getException(e), isError=True) return ret
def validateActionConfigUi(self, valuesDict, typeId, deviceId): errorDict = indigo.Dict() success = True try: # We don't get the action information here, only the device ID if a device was selected if deviceId != 0: dev = indigo.devices[deviceId] self.logger.threaddebug ("Validating configuration for an action group referencing '{0}'".format(dev.name)) else: self.logger.threaddebug ("Validating configuration for an action group") retval = self._callBack (BEFORE, [valuesDict, typeId, deviceId]) if retval is not None: if "success" in retval: success = retval["success"] if "valuesDict" in retval: valuesDict = retval["valuesDict"] if "errorDict" in retval: errorDict = retval["errorDict"] retval = self._callBack (AFTER, [valuesDict, typeId, deviceId]) if retval is not None: if "success" in retval: success = retval["success"] if "valuesDict" in retval: valuesDict = retval["valuesDict"] if "errorDict" in retval: errorDict = retval["errorDict"] except Exception as e: self.logger.error (ext.getException(e)) return (success, valuesDict, errorDict)
def __init__ (self): try: self.isRunning = None self.isPaused = None self.activeZone = None self.pausedZone = None self.scheduleStartTime = None self.scheduleEndTime = None self.scheduleRunTime = None self.scheduleMinutesRemaining = None self.scheduleMinutesComplete = None self.schedulePercentCompleted = None self.schedulePercentRemaining = None self.scheduleZonesComplete = None self.scheduleZonesRemaining = None self.zoneStartTime = None self.zoneEndTime = None self.zoneRunTime = None self.zoneMinutesRemaining = None self.zoneMinutesComplete = None self.zonePercentCompleted = None self.zonePercentRemaining = None except Exception as e: self.logger.error (ext.getException(e))
def updateFromIndigoObject (self, characterDict): try: definedActions = [] for a in self.actions: definedActions.append (a["name"]) self.characterDict = characterDict # Always overwrite if self.devId != 0 and self.devId in indigo.devices: dev = indigo.devices[self.devId] if "onState" in dir(dev) and "On" not in characterDict: characterDict["On"] = dev.onState else: characterDict["On"] = False # Since all devices default to this type, this ensure that we never have NO characteristics if "On" not in definedActions: self.actions.append (HomeKitAction("On", "equal", False, "device.turnOff", [self.devId], 0, {self.devId: "attr_onState"})) self.actions.append (HomeKitAction("On", "equal", True, "device.turnOn", [self.devId], 0, {self.devId: "attr_onState"})) elif self.devId != 0 and self.devId in indigo.actionGroups: dev = indigo.actionGroups[self.devId] if "On" not in characterDict: characterDict["On"] = False if "On" not in definedActions: self.actions.append (HomeKitAction("On", "equal", True, "actionGroup.execute", [self.devId], 0, {})) except Exception as e: indigo.server.log (ext.getException(e), isError=True)
def __init__(self): try: self.isRunning = None self.isPaused = None self.activeZone = None self.pausedZone = None self.scheduleStartTime = None self.scheduleEndTime = None self.scheduleRunTime = None self.scheduleMinutesRemaining = None self.scheduleMinutesComplete = None self.schedulePercentCompleted = None self.schedulePercentRemaining = None self.scheduleZonesComplete = None self.scheduleZonesRemaining = None self.zoneStartTime = None self.zoneEndTime = None self.zoneRunTime = None self.zoneMinutesRemaining = None self.zoneMinutesComplete = None self.zonePercentCompleted = None self.zonePercentRemaining = None except Exception as e: self.logger.error(ext.getException(e))
def deviceInitialize (dev, devId, characterDict): try: dev.characterDict = characterDict dev.devId = 0 if int(devId) != 0 and (int(devId) in indigo.devices or int(devId) in indigo.actionGroups): dev.devId = int(devId) # One shared property is name, we can set the alias of this right away if dev.devId != 0: dev.Alias = characteristic_Name() # Generic enough for our use if int(devId) in indigo.devices: dev.Alias.value = indigo.devices[dev.devId].name elif int(devId) in indigo.actionGroups: dev.Alias.value = indigo.actionGroups[dev.devId].name dev.Model = characteristic_Name() if int(devId) in indigo.devices: dev.Model.value = indigo.devices[dev.devId].model elif int(devId) in indigo.actionGroups: dev.Model.value = "Action Group" dev.updateFromIndigoObject(characterDict) except Exception as e: indigo.server.log (ext.getException(e), isError=True)
def dateStringFormat (value, oldFormat, newFormat): try: oldDate = datetime.datetime.strptime (value, oldFormat) return oldDate.strftime (newFormat) except Exception as e: self.logger.error (ext.getException(e))
def _deviceList_JSON (self, query): try: self.logger.info ("HTTP returning JSON device list") content = "" # In case we're returning something other than straight JSON ret = [] for d in indigo.devices: dev = {} dev["restParent"] = "devices" dev["restURL"] = "/devices/" + urllib.quote(d.name) + ".json" dev["restURLEx"] = "/devices/" + str(d.id) + ".json" dev["nameURLEncoded"] = urllib.quote(d.name) dev["name"] = d.name ret.append (dev) if "css" in query: if query["css"][0] == "true": return "text/css", json.dumps(ret, indent=4) except Exception as e: self.logger.error (ext.getException(e)) return "application/json", json.dumps(ret)
def remove (self, obj): removeItems = [] try: for id, objinfo in self.items.iteritems(): if id == obj.id: removeItems.append(obj.id) # This parent device will be removed # Go through all items that we are watching for winfo in objinfo.watching: newChildWatchedBy = [] child = self.items[winfo.id] # This record should be there if we are watching something #indigo.server.log(unicode(child.id) + " - " + child.name) for cinfo in child.watchedBy: if cinfo.id != obj.id: newChildWatchedBy.append(cinfo) child.watchedBy = newChildWatchedBy if len(child.watching) == 0 and len(child.watchedBy) == 0: removeItems.append(child.id) # Remove child if watched by if it's not watching or being watched for id in removeItems: self.logger.threaddebug ("Cache item '{0}' is no longer referenced by anything, removing from cache".format(self.items[id].name)) del self.items[id] except Exception as e: self.logger.error (ext.getException(e))
def startServer (self, port, username = None, password = None): try: #self.factory.http.startServer (port, username, password) self.factory.http.run (port, username, password) except Exception as e: self.logger.error (ext.getException(e))
def dateStringFormat(value, oldFormat, newFormat): try: oldDate = datetime.datetime.strptime(value, oldFormat) return oldDate.strftime(newFormat) except Exception as e: self.logger.error(ext.getException(e))
def __init__(self, plugin): if plugin is None: return # pre-loading before init try: self.plugin = plugin # Sets the log format in the plugin and across all modules that can reference the plugin logformat = logging.Formatter('%(asctime)s.%(msecs)03d\t%(levelname)-12s\t%(name)s\t%(funcName)-25s\t%(msg)s', datefmt='%Y-%m-%d %H:%M:%S') plugin.plugin_file_handler.setFormatter(logformat) # Sets the localized logger with the module name appended self.logger = logging.getLogger ("Plugin.factory") # Initialize prefs and libraries self._prefInit () plugin.indigo_log_handler.setLevel(int(plugin.pluginPrefs["logLevel"])) self._libInit () # Do any previous generation cleanup self._cleanUp(plugin) # Done with init self.logger.threaddebug("EPS Factory {0} initialization complete".format(self.VERSION)) except Exception as e: self.logger.error (ext.getException(e))
def _check(self, force=False): try: if self.factory.plugin.UPDATE_URL == "" or self.factory.plugin.UPDATE_URL is None: return False if force == False and self._autoCheckOk() == False: return False self.logger.threaddebug("Checking site for current version") sock = urllib2.urlopen(self.factory.plugin.UPDATE_URL) page = sock.read() sock.close() result = re.findall("\#Version\|.*?\#", page) if len(result) == 0: return False versioninfo = result[0].replace("#", "").split("|") self.factory.plugin.pluginPrefs[ "lastUpdateCheck"] = indigo.server.getTime().strftime( "%Y-%m-%d %H:%M:%S") if self._upToDate(versioninfo[1]) == False: return versioninfo[1] except Exception as e: self.logger.error(ext.getException(e)) return False return False
def _setProperties(self): try: self.indent = 0 self.isRunning = False self.isPaused = False self.activeZone = 0 self.pausedZone = 0 self.scheduleStartTime = None self.scheduleEndTime = None self.scheduleRunTime = 0 self.scheduleMinutesRemaining = 0 self.scheduleMinutesComplete = 0 self.schedulePercentCompleted = 0 self.schedulePercentRemaining = 0 self.scheduleZonesComplete = 0 self.scheduleZonesRemaining = 0 self.zoneStartTime = None self.zoneEndTime = None self.zoneRunTime = 0 self.zoneMinutesRemaining = 0 self.zoneMinutesComplete = 0 self.zonePercentCompleted = 0 self.zonePercentRemaining = 0 self.pauseStartTime = None self.pauseEndTime = None self.isResuming = False except Exception as e: self.logger.error(ext.getException(e))
def _setProperties (self): try: self.indent = 0 self.isRunning = False self.isPaused = False self.activeZone = 0 self.pausedZone = 0 self.scheduleStartTime = None self.scheduleEndTime = None self.scheduleRunTime = 0 self.scheduleMinutesRemaining = 0 self.scheduleMinutesComplete = 0 self.schedulePercentCompleted = 0 self.schedulePercentRemaining = 0 self.scheduleZonesComplete = 0 self.scheduleZonesRemaining = 0 self.zoneStartTime = None self.zoneEndTime = None self.zoneRunTime = 0 self.zoneMinutesRemaining = 0 self.zoneMinutesComplete = 0 self.zonePercentCompleted = 0 self.zonePercentRemaining = 0 self.pauseStartTime = None self.pauseEndTime = None self.isResuming = False except Exception as e: self.logger.error (ext.getException(e))
def getWatchList(self): ret = {} ret["states"] = [] ret["attribs"] = [] try: ret["states"].append("activeZone") ret["states"].append("zone1") ret["states"].append("zone2") ret["states"].append("zone3") ret["states"].append("zone4") ret["states"].append("zone5") ret["states"].append("zone6") ret["states"].append("zone7") ret["states"].append("zone8") ret["attribs"].append("displayStateValRaw") ret["attribs"].append("displayStateValUi") ret["attribs"].append("enabled") ret["attribs"].append("pausedScheduleRemainingZoneDuration") ret["attribs"].append("pausedScheduleZone") ret["attribs"].append("zoneCount") ret["attribs"].append("zoneEnableList") ret["attribs"].append("zoneMaxDurations") ret["attribs"].append("zoneNames") ret["attribs"].append("zoneScheduledDurations") except Exception as e: self.logger.error(ext.getException(e)) return ret
def runConcurrentThread(self): try: if self.isRunning or self.isPaused: update = None self._refresh() # Do our calculations self.scheduleMinutesRemaining = round (dtutil.dateDiff ("minutes", self.scheduleEndTime, indigo.server.getTime()), 2) self.zoneMinutesRemaining = round (dtutil.dateDiff ("minutes", self.zoneEndTime, indigo.server.getTime()), 2) self.scheduleMinutesComplete = round (self.scheduleRunTime - self.scheduleMinutesRemaining, 2) self.zoneMinutesComplete = round (self.zoneRunTime - self.zoneMinutesRemaining, 2) self.schedulePercentRemaining = int(round(self.scheduleMinutesRemaining / self.scheduleRunTime, 2) * 100) self.zonePercentRemaining = int(round(self.zoneMinutesRemaining / self.zoneRunTime, 2) * 100) self.schedulePercentComplete = 100 - self.schedulePercentRemaining self.zonePercentComplete = 100 - self.zonePercentRemaining # Raise the event on the plugin update = self.parent.factory.raiseEvent ("onSprinklerProgressChanged", [self, self.SprinklerDeviceExUpdate()]) update = self.parent.factory.raiseEvent ("onZoneProgressChanged", [self, self.SprinklerDeviceExUpdate()]) self._processUpdateRecord (update) except Exception as e: self.logger.error (ext.getException(e))
def _cleanReturnList (self, dirtyList): ret = [] try: lastRetItem = "" for i in range (0, len(dirtyList)): try: if lastRetItem != "": if lastRetItem == dirtyList[i]: continue # don't add successive duplicates (mostly lines) if dirtyList[i] != "": lastRetItem = dirtyList[i] if dirtyList[i] is not None and dirtyList[i] != "": ret.append(dirtyList[i]) except: continue if len(ret) > 0: # Make sure we don't start on a line if ret[0] == ("-line-", self.factory.ui.getSeparator()): del ret[0] # Make sure we don't end on a line if len(ret) > 0 and ret[len(ret) - 1] == ("-line-", self.factory.ui.getSeparator()): del ret[len(ret) - 1] return ret except Exception as e: self.logger.error (ext.getException(e)) return dirtyList
def _updateFromSchedule (self): try: scheduledTimes = [] if len(self.dev.zoneScheduledDurations) > 0: scheduledTimes = self.dev.zoneScheduledDurations else: scheduledTimes = self.dev.zoneMaxDurations totalTime = 0 zoneTime = 0 zoneIdx = 1 # 1 based since activeZone is 1 based for i in scheduledTimes: if zoneIdx < self.dev.activeZone: zoneIdx = zoneIdx + 1 continue totalTime = totalTime + i if zoneIdx == self.dev.activeZone: zoneTime = i zoneIdx = zoneIdx + 1 self.scheduleStartTime = indigo.server.getTime() self.zoneStartTime = indigo.server.getTime() self.scheduleRunTime = totalTime self.zoneRunTime = zoneTime self.scheduleEndTime = dtutil.dateAdd ("minutes", totalTime, self.scheduleStartTime) self.zoneEndTime = dtutil.dateAdd ("minutes", zoneTime, self.zoneStartTime) except Exception as e: self.logger.error (ext.getException(e))
def _getActionUIList (self, plugInfo, deviceTypeId, showUIConfig, prefix = "plugin_"): ret = [] try: # Run through every device action and add a placeholder, we'll clean up after for id, action in plugInfo["xml"]["actions"].iteritems(): ret.append ("") for id, action in plugInfo["xml"]["actions"].iteritems(): isOk = True if "DeviceFilter" in action: isOk = self._isForDevice (plugInfo, deviceTypeId, action["DeviceFilter"]) if "ConfigUI" in action: if showUIConfig == False and len(action["ConfigUI"]) > 0: isOk = False if isOk: if action["Name"] == " - ": option = ("-line-", self.factory.ui.getSeparator()) ret[action["SortOrder"]] = option else: option = (prefix + id, action["Name"]) ret[action["SortOrder"]] = option except Exception as e: self.logger.error (ext.getException(e)) return ret
def addDevice (self, dev): try: if self.items.isInCache (dev.id): self.logger.debug ("Not adding {0} to cache because it's already there".format(dev.name)) return else: self.logger.debug ("Adding {0} to cache".format(dev.name)) cDev = cacheDev(dev) self.items.add(cDev) if cDev.pluginId == self.factory.plugin.pluginId: self._autoCacheFields (dev) if cDev.id in self.pluginDevices: pass else: self.pluginDevices.append(cDev.id) pluginItem = indigo.Dict() if cDev.deviceTypeId in self.pluginItems: pluginItem = self.pluginItems[cDev.deviceTypeId] else: pluginItem = indigo.List() if cDev.id in pluginItem: pass else: pluginItem.append(cDev.id) self.pluginItems[cDev.deviceTypeId] = pluginItem except Exception as e: self.logger.error (ext.getException(e))
def _cleanReturnList (self, dirtyList): ret = [] try: lastRetItem = "" for i in range (0, len(dirtyList)): try: if lastRetItem != "": if lastRetItem == dirtyList[i]: continue # don't add successive duplicates (mostly lines) if dirtyList[i] != "": lastRetItem = dirtyList[i] if dirtyList[i] is not None and dirtyList[i] != "": ret.append(dirtyList[i]) except: continue if len(ret) > 0: # Make sure we don't start on a line if ret[0] == ("-line-", self.factory.ui.getSeparator()): del ret[0] # Make sure we don't end on a line if len(ret) > 0 and ret[len(ret) - 1] == ("-line-", self.factory.ui.getSeparator()): del ret[len(ret) - 1] return ret except Exception as e: self.logger.error (ext.getException(e)) return dirtyList
def addWatchedProperty (self, parent, watchedItemsDict): try: for devId, property in watchedItemsDict.iteritems(): # If we are watching something then automatically turn on subscribeToChanges self.subscribeToChanges(indigo.devices[devId]) properties = [] # They can pass a single state or a list of states, we'll convert if needed if type(property) is list: properties = property else: properties.append(property) for property in properties: if ext.valueValid (indigo.devices[devId].ownerProps, property): self.logger.threaddebug ("Adding watched property '{0}' to child device '{1}' being watched by '{2}'".format(property, indigo.devices[devId].name, parent.name)) self.items.addWatchedProperty (parent, indigo.devices[devId], property) else: # If using our own engine then if there are no properties to watch it should be "-none-" if property != "-none-" and property != "": self.logger.warning ("Cannot watch property '{0}' on child device '{1}' for '{2}' because the child doesn't have that property ID".format(property, indigo.devices[devId].name, parent.name)) #self.logger.info(unicode(self.items)) except Exception as e: self.logger.error (ext.getException(e))
def _watchObject (self, dev, obj): try: self.subscribeToChanges (obj) self.items.addWatchedItem (dev, obj) except Exception as e: self.logger.error (ext.getException(e))
def addWatchedAttribute (self, parent, watchedItemsDict): try: for devId, attribute in watchedItemsDict.iteritems(): # If we are watching something then automatically turn on subscribeToChanges self.subscribeToChanges(indigo.devices[devId]) attributes = [] # They can pass a single state or a list of states, we'll convert if needed if type(attribute) is list: attributes = attribute else: attributes.append(attribute) for attribute in attributes: # Assuming we use our own factory to generate the list, get rid of "attr_" attribute = attribute.replace("attr_", "") # This should only come from our own core, therefore attributes should be pre-pended with "attr_", fix that attribute = attribute.replace("attr_", "") self.logger.threaddebug ("Adding watched attribute '{0}' to child device '{1}' being watched by '{2}'".format(attribute, indigo.devices[devId].name, parent.name)) self.items.addWatchedAttribute (parent, indigo.devices[devId], attribute) #self.logger.info(unicode(self.items)) except Exception as e: self.logger.error (ext.getException(e))
def addWatchedStates (self, parent, watchedItemsDict): try: # If we are watching something then automatically turn on subscribeToChanges self.subscribeToChanges(parent) for devId, state in watchedItemsDict.iteritems(): if int(devId) not in indigo.devices: self.logger.error ("Device '{0}' is referencing device ID {1} but that device is no longer an Indigo device. Please change the device reference or remove '{0}' to prevent this error".format(parent.name, str(devId))) continue states = [] # They can pass a single state or a list of states, we'll convert if needed if type(state) is list: states = state else: states.append(state) for state in states: if ext.valueValid (indigo.devices[devId].states, state): self.logger.threaddebug ("Adding watched state '{0}' to child device '{1}' being watched by '{2}'".format(state, indigo.devices[devId].name, parent.name)) self.items.addWatchedState (parent, indigo.devices[devId], state) else: # See if it's a custom state if state[0:7] == "custom_": self.logger.threaddebug ("Adding custom watched state '{0}' to child device '{1}' being watched by '{2}'".format(state, indigo.devices[devId].name, parent.name)) self.items.addWatchedState (parent, indigo.devices[devId], state) else: self.logger.warning ("Cannot watch state '{0}' on child device '{1}' for '{2}' because the child doesn't have that state".format(state, indigo.devices[devId].name, parent.name)) #self.logger.info(unicode(self.items)) except Exception as e: self.logger.error (ext.getException(e))
def __init__(self, plugin): if plugin is None: return # pre-loading before init try: #self.memory_summary () self.plugin = plugin # Sets the log format in the plugin and across all modules that can reference the plugin logformat = logging.Formatter( '%(asctime)s.%(msecs)03d-25s [%(levelname)-12s] %(name)-45s %(funcName)-45s %(msg)s', datefmt='%Y-%m-%d %H:%M:%S') plugin.plugin_file_handler.setFormatter(logformat) # Sets the localized logger with the module name appended self.logger = logging.getLogger("Plugin.factory") # Initialize prefs and libraries self._prefInit() plugin.indigo_log_handler.setLevel( int(plugin.pluginPrefs["logLevel"])) self._libInit() # Do any previous generation cleanup self._cleanUp(plugin) # Done with init self.logger.threaddebug( "EPS Factory {0} initialization complete".format(self.VERSION)) except Exception as e: self.logger.error(ext.getException(e))
def runConcurrentThread(self): try: for devId, dev in self.items.iteritems(): if "runConcurrentThread" in dir(dev): dev.runConcurrentThread () except Exception as e: self.logger.error (ext.getException(e))
def deviceUpdated (self, origDev, newDev, change): try: if newDev.id in self.items: if "deviceUpdated" in dir(self.items[newDev.id]): self.items[newDev.id].deviceUpdated (origDev, newDev, change) except Exception as e: self.logger.error (ext.getException(e))
def actionReturnedValue (self, action, id, args, value): try: self._callBack (BEFORE, []) self._callBack (AFTER, []) except Exception as e: self.logger.error (ext.getException(e))
def protocolCommandSentFromCache (self, dev, cmd, type): try: self._callBack (BEFORE, [dev, cmd, type]) self._callBack (AFTER, [dev, cmd, type]) except Exception as e: self.logger.error (ext.getException(e))