Hi guys!
I’m writing a rule to check for binding status and restart it if needed.
I’m in trouble due to strange foreach behaviour:
I defined some items with two tags each and I need to iterate through tags to perform different actions like, in “pseudocode”:
If Item1 has tag1 = somevalue do something else do another thing
These are my items:
Group gMonitor "Monitoring not yet working" <error>
Switch mMQTT_Temp1 "MQTT Temp1 [%s]" <switch> (gMonitor) ["mqtt:topic:MY-MQTT:RTL_433:temp" , "mqtt.things"]
Switch mGPIO_LED "GPIO LED verde [%s]" <switch> (gMonitor) ["gpio:pigpio-remote:raspiOH4:sample-output-10" , "GPIO.things"]
This is my rule file:
rule "Monitoring Things Status"
when Time cron "0 0/1 * * * ?"
then
gMonitor.members.forEach[ i |
{
var String vThingUID = i.tags.get(0).toString() // Reads the first tag
var String tt = i.tags.get(1).toString() // Reads the second tag
logWarn("Monitoring Things Status", "Tag0: " + vThingUID)
logWarn("Monitoring Things Status", "Tag1: " + tt )
]
end
The strange behaviour is this:
In the first loop, I correctly get first tag (tag0) with “i.tags.get(0)” and second tag (tag1) with “i.tags.get(1)”
In the second loop, I get Tag0 with “i.tags.get(1)” and Tag1 with with “i.tags.get(0)” !!
These is my Openhab log:
2024-10-09 11:54:02.349 [WARN ] [odel.script.Monitoring Things Status] - Tag0: mqtt:topic:MY-MQTT:RTL_433:temp
2024-10-09 11:54:02.350 [WARN ] [odel.script.Monitoring Things Status] - Tag1: mqtt.things
2024-10-09 11:54:02.360 [WARN ] [odel.script.Monitoring Things Status] - Tag0: GPIO.things
2024-10-09 11:54:02.362 [WARN ] [odel.script.Monitoring Things Status] - Tag1: gpio:pigpio-remote:raspiOH4:sample-output-10
Tags are not guaranteed to be stored nor returned in order. You cannot count on the first tag always being at index 0 and the second one always at index 1.
This problem is really outside the bounds of what tags are intended for and will not really work that well for you. A better approach would be to use Item metadata but metadata isn’t available in Rules DSL.
It’s one of several reasons why I do not recommend Rules DSL for new development. Any of the other languages are just as easy to work in, do not have weird problems with type, and have full access to everything in OH. Even Blockly is more capable than Rules DSL.
But thankfully, you don’t even need an Item for this. You can install Thing Status Reporting [4.0.0.0;5.9.9.9] from the add-on store. This will be configured to call a rule when ever a Thing changes status. The called rule will get the thingID, old status and new status of the Thing. You can set up a condition to only look for OFFLINE states, only certain Things, only Things from a certain binding.
For example, a rule that only looks for MQTT Things going offline would look something like this (this is a JS Scripting and a UI rule, again, Rules DSL lacks the ability to be called from another rule with arguments):
On underpowered machines like an RPi 3b, it can take some seconds for JS Scripting rules to be loaded and parsed. The fix is to use 64-bit Java (which of course requires 64-bit OS) which brings that loading time down by 10x. However, on an RPi 3 there isn’t that much RAM and moving to 64-bit is going to require more RAM.
So your best bet is to either use jRuby or Groovy or move to an RPi with more RAM with 64-bit OS and 64-bit Java.
Note that this slowness is only on the first load of the rule for recent versions of OH 4. Prior to that the slowness is on the first run of the rule. After that the rule runs as fast as expected.
Hi Rich!
I’m trying to check for binding status with JS, as you suggested me.
My JS script can’t read things.
It returns undefined on
var bbb = things.getThing(thing_element);
log:
Failed to execute rule Binding Checker: TypeError: Cannot read property "getStatus" from null: TypeError: Cannot read property "getStatus" from null
your code goes here
var thing_element =things.getThing("amazonechocontrol:account:0123456789");
whhic means thing_element is a Thing.
But then you try to use thing_element to get bbb?
var bbb = things.getThing(thing_element);
That’s never going to work. You can’t get a Thing using another Thing. You need to use a String containing the ThingID in a call to getThing. getThing is returning null and null of course doesn’t have a status.
One of these calls to getThing is redundant. If what you care about is the status of your amazoncontrol Thing, well you already have that in thing_element. You need not call things.getThing ever agaibn in this rule. You’ve already got the Thing you care about.
If you need the status of some other Things, you need to call things.getThing for each of them, passing a String that contains the ThingUID you care about.
One of the wonderful things you can do with Blockly is plop some blocks into a script then click the code tab and see what JS it generates. It’s a great way to learn.
Are you sure it’s that line? The error is complaining about getStatus(), not getThing(). That line doesn’t have an attempt to call getStatus().
Are you sure you don’t have “getStatus” anywhere in this .js file?
Have you ever installed openhab-js manually?
Which version of OH 4 are you running?
This specific error isn’t because things.getThing() is returning null. That would complain that status doesn’t exist. This is caused by something else.
What happens if you create a Blockly rule to get the status of the Thing. Does that work? Is there any difference between the code it generated and what you have in your file?
Well, if the Thing doesn’t exist you can test for that by testing for null. things.getThing() will return null when the Thing doesn’t exist.
Are you sure the missing Things were working in the first place? They seem to have been in some sort of inbetween state where they sort of existed but not fully existed. Both the call to thing.getThing() and the REST API call that populates the Things page get that information from the ThingsRegistry. If both are showing that the Thing doesn’t exist that means that as far as OH core is concerned those Things do not exist.
You will get the same behavior from any of the rules languages that support access to the ThingsRegistry. It’s not specific to JS.
What ever happened should be a rare occurance. In fact it should never happen again. If it does happen again an issue needs to be files to figure out what happened and fix it.
And while this is supposed to work and must be made to work properly, one of the reasons (not the bioggest reason, just one among several) I don’t use file based configs is weirdness like this which can crop up.