OH3 - How to get the type of an item

  • Platform information:
    • Hardware: Raspberry Pi 3 B+ / Pi 4 8Go
    • OS: openHABian 3.0.1
    • Java Runtime Environment: OpenJDK Runtime Environment Zulu11.45+27-CA (build 11.0.10+9-LTS)
    • openHAB version: 3.0.1
  • Issue of the topic: From OH3 rule, using ECMAScript, I want to retrieve the type of the data of the item that triggerred the rule

Hi everybody,

When writing a script for a rule, I want to get the type of the data from the triggeringItem. Here the code I wrote for testing purpose. It shows various information for the item, the channel and the thing from the triggeringItem. I have some problems with the last lines (mainItemType and itemTypeExtension values). When using RFLink items, the channelTypeUID is ‘rflink:temperature’ or ‘rflink:humidity’. But when I use Z-Wave items, the channelTypeUID is ‘zwave:sensor_temperature’, ‘zwave:sensor_luminance’, etc. So, for temperature, I’m getting ‘temperature’ in the first case and ‘sensor_temperature’ in the second case :frowning:

Question: Is there a way to get the type in a ‘canonical form’, i.e. the same ‘type’ for all temperature sensors ? I think it’s possible because without doing anything special, the UI is able to append “°C” when displaying temperature values for both items.

Thanks for your help,
Manuel

// Get native logger
var logger = Java.type(“org.slf4j.LoggerFactory”).getLogger(“org.openhab.model.script.Rules.Experiments”);

// Get infos on the Item that caused the event
logger.info("*** triggeringItem = "+triggeringItem);
var itemName = triggeringItem.name;
var itemState = triggeringItem.state;

// -----

// source: OpenHAB3 / Thing Status / How to extract the thing status and work with it on items - #10 by rlkoshak

// Want reference for
var ItemChannelLinkRegistry = Java.type(‘org.openhab.core.thing.link.ItemChannelLinkRegistry’);
var ThingRegistry = Java.type(‘org.openhab.core.thing.ThingRegistry’);

// OSGI
var Bundle = Java.type(‘org.osgi.framework.Bundle’);
var FrameworkUtil = Java.type(‘org.osgi.framework.FrameworkUtil’);

// Since ItemChannelLinkRegistry & ThingRegistry are in the same bundle we can use either of them
var thingBundle = FrameworkUtil.getBundle(ItemChannelLinkRegistry.class);
var bundleContext = thingBundle.getBundleContext();

// Get Service
var thingRegistryRef = bundleContext.getServiceReference(ThingRegistry.class);
var thingRegistryImpl = bundleContext.getService(thingRegistryRef);

// Get Service
var itemChannelLinkRegistryRef = bundleContext.getServiceReference(ItemChannelLinkRegistry.class);
var itemChannelLinkRegistryImpl = bundleContext.getService(itemChannelLinkRegistryRef); // Instance of ItemChannelLinkRegistry

// Get linked Things from given Item via ItemChannelLinkRegistry

var channelUID = itemChannelLinkRegistryImpl.getBoundChannels(itemName).toArray()[0];
var thing = itemChannelLinkRegistryImpl.getBoundThings(itemName).toArray()[0];
logger.info(" - Thing ‘" + thing.getLabel() + "’ with UID ‘" + thing.getUID() + "’ is ‘" + thing.getStatus() + "’");
logger.info(" - ChannelUID ‘"+channelUID+"’ with ThingUID ‘"+channelUID.getThingUID()+"’");

var channelTypeUID = thing.getChannel(channelUID).getChannelTypeUID();
logger.info(" - ChannelTypeUID ‘"+channelTypeUID+"’");

var ChannelTypeRegistry = Java.type(‘org.openhab.core.thing.type.ChannelTypeRegistry’);
var channelTypeRegistryRef = bundleContext.getServiceReference(ChannelTypeRegistry.class);
var channelTypeRegistryImpl = bundleContext.getService(channelTypeRegistryRef);

var channelType = channelTypeRegistryImpl.getChannelType(channelTypeUID);
logger.info(" - ChannelType ‘"+channelType+"’ with ItemType ‘"+channelType.getItemType()+"’ and Kind ‘"+channelType.getKind()+"’ and Category ‘"+channelType.getCategory()+"’");

var mainItemType = org.openhab.core.items.ItemUtil.getMainItemType(channelTypeUID);
var itemTypeExtension = org.openhab.core.items.ItemUtil.getItemTypeExtension(channelTypeUID);
logger.info(" - ChannelType → main ‘"+mainItemType+"’, extension ‘"+itemTypeExtension+"’");

That’s what Items are for. The type of the Item is the “canonical” type for the data. You should but be going to the Channel for this. Just check the type of the triggering item or that item’s state.

All of the Channel IDs are just that, identifiers. They are largely arbitrary and chosen by the binding author. They may not and usually do not have anything to do with the type of data produced by that Channel.

Even better is to check the type of the Item’s state because there are special states, NULL and UNDEF, that any Item can have regardless of it’s type.

Hi Rich, and thank you very much for your reply.

So this will not facilitate my script: group several items, trigger a rule when one of these items is updated, and adapt the behavior of the rule to the “type” of the triggeringItem.

I did several tests with two temperature items: one from the RFLink binding, and one from the Z-Wave binding. Here are the results:

Item.getType(): RFLink → Number / Z-Wave → Number:Temperature
Item.Category: RFLink → <nothing> / Z-Wave → Temperature
Item.getStateDescription().pattern: RFLink → %.1f °C / Z-Wave → %.1f %unit%
Channel.getChannelTypeUID(): RFLink → rflink:temperature / Z-Wave → zwave:sensor_temperature
ChannelType.getItemType(): RFLink → Number / Z-Wave → Number:Temperature
ChannelType.getCategory(): RFLink → null / Z-Wave → Temperature

So, if I understand the Binding/Thing/Channel/Item approach correctly, it all depends on how the Channel created the Item. And so I have to find another way to “homogenize” my various temperature items. Am I right ?

Regards,
Manuel

Why not?

That should generally be the case anyway. But the Channel doesn’t create the Item. You create the Item and link it to the Channel. The Channel will tell you what type of Item is required. So the Channel does dictate the type of the Item, but it does not create the Item. A Temperature Item can only be one of two different types of Items: Number:Temperature or just Number without a units of measurement. A humidity can be Number:Dimensionless, Number, or I suppose could be a Dimmer but I’ve never seen that.

The Category is just what icon is used when showing the Item when the icon is overridden. That can be pretty much anything. There are a fixed set of default icons or you can supply your own.

If you are using the Model, these Items will have a Point/Property tag pair. For a Temperature the Point would be Measurement and the Property would be Temperature. So you could use the tags as a way to distinguish between types of Items as well.

But if you want the rule to do something different based on what type of Item it is, why not just create separate rules?

I haven’t looked at the use of Model and tags yet. It seems to be the good way for my problem.

In my rule I want to publish the data in MQTT messages, so I want to name the topics uniformly, for example .../<itemId>/temperature, regardless of the source of the information (RFLink, Z-Wave, etc.). And if possible with a single rule for all members of the group.

MM

See Design Pattern: Associated Items and Design Pattern: Encoding and Accessing Values in Rules for more options.

But one thing that is key here is that Items already don’t care about the source of the information. That’s kind of the whole point of Items. They don’t care if they are linked to an RFLink or a Zwave or to nothing at all. A Number:Temperature is a Number:Temperature no matter where the information comes from.