JSR223/Javascript: Rule triggers for item updates, not changes

openHAB version: 2.5.9-1

I can’t work out whether or not it’s possible, in JSR223/Javascript, to trigger a rule when an item updates but its state doesn’t change. On the forum some posts seem to point towards it not being possible, but the problem may since have been fixed.

I’ve not been able to find a definitive list of triggers, but digging into bits and pieces of code I found and tried all of these:

  UpdatedEventTrigger("gRecordLastUpdate"), 
  ChangedEventTrigger("gRecordLastUpdate"),
  ChangedEventTrigger("gRecordLastUpdate",null,null),
  ItemStateChangeTrigger("gRecordLastUpdate"),
  ItemStateUpdateTrigger("gRecordLastUpdate")

Somewhere (I can’t find where now) somebody said that the first one should do the job. I also saw the third one suggested with the null parameters. And the last one has a very suggestive name. However, none trigger my rule unless there’s a state change. I read that maybe it doesn’t work with groups, so I tried it with a single item, but it makes no difference.

I’m not sure what you’re doing exactly but I suspect the last one would do what you want. An Item State Update happens when an item is sent a value (this value can be the same as the existing value).

Not so much “doesn’t work”, as that you might not get what you expect.
The state of a Group Item is derived from its members, by calculation using the “aggregation” property.
No aggregation selected, no updates. (In theory - I think I’ve seen folk report it though).
If aggregating, it’s an iterative process, and Group update may fire more than once for a single member update.
It’s not often useful as a trigger.

More commonly used are “Member of” type triggers.

OK. I’ll look at the “member of” triggers.

I find it all pretty confusing. I’ve tried to use the same triggers for an individual item, and it fails for some reason. When values change, the group triggers above work just fine. It’s updates without changes that are the problem.

Also, my impression is that not everything that works in normal rules works in JSR223, and not all of that works in Javascript. The startup trigger, for example, appears to be a “TODO” in Javascript.

Sure. Think about what you are really trying to find out though - when an Item updates that happens to be a member of a given Group (this is a useful tool!), or when the Group itself updates (e.g. the SUM of member states has been recalculated).

Definitely the former. When any item that is a member of the group is updated.

I’ve just created a rule from the UI where the trigger is “when a member of My_Group was updated” and it generated the following trigger:

triggers:
  - id: "1"
    configuration:
      groupName: My_Group
    type: core.GroupStateUpdateTrigger
conditions: []
actions: []

So it looks like core.GroupStateUpdateTrigger is what you need

1 Like

Do you know how would that translate to Javascript? A big part of my problem is that most of the examples are for DSL or Jython.

Here’s a .js rule I just put together using the “Raw API”:

'use strict';

scriptExtension.importPreset("RuleSupport");
scriptExtension.importPreset("RuleSimple");

var sRule = new SimpleRule() {
    log: Java.type("org.slf4j.LoggerFactory").getLogger("jsr223.javascript.example"),
    execute: function( module, inputs) {
        this.log.info("Hello World caused by update to member item! Item = " + inputs.event.itemName + " State = " + inputs.event.itemState);
    }
};

sRule.setTriggers([
    TriggerBuilder.create()
        .withId("aGroupMemberUpdateTrigger")
        .withTypeUID("core.GroupStateUpdateTrigger")
        .withConfiguration(
            new Configuration({
                "groupName": "gMotion"
            })).build()
    ]);

sRule.name = "JavaScript Hello World example (raw API)";
sRule.description = "This is an example Hello World rule using the raw API";
automationManager.addRule(sRule);

Then I used the Rest API to send multiple updates to the item:

2021-02-02 15:52:57.868 [INFO ] [jsr223.javascript.example           ] - Hello World caused by update to member item! Item = LivingRoom_MotionSensor_Motion State = ON
2021-02-02 15:52:58.012 [INFO ] [jsr223.javascript.example           ] - Hello World caused by update to member item! Item = LivingRoom_MotionSensor_Motion State = ON
2021-02-02 15:52:58.185 [INFO ] [jsr223.javascript.example           ] - Hello World caused by update to member item! Item = LivingRoom_MotionSensor_Motion State = ON
2021-02-02 15:52:58.334 [INFO ] [jsr223.javascript.example           ] - Hello World caused by update to member item! Item = LivingRoom_MotionSensor_Motion State = ON
2021-02-02 15:52:58.535 [INFO ] [jsr223.javascript.example           ] - Hello World caused by update to member item! Item = LivingRoom_MotionSensor_Motion State = ON

Hopefully that should be near enough there in terms of triggers, you just need to work out what code to run as your action.

Edit: @LordLiverpool, as a small disclaimer, I’ve just noticed you’re using OH2.5.9. While in theory this script should work for you, I’ve only tested it on my OH instance that’s running 3.1.0 snapshot.

2 Likes

Ahh, GroupStateUpdateTrigger. I didn’t know about that one. Is there a definitive list of triggers somewhere?

I’ve created a new rule with a single update trigger for a single item, and it works. Now I have to work out why it didn’t work when I added it to the triggers in my other rule.

I’ll try the GroupStateUpdateTrigger and see if that works with the group.

I think that one must be new in OH3.

"2021-02-02 17:11:22.218 [ERROR] [org.openhab.core.automation.module.script.internal.ScriptEngineManagerImpl] - Error during evaluation of script 'file:/etc/openhab2/automation/jsr223/javascript/personal/OnDeviceUpdate_SaveLastUpdateStamp.js': ReferenceError: "GroupStateUpdateTrigger" is not defined in <eval> at line number 31"

