With the method above, won’t the value of index from the forEach loop change as the loop iterates? That’s the problem that I have now, index always = 8 by the time the timer executes as it’s value changes with each loop iteration. I need a way to get an actual number value to pass. .
You’re right though, the code doesn’t work. It iterates in order of the items in the file and send a correct value to the timer but it doesn’t execute the sendCommand properly. I hadn’t gotten to fixing the sendCommand portion yet, I’ve been trying to just pass the right value to the timer. There is alot more to the code though, I stripped it to isolate the question a bit.
For reference, more detailed code is below. Any suggestions would be appreciated!
/*Items */
//Number 0 - 7 representing speed 1 - 8
Number filterPumpSpeedSetting "Pump Speed Preset" <pump>
/* Speed 0 Master Settings */
Switch pumpSpeed_0_Master "Speed 0 [%s]" <switch> (gPumpSpeed_0_Settings)
String pumpSpeed_0_StartTime "Start Time [%s]" <calendar> (gPumpSpeed_0_Settings)
Number pumpSpeed_0_StartTime_Hours "Hours [%d]" <settings> (gPumpSpeed_0_Settings)
Number pumpSpeed_0_StartTime_Minutes "Minutes [%d]" <settings> (gPumpSpeed_0_Settings)
Number pumpSpeed_0_Duration "Speed 0 Duration [%d mins]" <clock> (gPumpSpeed_0_Settings, gPumpSpeed_0_Duration, gInitializeZero)
String pumpSpeed_0_EndTime "Start Time [%s]" <calendar> (gPumpSpeed_0_Settings)
Switch Monday_pumpSpeed_0 "Monday [%s]" <switch> (gPumpSpeed_0_Settings, gPumpSpeed_0_DayOfWeek)
Switch Tuesday_pumpSpeed_0 "Tuesday [%s]" <switch> (gPumpSpeed_0_Settings, gPumpSpeed_0_DayOfWeek)
// similar items follow for speeds 0 - 7, with index changed as required.
//*******Rules File********
//Day of week string array. Used to evaluate day of week
val ArrayList<String> dayOfWeekArray = newArrayList(
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
"Sunday"
)
//Timer array to hold scheduled timers
var List<Timer> timers = newArrayList
rule "Schedule Run Times"
when
//Item testSwitch changed or
//Time cron "0 0 0 * * ?" or //Run at 12:00 daily
Item pumpSpeed_0_Master received command //or
then
// clear out the old timers if there are any
logInfo("Timers","--------------------Clearing Timers. Qty: " + timers.size)
timers.forEach[ t |
logInfo("TimerCancel", t.toString + " Cancelled")
t.cancel
]
timers.clear
// If pump speed preset is enabled, get durations and schedule timers
logInfo("Pool Schedule","------------------------gProgramSettings------------------------")
//Index used to reference pump speed setting
var int index = 0
//For each speed group (gPumpSpeed_X_Settings)
gProgramSettings.members.forEach[GroupItem gPS|
logInfo("Pool Schedule",gPS.name)
var logMessage = ""
if (gPS.members.filter[t|t.name.contains("Master")].head.state == ON){
logInfo("Pool Test", gPS.label + " - Master Switch is " + gPS.members.filter[t|t.name.contains("Master")].head.state)
//If pump speed is scheduled for today
if (gPS.members.filter[t|t.name.contains(dayOfWeekArray.get(now.getDayOfWeek-1).toString)].head.state == ON){
logInfo("Pool Test","Day of Week Switch is " + gPS.members.filter[t|t.name.contains(dayOfWeekArray.get(now.getDayOfWeek-1).toString)].head.state)
//Obtain Program X startTime. This happens at midnight, and whenever a change is made to the speed schedule.
var int progStartHours = (gPS.members.filter[t|t.name.contains("StartTime_Hours")].head.state as DecimalType).intValue()
var int progStartMinutes = (gPS.members.filter[t|t.name.contains("StartTime_Minutes")].head.state as DecimalType).intValue()
var DateTime startTime = parse(now.getYear() + "-" + now.getMonthOfYear() + "-" + now.getDayOfMonth() + "T" + progStartHours + ":" + progStartMinutes)
//Check if start time has passed for the day
if(startTime.isAfter(now())){
logMessage = gPS.label + " Start Time= " + startTime.toString("EEE MMM dd, yyyy hh:mm:ss a")
logInfo("Pool Schedule",logMessage)
//Why do we do this? Only one duration, could pull directly with progStartHours
for (t : gPS.members.filter[t|t.name.contains("Duration") && t.type == "Number" && t.state>0]){
var int speedDuration = (t.state as DecimalType).intValue
//val zoneName = (t.name.toString.subSequence(0,t.name.toString.indexOf("_"))) //Don't think I need this
var DateTime endTime = startTime.plusMinutes(speedDuration)
//startTimeTest used for logging only? Seems unnecessary
val startTimeTest = startTime
val endTimeTest = endTime
logInfo("Pool Schedule", " Start " + startTime.toString("EEE MMM dd, yyyy hh:mm:ss a") + " End " + endTime.toString("EEE MMM dd, yyyy hh:mm:ss a"))
timers.add((createTimer(startTime) [|
sendCommand(filterPumpSpeedSetting.state, index) //pump speed = index
logInfo("Pool Schedule", "Pump Speed Index set to (" + index + ")" + startTimeTest.toString("EEE MMM dd, yyyy hh:mm:ss a"))
]))
logInfo("Pool Schedule", "Pump Speed Index set to (" + index + ")" + startTimeTest.toString("EEE MMM dd, yyyy hh:mm:ss a"))
//Check to see if pump is still at the indexed speed setting. If it is not, another speed has taken control.
timers.add((createTimer(endTime) [|
if (filterPumpSpeedSetting.state == index){
//Set speed to default low speed.
//Designed to have pump run continuously at low speed unless scheduled otherwise.
//Currently speed 0, this can be altered per pump performance.
sendCommand(filterPumpSpeedSetting.state, 0)
logInfo("Pool Schedule", "Pump Speed set to default low speed" + endTimeTest.toString("EEE MMM dd, yyyy hh:mm:ss a"))
}
]))
logInfo("Pool Schedule", "Pump Speed Index set to (" + index + ")" + startTimeTest.toString("EEE MMM dd, yyyy hh:mm:ss a"))
startTime = endTime.plusMinutes(1)
}
}
else logMessage = gPS.label + " Start Time has already passed. Start Time = " + startTime.toString("EEE MMM dd, yyyy hh:mm:ss a")
}
else logMessage = gPS.label + " - Pump Speed is not scheduled for today"
}
else logMessage = gPS.label + " - Master Switch is off, Pump Speed is disabled"
if (logMessage != ""){
logInfo("Pool Schedule", logMessage)
}
index = index + 1
]
timers.forEach[ t |
logInfo("Scheduled Timers", t.toString)
]
end