def autoCollapseConditions (self, valuesDict): try: currentBlock = int(valuesDict["currentCondition"]) # Run through all conditions, if any other than the current is checked then update for i in range (1, self.maxConditions + 1): if eps.valueValid (valuesDict, "expandConditions" + str(i)): if valuesDict["expandConditions" + str(i)] and i != currentBlock: currentBlock = i break # Now collapse all but the current block for i in range (1, self.maxConditions + 1): if eps.valueValid (valuesDict, "expandConditions" + str(i)): if i != currentBlock: valuesDict["expandConditions" + str(i)] = False # Hide/show fields for all unexpanded/expanded conditions for i in range (1, self.maxConditions + 1): if eps.valueValid (valuesDict, "expandConditions" + str(i)): valuesDict = self.setUIValueVisibility (valuesDict, i) # also hide options # Save the current block self.debugLog ("Current condition block set to %i" % currentBlock) valuesDict["currentCondition"] = str(currentBlock) except Exception as e: eps.printException(e) return valuesDict
def conditionsPass (self, dev): try: isTrue = 0 isFalse = 0 if eps.valueValid (dev.pluginProps, "conditions", True) == False: return False condition = dev.pluginProps["conditions"] self.debugLog ("\tCondition is set to %s, testing condition(s)" % condition) if condition == "none": return True for i in range (0, self.maxConditions + 1): if eps.valueValid (dev.pluginProps, "condition" + str(i), True) == False: continue # no condition for this index if dev.pluginProps["condition" + str(i)] == "disabled": continue # this condition is disabled val = [0,0] # Failsafe if dev.pluginProps["evaluation" + str(i)] == "between" or dev.pluginProps["evaluation" + str(i)] == "notbetween": val = self.conditionBetween (dev, i) if dev.pluginProps["evaluation" + str(i)] == "equal" or dev.pluginProps["evaluation" + str(i)] == "notequal": val = self.conditionEquals (dev, i) if dev.pluginProps["evaluation" + str(i)] == "greater": val = self.conditionGreater (dev, i) if dev.pluginProps["evaluation" + str(i)] == "less": val = self.conditionLess (dev, i) if dev.pluginProps["evaluation" + str(i)] == "contains" or dev.pluginProps["evaluation" + str(i)] == "notcontains": val = self.conditionContain (dev, i) isTrue = isTrue + val[0] isFalse = isFalse + val[1] if condition == "alltrue" and isFalse <> 0: return False if condition == "anytrue" and isTrue == 0: return False if condition == "allfalse" and isTrue <> 0: return False if condition == "anyfalse" and isFalse == 0: return False except Exception as e: eps.printException(e) return False
def getDevStateDateTime (self, dev, devEx, index): d = indigo.server.getTime() try: if eps.valueValid (devEx.states, dev.pluginProps["state" + str(index)]) and eps.valueValid (dev.pluginProps, "dtFormat" + str(index), True): compareString = unicode(devEx.states[dev.pluginProps["state" + str(index)]]) self.debugLog ("\tConverting state '%s' date of '%s' using format '%s'" % (dev.pluginProps["state" + str(index)], compareString, dev.pluginProps["dtFormat" + str(index)])) d = datetime.datetime.strptime (compareString, dev.pluginProps["dtFormat" + str(index)]) except Exception as e: eps.printException(e) return d
def getVarDateTime (self, dev, index): d = indigo.server.getTime() try: if eps.valueValid (dev.pluginProps, "variable" + str(index), True) and eps.valueValid (dev.pluginProps, "dtFormat" + str(index), True): compareString = indigo.variables[int(dev.pluginProps["variable" + str(index)])].value self.debugLog ("\tConverting variable '%s' date of '%s' using format '%s'" % (indigo.variables[int(dev.pluginProps["variable" + str(index)])].name, compareString, dev.pluginProps["dtFormat" + str(index)])) d = datetime.datetime.strptime (compareString, dev.pluginProps["dtFormat" + str(index)]) except Exception as e: eps.printException(e) return d
def collapseAllConditions (self, dev): try: props = dev.pluginProps # See if this is a brand new device and if it is then set defaults if eps.valueValid (dev.pluginProps, "isNewDevice"): if dev.pluginProps["isNewDevice"]: #indigo.server.log("%s added, enabling conditions. You can now re-open the device to use conditions" % dev.name) props["conditions"] = "none" props["isNewDevice"] = False for i in range (1, self.maxConditions + 1): props = self.setUIDefaults (props, "disabled", "onOffState") dev.replacePluginPropsOnServer(props) return # don't do anything else # Set up collapse options if eps.valueValid (dev.pluginProps, "expandConditions1"): if props["expandConditions1"] == False: props["expandConditions1"] = True props["currentCondition"] = "1" props["noneExpanded"] = False # Check for multiple conditions to see if we need the padding if props["conditions"] != "none": for i in range (2, self.maxConditions + 1): if eps.valueValid (dev.pluginProps, "expandConditions" + str(i)): props["multiConditions"] = True # gives us extra padding on multiple conditions break props = self.setUIValueVisibility (props, 1) else: # If we don't have condition 1 then we don't have any return for i in range (2, self.maxConditions + 1): if eps.valueValid (dev.pluginProps, "expandConditions" + str(i)): if dev.pluginProps["expandConditions" + str(i)]: props["expandConditions" + str(i)] = False props = self.setUIDefaults (props, "disabled", "onOffState") if props != dev.pluginProps: self.debugLog ("Collapsing all conditions for %s" % dev.name) dev.replacePluginPropsOnServer(props) except Exception as e: eps.printException(e) return
def conditionBetween (self, dev, index): ret = [] isTrue = 0 isFalse = 0 try: #if dev.pluginProps["condition" + str(index)] == "timeonly" or dev.pluginProps["condition" + str(index)] == "devstatetimeonly" or dev.pluginProps["condition" + str(index)] == "vartimeonly": val = self.conditionsDateBetween (dev, index, True, False) #if dev.pluginProps["condition" + str(index)] == "dateonly" or dev.pluginProps["condition" + str(index)] == "devstatedateonly" or dev.pluginProps["condition" + str(index)] == "vardateonly": val = self.conditionsDateBetween (dev, index, False, True) #if dev.pluginProps["condition" + str(index)] == "datetime" or dev.pluginProps["condition" + str(index)] == "devstatedatetime" or dev.pluginProps["condition" + str(index)] == "vardatetime": val = self.conditionsDateBetween (dev, index, True, True) #if dev.pluginProps["condition" + str(index)] == "dow" or dev.pluginProps["condition" + str(index)] == "devstatedow": val = self.conditionsDow (dev, index) if dev.pluginProps["condition" + str(index)] == "datetime" or dev.pluginProps["condition" + str(index)] == "devstatedatetime" or dev.pluginProps["condition" + str(index)] == "vardatetime": val = self.conditionsDate (dev, index) if dev.pluginProps["condition" + str(index)] == "device": val = [0, 0] # Failsafe devEx = indigo.devices[int(dev.pluginProps["device" + str(index)])] if eps.valueValid (devEx.states, dev.pluginProps["state" + str(index)]): compareString = unicode(devEx.states[dev.pluginProps["state" + str(index)]]) self.debugLog ("\tChecking if device state '%s' value of '%s' is between '%s' and '%s'" % (dev.pluginProps["state" + str(index)], compareString, dev.pluginProps["value" + str(index)], dev.pluginProps["endValue" + str(index)])) if compareString.lower() >= dev.pluginProps["value" + str(index)].lower() and compareString.lower() <= dev.pluginProps["endValue" + str(index)].lower(): val[0] = 1 val[1] = 0 else: val[0] = 0 val[1] = 1 if dev.pluginProps["condition" + str(index)] == "variable": val = [0, 0] # Failsafe var = indigo.variables[int(dev.pluginProps["variable" + str(index)])] compareString = unicode(var.value) self.debugLog ("\tChecking if variable '%s' value of '%s' is between '%s' and '%s'" % (var.name, compareString, dev.pluginProps["value" + str(index)], dev.pluginProps["endValue" + str(index)])) if compareString.lower() >= dev.pluginProps["value" + str(index)].lower() and compareString.lower() <= dev.pluginProps["endValue" + str(index)].lower(): val[0] = 1 val[1] = 0 else: val[0] = 0 val[1] = 1 if dev.pluginProps["evaluation" + str(index)] == "between": isTrue = isTrue + val[0] isFalse = isFalse + val[1] else: # It's the negative version so reverse the values isTrue = isTrue + val[1] isFalse = isFalse + val[0] except Exception as e: eps.printException(e) isTrue = 0 isFalse = 0 ret.append(isTrue) ret.append(isFalse) return ret
def updateChangedLCD(devChild, stateChangedAry): try: for pluginDevId, stateProps in stateChangedAry.iteritems(): for s in stateProps["stateChanges"]: if s in devChild.states: devParent = indigo.devices[int(pluginDevId)] # Make sure the state is valid - 1.13 if eps.valueValid(devChild.states, s) == False: indigo.server.log( "The watched state of '%s' on '%s' for LCD device '%s' is not a valid state and won't be converted" % (s, devChild.name, devParent.name), isError=True, ) return state = getStateDetails(devParent, s) if state is None: return # Added in 1.13 to handle invalid states stateValue = devChild.states[s] # Convert if required if state[3]: stateValue = convertStateValue(devParent, devChild, s, stateValue) parent.debugLog("\t%s changed to %s" % (s, unicode(devChild.states[s]))) if state[0]: # Convert a string to LCD value = lcdlib.stringToLCD(stateValue, state[2], devParent.pluginProps["textspaces"]) parent.debugLog("\t%s LCD readout string value is %s" % (s, value)) lcdlib.stringToGraphics(devParent, state[1], value) else: # Converting from a number to LCD padCharacter = "0" if devParent.pluginProps["spaces"]: padCharacter = " " # If this is a set point on a thermostat (or setmodesetpoint on extended), make sure decimals are zero since we can't set fractional temperatures on a thermostat if devParent.deviceTypeId == "epslcdth" and ( state[1] == "setpointHeat" or state[1] == "setpointCool" or state[1] == "setModeSetPoint" ): parent.debugLog("\t\tForcing integer value for set points") value = lcdlib.numberToLCD(stateValue, state[2], "round", padCharacter) else: value = lcdlib.numberToLCD( stateValue, state[2], devParent.pluginProps["decimals"], padCharacter ) parent.debugLog("\t%s LCD readout value is %s" % (s, value)) lcdlib.stringToGraphics(devParent, state[1], value) except Exception as e: eps.printException(e)
def getDataList(filter, valuesDict=None, typeId="", targetId=0): myArray = [("default", "No compatible value items found")] filter = str(filter) #indigo.server.log("Looking for %s" % filter) # i.e., "times" # i.e., "xyz.dat" # i.e., "xyz.dat:abc" - Find 'abc' in list # i.e., "xyz.dat:#varname - Find value of field 'varname' in list # i.e., "xyz.dat:#varname|abc - Find value of field 'varname' in list, if valuesDict is empty find "abc" instead # i.e., "xyz.dat:#varname|* - Find value of field 'varname' in list, if valuesDict is empty return entire list with no filter instead # i.e., "dayofmonth:#varname" - Return each day of the month for the varname value try: if filter == "": return myArray retAry = [] # Create list of times for 24 hours every 15 minutes if filter.lower() == "times": for h in range (0, 24): for minute in range (0, 4): hour = h hourEx = h am = " AM" if hour == 0: hourEx = 12 elif hour == 12: am = " PM" elif hour > 12: hourEx = hour - 12 am = " PM" key = "%02d:%02d" % (hour, minute * 15) value = "%02d:%02d %s" % (hourEx, minute * 15, am) option = (key, value) retAry.append(option) return retAry # Create list for months of the year - 1.0.5 if filter.lower() == "months": monthAry = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"] monthnum = 1 for s in monthAry: option = ("%02d" % monthnum, s) retAry.append(option) monthnum = monthnum + 1 return retAry # Years (from 2010 to 2030) if filter.lower() == "years": startyear = 2010 for i in range (0, 21): option = (str(startyear + i), str(startyear + i)) retAry.append(option) return retAry # Days of the week if filter.lower() == "dow": dayAry = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"] daynum = 0 for s in dayAry: option = (daynum, s) retAry.append(option) daynum = daynum + 1 return retAry # Days of the month (i.e., monthdays#month#year - 1.0.5 x = string.find (filter, 'monthdays') if x > -1: data = filter.split("#") if len(data) == 1: # no options, return 31 days for i in range (1, 32): option = ("%02d" % i, i) retAry.append(option) return retAry elif len(data) == 2 or len(data) == 3: # Month variable if eps.valueValid(valuesDict, data[1], True) == False: return retAry # no data will cause an error try: month = int(valuesDict[data[1]]) except: # Could be doing something like "any", return generic for i in range (1, 32): option = ("%02d" % i, i) retAry.append(option) return retAry d = indigo.server.getTime() year = int(d.strftime("%Y")) # assume this year if len(data) == 2: year = int(d.strftime("%Y")) else: if eps.valueValid (valuesDict, data[2], True): year = valuesDict[data[2]] if year == "current": year = int(d.strftime("%Y")) elif year == "last": year = int(d.strftime("%Y")) - 1 elif year == "next": year = int(d.strftime("%Y")) + 1 elif year == "any": # base months on this year year = int(d.strftime("%Y")) else: year = int(year) m = calendar.monthrange(year, month) for i in range (1, m[1] + 1): option = ("%02d" % i, i) retAry.append(option) return retAry # Return month strings with number values - 1.0.3 #if filter.lower() == "months": # return _getMonths (filter, valuesDict) # Take a month variable number and return days in that month - 1.0.3 if filter.lower() == "dayofmonth": # Always return either the current month or a future month, never the past z = string.find (filter, '#') if z < 0: # We didn't get a variable to use as the baseline, return 31 days generically for i in range (1, 32): option = (i, i) retAry.append(option) return retAry else: # The month variable must be a number data = filter.split("#") month = int(data[1]) d = indigo.server.getTime() year = int(d.strftime("%Y")) if month < int(d.strftime("%-m")): # It's in the past, use next year m = calendar.monthrange(year + 1, month) else: # It's this year or this month m = calendar.monthrange(year, month) for i in range (1, m[1]): option = (i, i) retAry.append(option) return retAry # Read in a data file and use those options x = string.find (filter, '.') if x > -1: filterEx = "" y = string.find (filter, ':') if y > -1: # Filtering for term data = filter.split(":") filter = data[0] filterEx = data[1] if filterEx[0] == "#": # Filter value is based on another field field = filterEx[1:] if field in valuesDict: filterEx = valuesDict[field] else: z = string.find (field, '|') if z > -1: # There is a default search term (generally in case valuesDict is empty like when a device first loads config) f = field.split("|") if f[0] in valuesDict: filterEx = valuesDict[f[0]] else: if f[1] == "*": filterEx = "" # * means no filtering else: filterEx = f[1] # Literal search else: # Field doesn't have a condition and it's not in valuesDict if field == "-nothing-": filterEx = "-nothing-" else: filterEx = "---INVALID---" return myArray lines = open("eps/" + filter).read().split('\n') for l in lines: details = l.split("\t") if len(details) == 2: # 2 option list (1 = value, 0 = display) if filterEx == "": option = (details[1], details[0]) retAry.append(option) else: # Special condition, if filterEx is -nothing- then we are looking for empty values isnothing = False if filterEx == "-nothing-": filterEx = "" isnothing = True if details[0] == filterEx or details[1] == filterEx: option = (details[1], details[0]) retAry.append(option) if isnothing == True: filterEx = "-nothing-" # reset for next loop else: # 2 elements is a simple value/display lookup, more than that is follows the design of: # 0 = Index number, 1 = Filter, 2 = Display, 3+ = Filter & data if filterEx == "": data = "" for i in range (3, len(details)): data += details[i] + "|" data = details[0] + "|" + data[:-1] # add index and strip last delimiter option = (data, details[2]) retAry.append(option) else: # Special condition, if filterEx is -nothing- then we are looking for empty values isnothing = False if filterEx == "-nothing-": filterEx = "" isnothing = True # See if the main filter field matches, then check the data fields filterMatch = False data = "" if details[1] == filterEx: filterMatch = True for i in range (3, len(details)): if details[i] == filterEx: filterMatch = True if filterMatch: for i in range (3, len(details)): data += details[i] + "|" data = details[0] + "|" + data[:-1] # add index and strip last delimiter option = (data, details[2]) retAry.append(option) if isnothing == True: filterEx = "-nothing-" # reset for next loop return retAry except Exception as e: indigo.server.log("Error in ui.getDataList: %s" % str(e), isError=True) return myArray return myArray
def getIndigoOperations (self, filter, valuesDict=None, typeId="", targetId=0): myArray = [("default", "No compatible Indigo or device operations found")] filter = str(filter) try: if filter == "": return myArray retAry = [] l = "" for i in range (0, 25): l += unicode("\xc4", "cp437") line = ["-1|" + l] capable = [] # If we are filtering for the target device get some info about it, otherwise use the filter passed if filter[0] == "#": if eps.valueValid (valuesDict, filter[1:], True): targetId = int(valuesDict[filter[1:]]) filter = "targetId" else: filter = "none" thisFilter = filter.lower() if filter == "targetId": thisFilter = "none" dev = indigo.devices[int(targetId)] #indigo.server.log(unicode(type(dev))) #indigo.server.log(unicode(dev)) if dev.supportsStatusRequest: capable.append("status") if unicode(type(dev)) == "<class 'indigo.DimmerDevice'>": capable.append("dimmer") if unicode(type(dev)) == "<class 'indigo.RelayDevice'>": capable.append("relay") if unicode(type(dev)) == "<class 'indigo.SprinklerDevice'>": capable.append("sprinkler") # Relay device commands lists = 0 if "status" in capable: cmdList = ["fullstatus|Request Full Status Update"] retAry = self.appendOptionList (retAry, cmdList) retAry = self.appendOptionList (retAry, line) cmdList = ["energyupdate|Request Energy Update", "energyusage|Request Energy Usage"] retAry = self.appendOptionList (retAry, cmdList) lists = lists + 1 if len(capable) > lists: retAry = self.appendOptionList (retAry, line) if "relay" in capable: cmdList = devactiondefs.INDIGO_RELAY retAry = self.appendOptionList (retAry, cmdList) lists = lists + 1 if len(capable) > lists: retAry = self.appendOptionList (retAry, line) if "dimmer" in capable: cmdList = devactiondefs.INDIGO_DIMMER retAry = self.appendOptionList (retAry, cmdList) lists = lists + 1 if len(capable) > lists: retAry = self.appendOptionList (retAry, line) if "sprinkler" in capable: cmdList = devactiondefs.INDIGO_SPRINKLER retAry = self.appendOptionList (retAry, cmdList) lists = lists + 1 if len(capable) > lists: retAry = self.appendOptionList (retAry, line) if dev: if dev.pluginId != "" or dev.deviceTypeId != "": # Not a built-in Indigo device actionAry = self.getCachedActions (dev) if len(actionAry) > 0 and len(capable) > 0: retAry = self.appendOptionList (retAry, line) # Separate the specific commands for s in actionAry: retAry.append (s) if len(retAry) > 0: return retAry else: return myArray except: return myArray
def setUIDefaults (self, valuesDict, defaultCondition = "disabled", defaultState = "onOffState"): try: # Make sure times are defaulted if eps.valueValid (valuesDict, "startTime1", True) == False: self.debugLog ("Setting default values") for i in range (1, self.maxConditions + 1): if eps.valueValid (valuesDict, "condition" + str(i)): valuesDict["condition" + str(i)] = defaultCondition if eps.valueValid (valuesDict, "evaluation" + str(i)): valuesDict["evaluation" + str(i)] = "equal" if eps.valueValid (valuesDict, "state" + str(i)): valuesDict["state" + str(i)] = defaultState if eps.valueValid (valuesDict, "startTime" + str(i)): valuesDict["startTime" + str(i)] = "08:00" if eps.valueValid (valuesDict, "endTime" + str(i)): valuesDict["endTime" + str(i)] = "09:00" if eps.valueValid (valuesDict, "startMonth" + str(i)): valuesDict["startMonth" + str(i)] = "01" if eps.valueValid (valuesDict, "endMonth" + str(i)): valuesDict["endMonth" + str(i)] = "02" if eps.valueValid (valuesDict, "startDay" + str(i)): valuesDict["startDay" + str(i)] = "01" if eps.valueValid (valuesDict, "endDay" + str(i)): valuesDict["endDay" + str(i)] = "15" if eps.valueValid (valuesDict, "startDow" + str(i)): valuesDict["startDow" + str(i)] = "0" if eps.valueValid (valuesDict, "endDow" + str(i)): valuesDict["endDow" + str(i)] = "6" if eps.valueValid (valuesDict, "startYear" + str(i)): valuesDict["startYear" + str(i)] = "any" if eps.valueValid (valuesDict, "endYear" + str(i)): valuesDict["endYear" + str(i)] = "any" valuesDict = self.autoCollapseConditions (valuesDict) valuesDict = self.showPlaceholders (valuesDict) # If everything is collapsed then show the full placeholder if conditions are enabled if valuesDict["currentCondition"] == "0" and valuesDict["conditions"] != "none": self.debugLog("Current block is 0, setting placeholder") valuesDict["noneExpanded"] = True else: valuesDict["noneExpanded"] = False #indigo.server.log("\n" + unicode(valuesDict)) return valuesDict except Exception as e: eps.printException(e) return valuesDict
def conditionContain (self, dev, index): ret = [] isTrue = 0 isFalse = 0 try: compareString = "" devEx = None if dev.pluginProps["condition" + str(index)] == "device" or dev.pluginProps["condition" + str(index)] == "devstatedateonly" or dev.pluginProps["condition" + str(index)] == "devstatetimeonly" or dev.pluginProps["condition" + str(index)] == "devstatedatetime" or dev.pluginProps["condition" + str(index)] == "devstatedow": devEx = indigo.devices[int(dev.pluginProps["device" + str(index)])] if dev.pluginProps["condition" + str(index)] == "device": if eps.valueValid (devEx.states, dev.pluginProps["state" + str(index)]): compareString = unicode(devEx.states[dev.pluginProps["state" + str(index)]]) elif dev.pluginProps["condition" + str(index)] == "variable": var = indigo.variables[int(dev.pluginProps["variable" + str(index)])] compareString = unicode(var.value) elif dev.pluginProps["condition" + str(index)] == "datetime" or dev.pluginProps["condition" + str(index)] == "devstatedatetime" or dev.pluginProps["condition" + str(index)] == "vardatetime": d = indigo.server.getTime() if dev.pluginProps["condition" + str(index)] == "devstatedatetime": d = self.getDevStateDateTime (dev, devEx, index) if dev.pluginProps["condition" + str(index)] == "vardatetime": d = self.getVarDateTime (dev, index) compareString = d.strftime ("%Y-%m-%d %H:%M:%S | %m %b %B | %A %w | %I | %p") else: indigo.server.log("Unknown condition %s in contains" % dev.pluginProps["condition" + str(index)], isError=True) self.debugLog ("\tChecking if %s is in %s" % (dev.pluginProps["value" + str(index)], compareString)) compareValue = "" if compareString != "": compareValue = compareString.lower() findValue = "" if dev.pluginProps["value" + str(index)] != "": findValue = str(dev.pluginProps["value" + str(index)]).lower() if findValue != "": foundAt = string.find (compareString, findValue) if foundAt > -1: isTrue = 1 else: # It's the negative version so reverse the values isFalse = 1 else: if compareValue == "": isTrue = 1 else: isFalse = 1 except Exception as e: eps.printException(e) isTrue = 0 isFalse = 0 ret.append(isTrue) ret.append(isFalse) return ret
def validateDeviceConfigUi(self, valuesDict, typeId, devId): self.debugLog ("Validating conditions on device") errorDict = indigo.Dict() msg = "" for i in range (1, self.maxConditions + 1): if eps.valueValid (valuesDict, "condition" + str(i), True): if valuesDict["condition" + str(i)] == "device" or valuesDict["condition" + str(i)] == "devstatedatetime": if valuesDict["state" + str(i)] == "": errorDict["state" + str(i)] = "State is required" msg += "Condition %i is missing required state. " % i if valuesDict["condition" + str(i)] == "variable" or valuesDict["condition" + str(i)] == "vardatetime": if valuesDict["variable" + str(i)] == "": errorDict["variable" + str(i)] = "Variable is required" msg += "Condition %i is missing required variable. " % i if valuesDict["condition" + str(i)] == "datetime" or valuesDict["condition" + str(i)] == "devstatedatetime" or valuesDict["condition" + str(i)] == "vardatetime": if valuesDict["startDay" + str(i)] == "first" or valuesDict["startDay" + str(i)] == "second" or valuesDict["startDay" + str(i)] == "third" or valuesDict["startDay" + str(i)] == "fourth" or valuesDict["startDay" + str(i)] == "last": if valuesDict["startDow" + str(i)] == "any": errorDict["startDow" + str(i)] = "Can't use 'any' when using calculations in the day field" msg += "Condition %i is using '%s' as the start day but 'any' for the day of the week.\n\n" % (i, valuesDict["startDay" + str(i)]) if valuesDict["endDay" + str(i)] == "first" or valuesDict["endDay" + str(i)] == "second" or valuesDict["endDay" + str(i)] == "third" or valuesDict["endDay" + str(i)] == "fourth" or valuesDict["endDay" + str(i)] == "last": if valuesDict["endDow" + str(i)] == "any": errorDict["endDow" + str(i)] = "Can't use 'any' when using calculations in the end day field" msg += "Condition %i is using '%s' as the end day but 'any' for the day of the week.\n\n" % (i, valuesDict["endDay" + str(i)]) if valuesDict["startYear" + str(i)] == "any" and valuesDict["startMonth" + str(i)] == "any" and valuesDict["startDay" + str(i)] == "any" and valuesDict["startDow" + str(i)] == "any" and valuesDict["startTime" + str(i)] == "any": if valuesDict["evaluation" + str(i)] == "between" or valuesDict["evaluation" + str(i)] == "notbetween": if valuesDict["endYear" + str(i)] == "any" and valuesDict["endMonth" + str(i)] == "any" and valuesDict["endDay" + str(i)] == "any" and valuesDict["endDow" + str(i)] == "any" and valuesDict["endTime" + str(i)] == "any": errorDict["startYear" + str(i)] = "Catch-all defeats the purpose of a condition" errorDict["startMonth" + str(i)] = "Catch-all defeats the purpose of a condition" errorDict["startDay" + str(i)] = "Catch-all defeats the purpose of a condition" errorDict["startDow" + str(i)] = "Catch-all defeats the purpose of a condition" errorDict["startTime" + str(i)] = "Catch-all defeats the purpose of a condition" errorDict["endYear" + str(i)] = "Catch-all defeats the purpose of a condition" errorDict["endMonth" + str(i)] = "Catch-all defeats the purpose of a condition" errorDict["endDay" + str(i)] = "Catch-all defeats the purpose of a condition" errorDict["endDow" + str(i)] = "Catch-all defeats the purpose of a condition" errorDict["endTime" + str(i)] = "Catch-all defeats the purpose of a condition" msg += "Condition %i is using 'any' for all fields, this defeats the purpose of having a condition! Try changing at least one to something else.\n\n" % (i) else: errorDict["startYear" + str(i)] = "Catch-all defeats the purpose of a condition" errorDict["startMonth" + str(i)] = "Catch-all defeats the purpose of a condition" errorDict["startDay" + str(i)] = "Catch-all defeats the purpose of a condition" errorDict["startDow" + str(i)] = "Catch-all defeats the purpose of a condition" errorDict["startTime" + str(i)] = "Catch-all defeats the purpose of a condition" msg += "Condition %i is using 'any' for all fields, this defeats the purpose of having a condition! Try changing at least one to something else.\n\n" % (i) fields = ["Year", "Month", "Day", "Dow", "Time"] for s in fields: if valuesDict["evaluation" + str(i)] == "between" or valuesDict["evaluation" + str(i)] == "notbetween": if valuesDict["start" + s + str(i)] == "-1": errorDict["start" + s + str(i)] = "You must select a value" msg += "Condition %i field %s has an invalid value.\n\n" % (i, s) if valuesDict["end" + s + str(i)] == "-1": errorDict["end" + s + str(i)] = "You must select a value" msg += "Condition %i field End %s has an invalid value.\n\n" % (i, s) else: if valuesDict["start" + s + str(i)] == "-1": errorDict["start" + s + str(i)] = "You must select a value" msg += "Condition %i field %s has an invalid value.\n\n" % (i, s) if msg != "": msg = "There are problems with your conditions:\n\n" + msg errorDict["showAlertText"] = msg return (False, valuesDict, errorDict) return (True, valuesDict)
def updateDevice (devId, changedStates): try: dev = indigo.devices[devId] # Our device if dev.pluginProps["chdevice"]: devEx = indigo.devices[int(dev.pluginProps["device"])] # Device we are watching if eps.valueValid (devEx.states, dev.pluginProps["states"]): value = devEx.states[dev.pluginProps["states"]] else: # It's a property if dev.pluginProps["states"] == "lastChanged": value = devEx.lastChanged else: devEx = "" value = indigo.variables[int(dev.pluginProps["variable"])] debugLog ("Processing changes on %s for value of '%s'" % (dev.name, unicode(value))) # ALWAYS TRUE if dev.pluginProps["action"] == "true": debugLog ("\tConverting to 'Always true'") setStates (dev, "true", "true", None, True) # ALWAYS FALSE if dev.pluginProps["action"] == "false": debugLog ("\tConverting to 'Always false'") dev.updateStateImageOnServer(indigo.kStateImageSel.None) setStates (dev, "false", "false", None, False) # VALUE TO BOOLEAN if dev.pluginProps["action"] == "bool": debugLog ("\tConverting value to boolean (bool)") value = unicode(value).lower() #if devEx.pluginProps["booleanstatetype"] == "float": value = float(value) truevalue = unicode(dev.pluginProps["truewhen"]).lower() falsevalue = unicode(dev.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 setStates (dev, unicode(statevalue).lower(), unicode(statevalue).lower(), None, statevalue) # BOOLEAN TO STRING if dev.pluginProps["action"] == "boolstr": debugLog ("\tConverting boolean value to string (boolstr)") value = unicode(value).lower() truevalue = unicode(dev.pluginProps["truewhen"]) falsevalue = unicode(dev.pluginProps["falsewhen"]) statevalue = falsevalue if value == "true": statevalue = truevalue setStates (dev, unicode(statevalue), unicode(statevalue)) # STRING TO NUMBER if dev.pluginProps["action"] == "strtonum": debugLog ("\tConverting string to number (strtonum)") value = unicode(value) if eps.valueValid (dev.pluginProps, "trimstart", True): if dev.pluginProps["trimstart"] != "0" and len(value) > int(dev.pluginProps["trimstart"]): self.debugLog("\tRemoving %i characters from beginning of string" % int(dev.pluginProps["trimstart"])) diff = int(dev.pluginProps["trimstart"]) value = value[diff:len(value)] if eps.valueValid (dev.pluginProps, "trimend", True): if dev.pluginProps["trimend"] != "0" and len(value) > int(dev.pluginProps["trimend"]): self.debugLog("\tRemoving %i characters from end of string" % int(dev.pluginProps["trimend"])) diff = int(dev.pluginProps["trimend"]) diff = diff * -1 value = value[:diff] try: dec = string.find (value, '.') numtype = dev.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) if numtype == "float": value = float(value) setStates (dev, value, value) except Exception as e: eps.printException(e) devEx.updateStateOnServer(key="statedisplay", value="Error", uiValue="Error") return except Exception as e: eps.printException(e)
def getStateDetails(dev, value): # Most of our device states should have digits, hidden or otherwise d = 4 try: if "digits" in dev.pluginProps: d = int(dev.pluginProps["digits"]) # defAlarmClock = ["durationMinutes","startTime.ui","endTime.ui","timeUntilOn","timeUntilOff"] # 1.1.0 for EPS Alarm Clock if dev.deviceTypeId == "epslcdalc": # 1.1.0 if value == "startTime.ui": return [True, "startTime", d, False] if value == "endTime.ui": return [True, "endTime", d, False] if value == "durationMinutes": return [False, value, d, False] parent.debugLog(u"Returning defaults for %s" % value) return [True, value, 4, False] # The rest of the state names are a direct match if dev.deviceTypeId == "epslcdsb": devChild = indigo.devices[int(dev.pluginProps["device"])] for i in range(1, 6): if dev.pluginProps["state" + str(i)] != "": if value == dev.pluginProps["state" + str(i)]: if eps.valueValid(devChild.states, dev.pluginProps["state" + str(i)]) == False: # 1.13 indigo.server.log( "State '%s' is not a valid state on '%s', '%s' is unable to convert this value" % (dev.pluginProps["state" + str(i)], devChild.name, dev.name), isError=True, ) return [True, "state" + str(i) + "_", d, False] if dev.pluginProps["type" + str(i)] == "auto": stateValue = devChild.states[dev.pluginProps["state" + str(i)]] if type(stateValue) is int or type(stateValue) is float or type(stateValue) is long: parent.debugLog(u"\tDetermined state %s value is a number" % value) return [False, "state" + str(i) + "_", d, False] else: parent.debugLog( u"\tDetermined state %s value is a %s and will be treated like a string" % (value, type(value)) ) return [True, "state" + str(i) + "_", d, False] elif ( dev.pluginProps["type" + str(i)] == "sectommss" or dev.pluginProps["type" + str(i)] == "sectohhmmss" ): # 1.1.1 - require a calculation return [True, "state" + str(i) + "_", d, True] else: return [False, "state" + str(i) + "_", d, False] if dev.deviceTypeId == "epslcdth": # These will only be returned if there is an Extended Device, none of the other plugins return these states: if value == "hightemp": return [False, value, d, False] if value == "lowtemp": return [False, value, d, False] if value == "highhumidity": return [False, value, d, False] if value == "lowhumidity": return [False, value, d, False] if value == "setModeSetPoint": return [False, value, d, False] return [False, value, 4, False] # All thermostat LCD's are numbers and all state names match if dev.deviceTypeId == "epslcdwe": # Weather LCD devChild = indigo.devices[int(dev.pluginProps["device"])] # These will only be returned if there is an Extended Device, none of the other plugins return these states: if value == "hightemp": return [False, value, d, False] if value == "lowtemp": return [False, value, d, False] if value == "highhumidity": return [False, value, d, False] if value == "lowhumidity": return [False, value, d, False] if devChild.pluginId == "com.fogbert.indigoplugin.wunderground": # Weather Underground plugin if value == "relativeHumidity": return [False, "humidity", d, False] if value == "temp": return [False, "temperature", d, False] if value == "precip_1hr": return [False, "hourrain", d, False] if value == "precip_today": return [False, "dayrain", d, False] if value == "currentWeather": return [True, "conditions", d, True] if value == "foreDay1": return [True, value, d, False] if value == "foreDay2": return [True, value, d, False] if value == "foreDay3": return [True, value, d, False] if value == "foreDay4": return [True, value, d, False] if value == "historyHigh": return [False, value, d, True] if value == "historyLow": return [False, value, d, True] # 1.1.0 (for values where our state name don't match WUnderground) if value == "windDIR": return [True, "windDirection", d, False] if value == "uv": return [False, "solarRadiation", d, False] # Everything else is "forXXX" and is matched in our state names return [False, value, d, False] elif devChild.pluginId == "com.perceptiveautomation.indigoplugin.weathersnoop": # Weathersnoop plugin if value == "humidity": return [False, value, d, False] if value == "temperature_" + dev.pluginProps["temps"]: return [False, "temperature", d, False] if value == "dayRain_" + dev.pluginProps["measures"]: return [False, "dayrain", d, False] if value == "rainOneHour_" + dev.pluginProps["measures"]: return [False, "hourrain", d, False] if value == "weather": return [True, "conditions", int(dev.pluginProps["conditions"]), True] # 1.1.0 (for values where our state name don't match WeatherSnoop) if value == "dewPoint" + dev.pluginProps["measures"]: return [False, "dewpoint", d, False] if value == "temperature_F.ui": parent.debugLog(u"\t### %s being used only as a trigger for 'feelslike' ###" % value) return [ False, "feelslike", d, True, ] # Phony state update, we use this to calculate the feels like temperature if value == "windChill" + dev.pluginProps["measures"]: return [False, "windchill", d, False] if value == "windDirection": return [False, "windDegrees", d, False] if value == "windDirection.ui": return [True, "windDirection", d, True] if value == "windSpeed_" + dev.pluginProps["speed"]: return [False, "windSpeed", d, False] if value == "windGust_" + dev.pluginProps["speed"]: return [False, "windGust", d, False] if value == "relativeBarometricPressure_" + dev.pluginProps["pressure"]: return [False, "pressure", d, False] return [False, value, d, False] if dev.deviceTypeId == "epslcdws": # DEPRECIATED if value == "humidity": return [False, value, d, False] if value == "temperature_" + dev.pluginProps["temps"]: return [False, "temperature", d, False] if value == "dayRain_" + dev.pluginProps["measures"]: return [False, "dayrain", d, False] if value == "rainOneHour_" + dev.pluginProps["measures"]: return [False, "hourrain", d, False] if value == "weather": return [True, "conditions", int(dev.pluginProps["conditions"]), True] if dev.deviceTypeId == "epslcdir": if value == "activeZone": return [False, "activezone", d, False] if value == "activeZone.ui": return [True, "activezonename", 20, False] # These will only be returned if there is an Extended Device, none of the other plugins return these states: if value == "zoneRunTimeRemaining": return [True, value, d, False] if value == "scheduleRunTimeRemaining": return [True, value, d, False] if value == "pauseTimeRemaining": return [True, value, d, False] indigo.server.log( u"Should have gotten state details for %s but it is returning a default instead of %s" % (dev.name, unicode(value)), isError=True, ) except Exception as e: eps.printException(e) return [True, value, d, False]