Open Reminder [3.3.0;3.4.9)

image

NOTE: Please upgrade if you installed this prior to 2022-10-19. There is a pretty bad bug in earlier versions.

This rule template addresses the problem where one wants to do something periodically after an Item changes from a given state for long enough. For example, send an alert when a door has been open for 15 minutes and repeat the alert every five minutes until the door is closed. Or wait until a motion sensor stops triggering for five minutes and turn off the light.

This rule template is closely related to Threshold Alert. The primary difference is Threashold Alert looks for numerical values above or below a given value where this one looks for Item states that are exactly the same or exactly different from a given state. In other words, Threshold Alert is for number Items and this is for Switch, Contact, or looking for Items going to NULL or UNDEF. Some day I hope to merge them but the configuration is going to be challenging.

In addition to supporting an initial timeout (how long the Item should be in the alert state before alerting) and a potentially different repeat timeout (how often to generate the alert again), the template also supports an optional time period where the alerts are not allowed so, for example, you can prevent an alert on your phone every five minutes during the day when you donā€™t care as much if the window is open. Any alert that occurs during this time will be moved to the end of the period, as long as the Item remains in the alerting state.

The rule has a number of properties.

Property Required Default Description
Group of Triggering Items X The Group containing the Items this rule will monitor.
Alert State X The state the Item has to be different from for alerts. For example, an open door reminder would use CLOSED as the Alert State.
Invert false If checked, it inverts the meaning of Alert State so the alerts are sent when the Item is the same as Alert State instead of different.
Default Initial Timeout PT15m By default how long the Item needs to be different from the Good State before the first time the alert script is called. Set to ā€œPT0sā€ to run immediately.
Default Item Initial Timeout Metadata rem_time The Default Initial Timeout can be overridden on a per Item basis by adding metadata to the Items. The value of the metadata is used and should be in duration format (see below).
Repeat Period How often to call the alert script again after the first initial timeout. If left blank no repeats will be performed.
Reschedule false If the rule is triggered again with the alerting state, whether to reschedule the looping timer or ignore the state change. Default is to ignore the state change.
Alert Rule Rule UID to be called after the initial timeout and again every repeat period.
Alert Starting Time 00:00 The time to start allowing the rule to call the alert rule.
Alerting Ending Time 00:00 The time to stop allowing the rule to call the alert rule.

If you need to have a different trigger type than changed, you can edit the rule after you create it. Unfortunately it appears that the trigger type cannot be a rule template parameter.

The initial timeout, value of the initial timeout metadata, and repeat period should all be in ISO-8601 Duration format. In general that will be a String starting with PT followed by numbers and a designator for time units. For example, one hour and two seconds would be PT1h2s.

You provide the Item metadata namespace for the default Item initial timeout metadata. The value of this metadata will be the initial timeout duration used for that Item. In a text Item, assuming the namespace is ā€œrem_timeā€ that will look like rem_time=PT10m. In the UI add metadata named rem_time and supply the timeout String as the value.

If the alerting starting time and ending time are the same, the rule will call the alert script with no time based restrictions. If the starting time is later than the ending time, the time period is assumed to span midnight (e.g. if starting time is 09:00 and ending time is 21:00, the do not disturb period will be between 9:00 pm and 9:00 AM the next morning). If an alert is looping/ongoing or an alert needs to start during the do not disturb period, the alerts will be moved to the end of the period, as long as the Item remains in the alerting state.

The call to your alerting rule will follow any conditions defined there so you can provide additional restrictions as desired (for example, only alert on an open window when the AC is ON).

If this rule is triggered and you manually edit it, be sure to run the rule manually to clear out the old looping timers or you will see ā€œcontext has been closedā€ errors in the log.

Language: ECMAScript 2011

Dependencies:

  • JS Scripting add-on
  • openhab-js version after Aug. 17, 2022 (until the fix makes it into the release to install the fix from the $OH_CONF/autmation/js folder run npm install openhab). Remember to remove it or manually keep it up to date.
  • openhab-rules-tools 1.1.2 or later (to install navigate to the $OH_CONF/automation/js directory and run npm install openhab_rules_tools).

To Do

  • see if there is any way to merge this and Threashold Alert into one rule template

Changelog

