OK, this is what I'm testing today. I moved the EZIO8T output control script to an external file, to eliminate the errors I've been getting (because it sometimes takes longer than 10 seconds to execute).
I run a small external py script file to establish the parameter, from an Action Group, and then that script imports and executes the "master" file. Matt explained that I can't import the "master" file (even though externally located) into an internal py script, because it will then execute "internally," and still bump into the 10 seconds limit. This was the only way I could figure out how to pass parameters to an external py file. I could do it with variables, I suppose, but it "feels" more reliable to do it this way.
So an Action Group executes this linked external script file:
- Code: Select all
# calls indigo_irrigation.valveOn('1')
import indigo_irrigation
indigo_irrigation.valveOn('1')
I have six of those: to pass parameters "1" thru "6", and a seventh to pass a parameter of "0", which executes the portion of the script that turns off all the outputs, but doesn't then turn any on. I use the latter a lot: before I turn any valves on, and after all the schedules execute. I also run it once an hour, 24-7, just to make sure my irrigation doesn't run and run and run for days, should an output somehow come on, or stay on after it's supposed to be off (darn EZIO8T reliability).
That small py script file imports and executes the "master" script:
- Code: Select all
"""
indigo_irrigation.py
controls EZIO8T outputs, with redundancy to accommodate its unreliability
tests each output (for on or off) and logs any errors, including number of repeat attempts
In this file you can insert any methods and classes that you define.
They will be shared by all Python scripts - you can even import the
IOM (as shown below) but if you do then you'll only be able to import
this script in Python processes started by Indigo. If you don't need
the IOM then skip the import and it'll work in any Python script
no matter where it's run from.
"""
try:
import indigo
except ImportError:
print "Attachments can only be used from within Indigo"
raise ImportError
import time
def valveOn(mWhichValve):
# turns off EZi08T outputs 1-6 and repeats until they are all off
indigo.server.log("indigo_irrigation.valveOn('"+mWhichValve+"') executing...", type="External Script")
maxAttempts = 5 # number of times repeat loops will attempt to turn on or off an exio8t output
repeatCounterOn = 0
ezio8t = indigo.devices[134979129] # "EZi08T"
for repeatCounterOff in range(maxAttempts):
indigo.iodevice.setBinaryOutput(134979129, 0, False) # "EZi08T" output 1 OFF
indigo.iodevice.setBinaryOutput(134979129, 1, False) # "EZi08T" output 2 OFF
indigo.iodevice.setBinaryOutput(134979129, 2, False) # "EZi08T" output 3 OFF
indigo.iodevice.setBinaryOutput(134979129, 3, False) # "EZi08T" output 4 OFF
indigo.iodevice.setBinaryOutput(134979129, 4, False) # "EZi08T" output 5 OFF
indigo.iodevice.setBinaryOutput(134979129, 5, False) # "EZi08T" output 6 OFF
indigo.device.statusRequest(134979129) # "EZi08T"
time.sleep(1)
ezio8t.refreshFromServer(waitUntilServerIdle=True)
binaryOutput1 = ezio8t.states["binaryOutput1"]
binaryOutput2 = ezio8t.states["binaryOutput2"]
binaryOutput3 = ezio8t.states["binaryOutput3"]
binaryOutput4 = ezio8t.states["binaryOutput4"]
binaryOutput5 = ezio8t.states["binaryOutput5"]
binaryOutput6 = ezio8t.states["binaryOutput6"]
if (not binaryOutput1) and (not binaryOutput2) and (not binaryOutput3) and (not binaryOutput4) and (not binaryOutput5) and (not binaryOutput6):
break
if mWhichValve in "123456":
# turn on valve and repeat until it is really on
if mWhichValve == "1":
stateName = ("binaryOutput1")
tTimerDuration = unicode(indigo.variables[128363799].value) # "irrigation_duration_1" value as unicode
elif mWhichValve == "2":
stateName = ("binaryOutput2")
tTimerDuration = unicode(indigo.variables[1092635302].value) # "irrigation_duration_2" value as unicode
elif mWhichValve == "3":
stateName = ("binaryOutput3")
tTimerDuration = unicode(indigo.variables[8186003].value) # "irrigation_duration_2" value as unicode
elif mWhichValve == "4":
stateName = ("binaryOutput4")
tTimerDuration = unicode(indigo.variables[780129921].value) # "irrigation_duration_2" value as unicode
elif mWhichValve == "5":
stateName = ("binaryOutput5")
tTimerDuration = unicode(indigo.variables[50403568].value) # "irrigation_duration_2" value as unicode
elif mWhichValve == "6":
stateName = ("binaryOutput6")
tTimerDuration = unicode(indigo.variables[1214967738].value) # "irrigation_duration_2" value as unicode
for repeatCounterOn in range(maxAttempts):
indigo.iodevice.setBinaryOutput(134979129, (int(mWhichValve)-1), True) # "EZi08T" output x ON
indigo.device.statusRequest(134979129) # "EZi08T"
time.sleep(1)
ezio8t.refreshFromServer(waitUntilServerIdle=True)
binaryOutput = ezio8t.states[stateName]
if binaryOutput:
indigo.variable.updateValue(126668483, value=tTimerDuration) # "irrigation_timer"
break
if (repeatCounterOff >= (maxAttempts - 1)) or (repeatCounterOn >= (maxAttempts - 1)):
indigo.server.log("indigo_irrigation.valveOn('"+mWhichValve+"') executed but exceeded maximum attempts limit! Off repeats: "+unicode(repeatCounterOff)+". On repeats: "+unicode(repeatCounterOn), type="External Script", isError=True)
indigo.actionGroup.execute(848159626) # "Irrigation Valve Error Warning"
elif (repeatCounterOff > 0) or (repeatCounterOn > 0):
indigo.server.log("indigo_irrigation.valveOn('"+mWhichValve+"') executed with some repeats. Off repeats: "+unicode(repeatCounterOff)+". On repeats: "+unicode(repeatCounterOn), type="External Script", isError=True)
else:
indigo.server.log("indigo_irrigation.valveOn('"+mWhichValve+"') executed. Off repeats: "+unicode(repeatCounterOff)+". On repeats: "+unicode(repeatCounterOn), type="External Script")
"""
mWhichValve (parameter 1) can be:
"0" (turns off all valves)
"1" (turns off all valves and turns on valve 1)
"2" (turns off all valves and turns on valve 2)
"3" (turns off all valves and turns on valve 3)
"4" (turns off all valves and turns on valve 4)
"5" (turns off all valves and turns on valve 5)
"6" (turns off all valves and turns on valve 6)
"""
The script keeps track if any of the off or on attempts needed to be repeated (based on checking the EZIO8T output status), and reports those in the log. If the attempts to turn outputs on or off exceeds a maximum of 5 attempts, the script calls an Action Group that alerts me with an email, a reminder AND a text. Again, I'm so paranoid about a valve staying on, that I built in a bunch of redundancy and error checking to help ward off a $500 water bill!!
If there's a more elegant way to do any of this, please let me know. Sorry, Joe, your excellent tips about how to use iteration to clean up some of this didn't make it in. As I explained, I'm using a more verbose version to help my ol' brain to understand the code better (now, and days/months/years from now).