Threshold Alert [3.2.0;3.4.9)


Note: Sometime in the first half of 2023 this template will be updated to only support JS Scripting and use openhab_rules_tools.

Frequently one wants to do something when one or more Items exceed or fall below a certain threshold; for example sending an alert message or taking remedial actions.

This rule is triggered by the state of a Group. The Group should be of type Number and have a suitable aggregation function to change the state of the Group in a meaningful way. For example, if the rule is to generate an alert when battery Items get below 25%, the Group should be Group:Number:Min so the rule triggers when ever the minimum of all the battery levels changes.

Of course the trigger can be modified after a rule is created to change the trigger if needed, e.g. change to using a member of trigger instead.

When the rule triggers it compares the state of the Group using the selected comparison and value. If the comparison passes the rule is called.

Inside the rule all the members of the Group that are NULL or UNDEF are collected as well as all those that match the comparison. These are passed as attributes to a user selected script.

  • nullItems: a java.util.List collection of all the Items in the Group that are NULL or UNDEF.
  • nullItemLabels: a String with all the nullItems labels listed, separated by commas.
  • threshItems: a java.util.List collection of all the Items in the Group that match the comparison.
  • thresItemLabels: a String with all the threshItemslabes listed, separated by commas.

To access these attributes in your called script use context.getAttribute("name");, for example context.getAttribute("threshItemLabels");.

One more check is performed. To avoid lots of alerts there is a rate limit that causes the script to be called no more often than the amount of time defined (e.g. “24h”). This can be as long as days or as short as milliseconds.

Finally, there is an optional do not disturb period that can be defined. Set the “Do Not Disturb Start Time” and “Do Not Disturb End Time” parameters with the hour and minute of the day defining when the script should not be called. When an event occurs during that time period, the script will be called at the end of the time period. When the end time is before the start time, the do not disturb period is treated as spanning midnight (e.g. a start time of 22:00 and end time of 08:00 will go from 22:00 today through 08:00 tomorrow).

When the start and end times are the same no DND period is applied so only the rate limit applies.

An example use case would be to generate an alert with the labels from all your battery Items that are below 25% but send this alert no more than once a day and wait until 07:00 if the alert occurs after 22:00. To implement that:

  1. Create an AllBatteries Group:Number using MIN as the aggregation function.
  2. Add all the battery level Items to this Group.
  3. Create a script with the actions to take when one or more batteries fall below the given level. For example, send a notification, send an email, flash a light, etc.
  4. Instantiate the template and populate the properties selecting the Group, setting the threshold, selecting the comparison, the rate limit (how long to wait before calling the script again), the script to call that implements actually sending the alert (coded by you), set the do not disturb start time to 22:00 and the end time to 07:00.

Limitations:

  • Only number Items are supported

Language: Nashorn JavaScript or JS Scripting

Dependencies:

  • A script to call when one or more Items fail to match a comparison.
  • A Group containing all the Items to trigger this rule.
  • The Group should be a Group:Number:X where X is a meaningful aggregation.
  • If on OH 4+ Nashorn must be installed separately or change the script type to application/javascript;version=ECMAScript-2021 in the “Code” tab to use JS Scripting

Changelog

Version 0.7

  • adjusted for breaking change, will no longer work for versions of OH prior to December 15th

Version 0.6

  • Made compatible with Nashorn and JSScripting
    NOTE: Will drop support for Nashorn sometime after OH 3.2 release.

Version 0.5

  • If an alert occurs during DND, when the end of DND occurs don’t call the script if no longer outside of the threshold.

Version 0.4

  • Fixed the check for the do not disturb time when that time spans midnight

Version 0.3

  • Fixed problem with parameters

Version 0.2

  • added support for a do not disturb period

Version 0.1

  • initial release

Resources

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

4 Likes

you would save me a lot of time if you could give me a hint how to do this Alert Script in ECMAScript 2021+ …i’m to tried to use your treshold alert rule to monitor my fridge, but wasted 2 hours… plz give me a full example of an simple the alert script (which only logs to console for example) …would be great for newbies to :slight_smile:

thanks in advance

configuration: {}
triggers: []
conditions: []
actions:
  - inputs: {}
    id: "1"
    configuration:
      type: application/javascript;version=ECMAScript-2021
      script: |-
        console.log(this.name);
        console.log(this.threshItemLabels);
    type: script.ScriptAction

But that’s not so helpful, is it?

See Rules - Introduction | openHAB. Skim through and make sure you understand everything up to “Rules Advanced”. Read “Rules Advanced” in detail.

