ZHA show last_seen, LQI and RSSI as entity attributes

It would be great to get these values as attributes so that they can be used in automations. I know that these values are displayed in the ZHA visualization card and this is good but not useful in automations.
I have xiaomi temperature devices that fall off of the mesh occasionally, despite my efforts to add many repeaters, and they show as unavailable after quite a while. Normally I see these report at least once an hour when looking at the ZHA visualization card. I could check the last_seen attribute in an automation so that I could get an earlier warning or also check for bad LQI or RSSI values as an early failure warning.
Thanks for your consideration.

I also would like to know this. Hope someone could shed some light over this.

I also hope the zha team comes with a solution. At this moment there is no solution to check if all sensors are ok. For example smoke, if everything is ok those have never had an last_changed thus I don’t know of there are still ok.

2 Likes

It would be helpful if you could click on the Vote button on the top of this page. thanks.

I would also like to see this feature implemented.

Imagine something like Smoke Detection or Water Leakage sensors, that basically never send status change messages. For those it is crucial to know that they are still operational via something like the “last seen” value.

Without such a feature the integration of Smoke Detection and Water Leakage sensors is basically useless - because you can’t trust it.

1 Like

In addition to Smoke and Water leak detectors I also monitor my fridge and freezer temps as sometimes the doors are not properly closed and the temps go way up. I need to know when/if these sensors drop off the zigbee network as they occasionally do.

1 Like

Need help for the same issue. I am using all the devices that is been listed on ZHA page and still iam getting all the above errors. My CC235* stick to gets offline therefore making me unable to use any of my devices…

Not sure if it helps but you can get at all this information using the ZHA Network Card in HACS:

Yes, I use this card all of the time but it needs me to look at it constantly to see if the Last Seen value is more than an hour or two old. This is how I know if one of my critical sensors has become unavailable. I have two temp sensors in my fridges so that I can get an alert if the temps go too high because the doors have not been properly closed. The work great but occasionally become unavailable. When this happens the ‘last seen’ will visually tell me if it becomes older than about an hour. The actual status is not changed to unavailable for many hours later. What would be very useful is if we can get the ‘last seen’ as an attribute so that it can be checked in an automation instead of having to look at the card. I currently can only trigger an alert when the status becomes unavailable but this is far too late.

1 Like

Maybe you could reach out to the developer of the ZHA Network Card @dmulcahey to see if he could help you write a Python script to write the Last Seen attribute to an entity in HA. That way you would have something that works while you wait for the feature request to hopefully get implemented.

Here is some python code I wrote a while back to collect the zigbee device info via HA CLI and websockets. You could adapt it to run in AppDaemon or similar to create HA sensors or events.

You will need to create a HA long lived token to allow access from outside HA.

My newer ‘solution’ is to let the flakey vendor zigbee devices die and simply remove them. Zigbee has unfortunately become a fragmented mess with some combos of devices, rather frustrating considering how stable a ‘good’ zigbee network can be.

Hi, thanks for the info.
Is there any way to convert your code to run as an add-on or custom component? If not, how do I get started to run it in AppDaemon? Sorry but I am a Python newbie.
cheers

We all learning and nubs :wink: Just take small steps each evolution. A couple routes you could go.

  1. Do an alert outside HA. Take a look at the simple example I wrote, ws02.py. And then use something like the code I link below to give you a iOS or Android alert.

ws02.py just prints out the current ZHA view of all of its zigbee devices every 5 seconds in JSON format. This should give you a feel for how you read a HA websocket and what the ZHA JSON data looks like. The parsing examples I show using JQ app to extract out subsets of the ZHA JSON data should give you a feel for how to get to the data you want in the ZHA websocket output. Python’s JSON libraries can do the same extract and filtering that the JQ app does.

You can look at the ‘last seen’ and ‘online’ values for each of your zigbee devices and used these to help determine the devices states. You could mash this up with the code I show below to create an app outside of HA that alerts you when the age of a device exceeds a selected value.

I wrote a simple python script for monitoring whether MQTT bluetooth sensors drop off, it is a bit different a flow, but it might give you an idea of how to do an alert outside of HA when a sensor goes rogue. I use a iOS and Android alerting service called ‘Pushover’ in this app to alert me when a MQTT value has not updated for a period:

  1. If you want to create a HA sensor, using AppDaemon is the route I know. There maybe other ways. However, you need to be able to call a HA websocket in the environment you are running, I think you can do this with javascript within HA (as the ZHA Network Card example shows) however I do not know how or if you can create a HA sensor using this route. I am not familiar with how to call websockets using python within HA, I am not sure all the necessary libraries are available in HA’s python. So this is why I recommended the AppDaemon route.

