Please test the new Expire Binding

The binding does indeed check its map of item names+expire times every second, but I think the biggest burden it imposes is if TRACE logging is on. The amount of work to check the map is (I think) very minimal. The current implementation does create a new ArrayList of bound item names every second, but I will change that. I think it’s a better implementation than scheduling and cancelling jobs because the code is simpler, but I would be happy to hear contrary arguments.

Your TRACE log above looks correct except for the second OFF update it received. I will look into that.

Once it’s deemed fit, it will be added to the build.

1 Like

Ok, so this is just checking its internal map? I don’t suppose this can be made to be more event driven as opposed to polling? It may not take much resources once trace is turned off, but if every binding started polling every second, it could possibly start impacting less powerful systems (I’m guessing).

That is definitely true. Minimising the work to do on each polling cycle will only go so far, if there is a lot of polling. One tiny change I’ve made from your feedback is to have to poll cycle skip iterating binding providers and item names if there are no outstanding expirations.

Great, every little bit counts!

I wanted to mention a binding idea I had a few moons back:

The idea there was a bit similar to what your binding is about. How do you feel about either extending the binding by functionality mentioned there or about building a second binding that might use some of the same logic?

My issue with a “timer binding” is that what happens at the expiration of a timer should be very open-ended, and is already addressed by rules. Bindings should be concerned with updating items with new states, and fielding commands to instruct external systems to do things, and not much else. So bindings shouldn’t reference other items or lots of other things that might be to be accessed on the expiration of a timer.

The expire binding does fit the model of a binding, because it’s concerned with updating states of items that are bound to it, and listening to updates and commands to influence when the expirations should occur. The only thing it lacks is a connection to an external system, but you could think of the passage of time as an external system. So the expire binding is a simple way of implementing a “watchdog” or “heartbeat” system. And it’s a lot simpler than the set of rules needed to achieve a similar outcome but with much more overhead.

I don’t think there is a good case for adding support for cron expressions or making a “cron binding”, because that gets back to the “so what do you do when the trigger fires at these specific future times?” question. And rules already address cron triggers nicely and the open-ended things users can do inside the then/end blocks.

1 Like

Hey John,
I’m not sure if we are talking about the same thing. Check my second posting in the thread where I described my view on things.

Imagine a new product called “Wifi Egg Timer”. One could build a binding for this one. A user can then for example:

  1. Set a timer duration
  2. Activate the timer
  3. Read the remaining time
  4. Get informed that the timer reached it’s deadline

This would be a nice addition to openHAB and could be nicely integrated in both UIs and rules. If we now remove the hardware from the equation, we’ve got the Timer Binding.

The binding on it’s own doesn’t interact with any other item or binding. It’s up to the user to define a sitemap element to trigger (2.) or build a rule to react on (4.).

I’m not sure if I understood you right here. What does “open-ended” mean? Currently you can not define a rule in this way (which is the whole point of my proposal):

rule "Set timer"
when
    # Timer reached deadline 
then
    # react
end

Just wanted to drop a quick thank you for this binding!

I have a few motion sensors that (in)frequently miss there “no motion” reports and continue to show motion for hours. I was literally lying in bed this morning thinking of the rule I would write for this. I woke up and saw this binding! Perfect!

1 Like

Sorry for my confusion, @ThomDietrich.

Would "7m" in the .items file not suffice, or do you want to send a "5m" command or some other duration to an item dynamically?

Switch EggTimer { expire="7m,command=OFF" }

rule BoilAnEgg
when
  Item EggTimer received command ON
then
  Cooker.sendCommand(ON)
end
EggTimer.sendCommand(ON)

You could add to the BoilAnEgg rule that recorded the current time, and maybe a cron rule to repeatedly updates the state of another item to show the decreasing duration. Or something similar to what is described here.

rule EggIsDone
when
  Item EggTimer received command OFF
then
  Cooker.sendCommand(OFF)
  sendEmail(...)
end

Ya, I was looking forward to alert/alarm support, I have a LOT of items that I think it would work with.

1 Like

At least … :slight_smile: a “set time widget” would be nice, just as a “text input widget” e.g. to set a short message through UI. Just my two cents…

1 Like

I replaced a simple timer with this binding and it works without any problems.
Very easy to use, thanks a lot :+1:

