Hi all,
This topic is about how-to monitor Zigbee devices connected via Zigbee2mqtt using only Openhab power.
I have around 30 Zigbee devices in network, many of them are battery-powered, and:
- Some of Zigbee devices do not report battery level properly.
- Some of Zigbee devices report wrong battery level.
- We have important devices (like Water-leak sensors) which should be monitored.
It may cause that sometimes i missing the moment when device goes offline. So, let’s setup some device monitoring on it. Zigbee2mqtt has built-in device checker, but i don’t like it - i want to check only some of devices and i don’t want to push them to prolong battery life.
First of all, will declare device with special channels on it. Classic link/battery and new - activity
.
// Xiaomi MiJia temperature & humidity sensor (WSDCGQ01LM)
Thing mqtt:topic:openhab:mi-sensor-cc22 (mqtt:broker:openhab) {
Channels:
Type number : temperature [ stateTopic="zigbee2mqtt/0x00158d0001c2cc22", transformationPattern="JSONPATH:$.temperature" ]
Type number : humidity [ stateTopic="zigbee2mqtt/0x00158d0001c2cc22", transformationPattern="JSONPATH:$.humidity" ]
Type number : battery [ stateTopic="zigbee2mqtt/0x00158d0001c2cc22", transformationPattern="JSONPATH:$.battery" ]
Type switch : battery_low [ stateTopic="zigbee2mqtt/0x00158d0001c2cc22", transformationPattern="JS:z2m-lowbatt.js" ]
Type number : link [ stateTopic="zigbee2mqtt/0x00158d0001c2cc22", transformationPattern="JSONPATH:$.linkquality" ]
Type datetime : activity [ stateTopic="zigbee2mqtt/0x00158d0001c2cc22", transformationPattern="JS:z2m-activity.js" ]
}
I have added special transformation to record last activity update, by return current date:
// z2m-activity.js
(function (dataString) {
var now = new Date();
return now.toISOString();
})(input)
This will save latest received packet to activity channel. Will add item on it:
DateTime mi_sens_weather_activity "MI Sens Weather [JS(display-activity.js):%s]" <time> (g_zigbee_activity) { channel="mqtt:topic:openhab:mi-sensor-cc22:activity" }
I have added special display-formatter to show last activity time in human-friendly way, without date-time parsing:
// display-activity.js
(function (dataString) {
// Make a fuzzy time
// https://stackoverflow.com/a/7641812
var delta = Math.round((+new Date - new Date(dataString)) / 1000);
if (isNaN(delta)) {
return "?"
}
var minute = 60,
hour = minute * 60,
day = hour * 24,
week = day * 7;
var fuzzy;
if (delta < 30) {
fuzzy = 'Now';
} else if (delta < minute) {
fuzzy = delta + ' s';
} else if (delta < hour) {
fuzzy = Math.floor(delta / minute) + ' m';
} else if (delta < day) {
fuzzy = Math.floor(delta / hour) + ' h';
} else {
fuzzy = Math.floor(delta / day) + ' d';
}
return fuzzy;
})(input)
Now we have item, which either stores correct value format (DateTime) and has nice printout in the same time. Now we can group this items to have some aggregation (will print WORST value, earliest item in group):
Group:DateTime:EARLIEST g_zigbee_activity "Zigbee Activity [JS(display-activity.js):%s]" <time>
And we can add it to sitemap:
And, for sure, we can now monitor - to find out stale devices (or just check the Group value instead of loop. I have it, as i want to have exact names to be sent):
// This rule send notifications if item was not updated within 24 hrs
rule "Test devices responce time"
when
Time cron "0 00 12 ? * *"
or Item test_sw_check_activity received command
then
g_zigbee_activity.members.forEach [s |
if (s.state != NULL) {
val date_item = new DateTime(( s.state as DateTimeType).zonedDateTime.toInstant.toEpochMilli)
val date_now = new DateTime()
var double diff_hours = (date_now.millis - date_item.millis) / 1000 / 60 / 60
logInfo("activity", "Item " + s.label + " last update: " + diff_hours)
if (diff_hours > 24) {
sendBroadcastNotification("Item " + s.label + " no activity for " + diff_hours + " h")
}
} else {
logInfo("activity", "Item " + s.label + " never updated")
}
]
end
That’s all, folks! Now we have some monitoring and report statement on sitemap.
Full source code is available in my github repository petrows/smarthome-openhab.