I would like to set up a variable timer on my sitemap.
I have integrated my ceiling fan as an item via a Zigbee plug. Can I include an element in my sitemap where I can put in any amount of minutes (text box, drop down…) and then hit run to power the fan for set time?
As a compromise, 2 or three fixed scenarios (run for 15, 30 or 60 minutes) to choose from would be fine as well.
Okay, I’ve stumbled about something similar in a coding example for an irrigation. It uses two sitemap items: one Selection and one Switch.
When the switch is changed to ON, the item is turned on and an OFF command is scheduled via
“createTimer(now.plusMinutes(Integer::parseInt(FanDuration.state.toString))) [|
Fan_State.sendCommand(OFF)]”
Is this the simplest way or is there a solution that only uses one line of the sitemap?
Well, if you use a Selection on your sitemap, you can have a rule that listens for commands to the selected Item from user clicking. That could take the place of a separate “go” button, it’s up to you.
Is there any way to kill previous timers? E.g., if I select 15 minutes and then change my mind and select 30, the 15 minute timer will still kill the fan, right?
Even from testing now, I probably have like 15 timers in line waiting to turn the fan off
val String filename = "fan.rules"
rule "Fan Timer"
when
Item FF_Fan_Duration changed
then
if (FF_Fan_Duration != 0) {
FF_Fan.sendCommand(ON)
logInfo(filename,"Ventilator gestartet.")
createTimer(now.plusMinutes(Integer::parseInt(FF_Fan_Duration.state.toString))) [|
FF_Fan.sendCommand(OFF)
logInfo(filename,"Ventilator gestoppt.")
FF_Fan_Duration = null]
}
end
Yes, this is very common. The trick is to keep a “handle” to the Timer in a global variable, allowing you check if one is off already and then cancel or reschedule it.
When you click in a sitemap, it sends commands to the Item. Very often (but not always) that can result in a state update as well.
If you want to change the state of an Item in a rule, use one of the provided postUpdate methods, which are smart enough to use type conversions in many cases.
Yes, seems to work. Now the conditions don’t work as intended. Again my code:
val String filename = "fan.rules"
rule "Fan Timer"
when
Item FF_Fan_Duration changed
then
if (FF_Fan_Duration == 0) {
FF_Fan.sendCommand(OFF)
logInfo(filename,"Ventilator gestoppt.")
}
else if (FF_Fan_Duration == 99) {
FF_Fan.sendCommand(ON)
logInfo(filename,"Ventilator gestartet.")
}
else if (FF_Fan_Duration != 0) {
FF_Fan.sendCommand(ON)
logInfo(filename,"Ventilator gestartet.")
createTimer(now.plusMinutes(Integer::parseInt(FF_Fan_Duration.state.toString))) [|
logInfo(filename,"Ventilator gestoppt.")
FF_Fan_Duration.sendCommand(0)]
}
end
Starting the fan and timer with the Selection works:
2019-04-29 20:47:58.599 [ome.event.ItemCommandEvent] - Item 'FF_Fan_Duration' received command 1
2019-04-29 20:47:58.621 [vent.ItemStateChangedEvent] - FF_Fan_Duration changed from 0 to 1
2019-04-29 20:47:58.652 [ome.event.ItemCommandEvent] - Item 'FF_Fan' received command ON
==> /var/log/openhab2/openhab.log <==
2019-04-29 20:47:58.652 [INFO ] [pse.smarthome.model.script.fan.rules] - Ventilator gestartet.
==> /var/log/openhab2/events.log <==
2019-04-29 20:47:58.666 [nt.ItemStatePredictedEvent] - FF_Fan predicted to become ON
2019-04-29 20:47:58.676 [vent.ItemStateChangedEvent] - FF_Fan changed from OFF to ON
After one minute FF_Fan_Duration is set to 0 and should trigger the first if clause to turn the item off. However, it only puts the text of the first if clause into the log and apparently enters the last if clause once more…
19-04-29 20:48:58.660 [INFO ] [pse.smarthome.model.script.fan.rules] - Ventilator gestoppt.
==> /var/log/openhab2/events.log <==
2019-04-29 20:48:58.674 [ome.event.ItemCommandEvent] - Item 'FF_Fan_Duration' received command 0
2019-04-29 20:48:58.704 [vent.ItemStateChangedEvent] - FF_Fan_Duration changed from 1 to 0
==> /var/log/openhab2/openhab.log <==
2019-04-29 20:48:58.752 [INFO ] [pse.smarthome.model.script.fan.rules] - Ventilator gestartet.
==> /var/log/openhab2/events.log <==
2019-04-29 20:48:58.762 [ome.event.ItemCommandEvent] - Item 'FF_Fan' received command ON
2019-04-29 20:48:58.777 [nt.ItemStatePredictedEvent] - FF_Fan predicted to become ON
==> /var/log/openhab2/openhab.log <==
2019-04-29 20:48:58.777 [INFO ] [pse.smarthome.model.script.fan.rules] - Ventilator gestoppt.
==> /var/log/openhab2/events.log <==
2019-04-29 20:48:58.797 [ome.event.ItemCommandEvent] - Item 'FF_Fan_Duration' received command 0
Side note: is there another platform for this nitty gritty trouble shooting? I feel like I’m taking up the time and place here from bigger issues…
I’ve tried to implement the timer logic as per the previous link. Everything looks good up until the first createTimer.
The } after FF_Fan_Duration.sendCommand(0)] is marked with the comment “extraneous input ‘]’ expecting ‘}’(org.eclipse.xtext.diagnostics.Diagnostic.Syntax)”
var Timer fantimer = null
val String filename = "fan.rules"
rule "Fan Timer"
when
Item FF_Fan_Duration changed
then
if (FF_Fan_Duration.state == 0) {
fantimer.cancel
FF_Fan.sendCommand(OFF)
logInfo(filename,"Ventilator gestoppt.")
}
else if (FF_Fan_Duration.state == 99) {
if(FF_Fan == ON) {
fantimer.cancel
logInfo(filename,"Timer gestoppt, Ventilator bleibt an.")
}
else {
FF_Fan.sendCommand(ON)
logInfo(filename,"Ventilator gestartet.")
}
}
else if (FF_Fan_Duration.state != 0) {
if (fantimer === null) {
FF_Fan.sendCommand(ON)
fantimer = createTimer(now.plusMinutes(Integer::parseInt(FF_Fan_Duration.state.toString))) [|
FF_Fan_Duration.sendCommand(0)]
}
else {
fantimer.reschedule(now.plusMinutes(Integer::parseInt(FF_Fan_Duration.state.toString)))
}
}
end
Thank you very much! After a few changes it works like a charm now. I’m sure the code could be improved but the logic is not complicated at all once you get the syntax
If any other beginner is interested in a simple fan control: