Threshold Alert and Open Reminder [4.0.0.0;5.9.9.9]

OK given this config (either with != UnDefType or with = UndefType inverted) I would expect rule 7a585dac53 to be called under the following circumstances:

Condition isAlerting isInitialAlert rule
changed from NULL or UNDEF to something else true true initAlertRuleUID
changed from anything to NULL or UNDEF false false endAlertUID
has remained in a state that is not NULL or UNDEF for delay time, which in this case is immediately true false alertRuleUID

Because you don’t have any alerting delay, get rid of the alertRuleUID from the config. Your rule will get called immediately once it enters the alerting state through the initAlertRuleUID property. You don’t need your rule to be called twice. To get the end alert call, I think you’ll want to remove the initAlertRuleUID.

I’m assuming that there isn’t some weird interaction going on here and will have to look into it in more detail. It really makes no sense to have both alertRuleUID and initiAlertRuleUID set at the same time if the defaultAlertDelay isn’t set. You haven’t set the defaultAlertDelay on the Item metadata, right? Regardless, I never tested this use case as it doesn’t really make sense to send an initial alert and the main alert at the same time. The expected process is first the initiAlert is called to indicated that the Item potentially changed to an alerting state. Then alert is called when enough time has passed to indicate that it’s a real alert. If repeat is configured the alert rule is called again after the repeat time. Finally, if the alert rule was called and the Item returns to the non-alerting state the endAlert rule is called.

That is definitely not expected. This happened when the Item changed from something to UNDEF? Was that something already alerted?

If the strange behavior persists after removing the initAlert config or adding an alert delay, capture some debug logs showing the Item entering the alert state, calling the alert rule, and then when the Item exits the alerting state. I need to trace through what is going on.

I think I’ll also add a test to warn if the rule is configured with an initAlertRule without a defaultDelay.

Here’s a complete log history:

  1. The rule triggers for a thunderstorm warning as expected:
2024-10-15 15:57:43.694 [INFO ] [nhab.automation.script.ui.7a585dac52] - Weather warning triggered with Item OpenWeatherMapLocalWeather_Warnings_1_Alerts_Event, state Thunderstormwarning initialAlert true and alerting false
  1. The alerting rule is triggered immediately after because I do not have a dely, so that’s expected:
2024-10-15 15:57:44.089 [INFO ] [nhab.automation.script.ui.7a585dac52] - Weather warning triggered with Item OpenWeatherMapLocalWeather_Warnings_1_Alerts_Event, state Thunderstormwarning initialAlert false and alerting true
  1. I would expect an isAlerting = isInitialAlert = false first, but the end rule is not triggered in that case because I restarted the system. After the restart, the state of the item changes to UNDEF because the weather warning went away in the meantime:
2024-10-15 17:31:20.017 [INFO ] [nhab.automation.script.ui.7a585dac52] - Weather warning triggered with Item OpenWeatherMapLocalWeather_Warnings_1_Alerts_Event, state UNDEF initialAlert true and alerting false
  1. As expected, the alerting rule triggers immediately after the initial alert due to a lack of the alerting delay
2024-10-15 17:31:20.143 [INFO ] [nhab.automation.script.ui.7a585dac52] - Weather warning triggered with Item OpenWeatherMapLocalWeather_Warnings_1_Alerts_Event, state UNDEF initialAlert false and alerting true

So regardless of having an alert delay and having an unnecessary touble trigger, why does the rule go into alerting state for both “Thunderstormwarning” and UNDEF if the threshold is != UnDefType?

It should not right? I’ll try with debug output…

The initialAlert should always be first. The whole purpose of initialAlert is to call a rule before the threshold alert rule decides that we are alerting. For example, if we want to alert when the door first opens, when the door has been open for 15 minutes, and then when the door closes you’d use all three and they would be called in this order: initial, alerting, end alert.

However, your logs do show that the initial alert and alerting are working as expected.

