Get Thing from Item to tell Item status (e.g. online or offline)

Ok makes sense. Even when channels go to undef it doesn’t tell anything about the why.

I think it’s possible to create a rule that would trigger on the status change. That way you don’t need to use a timer.

I also have a lot problems with connectivity with one device (to far away. I guess) and had also problems with it getting a different ip address after it came back online. Therefor in the latest version of the binding it also keeps track of the id. If the ip address changes it will update the ip address (with manual configuration it requires to set the id to make this work and with things created with an older binding they need to be readded to get the id configuration).

1 Like

It is possible. See Rules | openHAB. However, it is less than ideal because if you want to know when a specific Thing goes offline you need to have one Rule for each Thing because there is no way to figure out which Thing going offline cause the Rule to trigger if you have more than one trigger.

Some have done some work arounds using a lambda and the REST API to pull down the list and figure out which Things are offline but I can’t find the post at the moment.

This should be qualified… this is true for the Rules DSL, but the new rule engine does provide event.thingUID for ThingStatusInfoEvent and ThingStatusInfoChangedEvent, when using a GenericEventTrigger. Here is an example for Kodi system states…

from core.rules import rule
from core.triggers import when

@rule("Alert: Kodi system status update")
@when("Thing kodi:kodi:familyroom changed")
@when("Thing kodi:kodi:bedroomupstairs changed")
@when("Thing kodi:kodi:bedroomdownstairs changed")
def kodiSystemStatusUpdate(event):
    kodiDict = {"kodi:kodi:familyroom"        : "DS_FamilyRoom_Kodi_System",
                "kodi:kodi:bedroomupstairs"   : "US_MasterBedroom_Kodi_System",
                "kodi:kodi:bedroomdownstairs" : "DS_MasterBedroom_Kodi_System"}
    kodiName = kodiDict[str(event.thingUID)]
    kodiSystemStatusUpdate.log.debug("Kodi system update: [{}]: [{}]".format(kodiName, event.statusInfo))
    if items[kodiName] == OFF and str(event.statusInfo) == "ONLINE":
        events.sendCommand(kodiName,"ON")
        log.info("Kodi system update: [{}]: ON".format(kodiName))
    elif items[kodiName] == ON:
        events.sendCommand(kodiName,"OFF")
        kodiSystemStatusUpdate.log.info("Kodi system update: [{}]: OFF".format(kodiName))

Note: you could put the Items in a group, iterate through them, and use ItemChannelLinkRegistry to compare the associated ThingUIDs to the one that came through the event, but the dictionary is much cleaner.

The new rules engine is a completely different rules language syntax? :roll_eyes: I’m barely able to plagiarize code for the current rules DSL as it is… I’m afraid; very afraid. :cry:

Sorry… I thought the link to the openhab-jython repo would be enough to explain. This example is for the new rules engine, utilizing JSR223, Jython, and using modules with decorators to simulate Rules DSL syntax. IMO, it’s only a small learning curve, with much more support than when I got into it.

Yes but because the new engine allows the creation and use of libraries, you should find you don’t have to plagerize code that much. Instead you download and use it.

That’s the vision at least. You should find you have to actually write code far less.

But it’s not ready yet. Soon…

Hi Scott, I’m interested in getting corresponding Channels for a given item name and would like to use ItemChannelLinkRegistry as you have indicated.
could you maybe help me on how to use this class in a jython based rule?
(my clumsy try:)


from org.slf4j import LoggerFactory
import org.eclipse.smarthome.core.thing.link.ItemChannelLinkRegistry
import org.eclipse.smarthome.core.thing.ChannelUID
import java.util
scriptExtension.importPreset("RuleSupport")
scriptExtension.importPreset("RuleSimple")

class ItemChannelFinder(SimpleRule):
    def __init__(self):
		self.triggers = [
            TriggerBuilder.create()
                    .withId("ItemAddedTrigger")
                    .withTypeUID("core.GenericEventTrigger")
                    .withConfiguration(
                        Configuration({
                            "eventTopic": "smarthome/*",
							"eventSource": "",
							"eventTypes": "ItemAddedEvent"
                        })).build()
        ]
		self.name = "Jython find Channel for created items"
		self.description = "This rule is triggered on every new Item creation. If its Channel..."
		self.log = LoggerFactory.getLogger("jsr223.jython.BTItemFinder")
		self.reg = org.eclipse.smarthome.core.thing.link.ItemChannelLinkRegistry()
    def execute(self, module, input):
		test = self.reg.getBoundChannels("CC2650SensorTag_Authenticated").toArray()
		self.log.info(str(input["event"]))
		for channeluuids in test:
			self.log.info(str(channeluuids.getId()))

automationManager.addRule(ItemChannelFinder())

getBoundChannels sadly doesn’t seem to return anything

ItemChannelLinkRegistry is registered as an OSGi service. To get to it, I suggest using the helper libraries. Here’s something from my test scripts, which provides the Links for a particular Item…

from core import osgi
from core.log import logging, LOG_PREFIX, log_traceback
log = logging.getLogger("{}.TEST".format(LOG_PREFIX))
from org.eclipse.smarthome.core.thing import ChannelUID

my_item_name = "DS_FamilyRoom_Ceiling_Motion"

ItemChannelLinkRegistry = osgi.get_service("org.eclipse.smarthome.core.thing.link.ItemChannelLinkRegistry")
channels = ItemChannelLinkRegistry.getBoundChannels(my_item_name)
log.warn("Thing Channels [{}]".format(channels))
from org.eclipse.smarthome.core.thing.link import ItemChannelLink
links = map(lambda channel: ItemChannelLink(my_item_name, channel), channels)
log.warn("Links [{}]".format(links))
2019-08-01 13:40:31.215 [WARN ] [jsr223.jython.TEST] - Thing Channels [[zwave:device:55555:node5:sensor_binary]]
2019-08-01 13:40:31.216 [WARN ] [jsr223.jython.TEST] - Links [[DS_FamilyRoom_Ceiling_Motion -> zwave:device:55555:node5:sensor_binary]]

Here’s some other stuff I found in there…

log.warn("getBoundChannels=[{}]".format(ItemChannelLinkRegistry.getBoundChannels(my_item_name)))
log.warn("ChannelUID=[{}]".format(list(ItemChannelLinkRegistry.getBoundChannels(my_item_name))[0]))
log.warn("ThingUID=[{}]".format(list(ItemChannelLinkRegistry.getBoundChannels(my_item_name))[0].getThingUID()))
log.warn("statusInfo=[{}]".format(things.get(list(ItemChannelLinkRegistry.getBoundChannels(my_item_name))[0].getThingUID()).statusInfo))
log.warn("location=[{}]".format(things.get(list(ItemChannelLinkRegistry.getBoundChannels(my_item_name))[0].getThingUID()).location))
log.warn("getBoundThings=[{}]".format(ItemChannelLinkRegistry.getBoundThings(my_item_name)))
log.warn("ThingUID=[{}]".format(list(ItemChannelLinkRegistry.getBoundThings(my_item_name))[0].UID))
log.warn("Item from ChannelUID=[{}]".format(list(ItemChannelLinkRegistry.getLinkedItemNames(list(ItemChannelLinkRegistry.getBoundChannels(my_item_name))[0]))[0]))
1 Like