At home I have a couple bindings having things going offline every now and then, so I wanted to be able to keep track of their status and display it in a sitemap.
In this case I had to create proxy items that will contain the actual thing’s status and a rule takes care of updating these status items whenever needed / requested.
Here’s the code (JSR223 Python, store in /etc/openhab2/automation/jsr223/python/personal/
):
from core.rules import rule
from core.triggers import when
from org.eclipse.smarthome.core.thing import ThingUID
@rule("Alert: Key thing status update")
## Update thing status when rule engine starts:
@when("System started")
## Update thing status every 10 minutes:
@when("Time cron 0 0/10 * * * ?")
######################################################################
# TO DO:
# (1) make sure each thing has its @when() rule decorator below;
# (2) make sure each thing also appears in keyThingsDict
# (3) make sure each ThingStatusItem (see keyThingsDict) exists in the Item Registry
######################################################################
## Z-Wave controller (ZME E UZB1)
@when("Thing zwave:serial_zstick:controller changed")
## Roller Shutters:
@when("Thing zwave:device:controller:node2 changed")
# (etc.)
## IKEA TRÅDFRI gateway (replace 'a1b2c3d4e5f6' with your gateway ID):
@when("Thing tradfri:gateway:gwa1b2c3d4e5f6 changed")
## OpenWeathermaps status (replace 'a1b2c3d4' with your OWM Thing identifier):
@when("Thing openweathermap:weather-api:a1b2c3d4 changed")
@when("Thing openweathermap:weather-and-forecast:a1b2c3d4:local changed")
## Buienradar:
@when("Thing buienradar:rain_forecast:home changed")
def KeyThingStatusUpdate(event):
keyThingsDict = {
## Format: "ThingUID": "ThingStatusItemName"
"zwave:serial_zstick:controller": "ZWave_Controller_Status",
"zwave:device:controller:node2": "Bedroom_NE_Shutter_Status",
# (etc.)
# IKEA TRÅDFRI:
"tradfri:gateway:gwa0c9a0d644f9": "IKEA_TRADFRI_Gateway_Status",
# OpenWeatherMaps Binding:
"openweathermap:weather-api:7f556256": "Wx_OWM_API_Status",
"openweathermap:weather-and-forecast:7f556256:local": "Wx_OWM_Weather_Status",
# BuienRadar binding:
"buienradar:rain_forecast:home": "BuienRadar_Status",
}
KeyThingStatusUpdate.log.info("event = " + pp.pformat(event))
# Store a list of all things that must be updated:
keyThings = []
if event:
# Rulle triggered by a thing status change --> only one thing to process
keyThings.append(str(event.thingUID))
else:
# Rulle has not been triggered by a thing status change --> process all things
for k in keyThingsDict.keys():
keyThings.append(k)
for k in keyThings:
keyItem = keyThingsDict[k]
nodeName = k.split(':')[-1]
# thing state is not available in event if rule triggered by cron:
nodeState = str(event.statusInfo) if event else things.get(ThingUID(k)).status
KeyThingStatusUpdate.log.debug("Thing '{node_name}' (item {item_name}) status changed to '{node_state}'".format(
node_name = nodeName,
item_name = keyItem,
node_state = nodeState,
))
# Post the status update to the thing status item:
events.postUpdate(keyItem, str(nodeState))
Here are the status items:
// Z-Wave Things:
String ZWave_Controller_Status "Z-Wave Controller Status [%s]" <traffic_light> (gPersist_everyChange)
// This group item with aggregation will have value in 'ONLINE' if all of its direct children
// have their state set to 'ONLINE', else the group item will have value 'ERROR':
Group:String:AND('ONLINE','ERROR') gKeyZWaveThings "Key Z-Wave Things [%s]" <traffic_light>
// The other Z-Wave things I want to keep status info from:
String Bedroom_NE_Shutter_Status "Bedroom NE Blinds Status [%s]" <traffic_light> (gKeyZWaveThings, gPersist_everyChange)
// (all other Z-Wave things defined in the same manner)
// IKEA TRÅDFRI Things:
String IKEA_TRADFRI_Gateway_Status "IKEA TRÅDFRI Gateway Status [%s]" <traffic_light> (gPersist_everyChange)
// OpenWeatherMaps Things:
// Aggregator group (see above): 'ONLINE' if all children are 'ONLINE' else set to 'ERROR'):
Group:String:AND('ONLINE','ERROR') gWxOWMKeyThings "Key OWM Things [%s]" <traffic_light>
// OWM API status:
String Wx_OWM_API_Status "OWM Weather API [%s]" <traffic_light> (gWxOWMKeyThings, gPersist_everyChange)
// OWM Current weather and forecast status:
String Wx_OWM_Weather_Status "OWM Weather & Forecast [%s]" <traffic_light> (gWxOWMKeyThings, gPersist_everyChange)
// Note: local UV currently not added in my setup)
// BuienRadar Things:
String BuienRadar_Status "Buienradar [%s]" <traffic_light> (gPersist_everyChange)
Notes:
- the
gPersist_everyChange
group is used for assigning the “everyChange” persistence strategy. - I created a
traffic_light
dynamic icon set for the purpose:
SVG:
PNG:
These icons can be placed in /etc/openhab2/icons/classic/
I created the following dynamic icon mappings with symbolic links (replace png
with svg
for the SVG mappings):
traffic_light-green.png
traffic_light-online.png -> traffic_light-green.png
traffic_light-orange.png
traffic_light-initializing.png -> traffic_light-orange.png
traffic_light-red.png
traffic_light-offline.png -> traffic_light-red.png
traffic_light.png -> traffic_light-red.png
traffic_light-uninitialized.png -> traffic_light-red.png
The sitemap entry reads as follows:
Frame label="Status Info" icon="error" {
Default item=IKEA_TRADFRI_Gateway_Status
Text item=gKeyZWaveThings {
Default item=ZWave_Controller_Status
Text label="Bedroom blinds" icon="firstfloor"
Default item=Bedroom_NE_Shutter_Status
// (etc.)
}
Text item=gWxOWMKeyThings {
Default item=Wx_OWM_API_Status
Default item=Wx_OWM_Weather_Status
}
Default item=BuienRadar_Status
}
Have fun!