In the Rules DSL, I used HashMaps, but now in JSR223, I use dictionaries to store data for particular Items. I use this data for setting the light levels based on the current time of day and the outdoor lux level.
areaLightLevels = {
"US_DiningRoom_Dimmer" : {
"Morning" : {"Low_Lux_Trigger" : 20, "Level" : 30},
"Day" : {"Low_Lux_Trigger" : 90, "Level" : 30},
"Evening" : {"Low_Lux_Trigger" : 90, "Level" : 30},
"Night" : {"Low_Lux_Trigger" : 90, "Level" : 30},
"Late" : {"Low_Lux_Trigger" : 90, "Level" : 1}
},
Using the openhab2-Jython modules, you can access the MetadataRegistry. This lets you read, add and remove metadata from Items. Eventually, metadata may become editable in a UI, but I may create a HABpanel widget for this too. Here is an example script to show you how it’s done:
from org.slf4j import Logger, LoggerFactory
log = LoggerFactory.getLogger("org.eclipse.smarthome.model.script.Rules")
from openhab import osgi
from org.eclipse.smarthome.core.items import Metadata
from org.eclipse.smarthome.core.items import MetadataKey
MetadataRegistry = osgi.get_service("org.eclipse.smarthome.core.items.MetadataRegistry")
# read metadata
testReadMetadata = MetadataRegistry.get(MetadataKey("Test1","Virtual_Switch_1"))# returns None if namespace does not exist
if hasattr(testReadMetadata, 'configuration'):# just checking to be safe
log.debug("JSR223: testReadMetadata.configuration=[{}], now removing it".format(testReadMetadata.configuration))
# remove metadata
MetadataRegistry.remove(MetadataKey("Test1","Virtual_Switch_1"))
else:
log.debug("JSR223: namespace \"Test1\" does not exist, so adding it")
# add metadata
MetadataRegistry.add(Metadata(MetadataKey("Test1","Virtual_Switch_1"), "TestValue", {"TestConfig1":5, "TestConfig2":55}))
# read metadata
testReadMetadata = MetadataRegistry.get(MetadataKey("Test1","Virtual_Switch_1"))# returns None if namespace does not exist
if hasattr(testReadMetadata, 'configuration'):# just checking to be safe
log.debug("JSR223: testReadMetadata.configuration=[{}], now removing it".format(testReadMetadata.configuration))
# remove metadata
MetadataRegistry.remove(MetadataKey("Test1","Virtual_Switch_1"))
else:
log.debug("JSR223: namespace \"Test1\" does not exist, so adding it")
# add metadata
MetadataRegistry.add(Metadata(MetadataKey("Test1","Virtual_Switch_1"), "TestValue", {"TestConfig1":5, "TestConfig2":55}))
test = MetadataRegistry.get(MetadataKey("Test","Virtual_Switch_1"))# returns None if namespace does not exist
lightLevels = MetadataRegistry.get(MetadataKey("Morning","Virtual_Switch_1"))
if hasattr(lightLevels, 'configuration'):
log.debug("JSR223: lightLevels.configuration=[{}]".format(lightLevels.configuration))
log.debug("JSR223: lightLevels.configuration[\"Trigger\"]=[{}], lightLevels.configuration[\"Level\"]=[{}]".format(lightLevels.configuration["Trigger"], lightLevels.configuration["Level"]))
You can set metadata in your managed Items by doing this…
Switch Virtual_Switch_1 "Virtual Switch 1 [%s]" <switch> (gVirtual,gTest) ["Switchable"] { Morning="LightLevels"[Trigger=1, Level=10], Day="LightLevels"[Trigger=2, Level=20], Evening="LightLevels"[Trigger=3, Level=30], Night="LightLevels"[Trigger=4, Level=40], Late="LightLevels"[Trigger=5, Level=50] }
… but if you do, you can’t modify it. You can still add metadata and then remove it though. To populate and verify my metadata, I used this script, which pulled the data from a dictionary like the above example…
# imports from above
for lightLevel in areaLightLevels:
for mode in areaLightLevels[lightLevel]:
if lightLevel != "Default":
log.debug("JSR223: lightLevel=[{}], mode=[{}], Low_Lux_Trigger=[{}], Level=[{}]".format(lightLevel, mode, areaLightLevels[lightLevel][mode]["Low_Lux_Trigger"], areaLightLevels[lightLevel][mode]["Level"]))
MetadataRegistry.add(Metadata(MetadataKey(mode,lightLevel), "LightLevels", {"Low_Lux_Trigger":areaLightLevels[lightLevel][mode]["Low_Lux_Trigger"], "Level":areaLightLevels[lightLevel][mode]["Level"]}))
testReadMetadata = MetadataRegistry.get(MetadataKey(mode,lightLevel))
log.debug("JSR223: testReadMetadata.configuration=[{}]".format(testReadMetadata.configuration))