It’s not reasonable to document all the basics of creating and writing rules and other openHAB basics in each and every rule template post. They’d all end up being the size of books with duplicated information that would have to be maintained. That’s why Getting Started exists

sorry to correct you but your posted code does not work in ECMAScript-2021, but it does in ECMAScript5.1, and it has a typo in “threshItemLabels”

what is working for me is this:

configuration: {}
triggers: []
conditions: []
actions:
  - inputs: {}
    id: "1"
    configuration:
      type: application/javascript
      script: >
        var logger =
        Java.type("org.slf4j.LoggerFactory").getLogger("org.openhab.model.script.Threshold");
        logger.info("debug start " + context.getAttribute("threshItemLabels") + " debug end");
    type: script.ScriptAction

I copied and pasted my actual rule I’m using but I replaced the action and just typed it. And I messed it up pretty badly.

It does work in JS Scripting but has syntax errors (which I’ll correct above). Both logs are missing the closing ).

And yes, I absent mindedly typed “threshold” instead of using “thresh” which is clearly documented above is what needs to be used.

And in JS Scripting the variables are in this, not context.

1 Like

Hi,

I set up a rule using this template the other day and it has only just triggered for the first time but I got the following error in the log:

2022-12-10 17:24:44.583 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID '9b59f3d3aa' failed: val mailActions = getActions("mail","mail:smtp:5ee1d43a6d")
val success = mailActions.sendMail("xxxx@yyyy.com", "Low Battery", "The following things have low batteries: \n\n" + context.getAttribute("threshItemLabels"))
   The method or field context is undefined; line 2, column 184, length 7

The email sending code sits in a separate script (written in RuleDSL) and is basically as shown in the log entry (email address changed for obvious reasons).

Any suggestions as to what I’m doing wrong? Thanks.

This is one of those places where you have to pay attention to how the different languages work. In ECMAScript 5.1 you use context.getAttribute.threshItemLabels. In ECMAScript 2021 you use this.threshItemLabels.

I don’t actually know what you use in Rules DSL. I suspect it’ll just be there “naked” threshItemLabels. Does that work? It’ll be tomorrow before I can get to testing this myself.

Hi @rlkoshak
I use this code to handle the notification:

configuration: {}
triggers: []
conditions: []
actions:
  - inputs: {}
    id: "1"
    configuration:
      type: application/javascript;version=ECMAScript-2021
      script: |-
        console.log(this.threshItemLabels);
        console.log(this.name);
    type: script.ScriptAction

the function this.threshItemLabels return the item label, but this.name return undefined
Here is logs:

2023-02-09 23:25:13.796	INFO 	nhab.automation.script.ui.3b70e91513	Finestra Cucina
2023-02-09 23:25:13.796	INFO 	nhab.automation.script.ui.3b70e91513	undefined

Why this?

Thanks

There is no name attribute, just these four.

These are passed as attributes to a user selected script.

  • nullItems: a java.util.List collection of all the Items in the Group that are NULL or UNDEF.
  • nullItemLabels: a String with all the nullItems labels listed, separated by commas.
  • threshItems: a java.util.List collection of all the Items in the Group that match the comparison.
  • thresItemLabels: a String with all the threshItemslabes listed, separated by commas.

The “name” in the example is just a place holder. You need to replace “name” with one of these four options.

Hi,
that’s clear. And is there a way to get Item name from this passed attributes? Thanks

Not from threshItemLabels but you can from threshItems. As the docs say, that’s a List of all the Items that are exceeding the threshold.

Hi @rlkoshak,

quick question. Does the Metadata Namesapce also support hysteresis per item?

For example, I send an alert if humidity exceeds a certain thresholds like 65%. The default hysteresis is set to 3%. So if the item returns back to at least 62%, the alerting state ends.

For one humidity sensor in the basement however, I want to set the hysteresis to 10% and trigger the end rule only at 55%. The reason for that is that I have a dehumidifier installed in that room and want to avoid it’s already stopping at 62% humidity.

Thanks,
Florian

I think you posted to the wrong version of the rule. This is the OH 3.x version of the rule template and it does not support hysteresis at all nor does it support overriding properties on a per-Item basis through Item metadata. I think you are referring to the 4.x version of the rule template.

My answers below are for the 4.x template.

Yes, all rule template properties can be set on a per-Item basis with the Item metadata.

This sort of thing is exactly why I added the per Item metadata option. Sometimes you want almost everything to work the same but there’s always that one outlier that is slightly different.

What the rule does is have the default properties hard coded when the rule gets instantiated (variables at the top of the script). Then when an event happens that metadata for that Item is pulled and overwrites the defaults to create an Object I call record. This record is used to process the event for that Item.

1 Like