Thing Status Reporting [4.0.0.0;4.9.9.9]

There was a recent PR that added a bunch of new Thing blocks. [blockly] Add more thing blocks by stefan-hoehn · Pull Request #2562 · openhab/openhab-webui · GitHub

I havn’t noticed that. How cool once again from @stefan.hoehn.
There seem to come quite a few options to get information from things (location, UID, status, enabled, bridge…). Have to try it after it’s part of the… next milestone?
And: You’re absolutely right, then there’s no need to extend your template.

1 Like

It’s in the snapshots now and will be part of the next milestone for sure. Let me know if there is something that doesn’t work as expected. I can change to send the raw Thing instead of the JS Thing. Though it should work since the Blockly converts to JS.

1 Like

You made mY day :star_struck:

2 Likes

I know it is kinda distracting this thread but I was just able to provide a new feature for Blockly which is TYPED VARIABLES and did not want you both @rlkoshak and @Larsen to miss this. I really makes a lot of difference for proper code generation which I waited “for years”. (Most like it will not make it into M2 but will be a gamer changer for the next milestone.)

Edited: It made it even into M2 :partying_face:

3 Likes

I have to admit that I really like those distractions.
Just updated to M3 and it’s all there. Looks absolutely great. I’m going to try it tomorrow.

How can I check whether my system has these dependencies?

If you manually run the rule created from the template it will throw an exception if these dependencies are not met. Alternatively you can run the following in a Script:

var {helpers} = require('openhab_rules_tools');
console.info('openhab-js version: ' + utils.OPENHAB_JS_VERSION);
console.info('OHRT version: ' + helpers.OHRT_VERSION);
helpers.validateLibraries('4.1.0', '2.0.1');

If you see errors in the logs you’ll know you do not meet the requirements.

1 Like
17:13:53.628 [ERROR] [.internal.handler.ScriptActionHandler] - Script execution of rule with UID '563b203981' failed: org.graalvm.polyglot.PolyglotException: TypeError: Cannot load CommonJS module: 'openhab_rules_tools'

I’ll try downloading this (openHAB Rules Tools [4.1.0.0;4.9.9.9]) and retry :wink:

Another question…

This doesn’t seem to work:

const { rules, triggers, items } = require('openhab');

rules.JSRule({
    name: "Thing niet meer online",
    description: "Soms is een 'thing' niet meer online, en daar wil ik graag een melding van ontvangen.",
    execute: (event) => {
        if (newStatus != "ONLINE") {
            console.log(thing.label + 'schijnt niet meer online.')
        }
    }
});

The rule doesn’t appear in the GUI rules overview. It does when I add ‘trigger info’:

const { rules, triggers, items } = require('openhab');

var triggering_item = items.getItem("Bewoners_Thuis")

rules.JSRule({
    name: "Thing niet meer online",
    description: "Soms is een 'thing' niet meer online, en daar wil ik graag een melding van ontvangen.",
    triggers: [triggers.GroupStateChangeTrigger(triggering_item)],
    execute: (event) => {
        if (newStatus != "ONLINE") {
            console.log(thing.label + 'schijnt niet meer online.')
        }
    }
});

But those triggers don’t make any sense, because this rule is triggered by the Thing Status Reporting rule…?

I don’t use .js files but my understanding is JSRule requires there to be a triggers property passed to it. But you can choose to pass and empty list of triggers.

triggers: [],

Always watch the logs when developing rules. I bet there was an error in openhab.log when it tried to load this rule telling you what’s wrong with it.

That makes sense… I’ll try to make a habit of it!

Indeed:

 Error during evaluation of script '/etc/openhab/automation/js/thingNotOnline.js': org.graalvm.polyglot.PolyglotException: ReferenceError: "triggering_item" is not defined

Mmm, still no luck…

What should I do to get the latest stable version of openhab_rules_tools?

At the link you’ve posted:

This library requires openhab_rules_tools to be installed. This can be installed from openhabian-config or by running the command npm install openhab_rules_tools from the $OH_CONF/automation/js folder.

1 Like

I tried running the rule manually, but that gave an error. I assume that makes sense, because there are no arguments given?

20:26:52.235 [ERROR] [.internal.handler.ScriptActionHandler] - Script execution of rule with UID 'thing_online_checker' failed: java.lang.IllegalArgumentException: UID must have at least 3 segments: [thing_online_checker]

