I have a problem controlling my irrigation Rule.
The following rule is mostly from another forum and I have tried to adapt it to my environment.
I would like to be able to start three magnetic valves with a given running time.
If I turn the switches one by one, everything works. If the switches are activated simultaneously, the timers run for different lengths of time. Unfortunately I cannot explain why. I already used three separate timer
variables, but that didn’t really help either.
Openhab.log
2`020-07-14 20:39:16.253 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Regel ‘Irrigation3’: ‘cancel’ ist kein Mitglied von ‘java.lang.Object’; Zeile 84, Spalte 25, Länge 24
val String filename = “Irrigation.rules”
val IrrigationTimer = null
rule "Irrigation1"
when
Item dummyMGV1_State received command
then
if (receivedCommand == ON) {
if (IrrigationTimer === null){
logInfo(filename,"Text")
IrrigationTimer = createTimer(now.plusSeconds(Integer::parseInt(IrrigationTime.state.toString)))[|
dummyMGV1_State.sendCommand(OFF)
Irrigation_R1_lastRun.postUpdate(new DateTimeType())
logInfo(filename,"Text")
IrrigationTimer = null
]
}
Irrigation_R1.sendCommand(ON)
logInfo(filename,"Text")
} else {
Irrigation_R1.sendCommand(OFF)
Irrigation_R1_lastRun.postUpdate(new DateTimeType())
if (IrrigationTimer !== null){
IrrigationTimer = null
}
logInfo(filename,"Text")
}
end
rule "Irrigation2"
when
Item dummyMGV2_State received command
then
if (receivedCommand == ON) {
if (IrrigationTimer === null){
logInfo(filename,"Text")
IrrigationTimer = createTimer(now.plusSeconds(Integer::parseInt(IrrigationTime.state.toString)))[|
dummyMGV2_State.sendCommand(OFF)
Irrigation_R2_lastRun.postUpdate(new DateTimeType())
logInfo(filename,"Text")
IrrigationTimer = null
]
}
Irrigation_R2.sendCommand(ON)
logInfo(filename,"Text")
} else {
Irrigation_R2.sendCommand(OFF)
Irrigation_R2_lastRun.postUpdate(new DateTimeType())
if (IrrigationTimer !== null){
IrrigationTimer = null
}
logInfo(filename,"Text")
}
end
rule "Irrigation3"
when
Item dummyMGV3_State received command
then
if (receivedCommand == ON) {
if (IrrigationTimer === null){
logInfo(filename,"Text")
IrrigationTimer = createTimer(now.plusSeconds(Integer::parseInt(IrrigationTime.state.toString)))[|
dummyMGV3_State.sendCommand(OFF)
Irrigation_R3_lastRun.postUpdate(new DateTimeType())
logInfo(filename,"Text")
IrrigationTimer = null
]
}
Irrigation_R3.sendCommand(ON)
logInfo(filename,"Text")
} else {
Irrigation_R3.sendCommand(OFF)
Irrigation_R3_lastRun.postUpdate(new DateTimeType())
if (IrrigationTimer !== null){
IrrigationTimer = null
}
logInfo(filename,"Text")
}
end
rule "Abort Irrigation"
when
Item dummyBeregnung_Disable received update ON
then
dummyMGV1_State.sendCommand(OFF)
dummyMGV2_State.sendCommand(OFF)
dummyMGV3_State.sendCommand(OFF)
end
The rule “Irrigation3” that you have shown us could not produce the error message relating to cancel, because there are no cancels in that rule.
(I think it would be a good idea if there were, though! Setting a timer handle variable to null does not stop or destroy a timer.)
It might be that you have another rule called “Irrigation3”, these names must be unique or they will overload each other.
or maybe you have an old rule version still in memory, and your edited file is not loading properly. You should always see an entry in your openhab.log about loading or refreshing a rules file.
If the “Irrigation3” rule shown was running, you would expect to see logInfos in your openhab.log, you haven’t shown those.
There would probably also be Item events to see in your events.log, you haven’t shown those.
You’re not going to get three different times without using three different timers.
It’s probably worth highlighting that when using someVariable = createTimer (blah )
the variable is just a handle or pointer to the timer, which is running independently. someVariable = null
does not stop an already running timer. The only way to do that is to instruct the timer using the handle someVariable.cancel
val String filename = "Irrigation.rules"
val IrrigationTimer = null
rule "Irrigation1"
when
Item dummyMGV1_State received command
then
if (receivedCommand == ON) {
if (IrrigationTimer === null){
logInfo(filename,"Text")
IrrigationTimer = createTimer(now.plusSeconds(Integer::parseInt(IrrigationTime.state.toString)))[|
dummyMGV1_State.sendCommand(OFF)
Irrigation_R1_lastRun.postUpdate(new DateTimeType())
logInfo(filename,"Text")
IrrigationTimer = null
]
}
Irrigation_R1.sendCommand(ON)
logInfo(filename,"Text")
} else {
Irrigation_R1.sendCommand(OFF)
Irrigation_R1_lastRun.postUpdate(new DateTimeType())
if (IrrigationTimer !== null){
IrrigationTimer.cancel()
IrrigationTimer = null
}
logInfo(filename,"Text")
}
end
rule "Irrigation2"
when
Item dummyMGV2_State received command
then
if (receivedCommand == ON) {
if (IrrigationTimer === null){
logInfo(filename,"Text")
IrrigationTimer = createTimer(now.plusSeconds(Integer::parseInt(IrrigationTime.state.toString)))[|
dummyMGV2_State.sendCommand(OFF)
Irrigation_R2_lastRun.postUpdate(new DateTimeType())
logInfo(filename,"Text")
IrrigationTimer = null
]
}
Irrigation_R2.sendCommand(ON)
logInfo(filename,"Text")
} else {
Irrigation_R2.sendCommand(OFF)
Irrigation_R2_lastRun.postUpdate(new DateTimeType())
if (IrrigationTimer !== null){
IrrigationTimer.cancel()
IrrigationTimer = null
}
logInfo(filename,"Text")
}
end
rule "Irrigation3"
when
Item dummyMGV3_State received command
then
if (receivedCommand == ON) {
if (IrrigationTimer === null){
logInfo(filename,"Text")
IrrigationTimer = createTimer(now.plusSeconds(Integer::parseInt(IrrigationTime.state.toString)))[|
dummyMGV3_State.sendCommand(OFF)
Irrigation_R3_lastRun.postUpdate(new DateTimeType())
logInfo(filename,"Text")
IrrigationTimer = null
]
}
Irrigation_R3.sendCommand(ON)
logInfo(filename,"Text")
} else {
Irrigation_R3.sendCommand(OFF)
Irrigation_R3_lastRun.postUpdate(new DateTimeType())
if (IrrigationTimer !== null){
IrrigationTimer.cancel()
IrrigationTimer = null
}
logInfo(filename,"Text")
}
end
rule "Abort Irrigation"
when
Item dummyBeregnung_Disable received update ON
then
// Beregnung abbrechen, wenn sie gestartet wurde
dummyMGV1_State.sendCommand(OFF)
dummyMGV2_State.sendCommand(OFF)
dummyMGV3_State.sendCommand(OFF)
end
2020-07-15 12:58:04.184 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule ‘Irrigation1’: ‘cancel’ is not a member of ‘java.lang.Object’; line 25, column 4, length 24
Looks to me that your shared timer handle will cause some odd interactions.
Example;
If you command valve 1 on, it turns it ON and sets up a timer to turn it OFF later.
If you now command valve 2 ON, it turns that ON but sets up no new timer at all.
If instead you command valve 2 OFF, it turns that OFF but cancels the running timer for valve 1, so valve 1 never gets turned off.
I can confirm this. If only one valve is activated, the timer will fit.
If all valves are activated at the same time or more than one valve is activated, the timers are not correct.
If I activate all three at the same time, they should of course also go out at the same time, as the timer is identical.
The running time should actually be the same for all valves.
however I do not find the error or do not know how to adjust the rules
if the var IrrigationTime is set to 5 sec. everything seems to work. if i set it a little higher 50 sec. not all timers run the same length. Very strange
val String filename = "Irrigation.rules"
val IrrigationTimer1 = null
val IrrigationTimer2 = null
val IrrigationTimer3 = null
rule "Irrigation1"
when
Item dummyMGV1_State received command
then
if (receivedCommand == ON) {
if (IrrigationTimer1 === null){
logInfo(filename,"Text")
IrrigationTimer1 = createTimer(now.plusSeconds(Integer::parseInt(IrrigationTime.state.toString)))[|
dummyMGV1_State.sendCommand(OFF)
Irrigation_R1_lastRun.postUpdate(new DateTimeType())
logInfo(filename,"Text")
IrrigationTimer1 = null
]
}
Irrigation_R1.sendCommand(ON)
logInfo(filename,"Text")
} else {
Irrigation_R1.sendCommand(OFF)
Irrigation_R1_lastRun.postUpdate(new DateTimeType())
if (IrrigationTimer1 !== null){
IrrigationTimer1.cancel()
IrrigationTimer1 = null
}
logInfo(filename,"Text")
}
end
rule "Irrigation2"
when
Item dummyMGV2_State received command
then
if (receivedCommand == ON) {
if (IrrigationTimer2 === null){
logInfo(filename,"Text")
IrrigationTimer2 = createTimer(now.plusSeconds(Integer::parseInt(IrrigationTime.state.toString)))[|
dummyMGV2_State.sendCommand(OFF)
Irrigation_R2_lastRun.postUpdate(new DateTimeType())
logInfo(filename,"Text")
IrrigationTimer2 = null
]
}
Irrigation_R2.sendCommand(ON)
logInfo(filename,"Text")
} else {
Irrigation_R2.sendCommand(OFF)
Irrigation_R2_lastRun.postUpdate(new DateTimeType())
if (IrrigationTimer !== null){
IrrigationTimer2.cancel()
IrrigationTimer2 = null
}
logInfo(filename,"Text")
}
end
rule "Irrigation3"
when
Item dummyMGV3_State received command
then
if (receivedCommand == ON) {
if (IrrigationTimer3 === null){
logInfo(filename,"Text")
IrrigationTimer3 = createTimer(now.plusSeconds(Integer::parseInt(IrrigationTime.state.toString)))[|
dummyMGV3_State.sendCommand(OFF)
Irrigation_R3_lastRun.postUpdate(new DateTimeType())
logInfo(filename,"Text")
IrrigationTimer3 = null
]
}
Irrigation_R3.sendCommand(ON)
logInfo(filename,"Text")
} else {
Irrigation_R3.sendCommand(OFF)
Irrigation_R3_lastRun.postUpdate(new DateTimeType())
if (IrrigationTimer3 !== null){
IrrigationTimer3.cancel()
IrrigationTimer3 = null
}
logInfo(filename,"Text")
}
end
rule "Abort Irrigation"
when
Item dummyBeregnung_Disable received update ON
then
dummyMGV1_State.sendCommand(OFF)
dummyMGV2_State.sendCommand(OFF)
dummyMGV3_State.sendCommand(OFF)
end
What makes you think that? You’ve got logInfo() in your rules, that would give you some idea of what is going on when, in your openhab.log. Taken with your events.log showing commands.
You could probably improve those diagnostics by not having all your logInfo() just say "text’.
I think now I’ve found the error.
i must have had a faulty configuration on the sonoff 4ch so not all outputs were deactivated at the same time.
in addition the faulty timer… but now it seems to work
2020-07-15 22:46:03.010 [ome.event.ItemCommandEvent] - Item 'dummyMGV2_State' received command ON
2020-07-15 22:46:03.018 [ome.event.ItemCommandEvent] - Item 'dummyMGV1_State' received command ON
2020-07-15 22:46:03.020 [vent.ItemStateChangedEvent] - dummyMGV2_State changed from OFF to ON
2020-07-15 22:46:03.020 [vent.ItemStateChangedEvent] - dummyMGV1_State changed from OFF to ON
2020-07-15 22:46:03.163 [ome.event.ItemCommandEvent] - Item 'dummyMGV3_State' received command ON
....
....
2020-07-15 22:47:06.665 [ome.event.ItemCommandEvent] - Item 'Irrigation_R2' received command OFF
2020-07-15 22:47:06.679 [ome.event.ItemCommandEvent] - Item 'Irrigation_R3' received command OFF
2020-07-15 22:47:06.690 [ome.event.ItemCommandEvent] - Item 'Irrigation_R1' received command OFF
as you can see all valves get the off command at the same time.
I’m currently still encountering new problems.
I would like my pump to be switched off about 10 seconds before the valve.
Can I check the remaining running time within the timer?
for eg
if (IrrigationTimer1 = “10 seconds remaining”’) {
pump .sendCommand(OFF)
}
when
Item dummyMGV1_State received command
then
if (receivedCommand == ON) {
if (IrrigationTimer1 === null){
logInfo(filename,"Text")
IrrigationTimer1 = createTimer(now.plusSeconds(Integer::parseInt(IrrigationTime.state.toString)))[|
if (IrrigationTimer1 = "10 seconds remaining"') {
pump .sendCommand(OFF)
}
dummyMGV1_State.sendCommand(OFF)
Irrigation_R1_lastRun.postUpdate(new DateTimeType())
logInfo(filename,"Text")
IrrigationTimer1 = null
]
}
Irrigation_R1.sendCommand(ON)
logInfo(filename,"Text")
} else {
Irrigation_R1.sendCommand(OFF)
Irrigation_R1_lastR
[details="Summary"]
This text will be hidden
[/details]
un.postUpdate(new DateTimeType())
if (IrrigationTimer1 !== null){
IrrigationTimer1.cancel()
IrrigationTimer1 = null
}
logInfo(filename,"Text")
}
end
....
No,not accessible.
You could set up two timers to begin with, with different durations.
Or you can use one timer that does task A, then itself sets up the timer for task B.