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
Esempio n. 7
0
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)
Esempio n. 8
0
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
Esempio n. 9
0
	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)
Esempio n. 13
0
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)	
Esempio n. 14
0
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]