Please test the new Expire Binding

I’m pretty sure groups can receive commands, for example a light group should accept OFF command and remit this to all direct group members.

According to the docs and examples you can…

https://docs.openhab.org/configuration/items.html

Right, ok.
Now that you mention your group is composed of items of different type, that might be your problem. I believe a dimmer will not accept OFF just as a switch does. Try with a homogenous group.

As an item of type dimmer accepts ON and OFF, an assorted group of dimmers and switches should also accept ON and OFF :slight_smile:

The plumbing of what Michael is trying to do should work.

You can indeed send a command to a Group and the command will be forwarded to all the members of the Group. If do this all the time. @mjcumming, I don’t know however whether that command will filter down to subGroups. Are you using nested Groups here?

And a Dimmer Item can receive ON/OFF commands (from Items | openHAB):

Dimmer Percentage value for dimmers OnOff, IncreaseDecrease, Percent

The third column defines those command types the Item can accept.

One thing that does pop out as a potential problem is we may not be able to have a binding config on a Group. The Group docs (Items | openHAB) does not include any { } clause. Since Expire is a binding I’m thinking that what you would like to do is not possible. The error you report is surprising though. I would have expected to see syntax errors when the .items file was loaded.

This is an interesting use case.

I am trying to find an easy way to use expire to turn off lights in a room when nothing has happened in that room for a period of time. Have read a lot of your posts on DP and would really like to find a solution along those lines.

Another example I am working on is our Mudroom. In that room I have a closet light (switch) a dimmer (overhead lights), motion sensor, and a door contact. I would like to use any event from those 4 sources to say that the room is occupied. If there are no events from any of those sources for 10 minutes, then turn off all the lights in that room.

Certainly, could code rules to manage that but for all the rooms I would like to do that in… yuck! :slight_smile :slight_smile:

Below are a few screenshots from a Occupancy plugin I wrote for Girder about 10 years ago… it accomplished all of this by using Locations within the house, the devices/sensors in that location to set when the room was occupied, each room would have a preset decay rate, and when empty, the various devices could be set to turn off ….

image

image

image

Each room has a Group for the lights (e.g. Kitchen_Lights, Hall_Lights, etc). That Group gets put into a parent Group (RoomLights) so we can access it later. Each room has a Timer Item with Expire binding config (e.g. Kitchen_Timer, Hall_Timer, etc) and all the Timers go into a Group (RoomTimers). Each Sensor goes into another Group (RoomOccupancySensors).

All Items are named using Assocaited Items DP.

rule "Sensor detected occupancy in a room"
when
    Member of RoomOccupancySensors received update
then
    // schedule/reschedule the timer
    sendCommand(triggeringItem.name.split("_").get(0) + "_Timer" , "ON") 
end

rule "A room is no longer occupied"
when
    Member of RoomTimers received command OFF
then
    // turn off the lights
    sendCommand(triggeringItem.name.split("_").get(0) + "_Lights", "OFF")
end

Theory of operation: When any sensor updates, use Assocaited Items to send a command to the associated Timer. You may need to do more checking here to make sure the update indicates presence. When a Timer Item expires another Rule runs which sends the OFF command to that room’s lights. You may need to loop through the Group and send a different command depending on the Item type. If you do you need to pull the Group out by name:

