Design Pattern: Expire Binding Based Timers

can I add this binding in the JSON file?
Whats the syntex, if yes?

“Stue_lys”: {
“class”: “org.eclipse.smarthome.core.items.ManagedItemProvider$PersistedItem”,
“value”: {
“groupNames”: [],
“itemType”: “Switch”,
“tags”: [],
“label”: “Lys i stuen”
}

No, you cannot. It’s a 1.x version binding so .items files must be used. In OH 3 some other mechanism will be created that will implement the Expire Binding feature.

Hello Rich,

Your post is very helpful. Thank you very much.

I am very new to Openhab, and was wondering if you could clarify what you meant by

So to trigger a Rule only when the timer expires you would use Item MyTimer received command OFF .

I have used your code snippet and would like to use that to create an alert when a door is left open. The first part of my code creates a ding-dong song (to keep my 3 year old from walking out by himself).

I have seen your other post on using groups to reduce the lines of code, but to be honest it’s over my head. And honestly, I’m still trying to figure out this whole OpenHab thing.

so in items, I have created the following switch
Switch FrontDoorOpen_Timer { expire="5m,command=OFF" }

And in my Rules folder, I have:

rule “front_door_open”
when
Item zwave_device_08f074d1_node6_sensor_door changed from CLOSED to OPEN
then
playSound(“chromecast:chromecast:ead9e7276c37c0aaaf5a2c261342d6da”,“Apartment-ding-dong-sound.mp3”)
playSound(“chromecast:chromecast:ecd97d69f28d9f1c0173a27b8c48df78”,“Apartment-ding-dong-sound.mp3”)
Thread::sleep(250)
say(“front door”)

if(FrontDoor_Timer.state == ON) {
    // do stuff if Timer is actively running
}

// cancel Timer
FrontDoor_Timer.postUpdate(OFF)

// start Timer
FrontDoor_Timer.sendCommand(ON)

// do some stuff

end

rule “Door Open timer expired”
when
Item FrontDoor_Timer received command OFF
then
// Timer body
say(“the front door has been left open for 5 minutes”)
end

The ding-dong works, but for the life of my I can’t figure out how to change this to only give the alert when the door remains open. Any help would be super appreciated!

You’d want to “cancel” the expire timer by setting the timing Item to OFF without using a command.
Make another rule, triggered by the door changing to closed, that issues
FrontDoor_Timer.postUpdate(OFF)
Don’t be afraid to have many small rules for each task.

Setting the timer Item to the same state as the “target action” cancels the expire effect; using postUpdate instead of sending a command avoid triggering your alerting rule.

I am on latest openhab snapshot and I get following error every few seconds in the logs:
[ERROR] [core.karaf.internal.FeatureInstaller] - Failed installing ‘openhab-binding-expire’

Within paperui the expire binding shows as installed but is not functioning (switch never expires)

If I remember correctly the expire binding was within the action addon section of the paperui and is now in the binding section. Could this error be related to this move?

NoTechi

I’m pretty positive that is not the case. Expire has always been a binding. It doesn’t work like an Action (i.e. you call it from a Rule) so it doesn’t belong as an Action.

First thing to try, assuming you already tried restarting OH is to Clear the Cache and try again.

OK then I have bad memories … old man you know :wink:

I just restarted OH and cleared the cache but I get the same error in the logfiles after installing Expire via paperui after the restart.

What version of OH and how did you install?

openHAB 2.5.0 Build #1715 using a docker on a Synology

I tried it again:

  • uninstall expire
  • shotdown openha
  • clear cache
  • start openhab
  • install expire

Now I get following error within the logs:

2019-10-16 19:45:26.815 [INFO ] [b.core.service.AbstractActiveService] - Expire Refresh Service has been started
2019-10-16 19:45:26.822 [ERROR] [core.karaf.internal.FeatureInstaller] - Failed installing 'openhab-binding-expire1': Error restarting bundles:
	Exception in org.eclipse.smarthome.io.rest.sse.internal.SseActivator.start() of bundle org.openhab.core.io.rest.sse.

@NoTechi If you are not testing for errors and reporting them on GitHub, why are you running an unstable snapshot? Things are expected to be broken there.
Testing & Stable builds are designed for the average user.

@Bruce You are right actually I went through stable, testing to snapshot (since it is pretty easy to do with a docker) to get a functionality in a different binding which is only in the snapshot for now. But yes I should consider going back to testing and be patient or live with the expire binding not working in the snapshot for now.
Sorry for looking for a solution to a problem in an unstable build and just ignore my question :slight_smile:
NoTechi

Don’t forget expire is a 1.x binding, and you need “enable legacy bindings”

I have legacy enabled yes but thanks for the hint.
NoTechi

I think this should iterate the members:

gResetExpire.members.forEach[ timer | timer.sendCommand(timer.state) ]

I also frequently get IDE errors on things like timer.sendCommand(timer.state).
I usually have to use timer.sendCommand(timer.state.toString)

Thanks for catching the bug. The IDE sometimes is sometimes more strict than it needs to be. I don’t use Rules DSL any more so haven’t see the error you refer to myself, but indeed, using toString would sort it out.

Hi,
This looks like the perfect solution for me.
I tried the DSL sample but the timer is never expiring. What is wrong in the code below?
I hope someone can help me with this.

// item created Switch MyTimer { expire=“20s,command=OFF” }

rule “System started”
when
System started
then
MyTimer.sendCommand(OFF)
end

rule “BadkamerMovement”
when
Item Beweging_gEVBadkamer changed from OFF to ON
// state will change from OFF to ON every 10 sec if no movement is detected for 10 sec and then detects movement.
then {
logInfo(“default.rules”, “Movement detected”)
if(MyTimer.state !== ON ) {
logInfo(“default.rules”, “Badkamer timer not started so start it”)
MyTimer.sendCommand(ON)
} else {
logInfo(“default.rules”, “Badkamer timer already started”)
// Here I want to reset the timer. Is the this the way to do. Can’t test if becase I first need to detect MyTimer is expired.
// MyTimer.postUpdate(OFF)
// MyTimer.sendCommand(ON)
}
}
end

// The rule below is never started.
rule “BadkamerTimerExpired”
when
Item MyTimer received command OFF
then {
logInfo(“default.rules”, “Badkamer timer 10m received off”)
// Do I need to do something if MyTimer is expired.
}
end

Does the trigger event occur? Look in your events.log

The first post says

It requires installation of the Expire binding.

and you’ve not mentioned doing that.

Thanks. I added the Expire binding and it works perfect.

Hi all,

I’ve been using the expire binding and similar dummy items to the design pattern above as a timer for a while. I thought it was a hack to avoid timers and sleep rather than an actual way to do it so pretty pleased with it all.

I’ve one question on the expire binding now as I’m implementing a new rule for a light switch. I’ve a motion sensor that turns ON when it senses motion, which in turns turns on the light item itself and also a dummy item with a 30 second expire to then turn the light off again after 30 seconds.

My issue is that I want the expire time to reset if the motion sensor detects more movement, ie the person is still milling about in the area.

I know from the docs that if you update the state of the item to be the same state it already was then it resets the timer, (which is what I want), but in this case is there a difference between sendcommand(ON) and postupdate(ON)? Will one rest the timer and the other do nothing???