This is a crucial bit of information. Threshold Alert loses all information about what’s happened before on a restart. It shouldn’t get confused by this but it’s a challenging thing to test properly so it’s possible there is a bug in the end alert logic.

The way it’s supposed to work is that if the Item returns to a non-alerting state and the flag that indicates whether an alert has already been sent is false it doesn’t call the end alert rule. Only if the alerting flag is true (and it gets set to true on the first call to the alert rule, not the initial alert rule) does it call the end alert rule.

To answer that I’ll need debug logs from the threshold alert rule to see what path it’s going down. But first an important test is to see what happens without restarting the system.

If the rule template is updated, what’s the best way to have this updated version “applied” to an existing rule?

  1. Go to the rule, click on the “Code” tab and copy the config block at the top.
  2. Delete the rule
  3. Recreate the rule and use the config block to configure the new rule with the properties you’ve been using.

That’s the most full proof approach.

You can open the template above and copy everything after

 // ~~~~~~~~~~~Functions

and paste that over everything after that line in the rule on the code tab, but that is error prone. And if a new property is added to the rule template you’ll miss out on that.

Not sure how to install and get this up and running, I went to rule, and “Code” pasted the yaml and saved. Not sure what to call it, I just called it alarm, does it need a specific name? When I tried to run it I got:

2024-10-26 18:59:35.712 [ERROR] [.automation.script.javascript.alarms] - Failed to execute script: SyntaxError: <eval>:17:62 Expected ; but found {
var comparison = (currState, threshold) => { return currState {{operator}} threshold; };
                                                              ^
<eval>:17:75 Expected ; but found threshold
var comparison = (currState, threshold) => { return currState {{operator}} threshold; };
                                                                           ^
<eval>:17:86 Expected eof but found }
var comparison = (currState, threshold) => { return currState {{operator}} threshold; };
                                                                                      ^

        at org.graalvm.polyglot.Context.eval(Context.java:399)
        at com.oracle.truffle.js.scriptengine.GraalJSScriptEngine.eval(GraalJSScriptEngine.java:458)
        at com.oracle.truffle.js.scriptengine.GraalJSScriptEngine.eval(GraalJSScriptEngine.java:426)
        at java.scripting/javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:262)
        at org.openhab.automation.jsscripting.internal.scriptengine.DelegatingScriptEngineWithInvocableAndAutocloseable.eval(DelegatingScriptEngineWithInvocableAndAutocloseable.java:52)
        ... 78 more
2024-10-26 18:59:35.713 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'alarms' failed: org.graalvm.polyglot.PolyglotException: SyntaxError: <eval>:17:62 Expected ; but found {
var comparison = (currState, threshold) => { return currState {{operator}} threshold; };
                                                              ^
<eval>:17:75 Expected ; but found threshold
var comparison = (currState, threshold) => { return currState {{operator}} threshold; };
                                                                           ^
<eval>:17:86 Expected eof but found }
var comparison = (currState, threshold) => { return currState {{operator}} threshold; };

I see you have to install it from the marketplace… I am a text file guy, I never use the UI so it took me a bit.

Just to provide some details, the stuff in {{ }} get replaced based on the properties choosen when you instantiate the rule from the tempalte. You can’t really just sopy and paste a rule template unless you also take on the job of remplacing those with the parameter you want.

I tend to put all the properties into block or variables at the top of the script sections to make it easier to maintain on my end. That makes it easier to manage if you wanted to just copy/paste it too. But rule tempaltes generally are intended to be installed from the marketplace and instantiated through the UI.

I assume it’s possible to populate some of the variables (e.g. the threshold integer) by an item state? Tweaking the code in the UI is then probably the easiest approach?

That’s been on my todo list. For now, instantiate the rule and then open the script action and replace the value in the appropriate variabe under “Properties” with items.NameOfItem.state.

1 Like

That’s what I meant indeed.

I just created a “Threshold Alert” rule which should trigger something (turn on a heating element) if a certain temperature is higher than 15 °C. This is the case, as I can see when checking the relevant item.

