Additional key/value attributes field for GenericItem

Hi all,

While working on the various light rules, one thing that has bugged me is the need to add virtual items that are really attributes of the actual light switch. Here are some example attributes: the dimming level, the illuminate level (to turn on the light), time range to disable motion sensor triggering, or the light to turn off if this light is turned on.

IMO, this could be achieved cleaner by allowing specifying the attributes in the item files. For example:

Switch FF_GreatRoom_LightSwitch "Great Room Light" (gLightSwitch)
  { channel="zwave:device:9e4ce05e:node7:switch_binary" }
  [dimmingLevel=50, luxLevel=10, disableMotionTrigger=true]

In the example above, I define three additional attributes: dimmingLevel, luxLevel, and disableMotionTrigger. There is no need for persistence; the attributes have the same life cycle as the item’s.

To support this in the back end, couple new methods can be added to the GenericItem class:

  • public void addProperty(final String key, final String value)
  • public void getProperty(final String key)
  • public void removeProperty(final String key)
  • public List getPropertyKeys()

What do you think of this? Has this been considered before?

Seems doable, though the is already taken for Item tags so you will have to figure out some other way to represent it as part of the Item definition.

You will also have to add REST API calls to get, set, change, and delete these properties. So the changes necessary are quite a bit bigger than adding a Map and some methods to the Item Interface and GenericItem class.

All of this would need to be implemented in the core so I’d recommend filing an issue at GitHub - eclipse-archived/smarthome: Eclipse SmartHome™ project. You might want to open a discussion on the ESH forum as well.

Personally, I’m ambivalent about the proposal itself. It doesn’t feel a whole lot less awkward than other approaches. But maybe seeing it in action would change my mind. You might look though to see if you can use Tags for this already. I know if you did so it might break some of the bindings that depend on tags like Google Assistant and Alexa, but I think I remember some people using tags for stuff like this in the past.

There are other approaches as well. For example, you can put these parameters into a .map file and use the transform Action to pull the value (e.g. transform("MAP", "lights_settings.map", triggeringItem.name+"_dimmingLevel")), or load a Properties object from a .properties file in your Rules and access the parameters from the resultant Map. You could even hard code a Map with the parameters.

There is still a separation between the Item and the parameters but it means you don’t have to store the parameters as a separate Item.

@rikoshak

Thanks for reading Rich. I think we can use <>. I will post a discussion on the ESH forum.

I am aware of the alternative you mentioned. I used it for my route rules. It is also a nice mechanism to allow sharing the source code, through github for example, but keeping the actual config values such as email address and home address private in a map file.

I think having the attribute will simplify the code quite a bit. Here is an example of doing the same thing in three different ways.

Using item attributes:

val dimmingLevelString = triggerItem.getProperty("dimmingLevel")

Simulate attributes using addition items:

// set up the initial value in a startup rule
FF_GreatRoom_DimmingLevel.sendCommand(50)

// retrieve the dimming level somewhere else
val itemName = triggeringItem.name.substring(0, triggerItem.lastIndexOf("_")) + "_DimmingLevel"
val dimmingLevelItem = gDimmingLevel.members.findFirst[ d | d.name == itemName ]
val dimmingLevelString = dimmingLevelItem.state

Read attributes from an external map file:

// set up the initial value in a startup rule
FF_GreatRoom_DimmingLevel.sendCommand(50)

// retrieve the dimming level somewhere else
val perfix = triggeringItem.name.substring(0, triggerItem.lastIndexOf("_")) + "_DimmingLevel"
val dimmingLevelString = transform("MAP", PROPERTIES_FILE, prefix + "dimmingLevel")

The additional support allow the initial values to be set explicitly within the .item file (no need for sending the command at startup). It also making changes to the values easy. We can kind of do this by hacking the tag mechanism (by encoding the key/value pair in a tag), but tag isn’t really built for this.

<> is used for the icon.

“Properties” can just be anything, so that’s nothing that should be added that way. They would not have any intrinsic meaning, so they could not be used by UIs or rules.
What ESH has introduced are the tags that @rlkoshak already mentioned as well as the metadata infrastructure, which allows adding metadata for specific use cases.

Could you please provide an example of how to access an item’s metadata through a DSL rule? The documentation does not have one, and the unit tests give hints but I have not gotten anything to work. This is also what I was requesting here…

I am afraid that this currently isn’t possible… The metadata is meant to be consumed by certain add-ons, not necessarily by the user in rules (not wanting to say that this cannot be added).

1 Like

Thank you! I will look into accessing it using JSR223-Jython… I can see light at the end of the tunnel with my migration.

In case you are still looking… and are willing to use JSR223…

Thanks @5iver. I think eventually I will have to gradually move to another language, python maybe. I am finding that as the rules get more complicated, the lack of code re-usability support in Xtend really hinders the development effort. Hopefully moving to JSR223 will allow breaking down the code into reusable units. I will try your dictionaries approach then.

If you haven’t you may want to take a look at this…

I just took a quick glance at the openhab2-Jython documentation, and I really like it. Thanks for the effort! I am still running OH 2.3. When I have sometimes to roll out a dev build, I will definitely try your Jython framework.

Not mine… I’m just helping to improve it!