******** See working example at the end of this thread **********
Hi,
I am currently running the latest stable image and am having some trouble successfully getting cascading timers to operate.
I have based my rules on the Cascading timers design pattern (Design Pattern: Cascading Timers).
When acting the item “Irrigation_Auto” or an individual zone (all zones have the setpoint at 2mins) I get the following error in openhab.log
[INFO ] [se.smarthome.model.script.Irrigation] - Irrigation started, turning on Zone 1
[ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Irrigation Cascade': cannot invoke method public abstract org.eclipse.smarthome.core.types.State org.eclipse.smarthome.core.items.Item.getState() on null
Zone 1 turns on as expected, however Zone 1 never turns off and no other zones are activated.
Turning on each zone manually works fine as well as turning off.
Is anyone able to offer some advice on what may be causing this issue?
Thanks.
I have the following configuration:
Items
Group gIrriAll "All Irrigation Devices"
Group:Switch:OR(ON,OFF) gIrrigation "Irrigation is currently [%s]"
Group:Number:SUM gIrrigation_Times "Total Irrigation Time is [%d mins]"
Switch Irrigation_Zone_1 "Side Garden" (gIrrigation, gIrriAll) { channel="opensprinkler:http:192_168_0_150:station01" }
Switch Irrigation_Zone_2 "Front Garden" (gIrrigation, gIrriAll) { channel="opensprinkler:http:192_168_0_150:station02" }
Switch Irrigation_Zone_3 "Veggie Garden" (gIrrigation, gIrriAll) { channel="opensprinkler:http:192_168_0_150:station03" }
Switch Irrigation_Zone_4 "Back Garden" (gIrrigation, gIrriAll) { channel="opensprinkler:http:192_168_0_150:station04" }
String Irrigation_Curr "Current active zone is [%s]" (gIrriAll)
Switch Irrigation_Auto "Irrigation Auto" (gIrriAll)
Switch Irrigation_Manual "Irrigation state [%s]" (gIrriAll)
Number Irrigation_Zone_1_Time "Side Garden duration [%d mins]" (gIrrigationTime, gIrriAll)
Number Irrigation_Zone_2_Time "Front Garden duration [%d mins]" (gIrrigationTime, gIrriAll)
Number Irrigation_Zone_3_Time "Veggie Garden duration [%d mins]" (gIrrigationTime, gIrriAll)
Number Irrigation_Zone_4_Time "Back Garden duration [%d mins]" (gIrrigationTime, gIrriAll)
Sitemap
Frame {
Group item=gIrriAll label="Irrgiation Test" icon="water_drops"
Switch item=gIrrigation
Text item=gIrrigation_Times
Setpoint item=Irrigation_Zone_1_Time minValue=1 maxValue=30 step=1
Setpoint item=Irrigation_Zone_2_Time minValue=1 maxValue=30 step=1
Setpoint item=Irrigation_Zone_3_Time minValue=1 maxValue=30 step=1
Setpoint item=Irrigation_Zone_4_Time minValue=1 maxValue=30 step=1
}
Rule
var Timer irrigationTimer = null
rule "Reset Irrigation at OH Start"
when
System started
then
// use this line to just turn everything off if OH happens to restart when irrigation is running
gIrrigation.members.filter[valve|valve.state != OFF].forEach[valve| valve.sendCommand(OFF)]
end
rule "Start Irrigation"
when
Item Irrigation_Auto received command ON
then
logInfo("Irrigation", "Irrigation started, turning on Zone 1")
Irrigation_Curr.postUpdate(Irrigation_Zone_1.name)
Irrigation_Zone_1.sendCommand(ON)
end
rule "Irrigation Cascade"
when
Item Irrigation_Zone_1 received command ON or
Item Irrigation_Zone_2 received command ON or
Item Irrigation_Zone_3 received command ON or
Item Irrigation_Zone_4 received command ON
then
// get info for the current valve
val currValve = gIrrigation.members.filter[valve|valve.name == Irrigation_Curr.state.toString].head
//logInfo("Irrigation", "currValue: " + currValve.name)
val currValveNum = Integer::parseInt(currValve.name.split("_").get(2))
//logInfo("Irrigation", "currValveNum: " + currValveNum)
val currValveMins = gIrrigation_Times.members.filter[t|t.name == currValve.name+"_Time"].head.state as Number
logInfo("Irrigation", "irrigation active for : " + currValveMins + " mins")
// get info for the next valve in the sequence
val nextValveNum = currValveNum + 1
val nextValveName = "Irrigation_Zone_"+nextValveNum
val nextValve = gIrrigation.members.filter[valve|valve.name == nextValveName].head // null if there is no member by that name
// Create a timer to turn off curr valve and start the next valve
irrigationTimer = createTimer(now.plusMinutes(currValveMins.intValue), [|
logInfo("Irrigation", "Turning off " + currValve.name)
currValve.sendCommand(OFF)
if(nextValve != null) {
logInfo("Irrigation", "Turning on " + nextValve.name)
Irrigation_Curr.postUpdate(nextValve.name)
nextValve.sendCommand(ON) // causes the Irrigation Cascade rule to trigger
}
else {
logInfo("Irrigation", "Irrigation is complete")
Irrigation_Auto.sendCommand(OFF) // causes the cancel rule to trigger for cleanup
}
irrigationTimer = null
])
end
rule "Cancel Irrigation"
when
Item Irrigation_Auto received command OFF
then
// Cancel the timer if there is one, the ? will cause the line to be skipped if timer is null
irrigationTimer?.cancel
irrigationTimer = null
// Turn off any open valves
gIrrigation.members.filter[valve|valve.state != OFF].forEach[valve| valve.sendCommand(OFF)]
// Update curr status
Irrigation_Curr.postUpdate("OFF")
end
Event log included for completeness:
[ome.event.ItemCommandEvent] - Item 'Irrigation_Auto' received command ON
[vent.ItemStateChangedEvent] - Irrigation_Auto changed from OFF to ON
[ome.event.ItemCommandEvent] - Item 'Irrigation_Zone_1' received command ON
[nt.ItemStatePredictedEvent] - Irrigation_Zone_1 predicted to become ON
[vent.ItemStateChangedEvent] - Irrigation_Curr changed from OFF to Irrigation_Zone_1
[vent.ItemStateChangedEvent] - Irrigation_Zone_1 changed from OFF to ON
[GroupItemStateChangedEvent] - gIrrigation changed from OFF to ON through Irrigation_Zone_1