I just created a rule to check for the last wake up time of my Zwave battery devices, because I had some devices which “died” for some reason and didn’t get marked as offline.
I just want to share my solution. Maybe some of you can need this.
Here ist my Rule.
Note that in my case the UIDs “:” needed to be replaced with “%3A”. You can see this in API Explorer.
You also have to create an API Key, which is needed in the shell script (see below)
rule "ZwaveThingLastWakeUp"
when
Time cron "0 0 19 ? * * *"
then
val String[] UIDs = newArrayList("zwave%3Adevice%3A50600ad9%3Anode30", "zwave%3Adevice%3A50600ad9%3Anode18", "zwave%3Adevice%3A50600ad9%3Anode14", "zwave%3Adevice%3A50600ad9%3Anode6", "zwave%3Adevice%3A50600ad9%3Anode3", "zwave%3Adevice%3A50600ad9%3Anode26", "zwave%3Adevice%3A50600ad9%3Anode22", "zwave%3Adevice%3A50600ad9%3Anode25", "zwave%3Adevice%3A50600ad9%3Anode2")
UIDs.forEach [ UID |
var String ThingAPI = executeCommandLine(Duration.ofSeconds(5),"/etc/openhab/scripts/ThingAPI2.sh", UID)
//Split before last wakeup
var String LastWakeUp = ThingAPI.toString.split('"zwave_lastwakeup":"').get(1)
//Split after last wakeup
LastWakeUp = LastWakeUp.toString.split('","zwave_neighbours').get(0)
//logInfo("ThingInfo", "LastWakeUp " + LastWakeUp)
val MyZonedDateTimeFromString = ZonedDateTime.parse(LastWakeUp).withZoneSameInstant(ZoneId.systemDefault())
//logInfo("ThingInfo", "DateTime LastWakeUp: " + MyZonedDateTimeFromString)
if(MyZonedDateTimeFromString.isBefore(now.minusHours(48))){
logInfo("ThingInfo", "No Update from Thing UID " + UID + " since " + LastWakeUp)
sendBroadcastNotification("Gerät " + UID + " hat sich seit über 48h nicht gemeldet, Batterie prüfen")
}
]
end
And this is my Shell script which I call in the rule. Note that the $1 is used to pass the UID in the rule to this script. Maybe you have to set the script as executeable using “chmod +x your-script.sh”
Unfortunately I get the following error message. No idea what it means.
2022-06-03 10:53:48.563 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'ZwaveThingLastWakeUp' failed: Index 1 out of bounds for length 1
I entered the UID of the Things with : and %3A. For me in the API exloper the UID always says :
Maybe you have to Split using another String.
You can run the .sh script directly on your OH Server (if it is Linux )
There you can see the hole output and if it is even working. You should get the same output as in the API Explorer. There you should see “zwave_lastwakeup”.
You should also see the value in the UI in the Things properties:
It is possible to get the thing properties without using the external script to make the API calls. In ECMAScript_2021, using the helper libraries, this is in fact fairly compact.
var ThingRegistry = osgi.getService('org.openhab.core.thing.ThingRegistry');
var ThingUID = Java.type('org.openhab.core.thing.ThingUID');
var myThing = ThingRegistry.get(new ThingUID('DEVICE UID HERE'));
logger.info(myThing.getProperties()['zwave_lastwakeup']);
Kinda; I believe two wakeup intervals need to pass. However, if the device isn’t fully initialized it will never show offline. For example lets say you pull the battery out and restart OH before two periods have passed it will never show offline. One way to check is in the Userdata/Zwave folder the time stamp of the Device XML needs to be after (later) than the controller time stamp for the offline timer to work
Not as slick as the solutions above, but I have a DateTime item linked to the Battery channel and have a page of label cards (13 devices) with the batteries % and have the footer as the DateTime. At a glance I can check the currency of the readings. I use a daily (86400) wakeup for a battery check/poll, so really just look at the day.
Same for me Bob, I use some DateTime items and have a rule that updates then whenever something changes on the thing. Then I have a page that shows all the last check ins, and I have a few scripts that kick off on some devices when they don’t check in on time. The scripts restart an OH service or kick something off the wifi so it can re-join. Ping back here if anyone needs some samples.
hmm, I’m using many different battery devices for example a “Popp mold detector” for over one year.
It works great but two weeks ago I removed the battery for another device and it didn’t show offline. But I think it should be fully initialized after one year of operating? However, the “node XML” time stamp is older than the last wakeup time stamp… (also daily wake up)
I’m not an expert, but I believe the device polling is the only section with a timer that can set a battery node as offline. If other commands to a battery device are not answered, the binding just assumes the device to be asleep and subsequent messages are queued. No commands are sent to a device that is asleep. Since the device itself sends the “I’m awake” message, a dead device can’t be discerned from a sleeping one.
There are three main ways a device will be uninitialized. Obviously while first being included is one. However, with every OH, binding or Controller restart all Zwave nodes are reinitialized from the XML files. For mains powered device this happens pretty quickly. For battery devices this happens when they send the “I’m awake” message. Since a dead device will never send that message, it will not be reinitialized after a restart, and polling will be deferred indefinitely, so will not be marked as offline. The third uninitialized state is if a “Heal” is requested but not completed. I do not use the Heal command enough to know if polling is suspended, but I suspect it is as well. My example was related to a OH restart that I have confirmed with a test.
As to the Device XML, when it is older than the controller XML, it is a clue the controller has been restarted (see above), but the device has not been reinitialized from the file yet because a new XML is created after that happens. However, after this reinitialization is complete, subsequent “awakes” will not generate a new XML, so the wakeup time stamp should always be younger or equal to the node XML time stamp.
Lastly another clue I use to determine if a node is fully initialized is if there are five lines at the bottom of the UI page for the device. If “reinitialize device” is not visible, then the device is not initialized, you can’t reinitialize an uninitialized device.
I think the “heal” is also causing some trouble.
If I add a new device, (after repeated wake up), I can see the “Reinitialise the Device” option. However the next day (after heal during night) the option is not there anymore. Before OH 3.x, this was not the case I think.
So I think i will continue to query the last wake up value to be notified if a node died for some reason. In my experience the battery status value is very inaccurate too.
The length of the “heal” gets longer the more devices you have. Recently some battery device optimization enhancements were merged (in OH3 M6) that should help both initialization and heal to complete in one wake-up. However, even with this, I still check the battery wake-up time, so I think that is still a good idea
It should be where the others are userdata/zwave folder. Mine is Node 1.