But the item hasn’t been updated after the rule was created. So there’s nothing triggered… But what when openHAB is starting up? I just tried this, and the rule wasn’t triggered.

So the “Threshold Alert” rule doesn’t trigger anything until an item of the Triggering Group is updated after the latest openHAB restart (or changes to the “Threshold Alert” rule). Is that a correct conclusion?

That too is on the todo list for this rule template.

In the mean time you can create change the rule trigger to an updated trigger and create another rule that starts sometime after runlevel 40 (so that the threashold alert rule gets loaded first) that updates the Item(s) you care about with their current state. That should be enough to kick off the threshold alert rule.

The rule gets triggered by changes to the Item. The rule has to be actually up and able to see the change to run. If the event occurred before the rule started there’s no way for the rule to know that the Item changed.

I plan on seeing if I can add a system started trigger to the rule and a loop through the Items to see if any came up in an alerting state and handling that accordingly, but there is a lot that can go wrong. And this template is already so complicated it’s challenging to maintain. Adding this in a way that doesn’t add more complexity is a concern.

But in your case the sensor should be changing periodically or at least updating periodically, frequently in fact. Therefore it shouldn’t take long after startup before the rule gets triggered. If you’ve some filters in place to keep the temp sensor from jittering, maybe change the rule trigger to updated. Then even if the Item doesn’t change, the rule will run every time the sensor is updated by the binding.

Understood.

I now understand what you mean. I first tried to change the code under the Code tab. That didn’t go so well…

1 Like

You can edit it from the code tab but there are quirks there which have to do with the fact that what you see there is a YAML translation of JSON. In this case, what you have to do is put two newlines for every single newline you want in the code. Otherwise the line gets treated as a continuation of the previous line.

I noticed :stuck_out_tongue:

What if two items of the group trigger this rule immediately after each other? Can it handle simultaneous runs, or does it abandon the first call? (I’ve got the impression the latter happened. But then again, this seems like a basic feature of rules in general…)

See this snippet:

2024-11-02 02:00:19.060 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'haard_eetkamer_procesbeschermingstimer' changed from 1 s to 0 s
2024-11-02 02:00:19.060 [INFO ] [hab.event.GroupItemStateChangedEvent] - Item 'haarden_procesbeschermingstimers' changed from 1 s to UNDEF through haard_eetkamer_procesbeschermingstimer
2024-11-02 02:00:19.079 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'haard_salon_procesbeschermingstimer' changed from 1 s to 0 s
2024-11-02 02:00:19.080 [INFO ] [hab.event.GroupItemStateChangedEvent] - Item 'haarden_procesbeschermingstimers' changed from UNDEF to 0 s through haard_salon_procesbeschermingstimer
2024-11-02 02:00:21.074 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'haard_salon_procesbescherming' received command OFF
2024-11-02 02:00:21.074 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'haard_salon_procesbescherming' changed from ON to OFF
2024-11-02 02:00:21.178 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'haard_salon_procesbescherming' received command OFF

If a *_procesbeschermingstimer reads 0 s for more than 2 seconds, *_procesbescherming should be turned OFF. But this didn’t happen for haard_eetkamer_procesbescherming. The rule normally works, so the syntax is correct (also, it works for haard_salon_procesbescherming, and it’s just a different variable).

Rules are locked, meaning that if the rule is triggered while it’s already running, the second and any additional triggers will be queued up and run in sequence. Triggers to the rule are never thrown away. But depending on how long the rule takes to run it might not run the rule for that trigger immediately. This is why it’s important to make sure rules run quickly.

I’ve not measured it but there shouldn’t be any performance issues with Threshold Alert. Even on RPi it should take much less than a second for the rule to run for each trigger.

However, all of the above does not apply to the rule(s) called from Threshold Alert. If you have more than one instance of TA calling the same rules, or your rules take some time to run, there might be strange interacctions or other problems.