I think we need to see a bit more about how you are creating/writing these rules. In text files or through the UI? Are you using the Helper Libraries?

If working in the UI, I think the received update is not supported simply because it was forgotten to add to the list and there is an issue open to add it back. But in text configs, at least while using the Helper Libraries in Python a received update trigger was absolutely possible. And if it’s possible in Jython it’s possible for all the languages.

The event for an update to the same state is ItemStateEvent.

And the trigger would be UpdateEventTrigger, not UpdatedEventTrigger (no “ed”).

Indeed, there will be N-1 updates where N is the number of direct members of the Group.

I know of nothing you can do in Rules DSL that cannot be done in JavaScript or Python or Groovy. In fact there is a ton of stuff that cannot be done in Rules DSL that can be done in these other languages including:

  • accessing and modifying Item Metadata
  • dynamically creating Items and Rules
  • support for common programming paradigms like libraries, functions, classes, etc.

The startup trigger should be working just like any other trigger but in OH 3 the way the System started trigger has changed in OH 3 for all languages. It no longer just fires when the script is loaded. It now does what it says and triggers the rule when openHAB has started. When you reload a script file openHAB is already started so the System started rules don’t fire. There was talk on github to implement a new “Rule Loaded” trigger but that hasn’t been done yet so the recommendation is to manually run the rule when you reload it in the mean time.

If you are using .js files, you can implement a scriptLoaded function that will get called when the script is loaded where you can do System started type stuff if that is preferable. There is a coresponding scriptUnloaded function that you can define to be called when the script is unloaded to do stuff like cancelling the timers so they don’t get orphaned. These are two more things that Rules DSL do not support.

But if you are looking at the Helper Libraries, indeed the JavaScript Helper Libraries are behind the Python libraries in terms of capability. They are also not yet compatible with OH 3 as far as I know.

I don’t think so. I’ve been using “Member of MyGroup received update” type triggers since they were introduced. I had them in use in my Python rules in OH 2.x and if they were supported there they are supported in all the JSR223 languages. That stuff isn’t language specific and, in fact, all that openHAB stuff are actually Java.

Though beware those are the OH 3 JavaDocs. That package may have moved and the class may have changed names between versions as part of the breaking changes. You’d probably need to dig through the 2.5 branch of the code to verify.

I’m just creating them in .js files. No UI involved.

If I change UpdatedEventTrigger to UpdateEventTrigger, I get this in the log:

2021-02-02 17:57:49.407 [ERROR] [org.openhab.core.automation.module.script.internal.ScriptEngineManagerImpl] - Error during evaluation of script 'file:/etc/openhab2/automation/jsr223/javascript/personal/OnDeviceUpdate_SaveLastUpdateStamp.js': ReferenceError: "UpdateEventTrigger" is not defined in <eval> at line number 23

Maybe a change in OH3? If you look through the forum, there are lots of references to UpdatedEventTrigger. All the posts referring to UpdateEventTrigger seem to be about OH3.

When I said “that one must be new”, I meant GroupStateUpdateTrigger.

Thanks for the list, but I notice that GroupStateUpdateTrigger isn’t on it.

I also get the same error as above for SystemOnStartupTrigger. In \openhabianpi\openHAB-conf\automation\lib\javascript\core\triggers.js I see this:

var StartupTrigger = function(triggerName){
    //DOES NOT WORK - TODO: return new Trigger( getTrName(triggerName), "jsr223.StartupTrigger", new Configuration());
}

I reckon a fair bit has changed in OH3.

That is probably true. You will see that there is a GroupMemberUpdateEventTrigger though. And I do know that I used member of group updates in OH 2 in Python. If it worked there it will work in JS too.

It’s important to realize that people have been using the JSR223 rules in Python and JavaScript since OH 1. This isn’t new and its not partially implemented in OH 2.5. So it’s not going to be a matter of “not yet implemented” as much as it will be figuring out how to do it. For that I recommend looking at the source code for the Helper Libraries. The current head brach is the 2.5 versions so what you see there should work on OH 2 as is. The updates for OH 3 are in another branch in a PR that has not yet been merged.

The rules trigger “when member of group…” was introduced in OH2.x so that’s why I said in theory it should work. When I was running OH2.5 I had jython jsr223 rules which triggered on a group member changing.

It might be worthwhile you showing us your script so far so that we can try and replicate your issues and hopefully find a solution.

Alas, OH3 also, by the looks of it.

I’ll do some more tests, see where I am and draw some conclusions.

Good luck! Don’t forget to report back when you’ve cracked it :slight_smile:

Sorry for the long delay. My conclusion for OH2 for the moment is that there is an inconsistency: if I use ChangedEventTrigger(“gRecordLastUpdate”) on a group, it works as expected, that is, I get a notification of a change to the value of any item in the group and I can obtain the item name and act accordingly. This allows me to have matching timestamp items with the same names as the items, but with _LastUpdate appended. With one rule I can handle changes to all of them. But if I try the same with UpdatedEventTrigger(“gRecordLastUpdate”), it doesn’t work. However, both UpdatedEventTrigger and ItemStateUpdateTrigger seem to work for individual items - but obviously that forces me to specify all of the items, negating the point of the group.