First try at creating a rule to have a switch on the sitemap I can turn on and it stays on for 3 seconds and then turns off.
This will energise a garage door to open or close. Eventually via MQTT to a mysensors relay.
I have two items,
Switch GD (displayed on sitemap)
Switch EnergiseGD (to connect to MQTT broker)
rule "Garage Door"
when
Item GD changed to ON
then
{sendCommand(EnergiseGD, ON)}
timer = Timer.create(now.plusSeconds(3) [|
{sendCommand(EnergiseGD, OFF)}
{sendCommand(EnergiseGD, OFF)}
]
end
rule "Garage"
when
Item Garage received command
then
QR1.sendCommand(ON)
Thread::sleep(3000)
QR1.sendCommand(OFF)
end
Edit: Also I would recommend to use a mapping for the switch on the sitemap so that you don’t have to turn off the switch again (or use a postUpdate in your rule to turn the switch off again):
If you want to use timers, though, it would have to look like this:
import org.openhab.model.script.actions.Timer
var Timer timer = null
rule "Garage Door"
when
Item GD changed to ON
then
sendCommand(EnergiseGD, ON)
timer = Timer.createTimer(now.plusSeconds(3) [|
sendCommand(EnergiseGD, OFF)
timer = null // reset the timer
])
end
sihui, thanks for that works really well and is nice and simple.
Birger I would really like to understand how to use timers for other things down the track. When I load that code into the designer it gives me a red cross on this line timer = Timer.createTimer(now.plusSeconds(3) [|
Is there an addon I need to add or something like that?
Basically a timer is just a piece of code that is executed at some point in the future. The createTimer() function takes two parameters: the point in time, and a lambda expression stating the code to execute. The code itself is started in a separate thread, so it can be executed even when the rule itself has already ended.
In the example above, we bind it to a variable outside the rule, so it stays in memory until the variable is somehow destroyed (by restarting openhab, reloading the rules file or by assigning timer = null once it has finished executing).
import org.openhab.model.script.actions.*
var Timer timer = null
rule "Garage Timer"
when
Item GD received command
then
if(receivedCommand==ON) {
if(timer==null) {
sendCommand(EnergiseGD, ON)
sendBroadcastNotification("Garage door energised")
timer = createTimer(now.plusSeconds(3)) [|
sendCommand(EnergiseGD, OFF)
sendCommand(GD, OFF)
timer = null
]
}
}
end
and
rule "Garage"
when
Item GD changed to ON
then
sendBroadcastNotification("Garage door energised")
sendCommand(EnergiseGD, ON)
Thread::sleep(3000)
sendCommand(EnergiseGD, OFF)
sendCommand(GD, OFF)
end
Not quite sure which one is best probably just different ways to do a task. Along the way I figured out the notifications via my.openhab which is a nice thing to have.
Thanks for the pointers, I am on a steep learning curve at the moment and it is great to understand how the basics work. Heaps more to learn but I can now see some amazing outcomes are possible.
Actually not too much. An unused timer object will stay in memory. I guess it will not take too much space, but it is always good practice to remove unused resources, because quite often openhab will run on limited hardware.
Since we are talking about Java, I assume you don’t even actually free the memory, you just create a hint for the garbage collector that it can free the memory if necessary.
Since it’s just a 3 second timer, I think both attempts are good.
I personally would not recommend using Thread::sleep() for longer intervals or more complex rules. Every time the rule is triggered it will be kept in memory entirely, just for the purpose of waiting and then executing a few more lines.
You are more flexible with timers when it comes to complicated timing (“one hour after sunset”, “three minutes after system startup”, etc.) or if you plan to re-schedule (“keep the lights on if the motion sensor reports presence”) or cancel timers (“raise alarm in 5 minutes, except someone enters the correct code on the keypad”).
One thing to watch is that the timer spawns a new thread so if your using locks that count on a rule finishing before the next one starts (Like I did with my generator start rule) the lock will unlock before your timer has finished.
Good question.
As long as you always assign it to the same variable I would expect it to be written to the same place in the memory (at least logically). So your memory consumption should not increase over time.
If you don’t plan to cancel or re-schedule it, you don’t even need to assign it to a variable. Then it will be garbage-collected as soon as it has run (or the rules file is refreshed, or the service is restarted, of course).
But I have to admit I don’t really know all those things. I just recall some useful facts I have learned about the JVM years ago and fill the gaps with clever i-would-have-developed-it-like-this-assumptions…
Hello All,
I tried to adapt the example to my sonoff S20. But somehow it doesn’t work.
I can’t find the error in my code. Can someone please advise:
import org.openhab.*
var Timer timer = null
rule "Steckdose KĂĽche Timer"
when
Item ki_plug1_SWITCH received command
then
if(receivedCommand==ON) {
if(timer==null) {
timer = createTimer(now.plusSeconds(5)) [|
publish("mosquitto:cmnd/sonoff_ki_plug1/POWER:OFF")
timer = null
]
}
}
end