You can put the TA rule into debug logging and see everything that it’s doing. That’s going to be a minimum to determine what is happening here.

No, depending on the triggering item, a different script is run by Threshold Alert…

How does that work? Do you mean this? Because the Threshold Alert rule is very complicated; I wouldn’t know where to start logging :slight_smile:

But it sounds like “putting a rule into debug logging” is something else than adding console.log() here and there?

EDIT
This is probably what you meant. I’ll give it a try later today!

EDIT 2*
The Rule ID of my Threshold Alert rule is haarden-procesbescherming-UIT. But when I try to set the logger level in openHAB’s CLI:

openhab> log:set DEBUG org.openhab.automation.script.ui.haarden-procesbescherming-UIT
Error executing command: Unable to set level for logger

What am I doing wrong…?

EDIT 3
More importantly: I figured out why the Threshold Alert only triggered one of the rules:

2024-11-03 15:18:35.548 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'haard_eetkamer_procesbeschermingstimer' changed from 3 s to 2 s
2024-11-03 15:18:35.549 [INFO ] [hab.event.GroupItemStateChangedEvent] - Item 'haarden_procesbeschermingstimers' changed from 3 s to UNDEF through haard_eetkamer_procesbeschermingstimer
2024-11-03 15:18:35.561 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'haard_salon_procesbeschermingstimer' changed from 3 s to 2 s
2024-11-03 15:18:35.564 [INFO ] [hab.event.GroupItemStateChangedEvent] - Item 'haarden_procesbeschermingstimers' changed from UNDEF to 2 s through haard_salon_procesbeschermingstimer
2024-11-03 15:18:36.550 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'haard_eetkamer_procesbeschermingstimer' changed from 2 s to 1 s
2024-11-03 15:18:36.550 [INFO ] [hab.event.GroupItemStateChangedEvent] - Item 'haarden_procesbeschermingstimers' changed from 2 s to UNDEF through haard_eetkamer_procesbeschermingstimer
2024-11-03 15:18:36.560 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'haard_salon_procesbeschermingstimer' changed from 2 s to 1 s
2024-11-03 15:18:36.563 [INFO ] [hab.event.GroupItemStateChangedEvent] - Item 'haarden_procesbeschermingstimers' changed from UNDEF to 1 s through haard_salon_procesbeschermingstimer
2024-11-03 15:18:37.551 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'haard_eetkamer_procesbeschermingstimer' changed from 1 s to 0 s
2024-11-03 15:18:37.553 [INFO ] [hab.event.GroupItemStateChangedEvent] - Item 'haarden_procesbeschermingstimers' changed from 1 s to UNDEF through haard_eetkamer_procesbeschermingstimer
2024-11-03 15:18:37.567 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'haard_salon_procesbeschermingstimer' changed from 1 s to 0 s
2024-11-03 15:18:37.567 [INFO ] [hab.event.GroupItemStateChangedEvent] - Item 'haarden_procesbeschermingstimers' changed from UNDEF to 0 s through haard_salon_procesbeschermingstimer
2024-11-03 15:18:39.630 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'haard_salon_procesbescherming' received command OFF
2024-11-03 15:18:39.631 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'haard_salon_procesbescherming' changed from ON to OFF
2024-11-03 15:18:39.736 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'haard_salon_procesbescherming' received command OFF

The group item haarden_procesbeschermingstimers was changed to 0 s by member haard_salon_procesbeschermingstimer. The fact that member haard_eetkamer_procesbeschermingstimer also changed to 0 s is apparently not registered.

So I assume in general, that if two members of the “Triggering Group” change to the same state at the same time, the Threshold Alert rule only registers one of those two triggers…?

(The reason this happens in my case, is because during openHAB startup, an ESPHome channel is switched from ON to OFF, which triggers the countdown of these timers. And there are two ESP32’s, meaning there are two ESPHome channels doing this, triggering both timeouts. I could delete the item to this particular channel, as it’s not needed, but that’s only a stopgap for this particular situation…)