Version 0.7

  • fixed a pretty significant two part bug. The first part was the test to see if the timer was schedule to go off between DND times failed if the DND spanned midnight. This was actually a bug in the upstream openhab-js and Iā€™ve submitted a fix there and added a work around here. The second was if the DND time spanned midnight, the rule would erroneously schedule the looping timer to repeat at the DND end time today which resulted in a time in the past and the loop would execute immediately creating a near infinite loop.

Version 0.6

  • added an option to reschedule the timer in cases where the rule is triggered with the alerting state and an Item already has a Timer scheduled. This is useful for stuff like motion sensor timers where you want something to occur only after the Item has been in the alerting state for the timeout as opposed to wanting an alert from the first event.

Version 0.5

  • Changed how I avoid timers going off at the same time to be based on the actual scheduled timerā€™s times instead of when the rule is triggered. This avoids collisions when the timeout times are different for each Item as well as avoids the looping reschedules from colliding.

  • If an alert is looping, or a new alert occurs during the do not disturb period, move the next alert to the end of the do not disturb period instead of canceling it entirely.

  • Added the ability to choose the event that triggers the rule to support more use cases. Apparently this is not supported at this time.

Version 0.4

  • if a lot of Items match all at once, the timers will be triggered on top of each other causing ā€œmultithreadedā€ exceptions. This version staggers the timers half a second apart when they occur too close together. This staggering will eventually be moved to all the timer libraries in openhab-rules-tools.

Note this change corresponds with a requirement to upgrade openhab-rules-tools to v1.1.2.

Version 0.3

  • added the ability to invert the match so any Item that does match the ā€œgood stateā€ triggers the alert.

Version 0.2

  • added ability to not repeat the alert by setting the repeatPeriod to the empty string.

Version 0.1

  • initial release

Resources

https://raw.githubusercontent.com/rkoshak/openhab-rules-tools/main/rule-templates/openReminder/open_reminder.yaml

9 Likes

hello
Quick question will be possible to have multiple states within a group :slight_smile: like ON or OFF 1 or 0?

1 Like

This rule template only handles one ā€œgoodStateā€. The Items can have any number of states but the looping timer will only start when the Item changes from that one ā€œgoodStateā€.

However, you could use two Groups and two instances of rules created from this template, one for OFF and another for 0. They both can be configured to call the same rule you write to generate the alert.

The nice thing about rule templates is itā€™s really easy to just instantiate and configure them. Itā€™s no big deal if you have more than one copy of the rule with different configurations.

Hi,

I added the template to learn more about it but I received a failure when I ran it. I believe it is because the item word on line 130 has an extra ā€˜mā€™

Console Log

2022-09-19 20:15:05.356 [DEBUG] [.script.rules_tools.reminderswitches] - WemoPlug_Switch is in the alert state of OFF
2022-09-19 20:15:05.359 [ERROR] [b.automation.script.javascript.stack] - Failed to execute script:
org.graalvm.polyglot.PolyglotException: ReferenceError: "itemm" is not defined