Yes, that’s the expected error when the rule is run manually. There’s no trigger information so the code tries to get the Thing with the UID undefined and of course fails to. That means the all the libraries needed are installed and at or above the minimum versions required.

I tested the rule, rebooting one of my Shelly devices. Alas:

18:25:37.544 [INFO ] [hab.event.ThingStatusInfoChangedEvent] - Thing 'shelly:shellyplus2pm-relay:d4d4da09b2c8' changed from ONLINE to OFFLINE (COMMUNICATION_ERROR): Unexpected error: WebSocket error
18:25:37.549 [WARN ] [re.automation.internal.RuleEngineImpl] - Failed to execute action: 1(Error: Failed to execute rule Thing-niet-meer-online-5547c625-e8ee-4c6c-b3d4-ab941aecfd70: ReferenceError: "newStatus" is not defined: ReferenceError: "newStatus" is not defined
        at execute (thingNotOnline.js:11)
        at doExecute (/node_modules/openhab.js:2))

This is the rule:

const { rules, triggers, items } = require('openhab');

rules.JSRule({
    name: "Thing niet meer online",
    description: "Soms is een 'thing' niet meer online, en daar wil ik graag een melding van ontvangen.",
    triggers: [],
    execute: (event) => {
        if (newStatus != "ONLINE") {
            console.log(thing.label + 'schijnt niet meer online.')
        }
    }
});

From the documentation of this rule template, I assumed the argument newStatus would be something I could use?

I have never tested this with file based rules. Generally those who use file based rules don’t even consider using rule templates so it’s not come up that much.

It might be the case that it works differently with JSRule from a UI rule with a JS Script Action. You can try this.thing, ctx['thing'], or context['thing'], event.thing, event.module.thing and the like.

It might be that the way JSRule is implemented the passed in context gets filtered out and it won’t work. I don’t know. Looking at the way JSRule is implemented it certainly looks like extra passed in data does indeed get excluded when your execute function is called with only the event being passed through, but I don’t know this code that well and might be missing something.

The easy solution would be to paste the code in the GUI, but I thought I’d do some testing for future reference.
These variables work in JSRule:

var thingID = event.thingUID
var oldStatus = event.payload[0].status
var oldDetail = event.payload[0].statusDetail
var newStatus = event.payload[1].status
var newDetail = event.payload[1].statusDetail
var newDescription = event.payload[1].description
var thing = things.getThing(thingID)

During this search, I posted several times, then updated etc. For reference:

Summary

The easy solution would be to paste the code in the GUI, but I thought I’d do some testing for future reference.
Update: things.getThing(event.thingUID) works!

I realised I could log JSON.stringify(event), which showed event.thingUID logs the thing UID.

const { rules, triggers, items } = require('openhab');

rules.JSRule({
    name: "Thing niet meer online",
    description: "Soms is een 'thing' niet meer online, en daar wil ik graag een melding van ontvangen.",
    triggers: [],
    execute: (event, thing, context) => {
        try {
            console.log("'event.thingUID' doesn't throw an error! It logs "+event.thingUID)
        }
        catch (err8) {
            console.log("'event.thingUID' throws an error: "+err8)
        }
    }
});

Output:

2024-05-31 08:26:34.104 [INFO ] [mation.script.file.thingNotOnline.js] - 'JSON.stringify(event)' doesn't throw an error! It logs {"eventClass":"org.openhab.core.thing.events.ThingStatusInfoChangedEvent","payload":[{"status":"UNINITIALIZED","statusDetail":"DISABLED"},{"status":"OFFLINE","statusDetail":"COMMUNICATION_ERROR","description":"Unexpected error: WebSocket connection closed abnormal"}],"thingUID":"shelly:shellyplus2pm-relay:d4d4da09b2c8","eventType":"change","triggerType":"ThingStatusChangeTrigger","module":"3"}
2024-05-31 08:26:34.104 [INFO ] [mation.script.file.thingNotOnline.js] - 'event.thingUID' doesn't throw an error! It logs shelly:shellyplus2pm-relay:d4p9ty06b4c8

For full disclosure, I first did this:
I had this run:

const { rules, triggers, items } = require('openhab');