1 Like

Finally getting around to experimenting and finding the edges of this binding.

Unfortunately this idea does not work. The binding, as currently written, does not take system start as a starting event to expire the Item’s state.

@watou, would something like that make sense, or does it make more sense to keep that in a System started rule.

To reiterate my use case, I have a number of Items that store state (e.g. an override flag when a lighting rule has been overridden). Sometimes these state Items need to be boot strapped into an initial value using a System started rule. This rule only need run the one time if one is using persistence/restoreOnStartup. It would be a lot cleaner if one had a way to define a state for an Item in the Items file. This binding could provide that functionality if it took startup as an event to start the expiration timer running.

Or would this more appropriately be something implemented as a core feature of Items or just continue to use a System started rule that first time after an Item is defined to give it its very first value?

I have helped others with the question of how to give an initial state to Items so I know I’m not unique in this sort of use case.

The Expire binding has to be up and running, listening to states and commands of all its bound items. When it receives any state or command that isn’t used for the binding to “expire” the item, the binding schedules (or re-schedules) the expiring update or command. If it the binding receives the expiring state or command, it stops any future expiration.

So the binding has to be running and listening for commands or updates on its items in order to start the expiration.

One way to look at it is that the system does give all items an initial value (Undefined), and it’s up to bindings, scripts, rules, API or restoring from persistence to update them further. The Expire binding only responds to the item receiving a command or update. It does not interrogate the item’s state at startup time, partly because the point is to expire some fixed amount of time after the state change or command was received, but that can’t be learned by inspecting its bound items when the binding starts.

1 Like

Further testing shows everything checks out.

For the curious, here is a way to “reschedule” the Expiration similar to how one can do with a regular timer.

Items:

Contact	Door "Door [%s]" <frontdoor> 
Switch Door_Timer "Door Timer [%s]" { expire="60m,command=OFF"}

Rules:

rule "Door changed"
when
    Item Door changed
then
    // do some stuff

    if(Door.state == OPEN) Door_Timer.sendCommand(ON)
    else Door_Timer.postUpdate(OFF)
end

rule "Door timer"
when
    Item Door_Timer received command OFF
then

    // do timer stuff like sending alerts

    if(<reschedule condition>) Door_Timer.sendCommand(ON)

end

As I hope everyone can see, this is quite a bit cleaner than self coded Timers.

The code above works because the only thing that will send an OFF command is the Expire binding and the only time the Door Timer rule triggers is when an OFF command is received. This rule takes the place of the Timer body.

Sending the postUpdate(OFF) causes the Expire binding to cancel the timer.

Edit: Update, the check for whether the door is OPEN is not needed in the timer rule.

2 Likes

Very clever! I think you don’t need the if (Door.state == OPEN) test in the “Door timer” (second) rule because the only source of an OFF command is the timer expiring as defined in the item binding, but you would have cancelled it earlier if the door was closed with Door_Timer.postUpdate(OFF). Since you cancel the timer with an update, not a command, the rule doesn’t and won’t trigger.

I didn’t realize that the postUpdate(OFF) actually cancelled the timer. I assumed that the postUpdate(OFF) would essentially reschedule the timer because it is an update. So, in my case, 60 minutes after the postUpdate(OFF) I’d get a sendCommand(OFF) from the Expire binding.

So the Expire binding will cancel the timer if the Item gets set to whatever state it would be set to by the binding when the ? Or is something else going on?

I really just assumed the behavior and didn’t test it. This is good to know and it makes the rule even simpler. :slight_smile:

The Expire binding listens for all commands and updates on its bound items. If a command or update is received that matches the “expire” state or command you specified in the item binding config (OFF in your example):

Switch Door_Timer { expire="1h,command=OFF" }

any expire timer currently scheduled is canceled. So, in your example, Door_Timer.postUpdate(OFF) cancels any scheduled expiration. (But since it was an update and not a command, the second rule in your example isn’t triggered by this.)

If a command or update is received that does not match the “expire” state or command, an expire timer is either scheduled, or moved later in time if one is already scheduled (sendCommand(ON) in your example). If the door keeps opening and closing throughout the hour, timers will continue being cancelled and rescheduled, but no timer expiration will occur unless the door is actually left open for an hour.

1 Like

I added a wiki page for the Expire binding.