I would familiarize yourself with how AppDaemon works/runs apps by creating a simple dummy sensor from their examples. After you are comfortable with creating a HA sensor within App Daemon that updates on a regular period, I would then add in the ZHA websocket calling logic similar to the code in ws02.py combined with your logic to check the age of zigbee devices and then set some type of state in the HA sensor that you create to show the dead zigbee device info to HA.

Good hunting!

Thanks for your detailed reply. Trust me, I have spent hours trying to figure out the py code to do this with no luck. I just do not have the python skills. You have provided some additional info that might help me so I will try again.
I wish that ZHA would include this data as sensor attributes, just like zigbee2mqtt does. Oh well.
thanks again for the help.

See if you can get the ws02.py working and then see if you can make a few changes to it to check the last_seen and rssi attributes, below is how you would do it piping the output of ws02.py to the jq utility:

./ws02.py | jq -c '.result[] | {date: (now|strftime("%s")), ieee: .ieee, ls: .last_seen, rssi: .rssi}'

{"date":"1626152267","ieee":"xx:yy:xx:yy:xx:yy:xx:yy","ls":"2021-07-12T13:45:52","rssi":-48}
{"date":"1626152267","ieee":"xx:yy:xx:yy:xx:yy:xx:yy","ls":"2021-06-25T11:08:36","rssi":null}
{"date":"1626152267","ieee":"xx:yy:xx:yy:xx:yy:xx:yy","ls":"2021-07-12T13:57:33","rssi":-40}
{"date":"1626152267","ieee":"xx:yy:xx:yy:xx:yy:xx:yy","ls":"2021-07-12T13:57:46","rssi":null}
{"date":"1626152267","ieee":"xx:yy:xx:yy:xx:yy:xx:yy","ls":"2021-07-12T13:57:46","rssi":null}
{"date":"1626152267","ieee":"xx:yy:xx:yy:xx:yy:xx:yy","ls":"2021-07-12T13:57:46","rssi":null}
{"date":"1626152267","ieee":"xx:yy:xx:yy:xx:yy:xx:yy","ls":"2021-07-12T13:57:46","rssi":null}
{"date":"1626152267","ieee":"xx:yy:xx:yy:xx:yy:xx:yy","ls":"2021-07-12T13:57:46","rssi":null}
{"date":"1626152267","ieee":"xx:yy:xx:yy:xx:yy:xx:yy","ls":"2021-07-12T13:57:41","rssi":-36}
{"date":"1626152267","ieee":"xx:yy:xx:yy:xx:yy:xx:yy","ls":"2021-07-12T13:57:41","rssi":-41}
{"date":"1626152267","ieee":"xx:yy:xx:yy:xx:yy:xx:yy","ls":"2021-07-12T13:57:42","rssi":-40}
{"date":"1626152267","ieee":"xx:yy:xx:yy:xx:yy:xx:yy","ls":"2021-07-12T13:56:07","rssi":-38}
{"date":"1626152267","ieee":"xx:yy:xx:yy:xx:yy:xx:yy","ls":"2021-07-12T13:56:45","rssi":-49}
{"date":"1626152267","ieee":"xx:yy:xx:yy:xx:yy:xx:yy","ls":"2021-07-12T13:51:18","rssi":-66}
{"date":"1626152267","ieee":"xx:yy:xx:yy:xx:yy:xx:yy","ls":"2021-07-12T13:57:25","rssi":-44}
{"date":"1626152267","ieee":"xx:yy:xx:yy:xx:yy:xx:yy","ls":"2021-07-12T13:57:14","rssi":-40}
{"date":"1626152267","ieee":"xx:yy:xx:yy:xx:yy:xx:yy","ls":"2021-07-12T13:50:30","rssi":-37}
{"date":"1626152267","ieee":"xx:yy:xx:yy:xx:yy:xx:yy","ls":"2021-07-12T13:18:30","rssi":-62}

–or–

./ws02.py | jq -c '.result[] | {date: (now|strftime("%s")), ieee: .ieee, ls: .last_seen, rssi: .rssi, name: .user_given_name}'

