[Rules DSL] Get item from string name!

Tags: #<Tag:0x00007f51f2e2a360> #<Tag:0x00007f51f2e2a220> #<Tag:0x00007f51f2e2a068>

(Scott Rushworth) #1

For a couple years now, I’ve been wanting/looking for a way to construct an item from its name as a string. There are other ways to do this, and the most popular requires the item to be in a group, which can have it’s challenges. I’ll keep this short and SWEET… I finally figured it out, and it is extremely simple!

You’ll need this import…

import org.eclipse.smarthome.model.script.ScriptServiceUtil

Then you can access an item by string name like this…

val testItem = ScriptServiceUtil.getItemRegistry.getItem("Virtual_Switch_1")

Happy HABing!!!

Design Pattern: Associated Items
How to check if an item is a member of a group?
Concat Strings and create itemName out of it
Item Name as Variable in Rules
[SOLVED] Rule problem with groups
[Rules DSL] Send command or update to item only if the command/state is different than current state
[SOLVED] Add LastUpdated info for items for z-wave sensors
[SOLVED] Group Based Timestamps and durations with triggeringItem and Member of
[SOLVED] Get state with a calculated item name
[SOLVED] DateTime Items compare against fixed DateTimes
[SOLVED] Persistence and triggeringItem
How can I access generic items in a function?
(Rich Koshak) #2

That gives you a fully functional Item like you get when using other more will known methods of gaining access to Items?

I only ask because I’ve noticed while browsing through the javadocs that the Switch item, for example, we get in Rules had all sorts of methods I can’t find on the Switch item class or any of its parents. In particular I’ve yet to figure out where the persistence methods are implemented.

So my questions are:

  • can I cast the result of this call to the various Item types (e.g SwitchItem)?
  • Are all the methods available and do they function as expected? Obviously sendCommand and postUpdate, but also members for Groups and the persistence methods.

If this provides a fully functional Item that behaves the same in Rules as the rest then this can be as useful as Member of and triggeringItem.

(Scott Rushworth) #3

Yes… it appears to be a full blown Item! I found this while looking into the BusEvent.java to see how to properly add checkFirst methods to sendCommand and postUpdate. I should mention that I am using snapshot 1304, in case this was somehow recently exposed. I wonder how much more functionality is available but as of yet undocumented! It looks like there are some more goodies in there… ScriptServiceUtil.java.

I think you are looking for PersistenceExtensions.java.


These tests have all been successful…

val GenericItem test = ScriptServiceUtil.getItemRegistry?.getItem("Virtual_Switch_2") as GenericItem
val SwitchItem testSwitch = ScriptServiceUtil.getItemRegistry?.getItem("Virtual_Switch_2") as SwitchItem
val GroupItem testGroup = ScriptServiceUtil.getItemRegistry?.getItem("gTest") as GenericItem as GroupItem

logDebug("Rules","Test1: item from registry=[{}]",test)
logDebug("Rules","Test1: class=[{}]",test.class)
logDebug("Rules","Test1: tags=[{}]",test.tags)
logDebug("Rules","Test1: category=[{}]",test.category)
logDebug("Rules","Test1: changedSince=[{}]",test.changedSince(now.minusHours(1)))
logDebug("Rules","Test1: lastUpdate=[{}]",test.lastUpdate)
logDebug("Rules","Test1: historicState=[{}]",test.historicState(now.minusHours(1)).state)
logDebug("Rules","Test1: groupNames=[{}]",test.groupNames)
logDebug("Rules","Test1: members=[{}]",testGroup.members)
logDebug("Rules","Test1: allmembers=[{}]",testGroup.allMembers)

I was completely amazed when I triggered a test rule with this in it… and I’m still giddy about it! In the last couple years, I have probably spent at least a few days trying similar ways to access the ItemRegistry. My hopes are very high that this is the DSL :unicorn: I’ve been seeking! I only have about 1000 lines left to migrate to Jython, but hopefully someone can put it to use! :wink:

I’m still on the hunt for a way to access item metadata… but item.getTags and item.hasTag are the closest I’ve come.

(Rich Koshak) #4


:+1: :+1:

I’m going to have to play with this. I

I’m on 2.3 Release and VSCode didn’t complain about the import nor the call to getItem and it appears to work.

(Michael Cumming) #5

Did you look/find a way to modify item tags? I cannot get item.addTag or addTags to work…

(Sebastian) #6

Wow, thank you for this posting @5iver
This makes a lot of rules so much easier.
Just refactored a few of my rules to make them more generic with this approach.


(Scott Rushworth) #7

There are also methods for accessing the ThingRegistry and ModelRpository. I’m not sure what the latter does, but with the ThingRegistry, you can get Channels and check the state of a Thing. I have some examples somewhere, if interested.

(Michael Cumming) #8

Would that allow an indicator that a binding is down or that an external controller isn’t working. Say like the connection to the security panel?

(Rich Koshak) #9

You can already do that with Thing based triggers. I’ve no doubt that such triggers are also supported in JSR223.

For example

   Thing "avmfritz:FRITZ_DECT_210:dect:116570021295" received update OFFLINE

(Sebastian) #10

Yes, would like to see that. I have some kind of monitoring for my Zwave Things on my todo list. Sounds like this can be a possible approach.

(Scott Rushworth) #11

My memory was confused with JSR223… I had actually never played with this in the Rules DSL. But I took a quick look, and found a way to get a Thing status. I got excited about this, but there’s also the Thing Status Action.

You can also access a Things status by using…

// Rules DSL
import org.eclipse.smarthome.model.script.ScriptServiceUtil
import org.eclipse.smarthome.core.thing.ThingUID
logDebug("Rules", "Rules DSL: test=[{}]",ScriptServiceUtil.getInstance.thingRegistry.get(new ThingUID("kodi:kodi:familyroom")).statusInfo)

Bonus info… in JSR223, the Thing registry is already accessible through the predefined script variable things

# JSR223
from org.eclipse.smarthome.core.thing import ThingUID
log.debug("JSR223: test=[{}]".format(things.get(ThingUID("kodi:kodi:familyroom")).statusInfo))

There’s not much you can do with Channels, but you could potentially trigger them.

(rud) #12

This is great!