I need an automation that sends an MQTT message when a Z-Wave device is dead after a reboot. Some devices react to ping, but I have found that instead of pinging I can call a refresh of CC 112 (configuration), which will work on every single device. The MQTT action is like this:
The 43 in arguments is the node number. Then I have the trigger, which is a simple “every minute” trigger. And finally I have the condition. The reason I would like to use the condition result is that otherwise I’d have to make one automation for each node, even for those that are dead on startup maybe once a month (yes, I have tried re-adding and healing and refreshing routes). But if this can be done, I will have only one automation and then conditions for all the different nodes. I assume that will (in addition to declutter) tax the system less than having around 50 automations running every minute. So this is the condition for two of my devices:
condition: or
conditions:
- condition: device
device_id: 40a10659aa6dc3adbd1e049d449dba57
domain: zwave_js
type: node_status
status: dead
- condition: device
device_id: 135cb73086262ffece1b65c233765345
domain: zwave_js
type: node_status
status: dead
So what I was hoping to achive was that when one of the conditions are true, that I could use that to get the node number in the action. But is that even possible? I think the “OR” condition means that it skips the later conditions in the block, but if not I need a way to stop after the first true condition.
Is the node number a part of any entity of the device?
I would try and use a template instead of condition.
I have this as a trigger in one of my automations that dynamically finds all entities that comes from one integration and filters it.
I realize the seen variable should probably be renamed, but I was trying to use the entities called last_seen first and then swapped to pending updates.
{% set ns = namespace(trigger = false) %}
{% for seen in integration_entities("open_epaper_link") |select('match','sensor\..*pending_updates')|list -%}
{% if states(seen) | int > 0 -%}
{% set ns.trigger = true %}
{% endif -%}
{%- endfor -%}
{{ ns.trigger }}
I’m not saying this will work for you but perhaps there are some tweaks that can be done?
I don’t have Z2M so I can’t help much more than this.
No, I just want the first conditions in the list to pass, no matter what, so the next time that condition will fail and go to the next in the list, until they are all alive again.
And yes, they have entity IDs, here’s one of them. This is a condition based on the entity ID being unavailable. If I can get the node number out of that in a way, that is just as well. Maybeit can be set as a variable, or something?
condition: state
entity_id: light.lysror_over_kjokkenbenken
state:
- unavailable
Edit: That may actually be to say what condition that passed, when I think about it…
So you want to “round-robin” through the list every second?
Am I understanding right that you have a different node number for each of the device_ids?
If so, probably a better way to do this would be to define all of the device_ids and node numbers that you need in a dictionary. For example:
- variables:
devices:
# This assumes that the node for this device_id is 43
40a10659aa6dc3adbd1e049d449dba57: 43
other_device_id: other_node_number
- repeat:
for_each: "{{ devices.keys() | list }}"
sequence:
- action: mqtt.publish
metadata: {}
data:
evaluate_payload: false
qos: 0
topic: zwave/_CLIENTS/ZWAVE_GATEWAY-zwave-js-ui/api/refreshCCValues/set
payload: "{ \"args\": [{{devices[repeat.item]}}, 112] }"
- delay:
seconds: 1
I would use mode: single and probably trigger it less often. If you have 50 devices, maybe every minute, since each run would take about 50 seconds.
EDIT: But also, and maybe this is what you were referring to at the end of your post, if you get unavailable as the state for the entity when it dies, maybe a more direct way would be to trigger on changes to that state? You can use trigger IDs to figure out which entity is unavailable. Then the automation doesn’t have to constantly round-robin.
Thanks! But the round-robin would be every minute, actually. And the point was to trigger only on the devices that were unavailable. I think your sample would trigger on all devices, no matter if they are available or not.
The problem is that on startup the devices do not change to unavailable, they are already unavailable so they don’t trigger anything. I tried a state trigger, and it didn’t work when that happened. I may have made a mistake, but at least the way I understand it that won’t work, it only triggers when the state changes.
In that case, maybe this approach would work. Your automation triggers on the entity states as well as on homeassistant startup. In the body of the automation, you can have a loop that goes through all the entities, checks their state using an if condition, and then sends the MQTT message if the state is unavailable. That’s a little bit less efficient than ideal since you won’t be looking up your trigger ID directly to figure out which device is dead and instead checking the full set each time, but that’s really not a big deal.
Thank you! That sounds very interesting! Here are three, when I got the way of doing it I wanted to expand it to the whole setup, so no matter what device messes up, it will be fixed:
Thank you very much, @petro! That worked perfectly! Great idea to drop the device ID’s and use it on the complete integration! I’ll set an automation to run it on startup and then every five minutes or so. I couldn’t see any increase in CPU usage when running it, so it can’t be heavy on the system.
Edit: Note to self, and in case anybody reads this and wants to implement it, to run it when Z-Wave JS UI is restarted and Home Assistant is not restarted I added a trigger with an MQTT message that comes on every start of Z-Wave JS UI. Then I added a minute delay before the action. That is at least on my system enough for the mesh to settle down after startup.