Rule Script

  // Item changed to a not alertState, create a looping timer if one doesn't already exist
  else if(isAlertState(state)) {
    logger.debug(item + ' is in the alert state of ' + state);

    // There shouldn't be a Timer if the Item just changed to the alertState, log to show
    // something went wrong.
    if(timers.has(item) && reschedule) {
      logger.debug('Rescheduling timer for ' + item + ' with ' + timeout);
      timers.get(item).timer.reschedule(time.toZDT(timeout));
    }
    else if(timers.has(itemm) && !rescedule) {
      logger.warn(item + ' state is now ' + state + ' but an alert timer already exists! This should not have happened!');

The rule partially works after I correct it but I receive a new error. Any suggestions on how to troubleshoot this error. I have installed the prerequisites (sudo npm install openhab & openhab_rules_tools)

2022-09-19 20:37:52.289 [DEBUG] [.script.rules_tools.reminderswitches] - Running door alert rule with: 
  item:           WemoPlug_Switch
  state:          ON
  alertState:     ON
  invert:         true
  defaultTimeout: PT0
  repeatPeriod:   PT1m
  dndStart:       00:00
  dndEnd:         00:00
  noAlertPeriod:  true
  alertRuleUID:   door_open
2022-09-19 20:37:52.291 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'ReminderSwitches' failed: java.lang.IllegalStateException: The Context is already closed.

Thatā€™s weird. Iā€™m pretty sure I installed and used the latest version. Maybe it reinstalled a cached version and there latest remained untested. This is a huge pain with rule templates.

Yes, line 130 had a typo.

That last error is ready to deal with and in fact I mentioned it in the docs for the template above. If you edit and save the rule for any reason, you have to run it at least once manually so it can clear the stale timers out of the cache. Otherwise itā€™ll will generate that error.

When you fixed the typo, you didnā€™t trigger the rule manually.

Iā€™m on travel but I can manage to remove that extra m from my phone at least.

Let me know if you have any more problems with it.

edit: looks like I canā€™t edit it from my phone easily. Iā€™ll try to fix it when I get back to a computer.
Edit: Itā€™s fixed now

Can I somehow get the name of the trigger Item in the ā€œAlert Ruleā€, e.g. to use the item name in a notification.

What language is the called rule written in? If itā€™s ECMAScript 11, the Item is passes as alertItem and the state the Item was in to generate the call is in currState. These are just injected into your called rule as is.

console.log('Received alert from ' + alertItem + ' in state ' + currState);

If ECMAScript 5.1, it comes over in a variable called context.

logger.info('test', 'Received alert from ' + context.alertItem + ' in state ' + context.currState);

I think the other JSR223 rules languages will also get them in that context variable. Iā€™ve no idea how it works/if it works in Rules DSL. I would guess it works like ECMAScript 11, if it works at all.

You can see my use of these in several examples at How I Use Rule Templates

I ran the script in the rule manually but I still see that error

2022-09-21 10:54:23.629 [INFO ] [openhab.event.RuleStatusInfoEvent   ] - Door_Status updated: RUNNING
==> /var/log/openhab/openhab.log <==
2022-09-21 10:54:23.633 [INFO ] [ation.script.rules_tools.door_status] - Resetting looping timers
==> /var/log/openhab/events.log <==
2022-09-21 10:54:23.633 [INFO ] [openhab.event.RuleStatusInfoEvent   ] - Door_Status updated: IDLE
2022-09-21 10:54:33.449 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'WemoPlug_Switch' received command OFF
2022-09-21 10:54:33.450 [INFO ] [penhab.event.ItemStatePredictedEvent] - Item 'WemoPlug_Switch' predicted to become OFF
2022-09-21 10:54:33.453 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'WemoPlug_Switch' changed from ON to OFF
2022-09-21 10:54:33.453 [INFO ] [hab.event.GroupItemStateChangedEvent] - Item 'gTutorial' changed from ON to OFF through WemoPlug_Switch
==> /var/log/openhab/openhab.log <==
2022-09-21 10:54:33.455 [DEBUG] [.script.rules_tools.reminderswitches] - Running door alert rule with: 
  item:           WemoPlug_Switch
  state:          OFF
  alertState:     ON
  invert:         true
  defaultTimeout: PT0m
  repeatPeriod:   PT5m
  dndStart:       00:00
  dndEnd:         00:00
  noAlertPeriod:  true
  alertRuleUID:   door_open
2022-09-21 10:54:33.455 [DEBUG] [.script.rules_tools.reminderswitches] - WemoPlug_Switch is in the alert state of OFF
==> /var/log/openhab/events.log <==
2022-09-21 10:54:33.456 [INFO ] [openhab.event.RuleStatusInfoEvent   ] - ReminderSwitches updated: RUNNING
==> /var/log/openhab/openhab.log <==
2022-09-21 10:54:33.456 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'ReminderSwitches' failed: java.lang.IllegalStateException: The Context is already closed.

That error only occurs when a rule tries to reference something from the cache that was created by a rule that no longer exists (e.g. you edited the rule, therefore replacing it with a new rule). All I can recommend is to run it manually again or reboot to see if the problem persists. I canā€™t reproduce this behavior. Once I run the rule manually and I see that ā€œResetting looping timersā€ log statement the context errors go away.

Thanks Rich, rebooting cleared the error.

Hi Rich. Thank you for this ruler template.
I am writing this post just to help in case someone finds the problems that I have had.
The template works fine for me using it with a switch, with a PowerState channel defined as switch.
But at first it didnā€™t work with my garage door, because the status of my garage is reported on a channel defined as a contact point (not a switch). Looking at the logs, I can see that if I use the group in the template, the value of this.event is always undefined. But if I use the channel, it never triggers because the template defines the trigger as a group. This is how the template defines the triggers in the Code tab of the rule:
triggers:

  • id: ā€œ1ā€
    configuration:
    groupName: GarageDoor_DoorState
    type: core.GroupStateChangeTrigger

I resolved this changing in this section the words ā€˜groupā€™ to ā€˜itemā€™:
triggers:

  • id: ā€œ1ā€
    configuration:
    itemName: GarageDoor_DoorState
    type: core.ItemStateChangeTrigger

Yes. I tried really hard to make the trigger type be a property you can define when you instantiate the rule, but itā€™s simply not currently possible. It only results in syntax errros. So if you want any different type of trigger youā€™'ll have to modify your instantiated rule after the fact, just as you did.

You would probably want to do the same thing if you are using this to implement a motion sensor timer (e.g. turn off a light five minutes after the last time a motion sensor triggers). Iā€™ve posted an example of this and other ways to use this rule template to How I Use Rule Templates.

tl;dr, do not be afraid to adjust a rule created from a template if that works best for you.

Iā€™m glad you figured that out on your own. If you run into any other problems or suggestions for additions or improvements let me know. This rule template is turning out to be my most useful one so far.

And thanks for posting!

The rule stopped working after I updated to 3.4.0:

Failed to execute script:
org.graalvm.polyglot.PolyglotException: TypeError: undefined has no such function ā€œputā€
at .put(/etc/openhab/automation/node_modules/openhab/cache.js:47) ~[?:?]
at .:program(:23) ~[?:?]

First, what version of the js scripting library are you using, the one that comes with the add-on or did you install it using npm?

I do have a minor change in the version of the rules Iā€™m running but I made them to work with OH 4 snapshots. Maybe they also need to be back ported to 3.4, but then this template will no longer support 3.3 if I do that. Iā€™ll need to think about it the best way to solve it.

The problem revolves around changes made to the cache. Previously this was something only provided by the JS Scripting add-on. In 3.4, openhab-core added a universal registry as a replacement so now we should use cache.private and/or cache.shared. But I thought that the old cache was still backwards compatible except with an added deprecation warning in the logs. That appears not to be the case.

While I figure out how to handle this without ending up with three versions of this rule template (one for 3.3, one for 3.4, and one fore 4.0) you can make the following changes to your rules to get it working again.

Replace cache.put with cache.private.put and replace cache.get with cache.private.get` (should be two changes in total and they are right next to each other). In truth, the first one is redundant now. The new privateCache will clear itself out when the script is unloaded automatically but removing that stuff will be a bit more work than necessary to get this working again.

used an old version of this template on openhab 3.3, today uninstalled it to bring it up to dateā€¦ but now i can not install it from addon marketplace, because itā€™s not listed?? ā€¦what i am doing wrong? ā€¦found the .yaml for the template, but how can i install this manually??

I donā€™t think the 3.3 version of OH understands versioning of Rule Templates so this should be listed no matter what. But even if it did understand the versioning, it should be shown in all versions of OH 3.3.0 and later.

All I can think of is maybe youā€™ve inadvertantly disabled the marketplace or something.

Unfortunately there really isnā€™t a way to install a template by hand easily. Youā€™ll have to manually edit the JSONDB to add it which is error prone. You might be better off restoring the rule templates JSONDB file from backups. Hopefully youā€™ve not made too many changes since uninstalling it and itā€™ll have a backup with the old template still installed.

no marketplace is not disabled, as i see all other templates and just installed your ā€œthing status reportingā€ without problemsā€¦ running openhab 3.4.1

will have a look at the jsondb (/srv/openhab-userdata/jsondb/marketplace_ruletemplates.json ?) and backups in the eveningā€¦

I think this issue here is that the rule template is listed for up to version 3.4.0 and not 3.4.1. I have the same issue where I donā€™t see the Open Reminder template but I do for example see the Thing Status Reporting one which is listed for up to version 3.4.1.

From the marketplace page:

Open Reminder [3.3.0;3.4.0)
Thing Status Reporting [3.2.0;3.4.1]

1 Like

You are right. I wanted to block this from showing up in 4.0. Iā€™ll update it to 3.4.9 which should capture the current and future point releases of 3.4 without including 4.0.-

1 Like

Awesome, thanks for the quick fix! I saw you updated many of the other templates that had the same issue as well. :slight_smile:

1 Like