I have activated the Z2M availability warning, it is going quite well. I would like to have an alert when one of my devices is offline. Something that would scroll through the status of all z2m devices without having to add them myself by hand when I add new devices.
Is it possible to do something automated to monitor all devices?
For anyone using appdaemon, here is an app I wrote that will notify on any unavailable entity, and not just zigbee devices.
Key features include:
Excluding entities when they contain a given string
Batching and limiting notifications, so you only get a few if hundreds are offline (such as when shutting down zigbee2mqtt)
In apps.yaml (with my own examples in exclude):
unavailable:
module: unavailable
class: UnavailableNotifier
exclude:
- device_tracker.
- sensor.hp_laser
# Lights attached to a physical switch
- side_table
# These are a one-way switch
- switch.front_load_washer_power
- switch.dryer_power
- button.front_load_washer
- button.dryer
# Buggy in LG integration
- switch.refrigerator_ice_plus
# Camera drops wifi once or twice a day
- camera.freezer_room
- binary_sensor.freezer_room_motion_detected
- camera.cat_food_camera
- binary_sensor.cat_food_camera_motion_detected
# We have Bluetooth on a USB 3 cable and AirThings requires a GATT connection
# https://github.com/home-assistant/core/issues/116770
- sensor.airthings
- sensor.air_quality
And then in unavailable.py - note you for sure will need to change the notify service name, as I hadn’t bothered to make that a variable.
import appdaemon.plugins.hass.hassapi as hass
# noinspection PyAttributeOutsideInit
class UnavailableNotifier(hass.Hass):
def initialize(self):
self._exclude = self.args["exclude"]
self._state_handle = self.listen_state(self.unavailable)
self._unavailable = {}
self._timer_handle = None
def unavailable(self, entity, attribute, old, new, kwargs):
for exclude in self._exclude:
if exclude in entity:
return
if new == "unavailable" and not entity in self._unavailable:
if len(self._unavailable) > 6 * 4:
self.log(f"Skipping adding {entity} to the queue.")
return
self.log("Adding " + entity + " to the notification queue")
self._unavailable[entity] = self.get_now_ts()
if self._timer_handle is None:
self._timer_handle = self.run_in(self.send, 15)
def send(self, kwargs):
if len(self._unavailable) > 0:
to_notify = set()
next_round = {}
while len(to_notify) < 6 and len(self._unavailable) > 0:
entity, added = self._unavailable.popitem()
if added > self.get_now_ts() - 30:
next_round[entity] = added
elif self.get_state(entity_id=entity) == "unavailable":
to_notify.add(entity)
self._unavailable.update(next_round)
if len(to_notify) > 0:
self.log("Notifying on " + str(len(to_notify)) + " entities")
entities = "- " + "\n- ".join(to_notify)
self.notify(name="mobile_app_iphone", title="⚠ Unavailable Entities",
message=entities)
self._timer_handle = self.run_in(self.send, 15)
return
else:
self._timer_handle = self.run_in(self.send, 15)
self.log(str(len(self._unavailable)) + " notifications remaining")
return
self._timer_handle = None
I think I got lost with the explanation, if you could make it a little more detailed what this code is for and how to install it, it would be perfect! thanks!
This is very much for people comfortable with programming, who would just rather write Python than automation in a UI. If this is a rabbit hole you want to go down, I’d suggest starting with reading AppDaemon Tutorial for HASS Users — AppDaemon 4.4.3 documentation and going from there!