{"date":"1626152745","ieee":"xx:yy:xx:yy:xx:yy:xx:yy","ls":"2021-07-12T14:03:36","rssi":-38,"name":"SmartThings PGC313 01 Entry Way"}
{"date":"1626152745","ieee":"xx:yy:xx:yy:xx:yy:xx:yy","ls":"2021-07-12T14:05:15","rssi":-49,"name":"IKEA of Sweden TRADFRI motion sensor 01 Dining Room"}
{"date":"1626152745","ieee":"xx:yy:xx:yy:xx:yy:xx:yy","ls":"2021-07-12T13:51:18","rssi":-66,"name":"CREE  Connected A-19 60W Equivalent  01 HVAC Closet"}
{"date":"1626152745","ieee":"xx:yy:xx:yy:xx:yy:xx:yy","ls":"2021-07-12T14:05:25","rssi":-44,"name":"OSRAM LIGHTIFY A19 Tunable White 01 Living Room"}
{"date":"1626152745","ieee":"xx:yy:xx:yy:xx:yy:xx:yy","ls":"2021-07-12T14:03:56","rssi":-53,"name":"eWeLink TH01 Test"}
{"date":"1626152745","ieee":"xx:yy:xx:yy:xx:yy:xx:yy","ls":"2021-07-12T13:50:30","rssi":-37,"name":"IKEA of Sweden TRADFRI on/off switch stove"}
{"date":"1626152745","ieee":"xx:yy:xx:yy:xx:yy:xx:yy","ls":"2021-07-12T14:00:39","rssi":-62,"name":"LUMI lumi.weather Test"}

shout if I can help.

Thanks so much for your sample code. It was very helpful and I was able to create an AppDaemon app that does exactly what I need. :slight_smile: I am sure that the code could be better or simplified as I am not a python coder but it works!
I do not set a timer via AppDaemon to run this but through an automation as it suited my needs better.
I have included my code below in case it could help someone else.
cheers

import appdaemon.plugins.hass.hassapi as hass
import sys
import json
import time
import datetime

from websocket import create_connection

ACCESS_TOKEN = "***"

class zha_check(hass.Hass):

  def initialize(self):
    self.listen_event(self.ZHAmonitor, "ZHAcheck")
    #call this every 60 minutes from an HA automation by action: - event: ZHAcheck

    self.ZHAdump()

  def ZHAmonitor (self, event_name, data, kwargs): 
    self.ZHAdump()

  def ZHAdump (self): 
    count = 0
    last_seen = {}
    max_time = 5400 #90 minutes
    now = datetime.datetime.now()

    ws = create_connection("ws://192.168.1.*:8123/api/websocket")
    result =  ws.recv()

    ws.send(json.dumps( {'type': 'auth', 'access_token': ACCESS_TOKEN} ))
    result =  ws.recv()
    
    ident = 1
    ws.send(json.dumps( {'id': ident, 'type': 'zha/devices'} ))
    result =  ws.recv()    

    # convert the string that came back to JSON
    json_result = json.loads(result)

    # retrieve each device that was returned
    for device in json_result["result"] :
      #self.log("Device: " + str(device["user_given_name"]) + " " + str(device["last_seen"]))

      last_date = str(device["last_seen"])
      last_dat2 = last_date[:19]
      last_dat3 = datetime.datetime.strptime(last_dat2, '%Y-%m-%dT%H:%M:%S')
      diff = (now - last_dat3).seconds
      if diff > max_time:
        last_seen[str(device["user_given_name"])] = last_dat3
        count = count + 1

    last_seen['friendly_name'] = 'Last Seen ZHA'
    last_seen['icon'] = 'mdi:message-alert-outline'
    self.set_state('sensor.last_seen_zha',state=count,attributes=last_seen)
    #this will create a sensor called sensor.last_seen_zha with a list of attributes containing the name and last_seen time of each sensor not reporting for more then 90 minutes.
    #I then have an automation that emails me an alert when this sensor is greater than 0


2 Likes

Great job! As I was looking at my code and yours, I am not sure if the web socket JSON return give back timezone info (there might be a way in python to return a proper UTC time), so there might be a burp in code on DST change days.

I upvoted this feature request.

Check also the idea to get last_seen from the ZHA devices file:

FYI, basic RSSI and LQI sensors for diagnostics were added to ZHA in Home Assistant 2022.2 release:

https://community.home-assistant.io/t/showing-basic-rssi-prometheus-exporter/390632/

https://github.com/home-assistant/core/pull/62716

https://www.home-assistant.io/blog/2022/02/02/release-20222/

2 Likes

Hey Guys,

Meanwhile indeed RSS and LQI can be seen under the diagnostics tab.

Iam also interested in the last_seen (laatst gezien in dutch) property, but monitoring the last_seen property via the ZHA_Card I noticed that the last_seen property from OFFLINE devices is updated every second at least from the lightbulbs.

Notice the last seen property while the lamp is offline, for 2 months, in fact the lamp is in a drawer!!!

last_seen but not online2
3 bulbs all offline in a drawer, but updated every second as last seen…
last_seen but not online3

The 4th row location ‘woonkamer’ is a remote control without batteries and the last seen property stays at january 30th…

anybody an explanation why the lightbulbs in the drawer (lol) keeps being updated??

Regards Frank