How to get Thing uuid from Item name in JS Scripting?

Hi all,

I’m working with a JavaScript rule and I need to determine the Thing UID from an Item name.

For example, I have an Item declared like this:

Color Color_GF_Bathroom_ExtendedLight1 "Color_GF_Bathroom_ExtendedLight1" (Group_GF_Bathroom_CeilingLampBulbOne, Group_GF_Bathroom_ColorLight) ["Control", "Light"] {channel="deconz:extendedcolorlight:smarthome:Bathroomextendedcolorlight1:color"}

In my JS rule, I only have access to the Item object or its name (e.g., Color_GF_Bathroom_ExtendedLight1). Is there a way to extract or resolve the Thing UID (deconz:extendedcolorlight:smarthome:Bathroomextendedcolorlight1) from that?

Reason:
I want to check the online/offline status of the Thing inside the rule, and adapt behavior accordingly (e.g., skip actions or notify if the Thing is offline). So having a reliable way (with out hard coding) to go from Item → Thing UID → Thing status would really help.

Any help or pointer to the API/service I could use would be appreciated!

Thanks!

In JRuby it’s as simple as

Color_GF_Bathroom_ExtendedLight1.thing.uid

# you can directly check the thing's online status
Color_GF_Bathroom_ExtendedLight1.thing.online?

There doesn’t seem to be an easy way to do this in JSScripting. You’d need to get the ItemChannelLink of the item, then from there, get the channel → Then get the Thing. The doc is currently empty ItemChannelLink - openHAB JS

I saw this, that the doc is empty…. should I open an GitHub issue?

Or ideally write the doc..

if you point me to the code I can try

The doc is here: itemChannelLink - openHAB JS

The ItemChannelLink class is a class similarly to the Item class, though it is missing its doc. Anyway, the ItemChannelLink class doc won’t tell you how to retrieve an Item channel link …

A quick and easy work around that doesn’t take digging into the API is to add the Channel ID as a tag or Item metadata. Obviously this is a workaround, not a permament solution, but it can get you past this hurdle for now.

I personally configure a Status Item on the equipment and use that. I use Threshold Alert and Open Reminder [4.0.0.0;5.9.9.9] and a rule that triggers on Thing status changes to update that Status Item. Then I use the semantic part of the Item class to get to and check the status Item in my rules. As a bonus I have an oh_repeater widget that shows my all the equipment that is offline using that status Item.

To import and use the ItemChannelRegistry in your rule you can use the following code:

var itemChannelLinkRegistry = require('@runtime/provider').itemChannelLinkRegistry;
var allLinks = utils.javaSetToJsArray(itemChannelLinkRegistry.getAll());
allLinks.map(l => l.toString()).filter(l => l.startsWith('AdGuard_Protection')).map(l => l.split(' -> ')[1]).forEach(l => console.info(l));

The first line imports the registry.

The second line gets all the links. I couldn’t get the native methods on ItemChannelLinkRegistry to work but we can use the more generic methods for now. We use the utils to convert the Java Set to a JS Array to make things easier.

The last line converts all the links to Strings of the format <Item_Name> -> <Channel UID>. Then we filter down to just those that mention the Item (in this case 'AdGuard_Protection`) and finally we split those and extract just the Channel UID and log them out one by one.

Everything up to the last “:” is the Thing ID.

What happens if there is more than one Channel linked to the Item?

Possibly. That doc is automatically generated based on the comments in the source code. The source code does have comments so that class should have generated the blank page. Something might be wrong with the source code to documentation generation.

But that ItemChannelLink class wouldn’t have been useful in this case because the getChannelLink() method requires both the Item name and the Channel UID and you need both.

I could be worth filing an issue to add the above as a method to the Item to more easily get the links and things from the Item as well, though there might already be an issue open for that. I remember seeing something like that go by.

Good question!

Itemname.thing is a convenience method to return the first Thing. If the item is linked to multiple channels/things, you can get access to all of them using Itemname.things which is an array of Things.

as some mentioned jruby, I want to show how this would look in python.

from openhab.services import getService

things = getService("org.openhab.core.thing.link.ItemChannelLinkRegistry").getBoundThings("Color_GF_Bathroom_ExtendedLight1")
for thing in things:
    print(thing.getUID())

the next version will have something like

from openhab import Registry

things = Registry.getItem("Color_GF_Bathroom_ExtendedLight1").getThings()
for thing in things:
    print(thing.getUID())

If I use this code

console.log(itemChannelLink.getItemChannelLink(items\[“Color_GF_Bathroom_ExtendedLight1”\]));

I get this error

Failed to execute rule teset: ReferenceError: "itemChannelLink" is not defined: ReferenceError: "itemChannelLink" is not defined

I’m sure you did get an error since that code is nothing like the code I posted above and it’s incorrect based on the docs and code posted above.

I don’t know why one would escape the “[” and “]” like that. That makes no sense in any circumstances. Is this an AI generated block of code?

The code and the docs @florian-h05 posted show that getItemChannelLink() takes two arguments, the name of the Item and the Channel UID.

As I said above, that’s not going to help you. If you had the Channel UID, you’d already have the Thing UID. ItemChannelLink isn’t going to help you here. There is nothing in openhab-js (yet) that will help you here. So you must pull and use the ItemChannelLinkRegistry directly, as I demonstrated above.

Here it is again, with comments.

var itemChannelLinkRegistry = require('@runtime/provider').itemChannelLinkRegistry; // Make the ItemChannelLinkRegistry available in your rule
var allLinks = utils.javaSetToJsArray(itemChannelLinkRegistry.getAll()); // Get all the ItemChannelLinks from the registry, and convert the Java Set to a JS Array
var channelIDs = allLinks.map(l => l.toString()) // Convert all the Item Channel Links to a String
                         .filter(l => l.startsWith('AdGuard_Protection')) // Get all the links for the AdGuard_Protection Item
                         .map(l => l.split(' -> ')[1]); // Get the Channel UID

channelIDs is a JS Array of strings of the Channel UIDs linked to this Item. There can be more than one.

To get the Thing ID of the first Channel link:

var firstThingID = channelIDs[0].substring(0, channelIDs[0].lastIndexOf(':'));