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 _validatePrefs (self): try: if ext.valueValid (self.factory.plugin.pluginPrefs, "latestVersion", True) == False: self.factory.plugin.pluginPrefs["latestVersion"] = False if ext.valueValid (self.factory.plugin.pluginPrefs, "lastUpdateCheck", True) == False: d = indigo.server.getTime() d = dtutil.dateAdd ("days", -30, d) # Forces us to check next time self.factory.plugin.pluginPrefs["lastUpdateCheck"] = d.strftime("%Y-%m-%d %H:%M:%S") except Exception as e: self.logger.error (ext.getException(e))
def _validatePrefs(self): try: if ext.valueValid(self.factory.plugin.pluginPrefs, "latestVersion", True) == False: self.factory.plugin.pluginPrefs["latestVersion"] = False if ext.valueValid(self.factory.plugin.pluginPrefs, "lastUpdateCheck", True) == False: d = indigo.server.getTime() d = dtutil.dateAdd("days", -30, d) # Forces us to check next time self.factory.plugin.pluginPrefs[ "lastUpdateCheck"] = d.strftime("%Y-%m-%d %H:%M:%S") 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 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 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 formFieldChanged (self, valuesDict, typeId, devId): try: if devId != 0: self.logger.debug ("Plugin device '{0}' configuration field changed".format(indigo.devices[devId].name)) else: self.logger.debug ("Configuration field changed") retval = self._callBack (BEFORE, [valuesDict, typeId, devId]) if retval is not None: valuesDict = retval # If we are using a "uniqueIdentifier" field then generate it if needed so we can reference it in # other libs that might look for it if ext.valueValid (valuesDict, "uniqueIdentifier"): if valuesDict["uniqueIdentifier"] == "" or valuesDict["uniqueIdentifier"] == "0": uId = int(random.random() * 100000000) valuesDict["uniqueIdentifier"] = str(uId) self.logger.threaddebug ("Assigned unique identifier of {0}".format(str(uId))) # See if we cached a list that we can use for default values if devId > 0: for field, value in valuesDict.iteritems(): if type(valuesDict[field]) is indigo.List: # We cannot default lists because they are multiple choice, skip them pass else: valuesDict[field] = self.factory.ui.getDefaultListItem (devId, field, value) else: # See if we have a unique ID we can use instead if ext.valueValid (valuesDict, "uniqueIdentifier"): if valuesDict["uniqueIdentifier"] != "" or valuesDict["uniqueIdentifier"] != "0": targetId = int(valuesDict["uniqueIdentifier"]) for field, value in valuesDict.iteritems(): valuesDict[field] = self.factory.ui.getDefaultListItem (targetId, field, value) if "cond" in dir(self.factory): valuesDict = self.factory.cond.setUIDefaults (valuesDict) if "act" in dir(self.factory): valuesDict = self.factory.act.setUIDefaults (valuesDict) retval = self._callBack (AFTER, [valuesDict, typeId, devId]) if retval is not None: valuesDict = retval except Exception as e: self.logger.error (ext.getException(e)) return valuesDict
def validateDeviceConfigUi(self, valuesDict, typeId, devId): self.logger.debug("Validating action parameters on device") errorDict = indigo.Dict() msg = "" try: # Check that we have either a strValuePassOn or strValueFailOn, if we don't then this is either # not an action or it's a pseudo action device that the plugin is handling one-off if ext.valueValid(valuesDict, self.VALIDATION) == False: self.logger.threaddebug( "The current device is not an action device, not validating actions" ) return (True, valuesDict, errorDict) # Make sure no -line- items are selected for i in range(0, len(self.FORMTERMS)): method = self.FORMTERMS[i] if ext.valueValid(valuesDict, self.OPT_LABEL + method + "1") == False: continue # may not have pass or may not have fail for j in range(1, self.maxFields): if ext.valueValid(valuesDict, self.MENU_VAL + method + str(j)): if valuesDict[self.MENU_VAL + method + str(j)] == "-line-": msg += "Field {0} has a line selected. ".format( str(j)) errorDict[self.MENU_VAL + method + str(j)] = "Invalid selection" if msg != "": msg = "There are problems with your conditions:\n\n" + msg errorDict["showAlertText"] = msg return (False, valuesDict, errorDict) except Exception as e: self.logger.error(ext.getException(e)) return (True, valuesDict, errorDict)
def zwaveCommandAction (self, cmd): nodeId = 0 try: byteList = cmd['bytes'] byteListStr = ' '.join(["%02X" % byte for byte in byteList]) if ext.valueValid (cmd, "nodeId", True): nodeId = cmd['nodeId'] cmdFunc = "Unknown" cmdF = int(cmd['bytes'][8]) if cmdF == 0: cmdFunc = "off" if cmdF == 255: cmdFunc = "on" return [nodeId, cmdFunc] except Exception as e: self.logger.error (ext.getException(e)) return [nodeId, "Unknown"]
def _addFieldToUI (self, propsDict, obj, action, field, method, fieldIdx): try: #indigo.server.log(unicode(field)) if ext.valueValid (propsDict, self.OPT_GROUP + method + str(fieldIdx)): # See if this is a self callback, in which case we need to disable the action if len(field["List"]) > 0: for listItem in field["List"]: if listItem["class"] == "self": msg = "\n" + self.factory.ui.debugHeaderEx () msg += self.factory.ui.debugLine ("Incompatible Device Action") msg += self.factory.ui.debugLine (" ") msg += self.factory.ui.debugLine ("Plugin Device: " + obj.name) msg += self.factory.ui.debugLine ("Action : " + action["Name"]) msg += self.factory.ui.debugLine (" ") msg += self.factory.ui.debugLine ("This action cannot be called because the plugin that manages it") msg += self.factory.ui.debugLine ("requires that one or more of their fields must 'callback' to") msg += self.factory.ui.debugLine ("their plugin in order for the action to work properly.") msg += self.factory.ui.debugLine (" ") msg += self.factory.ui.debugLine ("Please consider asking the developer of the plugin to add support") msg += self.factory.ui.debugLine ("for " + self.factory.plugin.pluginDisplayName + " by") msg += self.factory.ui.debugLine ("visiting our forum topic regarding developer API's.") msg += self.factory.ui.debugHeaderEx () self.logger.warn (msg) propsDict["showWarning"] = True if field["hidden"]: return propsDict # never show hidden fields if field["Label"] != "": propsDict[self.OPT_LABEL + method + str(fieldIdx)] = field["Label"] else: propsDict[self.OPT_LABEL + method + str(fieldIdx)] = field["Description"] propsDict[self.OPT_GROUP + method + str(fieldIdx)] = field["type"] except Exception as e: self.logger.error (ext.getException(e)) return propsDict
def _cleanUp (self, plugin): if ext.valueValid (plugin.pluginPrefs, "debugMode"): self.logger.info(u"Upgraded plugin preferences from pre-Indigo 7, depreciated preferences removed") del plugin.pluginPrefs["debugMode"]
def _addFieldToUI(self, propsDict, obj, action, field, method, fieldIdx): try: #indigo.server.log(unicode(field)) if ext.valueValid(propsDict, self.OPT_GROUP + method + str(fieldIdx)): # See if this is a self callback, in which case we need to disable the action if len(field["List"]) > 0: for listItem in field["List"]: if listItem["class"] == "self": msg = "\n" + self.factory.ui.debugHeaderEx() msg += self.factory.ui.debugLine( "Incompatible Device Action") msg += self.factory.ui.debugLine(" ") msg += self.factory.ui.debugLine( "Plugin Device: " + obj.name) msg += self.factory.ui.debugLine( "Action : " + action["Name"]) msg += self.factory.ui.debugLine(" ") msg += self.factory.ui.debugLine( "This action cannot be called because the plugin that manages it" ) msg += self.factory.ui.debugLine( "requires that one or more of their fields must 'callback' to" ) msg += self.factory.ui.debugLine( "their plugin in order for the action to work properly." ) msg += self.factory.ui.debugLine(" ") msg += self.factory.ui.debugLine( "Please consider asking the developer of the plugin to add support" ) msg += self.factory.ui.debugLine( "for " + self.factory.plugin.pluginDisplayName + " by") msg += self.factory.ui.debugLine( "visiting our forum topic regarding developer API's." ) msg += self.factory.ui.debugHeaderEx() self.logger.warn(msg) propsDict["showWarning"] = True if field["hidden"]: return propsDict # never show hidden fields if field["Label"] != "": propsDict[self.OPT_LABEL + method + str(fieldIdx)] = field["Label"] else: propsDict[self.OPT_LABEL + method + str(fieldIdx)] = field["Description"] propsDict[self.OPT_GROUP + method + str(fieldIdx)] = field["type"] except Exception as e: self.logger.error(ext.getException(e)) return propsDict
def runAction (self, propsDict, method = None): try: if method is None: method = self.FORMTERMS[0] # Check that we have either a strValuePassOn or strValueFailOn, if we don't then this is either # not an action or it's a pseudo action device that the plugin is handling one-off if ext.valueValid (propsDict, self.VALIDATION) == False: self.logger.threaddebug ("The current device is not an action device with {0}, not running action".format(self.VALIDATION)) return False # See if we are allowing multiple objects, if not default to device objType = "device" # If we are allowing multiple objects make sure our selection is valid if ext.valueValid (propsDict, self.FIELDPREFIX + method): if ext.valueValid (propsDict, self.FIELDPREFIX + method, True): objType = propsDict[self.FIELDPREFIX + method] else: # It's blank or a line or something, just skip self.logger.warn ("No method was selected for an action, it cannot be run") return False self.logger.threaddebug ("Running action type '{0}' for a '{1}' condition".format(objType, method)) if objType == "action": if ext.valueValid (propsDict, "action" + method, True): indigo.actionGroup.execute(int(propsDict["action" + method])) if objType == "device": if ext.valueValid (propsDict, self.DEV + method, True): # No sense proceeding here unless they selected an action so we know what options to turn on if ext.valueValid (propsDict, self.DEV_ACTION + method, True): dev = indigo.devices[int(propsDict[self.DEV + method])] # Get the action list from plugcache for this device actions = self.factory.plugcache.getActions (dev) args = {} actionItem = None rawAction = "" fieldIdx = 1 for id, action in actions.iteritems(): if id == propsDict[self.DEV_ACTION + method]: actionItem = action rawAction = id if "ConfigUI" in action: if "Fields" in action["ConfigUI"]: for field in action["ConfigUI"]["Fields"]: args[field["id"]] = self._getGroupFieldValue (propsDict, method, field["ValueType"], field["Default"], fieldIdx) fieldIdx = fieldIdx + 1 return self._executeAction (dev, rawAction, actionItem, args) if objType == "server": # Get the action list from plugcache for this device actions = self.factory.plugcache.getActions ("server") args = {} actionItem = None rawAction = "" fieldIdx = 1 for id, action in actions.iteritems(): if id == propsDict["serverAction" + method]: actionItem = action rawAction = id if "ConfigUI" in action: if "Fields" in action["ConfigUI"]: for field in action["ConfigUI"]["Fields"]: args[field["id"]] = self._getGroupFieldValue (propsDict, method, field["ValueType"], field["Default"], fieldIdx) fieldIdx = fieldIdx + 1 return self._executeAction (None, rawAction, actionItem, args) if objType == "variable": if ext.valueValid (propsDict, self.VAR + method, True): # No sense proceeding here unless they selected an action so we know what options to turn on if ext.valueValid (propsDict, self.VAR_ACTION + method, True): var = indigo.variables[int(propsDict[self.VAR + method])] # Get the action list from plugcache for this device actions = self.factory.plugcache.getActions (var) args = {} actionItem = None rawAction = "" fieldIdx = 1 for id, action in actions.iteritems(): if id == propsDict[self.VAR_ACTION + method]: actionItem = action rawAction = id if "ConfigUI" in action: if "Fields" in action["ConfigUI"]: for field in action["ConfigUI"]["Fields"]: args[field["id"]] = self._getGroupFieldValue (propsDict, method, field["ValueType"], field["Default"], fieldIdx) fieldIdx = fieldIdx + 1 return self._executeAction (var, rawAction, actionItem, args) except Exception as e: self.logger.error (ext.getException(e)) return False return True
def setUIDefaults (self, propsDict, defaultCondition = "disabled", defaultState = "onOffState"): try: # Check that we have either a strValuePassOn or strValueFailOn, if we don't then this is either # not an action or it's a pseudo action device that the plugin is handling one-off if ext.valueValid (propsDict, self.VALIDATION) == False: self.logger.threaddebug ("The current device is not an action device, not setting defaults") return propsDict for i in range (0, len(self.FORMTERMS)): method = self.FORMTERMS[i] if ext.valueValid (propsDict, self.OPT_LABEL + method + "1") == False: self.logger.threaddebug ("{0} doesn't seem to apply to this device, skipping defaults".format(method)) continue # may not have pass or may not have fail # See if we are allowing multiple objects, if not default to device objType = "device" # If we are allowing multiple objects make sure our selection is valid if ext.valueValid (propsDict, self.FIELDPREFIX + method): if ext.valueValid (propsDict, self.FIELDPREFIX + method, True): objType = propsDict[self.FIELDPREFIX + method] else: # It's blank or a line or something, just skip continue # Assume no fields unless we find some maxFormFields = 0 for j in range (1, self.maxFields): if ext.valueValid (propsDict, self.OPT_GROUP + method + str(j)): propsDict[self.OPT_GROUP + method + str(j)] = "hidden" maxFormFields = maxFormFields + 1 # Assume this action can be run propsDict["showWarning" + method] = False propsDict["showFieldWarning" + method] = False if objType == "variable": if ext.valueValid (propsDict, self.VAR + method, True): # No sense proceeding here unless they selected an action so we know what options to turn on if ext.valueValid (propsDict, self.VAR_ACTION + method, True): var = indigo.variables[int(propsDict[self.VAR + method])] # Get the action list from plugcache for this device actions = self.factory.plugcache.getActions (var) fieldIdx = 1 for id, action in actions.iteritems(): if id == propsDict[self.VAR_ACTION + method]: if "ConfigUI" in action: if "Fields" in action["ConfigUI"]: # First make sure we have enough fields to support the action if len(action["ConfigUI"]["Fields"]) > maxFormFields: propsDict["showFieldWarning" + method] = True for field in action["ConfigUI"]["Fields"]: propsDict = self._addFieldToUI (propsDict, var, action, field, method, fieldIdx) fieldIdx = fieldIdx + 1 elif objType == "server": actions = self.factory.plugcache.getActions ("server") fieldIdx = 1 for id, action in actions.iteritems(): if id == propsDict["serverAction" + method]: if "ConfigUI" in action: if "Fields" in action["ConfigUI"]: # First make sure we have enough fields to support the action if len(action["ConfigUI"]["Fields"]) > maxFormFields: propsDict["showFieldWarning" + method] = True for field in action["ConfigUI"]["Fields"]: propsDict = self._addFieldToUI (propsDict, None, action, field, method, fieldIdx) fieldIdx = fieldIdx + 1 elif objType == "device": if ext.valueValid (propsDict, self.DEV + method, True): # No sense proceeding here unless they selected an action so we know what options to turn on if ext.valueValid (propsDict, self.DEV_ACTION + method, True): dev = indigo.devices[int(propsDict[self.DEV + method])] # Get the action list from plugcache for this device actions = self.factory.plugcache.getActions (dev) fieldIdx = 1 for id, action in actions.iteritems(): if id == propsDict[self.DEV_ACTION + method]: if "ConfigUI" in action: if "Fields" in action["ConfigUI"]: # First make sure we have enough fields to support the action if len(action["ConfigUI"]["Fields"]) > maxFormFields: propsDict["showFieldWarning" + method] = True for field in action["ConfigUI"]["Fields"]: propsDict = self._addFieldToUI (propsDict, dev, action, field, method, fieldIdx) fieldIdx = fieldIdx + 1 # In case our actions caused the developer warning, turn off all field options if propsDict["showWarning" + method] or propsDict["showFieldWarning" + method]: for j in range (1, self.maxFields): if ext.valueValid (propsDict, self.OPT_GROUP + method + str(j)): propsDict[self.OPT_GROUP + method + str(j)] = "hidden" # In case we got a developer warning make sure the field warning is off if propsDict["showWarning" + method]: propsDict["showFieldWarning" + method] = False except Exception as e: self.logger.error (ext.getException(e)) #indigo.server.log(unicode(propsDict)) return propsDict
def actionControlDimmerRelay(self, action, dev): try: self.logger.threaddebug ("Plugin device '{0}' command sent".format(dev.name)) self._callBack (BEFORE, [dev]) success = False stateName = "onOffState" stateVal = True command = "on" if action.deviceAction == indigo.kDimmerRelayAction.TurnOn: command = "on" stateName = "onOffState" success = self._callBack (NOTHING, [dev], "onDeviceCommandTurnOn") if success: stateVal = True elif action.deviceAction == indigo.kDimmerRelayAction.TurnOff: command = "off" stateName = "onOffState" success = self._callBack (NOTHING, [dev], "onDeviceCommandTurnOff") if success: stateVal = False elif action.deviceAction == indigo.kDimmerRelayAction.Toggle: command = "toggle" stateName = "onOffState" stateVal = dev.states["onOffState"] #success = self._callBack (NOTHING, [dev], "onDeviceCommandToggle") # Toggle is just a fancy name for on and off, so raise the on and off events if stateVal: success = self._callBack (NOTHING, [dev], "onDeviceCommandTurnOff") else: success = self._callBack (NOTHING, [dev], "onDeviceCommandTurnOn") if success: # Reverse the state value so we can update our own state to be the opposite of what it was if stateVal: stateVal = False else: stateVal = True elif action.deviceAction == indigo.kDimmerRelayAction.SetBrightness: command = "set brightness" stateName = "brightnessLevel" if ext.valueValid (dev.states, stateName): success = self._callBack (NOTHING, [dev, action.actionValue], "onDeviceCommandSetBrightness") stateVal = action.actionValue else: success = False if success: stateVal = action.actionValue else: self.logger.error ("Unknown device command: " + unicode(action)) if success: dev.updateStateOnServer(stateName, stateVal) self.logger.info(u"sent \"%s\" %s" % (dev.name, command)) else: self.logger.error (u"send \"%s\" %s failed" % (dev.name, command)) self._callBack (AFTER, [dev]) except Exception as e: self.logger.error (ext.getException(e))
def _getGroupFieldValue (self, propsDict, method, type, default, index): ret = "" try: if ext.valueValid (propsDict, self.OPT_GROUP + method + str(index), True): # In case the plugin is hiding a valid field, unhide it here propsDict[self.OPT_GROUP + method + str(index)] = self.toggleGroupVisibility (propsDict[self.OPT_GROUP + method + str(index)], True) if propsDict[self.OPT_GROUP + method + str(index)] == "textfield": ret = propsDict[self.STR_VAL + method + str(index)] elif propsDict[self.OPT_GROUP + method + str(index)] == "menu": ret = propsDict[self.MENU_VAL + method + str(index)] elif propsDict[self.OPT_GROUP + method + str(index)] == "list": ret = propsDict[self.LIST_VAL + method + str(index)] elif propsDict[self.OPT_GROUP + method + str(index)] == "checkbox": ret = propsDict[self.CHECK_VAL + method + str(index)] if ret is None or ret == "" and default is not None: ret = default if ret != "": if type == "integer": ret = int(ret) elif type == "delay": # Convert HH:MM:SS to seconds timeStr = ret.split(":") ret = 0 if len(timeStr) == 3: ret = ret + (int(timeStr[0]) * 1440) ret = ret + (int(timeStr[1]) * 60) ret = ret + int(timeStr[2]) elif type == "list": # Converts a string or comma delimited string to a list data = ret.split(",") ret = [] for d in data: ret.append(d.strip()) elif type == "indigo_enum": # The value is the enum to lookup ret = ret.replace("indigo.", "") data = ret.split(".") ret = getattr (indigo, data[0]) ret = getattr (ret, data[1]) else: # It's a string ret = ret except Exception as e: self.logger.error (ext.getException(e)) return ret
def runAction(self, propsDict, method=None): try: if method is None: method = self.FORMTERMS[0] # Check that we have either a strValuePassOn or strValueFailOn, if we don't then this is either # not an action or it's a pseudo action device that the plugin is handling one-off if ext.valueValid(propsDict, self.VALIDATION) == False: self.logger.threaddebug( "The current device is not an action device with {0}, not running action" .format(self.VALIDATION)) return False # See if we are allowing multiple objects, if not default to device objType = "device" # If we are allowing multiple objects make sure our selection is valid if ext.valueValid(propsDict, self.FIELDPREFIX + method): if ext.valueValid(propsDict, self.FIELDPREFIX + method, True): objType = propsDict[self.FIELDPREFIX + method] else: # It's blank or a line or something, just skip self.logger.warn( "No method was selected for an action, it cannot be run" ) return False self.logger.threaddebug( "Running action type '{0}' for a '{1}' condition".format( objType, method)) if objType == "action": if ext.valueValid(propsDict, "action" + method, True): indigo.actionGroup.execute( int(propsDict["action" + method])) if objType == "device": if ext.valueValid(propsDict, self.DEV + method, True): # No sense proceeding here unless they selected an action so we know what options to turn on if ext.valueValid(propsDict, self.DEV_ACTION + method, True): dev = indigo.devices[int(propsDict[self.DEV + method])] # Get the action list from plugcache for this device actions = self.factory.plugcache.getActions(dev) args = {} actionItem = None rawAction = "" fieldIdx = 1 for id, action in actions.iteritems(): if id == propsDict[self.DEV_ACTION + method]: actionItem = action rawAction = id if "ConfigUI" in action: if "Fields" in action["ConfigUI"]: for field in action["ConfigUI"][ "Fields"]: args[field[ "id"]] = self._getGroupFieldValue( propsDict, method, field["ValueType"], field["Default"], fieldIdx) fieldIdx = fieldIdx + 1 return self._executeAction(dev, rawAction, actionItem, args) if objType == "server": # Get the action list from plugcache for this device actions = self.factory.plugcache.getActions("server") args = {} actionItem = None rawAction = "" fieldIdx = 1 for id, action in actions.iteritems(): if id == propsDict["serverAction" + method]: actionItem = action rawAction = id if "ConfigUI" in action: if "Fields" in action["ConfigUI"]: for field in action["ConfigUI"]["Fields"]: args[field[ "id"]] = self._getGroupFieldValue( propsDict, method, field["ValueType"], field["Default"], fieldIdx) fieldIdx = fieldIdx + 1 return self._executeAction(None, rawAction, actionItem, args) if objType == "variable": if ext.valueValid(propsDict, self.VAR + method, True): # No sense proceeding here unless they selected an action so we know what options to turn on if ext.valueValid(propsDict, self.VAR_ACTION + method, True): var = indigo.variables[int(propsDict[self.VAR + method])] # Get the action list from plugcache for this device actions = self.factory.plugcache.getActions(var) args = {} actionItem = None rawAction = "" fieldIdx = 1 for id, action in actions.iteritems(): if id == propsDict[self.VAR_ACTION + method]: actionItem = action rawAction = id if "ConfigUI" in action: if "Fields" in action["ConfigUI"]: for field in action["ConfigUI"][ "Fields"]: args[field[ "id"]] = self._getGroupFieldValue( propsDict, method, field["ValueType"], field["Default"], fieldIdx) fieldIdx = fieldIdx + 1 return self._executeAction(var, rawAction, actionItem, args) except Exception as e: self.logger.error(ext.getException(e)) return False return True
def _cleanUp(self, plugin): if ext.valueValid(plugin.pluginPrefs, "debugMode"): self.logger.info( u"Upgraded plugin preferences from pre-Indigo 7, depreciated preferences removed" ) del plugin.pluginPrefs["debugMode"]
def _getGroupFieldValue(self, propsDict, method, type, default, index): ret = "" try: if ext.valueValid(propsDict, self.OPT_GROUP + method + str(index), True): # In case the plugin is hiding a valid field, unhide it here propsDict[self.OPT_GROUP + method + str(index)] = self.toggleGroupVisibility( propsDict[self.OPT_GROUP + method + str(index)], True) if propsDict[self.OPT_GROUP + method + str(index)] == "textfield": ret = propsDict[self.STR_VAL + method + str(index)] elif propsDict[self.OPT_GROUP + method + str(index)] == "menu": ret = propsDict[self.MENU_VAL + method + str(index)] elif propsDict[self.OPT_GROUP + method + str(index)] == "list": ret = propsDict[self.LIST_VAL + method + str(index)] elif propsDict[self.OPT_GROUP + method + str(index)] == "checkbox": ret = propsDict[self.CHECK_VAL + method + str(index)] if ret is None or ret == "" and default is not None: ret = default if ret != "": if type == "integer": ret = int(ret) elif type == "delay": # Convert HH:MM:SS to seconds timeStr = ret.split(":") ret = 0 if len(timeStr) == 3: ret = ret + (int(timeStr[0]) * 1440) ret = ret + (int(timeStr[1]) * 60) ret = ret + int(timeStr[2]) elif type == "list": # Converts a string or comma delimited string to a list data = ret.split(",") ret = [] for d in data: ret.append(d.strip()) elif type == "indigo_enum": # The value is the enum to lookup ret = ret.replace("indigo.", "") data = ret.split(".") ret = getattr(indigo, data[0]) ret = getattr(ret, data[1]) else: # It's a string ret = ret except Exception as e: self.logger.error(ext.getException(e)) return ret
def setUIDefaults(self, propsDict, defaultCondition="disabled", defaultState="onOffState"): try: # Check that we have either a strValuePassOn or strValueFailOn, if we don't then this is either # not an action or it's a pseudo action device that the plugin is handling one-off if ext.valueValid(propsDict, self.VALIDATION) == False: self.logger.threaddebug( "The current device is not an action device, not setting defaults" ) return propsDict for i in range(0, len(self.FORMTERMS)): method = self.FORMTERMS[i] if ext.valueValid(propsDict, self.OPT_LABEL + method + "1") == False: self.logger.threaddebug( "{0} doesn't seem to apply to this device, skipping defaults" .format(method)) continue # may not have pass or may not have fail # See if we are allowing multiple objects, if not default to device objType = "device" # If we are allowing multiple objects make sure our selection is valid if ext.valueValid(propsDict, self.FIELDPREFIX + method): if ext.valueValid(propsDict, self.FIELDPREFIX + method, True): objType = propsDict[self.FIELDPREFIX + method] else: # It's blank or a line or something, just skip continue # Assume no fields unless we find some maxFormFields = 0 for j in range(1, self.maxFields): if ext.valueValid(propsDict, self.OPT_GROUP + method + str(j)): propsDict[self.OPT_GROUP + method + str(j)] = "hidden" maxFormFields = maxFormFields + 1 # Assume this action can be run propsDict["showWarning" + method] = False propsDict["showFieldWarning" + method] = False if objType == "variable": if ext.valueValid(propsDict, self.VAR + method, True): # No sense proceeding here unless they selected an action so we know what options to turn on if ext.valueValid(propsDict, self.VAR_ACTION + method, True): var = indigo.variables[int(propsDict[self.VAR + method])] # Get the action list from plugcache for this device actions = self.factory.plugcache.getActions(var) fieldIdx = 1 for id, action in actions.iteritems(): if id == propsDict[self.VAR_ACTION + method]: if "ConfigUI" in action: if "Fields" in action["ConfigUI"]: # First make sure we have enough fields to support the action if len(action["ConfigUI"] ["Fields"]) > maxFormFields: propsDict["showFieldWarning" + method] = True for field in action["ConfigUI"][ "Fields"]: propsDict = self._addFieldToUI( propsDict, var, action, field, method, fieldIdx) fieldIdx = fieldIdx + 1 elif objType == "server": actions = self.factory.plugcache.getActions("server") fieldIdx = 1 for id, action in actions.iteritems(): if id == propsDict["serverAction" + method]: if "ConfigUI" in action: if "Fields" in action["ConfigUI"]: # First make sure we have enough fields to support the action if len(action["ConfigUI"] ["Fields"]) > maxFormFields: propsDict["showFieldWarning" + method] = True for field in action["ConfigUI"]["Fields"]: propsDict = self._addFieldToUI( propsDict, None, action, field, method, fieldIdx) fieldIdx = fieldIdx + 1 elif objType == "device": if ext.valueValid(propsDict, self.DEV + method, True): # No sense proceeding here unless they selected an action so we know what options to turn on if ext.valueValid(propsDict, self.DEV_ACTION + method, True): dev = indigo.devices[int(propsDict[self.DEV + method])] # Get the action list from plugcache for this device actions = self.factory.plugcache.getActions(dev) fieldIdx = 1 for id, action in actions.iteritems(): if id == propsDict[self.DEV_ACTION + method]: if "ConfigUI" in action: if "Fields" in action["ConfigUI"]: # First make sure we have enough fields to support the action if len(action["ConfigUI"] ["Fields"]) > maxFormFields: propsDict["showFieldWarning" + method] = True for field in action["ConfigUI"][ "Fields"]: propsDict = self._addFieldToUI( propsDict, dev, action, field, method, fieldIdx) fieldIdx = fieldIdx + 1 # In case our actions caused the developer warning, turn off all field options if propsDict["showWarning" + method] or propsDict[ "showFieldWarning" + method]: for j in range(1, self.maxFields): if ext.valueValid( propsDict, self.OPT_GROUP + method + str(j)): propsDict[self.OPT_GROUP + method + str(j)] = "hidden" # In case we got a developer warning make sure the field warning is off if propsDict["showWarning" + method]: propsDict["showFieldWarning" + method] = False except Exception as e: self.logger.error(ext.getException(e)) #indigo.server.log(unicode(propsDict)) return propsDict
def getActionOptionUIList (self, args, valuesDict): ret = [("default", "No data")] try: retList = [] if ext.valueValid (args, "group", True) and ext.valueValid (args, "method", True): group = args["group"] method = args["method"] objType = "device" if ext.valueValid (valuesDict, self.FIELDPREFIX + method, True): if valuesDict[self.FIELDPREFIX + method] == "variable": objType = "variable" if valuesDict[self.FIELDPREFIX + method] == "server": objType = "server" # In order to populate we have to have a device and an action if ext.valueValid (valuesDict, objType + method, True) or objType == "server": if objType == "device": obj = indigo.devices[int(valuesDict[objType + method])] if objType == "variable": obj = indigo.variables[int(valuesDict[objType + method])] if objType == "server": obj = "server" listData = self._getActionOptionUIList (obj, objType, valuesDict, method) #indigo.server.log(unicode(listData)) listIdx = 1 for listItem in listData: # Only return the list for this group if listIdx != int(group): listIdx = listIdx + 1 continue #indigo.server.log(unicode(listItem)) #indigo.server.log(unicode(listItem["Options"])) if len(listItem["Options"]) > 0: for opt in listItem["Options"]: if opt["value"] == "-line-": option = ("-line-", self.factory.ui.getSeparator()) else: option = (opt["value"], opt["Label"]) retList.append (option) elif listItem["class"] == "indigo.dimmer": for d in indigo.devices.iter("indigo.dimmer"): option = (d.id, d.name) retList.append (option) elif listItem["class"] == "indigo.triggers": for d in indigo.triggers: option = (d.id, d.name) retList.append (option) elif listItem["class"] == "indigo.schedules": for d in indigo.schedules: option = (d.id, d.name) retList.append (option) elif listItem["class"] == "indigo.devices": for d in indigo.devices: option = (d.id, d.name) retList.append (option) elif listItem["class"] == "indigo.variables": for d in indigo.variables: option = (d.id, d.name) retList.append (option) elif listItem["class"] == "custom.zonenames": for i in range (0, 8): if dev.zoneEnableList[i]: option = (str(i + 1), dev.zoneNames[i]) retList.append (option) listIdx = listIdx + 1 if len(retList) > 0: return retList except Exception as e: self.logger.error (ext.getException(e)) return ret return ret
def validateDeviceConfigUi(self, valuesDict, typeId, devId): self.logger.debug ("Validating action parameters on device") errorDict = indigo.Dict() msg = "" try: # Check that we have either a strValuePassOn or strValueFailOn, if we don't then this is either # not an action or it's a pseudo action device that the plugin is handling one-off if ext.valueValid (valuesDict, self.VALIDATION) == False: self.logger.threaddebug ("The current device is not an action device, not validating actions") return (True, valuesDict, errorDict) # Make sure no -line- items are selected for i in range (0, len(self.FORMTERMS)): method = self.FORMTERMS[i] if ext.valueValid (valuesDict, self.OPT_LABEL + method + "1") == False: continue # may not have pass or may not have fail for j in range (1, self.maxFields): if ext.valueValid (valuesDict, self.MENU_VAL + method + str(j)): if valuesDict[self.MENU_VAL + method + str(j)] == "-line-": msg += "Field {0} has a line selected. ".format(str(j)) errorDict[self.MENU_VAL + method + str(j)] = "Invalid selection" if msg != "": msg = "There are problems with your conditions:\n\n" + msg errorDict["showAlertText"] = msg return (False, valuesDict, errorDict) except Exception as e: self.logger.error (ext.getException(e)) return (True, valuesDict, errorDict)
def getActionOptionUIList(self, args, valuesDict): ret = [("default", "No data")] try: retList = [] if ext.valueValid(args, "group", True) and ext.valueValid( args, "method", True): group = args["group"] method = args["method"] objType = "device" if ext.valueValid(valuesDict, self.FIELDPREFIX + method, True): if valuesDict[self.FIELDPREFIX + method] == "variable": objType = "variable" if valuesDict[self.FIELDPREFIX + method] == "server": objType = "server" # In order to populate we have to have a device and an action if ext.valueValid(valuesDict, objType + method, True) or objType == "server": if objType == "device": obj = indigo.devices[int(valuesDict[objType + method])] if objType == "variable": obj = indigo.variables[int(valuesDict[objType + method])] if objType == "server": obj = "server" listData = self._getActionOptionUIList( obj, objType, valuesDict, method) #indigo.server.log(unicode(listData)) listIdx = 1 for listItem in listData: # Only return the list for this group if listIdx != int(group): listIdx = listIdx + 1 continue #indigo.server.log(unicode(listItem)) #indigo.server.log(unicode(listItem["Options"])) if len(listItem["Options"]) > 0: for opt in listItem["Options"]: if opt["value"] == "-line-": option = ("-line-", self.factory.ui.getSeparator()) else: option = (opt["value"], opt["Label"]) retList.append(option) elif listItem["class"] == "indigo.dimmer": for d in indigo.devices.iter("indigo.dimmer"): option = (d.id, d.name) retList.append(option) elif listItem["class"] == "indigo.triggers": for d in indigo.triggers: option = (d.id, d.name) retList.append(option) elif listItem["class"] == "indigo.schedules": for d in indigo.schedules: option = (d.id, d.name) retList.append(option) elif listItem["class"] == "indigo.devices": for d in indigo.devices: option = (d.id, d.name) retList.append(option) elif listItem["class"] == "indigo.variables": for d in indigo.variables: option = (d.id, d.name) retList.append(option) elif listItem["class"] == "custom.zonenames": for i in range(0, 8): if obj.zoneEnableList[i]: option = (str(i + 1), dev.zoneNames[i]) retList.append(option) listIdx = listIdx + 1 if len(retList) > 0: return retList except Exception as e: self.logger.error(ext.getException(e)) return ret return ret