val lights = RoomLights.members.findFirst[ lts | lts.name == triggeringItem.name.split("_).get(0) + "_Lights" ]
lights.filter[ l | l instanceof SwitchItem ].forEach[ l | l.sendCommand(OFF) ]
lights.filter[ l | l instanceof NumberItem ].forEach[ l | l.sendCommand(0) ]
...

The magic happens by using the Associated Item DP naming scheme and Groups so you can use the name of triggeringItem of the Rule to access the Items you need to interact with.

1 Like

@rlkoshak Rich, how would you see a couple of things using DP.

First, using a group hierarchy ie Home, Main Floor, Mudroom.

All rooms are “assumed” by the system to be vacant because no activity.

A light in the Mudroom is turned on, and an event should propagate up so that the Main Floor and Home would switch to an “occupied” state. That way, any event in any part of the home will keep the Home in an occupied state.

This becomes useful say when at sunset, you would like certain lights inside your home turned on but only if you are home.

But, also imagine the opposite, when the home is vacant. If someone approaches the house and an outdoor motion sensor sees that person, you could have that event turn on an inside light (often nice when coming home to a dark house or to scare away a trespasser). The problem in this scenario, is turning on that inside light will change the status of the home from vacant to occupied. So we then need a way to “lock” that state of the home while turning on that light so there is no change in occupancy.

Another scenario, say the security system is armed “AWAY”. In this instance, the Home would be set to vacant, this event would propagate to all the different rooms, and appropriate actions would be taken ie turn off lights, music, change temp etc.

As I mentioned above, I have done that before, but this looks daunting in openHab especially since the DSL offers essentially no debugging or test environment.

Mike

If it is night and the light was turned on by a Rule you know not to change the occupancy switch for that room.

Just send an OFF command to the Group that contains all the Items that indicate occupancy.

You will probably want to draw out a state diagram to make sure you don’t have any incompatible state transitions. You can easily end up in a situation where a state transition event changes and you end up in two incompatible states.

For a setup this complex you will probably want to use a bunch of proxy items so you have some control over how the events propigate.

Can I use the Expire Binding for a duration of a year? I have a thing that needs to be replaced once a year. I’d like to put a reed switch on it so that when it opens the expire bound switch turns on. Then after a year the switch turns off… sending me a notification.

Also, does anyone know what’s the max duration of the expire binding?

Google Calendar no good?

The expire timers don’t survive a restart/reboot.

Good point. Also the documentation for the binding says that “The Expire binding accepts a duration of time that can be made up of hours, minutes and seconds” which kinda makes me think it’s not made for really that long periods. I’ve never used it for anything longer than 15 minutes.

edit: I checked the source. If the time doesn’t match the pattern “(?:([0-9]+)H)?\s*(?:([0-9]+)M)?\s*(?:([0-9]+)S)?” it will throw an exception.

1 Like

why not set a persisted date item with the date the reed switch opens. Then, have a cron rule checking every week whether the date item is a year old.

1 Like

An other alternative to the suggestions by @greg and @dan12345 you can use a Timer and persisted date Item.

See Design Pattern: Encoding and Accessing Values in Rules for how to set your DateTime Item or Individual Alarm clock for each Day of week, with adjustable duration if you want to adjust the date from your sitemap.

Then you just need a System started Rule:

var Timer yearLongTimer = null

rule "Reset timer"
when
    System started
then
    yearLongTimer = createTimer(new DateTime(TimerItem.state.toString), [ |
        // do stuff when timer expires
    ])
end

Then you don’t have to poll and the event will occur exactly at the right time.

Note, you can use this same approach for Expire based timers, however, when OH restarts and you have a System started rule to reset the Expire timers, the time starts over so if you had a timer about to go off after 5 minutes, OH restarts and this System started Rule runs, it would reset the Expire binding to the full five minutes.

That often doesn’t matter but in this case it would. You could have OH running for 6 months and then it restarts and now the Expire timer would get reset for another year.

@greg I think the google calendar idea is a great solution. I’ll definitely check into it if I have other uses for it. Seems unnecessary to use it for just this one situation.

@sihui @DanielMalmgren Thanks for informing me of that. I thought expired items survived a reboot since I have persistence set up.

@dan12345 Good suggestion. However, I want to keep the cron rules to a minimum.

@rlkoshak This sounds like the way to go. Would you explain why I need the system started rule? The way I read it… the timer will be reset every time the system restarts. Is this correct?

Thanks

Correct. Like the Expire binding, Timers will not survive a reboot of OH so you need to use persistence to save the time you want the Timer to go off and a System started Rule to recreate the Timer when OH restarts.

Got it… I had to read the system started rule a few times to get it. Thank you

I gave it some thought and decided to go with the cron to check every Friday. @rlkoshak I looked at the referenced threads… to be honest I don’t understand any of it :expressionless: Wish I did! I would like to understand more about the nuts and bolts, if you will, about programming, but don’t know how or where to start.

I have an idea about what I want to do… would you all kindly check this out >> [SOLVED] Thermostat Rule Help (gpio, dht22, exec binding, things, items, rules)

Any suggestions on what I’m doing wrong would be greatly appreciated! Thanks