I have a problem with timers in openHAB 3.2. base is Ubuntu Server 20.04 LTS with Zulu Java. Various rules with timers can not be extended or stop not clean running timers.
For example, I have a rule for the basement that should turn off the lights in the stairwell after 3 minutes. If I do nothing, then the light also goes off after exactly these three minutes. However, if I manually switch off the light within the three minutes, and then switch it on again in the remaining timer time, the timer is not executed with the full runtime, but goes off after the remaining runtime. In the worst case, if you walk back and forth a lot, you turn on the light and it goes off again within a few seconds.
This problem also leads in other areas, where I actually work with a motion detector, to the fact that the light is not extended when motion detection stops and you are suddenly in the dark.
Attached is a rule for one of the basement lights. I hope that the German item descriptions are not a problem for understanding.
var Timer s_kg_flur_timer = null
rule "Wandleuchte Kellerdiele"
when
Item s_kg_diele_wandleuchte changed
then
if (s_automatisierung_innenbeleuchtung.state == ON) {
if (s_kg_diele_wandleuchte.state == ON) {
s_kg_diele_timer = createTimer(now.plusSeconds(180), [ |
s_kg_diele_wandleuchte.sendCommand(OFF)
s_kg_diele_timer = null
])
} else {
if (s_kg_diele_timer.isRunning) {
s_kg_diele_timer.cancel
s_kg_diele_timer = null
}
}
}
end
I had before also a little other version:
rule "Wandleuchte Kellerdiele"
when
Item s_kg_diele_wandleuchte changed
then
if (s_automatisierung_innenbeleuchtung.state == ON) {
if (s_kg_diele_wandleuchte.state == ON) {
s_kg_diele_timer = createTimer(now.plusSeconds(180), [ |
s_kg_diele_wandleuchte.sendCommand(OFF)
s_kg_diele_timer = null
])
} else if (s_kg_diele_timer !== null) {
if (s_kg_diele_timer.isRunning) {
s_kg_diele_timer.cancel
s_kg_diele_timer = null
}
}
}
end
The variable name was my mistake when I copy the example of the rules files, while different rules where in the file. So I had this defined:
var Timer s_ga_haustuer_timer = null
var Timer s_kg_diele_timer = null
var Timer s_kg_flur_timer = null
Edit: I changed the rule with .hasTerminated and my first tests are positiv. I have in different combinations the full three minutes before the light get off.
rule "Wandleuchte Kellerdiele"
when
Item s_kg_diele_wandleuchte changed
then
if (s_automatisierung_innenbeleuchtung.state == ON) {
if (s_kg_diele_wandleuchte.state == ON) {
s_kg_diele_timer = createTimer(now.plusSeconds(180), [ |
s_kg_diele_wandleuchte.sendCommand(OFF)
s_kg_diele_timer = null
])
} else if (s_kg_diele_timer !== null) {
if (s_kg_diele_timer.hasTerminated == false) {
s_kg_diele_timer.cancel
s_kg_diele_timer = null
}
}
}
end
Thank you rossko, for this hint. I have adjusted my rules accordingly. However, without your contribution, I don’t know if I can follow it in terms of content then. The short notation is quite abstract. And it has the small disadvantage in connection with the Visual Studio Code extension that the variable is no longer recognized as a variable.
Jruby has a specific feature that makes this easier.
rule 'Wandleuchte Kellerdiele' do
changed s_kg_diele_wandleuchte, to: ON, for: 180.seconds
only_if s_automatisierung_innenbeleuchtung
run { s_kg_diele_wandleuchte.off }
end
Specifically, the for parameter will cause the rule to run only when the item has changed to the given state (in this case, ON) for the given duration (180 seconds).
If the item turned off (changed state different to the parameter), the rule will not run and any internal timer is cancelled and cleared. When it changed again to ON, it will start a new timer from that moment.
I believe it does exactly what you want without having to write the boilerplate code. This scenario is quite common that the feature is built in to the scripting library.