rules.JSRule({
    name: "Thing niet meer online",
    description: "Soms is een 'thing' niet meer online, en daar wil ik graag een melding van ontvangen.",
    triggers: [],
    execute: (event) => {
        try {
            console.log("'this.thing' doesn't throw an error! It logs "+this.thing)
        }
        catch (err1) {
            console.log("'this.thing' throws an error: "+err1)
        }

        try {
            console.log("'context['thing']' doesn't throw an error! It logs "+context['thing'])
        }
        catch (err2) {
            console.log("'context['thing']' throws an error: "+err2)
        }

        try {
            console.log("'event.thing' doesn't throw an error! It logs "+event.thing)
        }
        catch (err3) {
            console.log("'event.thing' throws an error: "+err3)
        }

        try {
            console.log("'event.module.thing' doesn't throw an error! It logs "+event.module.thing)
        }
        catch (err4) {
            console.log("'event.module.thing' throws an error: "+err4)
        }

        try {
            console.log("'ctx['thing']' doesn't throw an error! It logs "+ctx['thing'])
        }
        catch (err1) {
            console.log("'ctx['thing']' throws an error: "+err1)
        }

    }
});

This was the output:

2024-05-31 08:03:17.780 [INFO ] [mation.script.file.thingNotOnline.js] - 'this.thing' doesn't throw an error! It logs undefined
2024-05-31 08:03:17.780 [INFO ] [mation.script.file.thingNotOnline.js] - 'context['thing']' throws an error: ReferenceError: "context" is not defined
2024-05-31 08:03:17.780 [INFO ] [mation.script.file.thingNotOnline.js] - 'event.thing' doesn't throw an error! It logs undefined
2024-05-31 08:03:17.781 [INFO ] [mation.script.file.thingNotOnline.js] - 'event.module.thing' doesn't throw an error! It logs undefined
2024-05-31 08:03:17.781 [INFO ] [mation.script.file.thingNotOnline.js] - 'ctx['thing']' throws an error: ReferenceError: "ctx" is not defined
2024-05-31 08:03:19.785 [INFO ] [mation.script.file.thingNotOnline.js] - 'this.thing' doesn't throw an error! It logs undefined
2024-05-31 08:03:19.786 [INFO ] [mation.script.file.thingNotOnline.js] - 'context['thing']' throws an error: ReferenceError: "context" is not defined
2024-05-31 08:03:19.786 [INFO ] [mation.script.file.thingNotOnline.js] - 'event.thing' doesn't throw an error! It logs undefined
2024-05-31 08:03:19.786 [INFO ] [mation.script.file.thingNotOnline.js] - 'event.module.thing' doesn't throw an error! It logs undefined
2024-05-31 08:03:19.787 [INFO ] [mation.script.file.thingNotOnline.js] - 'ctx['thing']' throws an error: ReferenceError: "ctx" is not defined
2024-05-31 08:03:19.942 [INFO ] [mation.script.file.thingNotOnline.js] - 'this.thing' doesn't throw an error! It logs undefined
2024-05-31 08:03:19.944 [INFO ] [mation.script.file.thingNotOnline.js] - 'context['thing']' throws an error: ReferenceError: "context" is not defined
2024-05-31 08:03:19.945 [INFO ] [mation.script.file.thingNotOnline.js] - 'event.thing' doesn't throw an error! It logs undefined
2024-05-31 08:03:19.946 [INFO ] [mation.script.file.thingNotOnline.js] - 'event.module.thing' doesn't throw an error! It logs undefined
2024-05-31 08:03:19.948 [INFO ] [mation.script.file.thingNotOnline.js] - 'ctx['thing']' throws an error: ReferenceError: "ctx" is not defined

So no luck…

1 Like

What I don’t quite understand is all of those variables are not the ones I’ve passed into your called rule as arguments. Somehow you are getting the event object that triggered the calling rule (i.e. the rule template instance).

Beware though, when the JSRule is triggered normally (i.e. from a trigger) the contents of the event Object get transformed into JavaScript Objects and primitives. However in this case (as evidenced by the Output you posted above, you are getting the raw Java event Object same as happens in a UI rule. So be careful in how you use these variables as the raw Java doesn’t always work exactly the same as the JavaScript the helper library usually wraps them in.

Edit: I’ve opened an issue and will be submitting a PR this weekend. To access the values it will most likely be something like event.raw.thing. Support passed in values for manually called JSRules · Issue #333 · openhab/openhab-js · GitHub