Retrieve Item by Name inside a rule

I am looking for a way to retrieve an item inside a rule identified by its name. The reason I am doing this is to create scenes, based on groups and the content of the scene is configured by items exposed in basicUI. So I can modify the scene in basicUI.

For example a TV scene would be defined like this

Color    lR_HueGo_Color               
Color    lR_HueGo_Color_sceneTV                            (sceneTV)
Color    lR_HueGo_Color_sceneDinner                      (sceneDinner)

So I am iterating over the sceneTV Group and I would like to send the value defined in item lR_HueGo_Color_sceneTV to the item lR_HueGo_Color. Getting the name of the target item is easy, but retrieving the real ColorItem is my problem.

Any hints??

Hi,

This is perfectly do-able. You can do this with the .name attribute.

Below you can find an example that is triggered by a group (gRaamcontact). I want to know what item in that group actually triggered that rule. I do that by using the .name attribute (more specifically: gRamen.allMembers.filter[sw|sw.name).

Here’s an example:

rule "Raamcontacten consolideren"

when   
    Item gRaamcontact received update
then
	var LastWindowContact = gRaamcontact.members.sortBy[lastUpdate].last
	var Window = gRamen.allMembers.filter[sw|sw.name.contains(LastWindowContact.name.substring(14, 17))].head
	var RelatedWindowContact = gRaamcontact.allMembers.filter[sw|sw.name.contains(LastWindowContact.name.substring(14, 17) + "_2")].head	
	if((LastWindowContact.name.substring(18, 19)) == "1") {
		// I'm doing stuff here.
		logInfo("Example","The name of my item is: " + LastWindowContact.name.toString)	
    }
	if((LastWindowContact.name.substring(18, 19)) == "2") {
		// I'm doing other stuff here.
		logInfo("Example","The name of my item is: " + LastWindowContact.name.toString)	
    }
	
end

Good luck. Let us know if you need more input.

@Dries

So to make things work… I would need to add lR_HueGo_Color to a group. I just hoped for a more generic way like… ItemService.getItem("lR_HueGo_Color")

Btw. what is the difference between member and allMembers? Will allMembers also respect members from subGroups??

Thanks in advance… :wink:

Ok, I must admit. I didn’t fully understand your use-case. What I did understand was that you wanted to derive the name of an item in a rule.

But now I’m thinking, do you really need the name or the value?

Maybe you need this then?

sendCommand(lR_HueGo_Color, lR_HueGo_Color_sceneTV )

Allmembers is indeed also including subgroups.

Hi Dries,

thanks for all your efforts. I will try to make my idea a bit clearer. The main target is to create scene without programming. I will just create VirtualItems for my Lights for example and add the theme to “scene”-Group. By selecting a central SceneSelector, all the items in the SceneGroup will be set to the configured values.

Here are some more details…

I want to derive the name of an item from a group and then retrieve the item itself. The idea is:

Group    gOptionsScenes                  "Scenes"                                                    (gOptions)
Group    sceneTV    (gOptionsScenes)

Color    lR_HueGo_Color               
Color    lR_HueGo_Color_sceneTV                            (sceneTV)
Color    lR_HueGo_Color_sceneDinner                      (sceneDinner)

lR_HueGo_Color is the linked channel to on of my HUEs. lR_HueGo_Color_sceneTV and lR_HueGo_Color_sceneDinner are virtual items holding a color configuration. These virtual items are also exposed by BasicUI. So I can access the value of these items by the UI and configure the scene the way I like without too much coding. :slight_smile: . I got a switch inside my sitemap (and the corresponding item inside the .items file) looking like this:

Selection item=lR_Scene_Selector            mappings=["--select--"="--select--","sceneTV"="TV", "sceneDinner"="Dinner"]

Group item=gOptionsScenes

I´ve started working on a rule:

rule "Select LR Scene"
when
	Item lR_Scene_Selector received command
then
	logInfo("SceneRule", "Selected scene name: " + lR_Scene_Selector.state)

	gOptionsScenes.allMembers.filter [ scene | 
		scene.name.contains(lR_Scene_Selector.state.toString)
	].forEach[ sceneMember | 
		logInfo("SceneRule", "SceneMember: {}", scene.name)
                // lR_HueGo_Color.sendCommand(sceneMember.state) if the sceneMember is lR_HueGo_Color_sceneTV for example

	]

end

So the magic block is my missing part. I can retrieve the lR_HueGo_Color_tvScene object according for the TV scene. But I cannot resolve the lR_HueGo_Color without hardcoding.

So my approach now would be to add all possible Scene Members to a group and use the all members function. I just looked for a way to get around and just retrieve the Items in a more generic way. Maybe there’s already a group containing all items by default??

Hi,

I think I understand your example a bit better. I think this might be interesting for you: https://community.openhab.org/t/configurable-scenarios/

I don’t see your “lR_Scene_Selector” in your .items file. Not sure what type it is (string?). I would maybe use “received update” instead of “received command” in your trigger, since it is a virtual item.

I’m assuming “lR_Scene_Selector.state” contains the exact name of the item that holds your color information (e.g. “lR_HueGo_Color_sceneTV”).

Maybe this works (I haven’t tested it)

rule "Select LR Scene"
when
     Item lR_Scene_Selector received update
then
    var ItemName =  lR_Scene_Selector.state.toString
    var ItemValue = ItemName.state.toString
    sendCommand(ItemName, ItemValue)
end

If not, I recommend processing the thread I mentioned above…

You’re right … totally forgot about that… sendCommand(item, value) stuff.

And you´re right. The thread is almost my approach. :slight_smile:

Improved my rule and now its actually fulfilling my current needs… :wink:

rule "Select LR Scene"
when
	Item lR_Scene_Selector received update
then
	logInfo("SceneRule", "Selected scene name: " + lR_Scene_Selector.state)

	var sceneName = lR_Scene_Selector.state.toString

	gOptionsScenes.allMembers.filter [ scene | 
		scene.name.contains(sceneName)
	].forEach[ sceneMember | 
		
		val sceneTarget = sceneMember.name.replace("_" + sceneName, "")
		var value = "NULL"

		switch (sceneMember.state) {
			DecimalType: 	value = String.valueOf(sceneMember.state)
			OnOffType:   	value = if (sceneMember.state==OnOffType.ON) "ON" else "OFF"
			PlayPauseType: 	value = if (sceneMember.state==PlayPauseType.PLAY) "PLAY" else "PAUSE"
			UnDefType:		value = "NULL"
			Default:     	value = sceneMember.state
		}

		if (value!="NULL") {
			logInfo("SceneRule", "SceneConfigItem: {} SceneTargetItem: {} SceneConfigState: {}", sceneMember.name, sceneTarget, value)
			sendCommand(sceneTarget, value)
		} else {
			logInfo("SceneRule", "SceneConfigItem: {} is not configured", sceneMember)
		}
		
	]

end

and your assumption was right… lR_Scene_Selector is of type string and receives the exact scene name. e.g. “sceneTV”

1 Like