The ping of dead nodes still “works” to bring my dead nodes back. With about 30 Z-wave devices I see at least one go down every day in my logs. I changed the automation to fire every 15 seconds if a node was unavailable (rather than when the node transitions to unavailable) and don’t have problems with my network or CPU being overly busy that I’m aware of.
Dear anonymous 700 series victim. Justs wanted to introduce myself with this post:
I originally bought a HUSBZB-1 because i tried to standardize on z-wave, but i also have some recessed ceiling lights i could only get as zigbee. Seemed to work fine, but when i researched, it seemed as if i could not backup/restore the zwave config on the stick. So i replaced it with a zst10-700 and some separate zigbee stick. And since then i think i have more radio problems with z-wave, exactly with dead nodes i can ping to revive them.
I was speculating that it might be radio interference between the zigbee and zwave stick. Both already are on USB extension cables with ferrite rings (connected to RPI4 running HAOS).
I then did download the SIlabs firmware upgrade onto windows (i hate using windows for this). Just 12 ? GByte of software to install the latest zst10-700 firmware. How easy! Such a nice move from SiLabs to force simple end-users to install a whole bloody development system for ALL their products.
Ok, not sure how much it helped. I still have dead nodes. I am almost about to go back to the HUSBZB-1, screw the ability to do backups - but re-enrolling 28 devices is really no fun.
Does this only work on a ZST10-500 when wanting to downgrade from a ZST10-700, or would this work with another 500 series stick, such as the HUSBZB-1 ? Aka: how does it work given how the zwave device registrations/key and the like are stored inside the zwave stick. Any URL explaining how this downgrade work, and to what zwave 500 sticks you can downgrade ?
…
I put all of z-wave ping handling into a “package” file, that I load from my configuration.yaml.
…
Dear Bretton,
I followed your instructions to put this config into my HAOSS installation 2022.9.4, but i can not figure out how to troubleshoot it. When i reboot my system (e.g.: power cycle), it does go on the screen up to the normal “Welcome to the Home Assistant… ha >” output - but then it never starts up , e.g.: i can never connect to the web interface on port 8123. I mounted the memory card from my RPI4 installation on another linux system to comment out zwave-ping.yaml, and then it boots again.
Alas, i have no clue how to troubleshoot this. Any good pointers for beginners would be helpful.
One thing i can think of is that i have a few non-powered zwave devices in my system, aka: that are dead to home assistant. Is it possible that the automation hangs on them, and because the automation hangs home assistant does not even finish booting ?
There’s nothing about the automations themselves that should cause HA to fail to load.
My first suspicion would be a syntax error in your changes, as YAML (like Python) is notoriously bad at dealing with indentation errors, and the whitespace aspect of this syntax makes these errors very hard to spot. (/endrant)
Here -
Yes thgose things are stored in the stick - rather UNLOCKED by your keys that ZWJS2mq… er. - ZwaveJS UI has in its config.
ALL 500 and ALL 700 sticks. Thats one of the benefits to all sticks using the same (required) Silicon Labs Zwave chips.
The NVM backup and restore only supports conversion to 500-series that are running Z-Wave SDK 6.61 or later. This excludes the stock Nortek HUSBZB-1 and Aeotec Gen 5 versions earlier than v1.2. Both of those are upgradable to newer supported SDKs.
There’s nothing about the automations themselves that should cause HA to fail to load.
My first suspicion would be a syntax error in your changes, as YAML (like Python) is notoriously bad at dealing with indentation errors, and the whitespace aspect of this syntax makes these errors very hard to spot. (/endrant)
The problem of course isn’t helped by me not speaking yaml. Any way for you to upload the yaml so it can be downloaded without copy&paste ?
Btw: not a good sign for HA to not even come up in the face of a wrong yaml though… This is what i am becoming worried about the most: fragility of HA. And not knowing how to troubleshoot it then ;-(
The syntax/indentation of the zwave-ping.yaml is correct - both the home assistant gui and the recommended YAML validator say so. But home assistant YAML check configuration says:
invalid slug zwave-ping (try zwave_ping) for dictionary value @ data[‘packages’]
argh found a web page that explained that file names can not have a ‘-’ in the name, so i changed the file name to zwaveping.yaml
Now i can see it running. No dead nodes yet. let’s see.
Ok. Managed to get the script to do its job. Some additional hazzle i had to fix:
The devices i needed to ping did not have the node_status entities. Those must be enabled in the device configuration.
Then the name of the node_status entities and the ping_entities didn’t match up. No idea why, sometimes either entity was not created with the friendly name, but with the zwave node number. In one case, i could not even set the entity name as i wanted, because HA complained the entity name was taken, but i could not find that entity name in the list of entities. All weird stuff. But finally i think i got the three devices with problems to be able to be pingable by the script. Those are all in-wall power switches, so i suspect zwave-700 is really weak for those well-metal-shielded zwave-devices. And i guess i may need to manually go check that all the naming is correct and the node_status entity enabled for any of the other devices, but i’ll do that whenever such a device fails.
I have also created a WTH posting to ask for this automation to be included into HA. If you have this problem, maybe upvote that post.
https://community.home-assistant.io/t/wth-automate-zwavejs-ping-dead-nodes/470031
How did you fix it from pinging the entity ID VS Friendly name? I am having the same issue, where it trying to ping the entity ID, I tested an automation with pining the friendly name and it works.
Having an issue similar to the last couple posts in my logs and the ping automation doesn’t work:
Logger: homeassistant.helpers.service
Source: helpers/service.py:637
First occurred: November 18, 2022 at 7:02:44 PM (2 occurrences)
Last logged: November 19, 2022 at 10:12:00 PM
Unable to find referenced entities button.amys_lamp_ping, button.back_garage_door_deadbolt_ping, button.back_gate_sensor_ping, button.back_patio_deadbolt_ping, button.chandelier_ping, button.family_room_lamp_ping, button.front_door_deadbolt_ping, button.front_entry_sconces_ping, button.front_landscaping_lights_ping, button.front_porch_lower_sconces_ping, button.front_porch_upper_sconces_ping, button.garage_deadbolt_ping, button.gym_motion_sensor_ping, button.karsons_lamp_ping, button.kitchen_sink_water_sensor_ping, button.main_garage_back_door_light_ping, button.main_kiosk_outlet_ping, button.master_bedroom_can_lights_ping, button.master_bedroom_fan_ping, button.master_bedroom_heater_switch_ping, button.master_bedroom_multisensor_ping, button.master_bedroom_nanomote_ping, button.north_family_room_sconces_ping, button.outside_garage_sconces_ping, button.range_extender_ping, button.shop_deadbolt_ping, button.sump_pit_water_sensor_ping, button.west_family_room_sconces_ping or it is/they are currently not available
Unable to find referenced entities button.karsons_lamp_ping or it is/they are currently not available
The node status & ping entities are all enabled for all 29 devices, with a friendly name configured for both entities. Not sure what the fix is, but I have never gotten this automation to work for six months due to this error.
template:
- sensor:
- name: "Dead ZWave Devices"
unique_id: dead_zwave_devices
unit_of_measurement: entities
state: >
{% if state_attr('sensor.dead_zwave_devices','entity_id') != none %}
{{ state_attr('sensor.dead_zwave_devices','entity_id') | count }}
{% else %}
{{ 0 }}
{% endif %}
attributes:
entity_id: >
{{
expand(integration_entities('Z-Wave JS') )
| selectattr("entity_id", "search", "node_status")
| selectattr('state', 'in', 'dead, unavailable, unknown')
| map(attribute="object_id")
| map('regex_replace', find='(.*)_node_status', replace='button.\\1_ping', ignorecase=False)
| list
}}
automation:
- id: ping_dead_zwave_devices
alias: Ping Dead ZWave Devices
description: ''
trigger:
- platform: state
entity_id:
- sensor.dead_zwave_devices
condition:
- condition: template
value_template: >
{{ int(states.sensor.dead_zwave_devices.state) > 0 }}
action:
- service: button.press
target:
entity_id: >
{{ state_attr('sensor.dead_zwave_devices','entity_id') }}
mode: single
I believe the issue here is the assumption that ping buttons have same name as node_status entities. However, if you enable the ping button entity after you had renamed the device, it will not be renamed and that is where it fails.
I go back to the device from the node_status entity, then get all its entities and look for the button…ping.
Like so:
{% set dead_nodes = integration_entities('zwave_js') | select('match', 'sensor\..*node_status')| select('is_state', 'dead') | list -%}
{% set ns = namespace(buttons=[]) -%}
{% for e in dead_nodes -%}
{% set device_id = device_id(e) -%}
{% set button = device_entities(device_id) | select('match','button\..*_ping') | first -%}
{% set ns.buttons = ns.buttons + [button] -%}
{% endfor -%}
{{ ns.buttons }}
@dadoj - could you post the YAML showing your code integrated in the sensor/automation I posted above? I spot checked 1 of my 30 devices, and you’re right. light.amys_lamp does not match button.amy_lamp_ping
attributes: entity_id: > {{ expand(integration_entities('Z-Wave JS') ) | selectattr("entity_id", "search", "node_status") | selectattr('state', 'in', 'dead, unavailable, unknown') | map(attribute="object_id") | map('regex_replace', find='(.*)_node_status', replace='button.\\1_ping', ignorecase=False) | list }}
I have a different logic when to ping my devices, so I use it differently (my devices do actually become “dead” from the system perspective, as they lose power during high tariff, so I ping them right after the tariff changes back). I have no need for the template sensor, as my trigger point is unrelated.
Regardless, I believe my code can be used basically as is in the template sensor entity_id attribute section, replacing the original:
attributes:
entity_id: >-
{% set dead_nodes = integration_entities('zwave_js') | select('match', 'sensor\..*node_status')| select('is_state', 'dead') | list -%}
{% set ns = namespace(buttons=[]) -%}
{% for e in dead_nodes -%}
{% set device_id = device_id(e) -%}
{% set button = device_entities(device_id) | select('match','button\..*_ping') | first -%}
{% set ns.buttons = ns.buttons + [button] -%}
{% endfor -%}
{{ ns.buttons }}
Brilliant - had a dead node I tested this on today and it’s the first time it worked all year. I’ll post my sensor template and automation YAML shortly for others to use in case it’s helpful.
So, I followed the process here as far as directory structure goes:
I agree it can be confusing when people only post part of their configuration, especially since yaml is such a non-descriptive format. I’ll try to elucidate. I put all of z-wave ping handling into a “package” file, that I load from my configuration.yaml. In the configuration.yaml, near the top: group: !include groups.yaml automation: !include automations.yaml script: !include scripts.yaml scene: !include scenes.yaml # added to the default includes to pull in packages homeassistant: package…
In the packages directory that is referenced inside configuration.yaml, I have a ping_zwave.yaml file with the following below. This ping_zwave.yaml is just your sensor to detect what nodes are dead. You could include unavailable, unknown in line 14, but I don’t run into those states ever, and pinging those nodes with those states will not resolve the problem anyway.
ping_zwave.yaml
template:
- sensor:
- name: "Dead ZWave Devices"
unique_id: dead_zwave_devices
unit_of_measurement: entities
state: >
{% if state_attr('sensor.dead_zwave_devices','entity_id') != none %}
{{ state_attr('sensor.dead_zwave_devices','entity_id') | count }}
{% else %}
{{ 0 }}
{% endif %}
attributes:
entity_id: >-
{% set dead_nodes = integration_entities('zwave_js') | select('match', 'sensor\..*node_status')| select('is_state', 'dead') | list -%}
{% set ns = namespace(buttons=[]) -%}
{% for e in dead_nodes -%}
{% set device_id = device_id(e) -%}
{% set button = device_entities(device_id) | select('match','button\..*_ping') | first -%}
{% set ns.buttons = ns.buttons + [button] -%}
{% endfor -%}
{{ ns.buttons }}
In the Automation GUI, I setup an automation like this:
If you’re into the YAML, here’s the backend of that GUI automation:
- id: '1669759724675'
alias: Ping Dead ZWave Devices
description: ''
trigger:
- platform: state
entity_id:
- sensor.dead_zwave_devices
condition:
- condition: template
value_template: '{{ int(states.sensor.dead_zwave_devices.state) > 0 }}'
action:
- service: button.press
target:
entity_id: '{{ state_attr(''sensor.dead_zwave_devices'',''entity_id'') }}'
mode: single
{% set dead_nodes = integration_entities('zwave_js') | select('match', 'sensor\..*node_status')| select('is_state', 'dead') | list -%}
Is the device marked as dead in ZJS-UI, or listed as something else? Line 14 I limited down to just dead, so if it’s showing as anything else it won’t be filtered on.
I thought I’d share my Node Red flow to Ping dead or unavailable z-wave nodes:
[{"id":"415cebd80b1d1d0d","type":"server-state-changed","z":"92da3f90.2062d","name":"Zwave device dead|unavailable|unknown >1 minute?","server":"5c29d263.09d2ac","version":4,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"_node_status","entityidfiltertype":"substring","outputinitially":false,"state_type":"str","haltifstate":"dead|unavailable|unknown","halt_if_type":"re","halt_if_compare":"is","outputs":2,"output_only_on_state_change":true,"for":"1","forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"eventData"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"}],"x":1290,"y":100,"wires":[["f9fd6509d9b89269"],[]]},{"id":"58abebe4e616a04c","type":"template","z":"92da3f90.2062d","name":"Render Template","field":"template","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"{{=<% %>=}}\n{{ device_entities(\"<% payload %>\") }}","output":"str","x":1970,"y":100,"wires":[["354ed32f1d7bbafc"]]},{"id":"354ed32f1d7bbafc","type":"api-render-template","z":"92da3f90.2062d","name":"Get all entities","server":"5c29d263.09d2ac","version":0,"template":"","resultsLocation":"payload","resultsLocationType":"msg","templateLocation":"template","templateLocationType":"msg","x":2160,"y":100,"wires":[["28cf4bbbc0322eb7"]]},{"id":"655be19debc68002","type":"api-render-template","z":"92da3f90.2062d","name":"Get Device ID","server":"86158645.d19e98","version":0,"template":"","resultsLocation":"payload","resultsLocationType":"msg","templateLocation":"template","templateLocationType":"msg","x":1780,"y":100,"wires":[["58abebe4e616a04c"]]},{"id":"28cf4bbbc0322eb7","type":"function","z":"92da3f90.2062d","name":"Find ping entity","func":"var str = msg.payload; // assuming the original string is in the \"payload\" property of the message object\nvar parts = str.split(\"'\");\n\nfor (var i = 0; i < parts.length; i++) {\nif (parts[i].includes(\"_ping\")) {\n return { ping: parts[i], original: msg}; // returning the result as a string in the \"payload\" property of the message object\n}\n}\n\n// If no element is found containing the substring _ping, return an empty string\nreturn { ping: \"\", original: msg};","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":2340,"y":100,"wires":[["a2e2687ac643954b"]]},{"id":"a2e2687ac643954b","type":"api-call-service","z":"92da3f90.2062d","name":"Ping z-wave device","server":"5c29d263.09d2ac","version":5,"debugenabled":false,"domain":"button","service":"press","areaId":[],"deviceId":[],"entityId":["{{ping}}"],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[{"property":"data","propertyType":"msg","value":"data","valueType":"msg"}],"queue":"none","x":2530,"y":100,"wires":[["45065c7f31993dd7"]]},{"id":"f9fd6509d9b89269","type":"template","z":"92da3f90.2062d","name":"Render template","field":"template","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"{{=<% %>=}}\n{{ device_id(\"<% data.entity_id %>\") }}","output":"str","x":1590,"y":100,"wires":[["655be19debc68002"]]},{"id":"0e263a6ef3cf35e3","type":"ha-wait-until","z":"92da3f90.2062d","name":"wait untill available","server":"5c29d263.09d2ac","version":2,"outputs":2,"entityId":"{{original.data.entity_id}}","entityIdFilterType":"exact","property":"state","comparator":"is_not","value":"dead|unavailable|unknown","valueType":"re","timeout":"60","timeoutType":"num","timeoutUnits":"seconds","checkCurrentState":true,"blockInputOverrides":true,"outputProperties":[],"x":1370,"y":220,"wires":[[],["e01bc2ee131d8510"]]},{"id":"e01bc2ee131d8510","type":"calculator","z":"92da3f90.2062d","name":"limit+1","inputMsgField":"limit","outputMsgField":"limit","operation":"sum","constant":"1","round":false,"decimals":0,"x":1530,"y":180,"wires":[["9ad4b90e09a36a0d"]]},{"id":"9e75f5158d501394","type":"switch","z":"92da3f90.2062d","name":"limit<=200?","property":"limit","propertyType":"msg","rules":[{"t":"lte","v":"200","vt":"num"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":1830,"y":180,"wires":[["0e263a6ef3cf35e3"],["b8d5d79e4fa25ba6"]]},{"id":"45065c7f31993dd7","type":"change","z":"92da3f90.2062d","name":"limit=0","rules":[{"t":"set","p":"limit","pt":"msg","to":"0","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":1210,"y":180,"wires":[["0e263a6ef3cf35e3"]]},{"id":"a75ab77c82fb9f37","type":"change","z":"92da3f90.2062d","name":"Define parameters","rules":[{"t":"set","p":"who","pt":"msg","to":"jane","tot":"str"},{"t":"set","p":"NotifyType","pt":"msg","to":"normal","tot":"str"},{"t":"set","p":"title","pt":"msg","to":"payload&\" unavailable\"","tot":"jsonata"},{"t":"set","p":"message","pt":"msg","to":"payload&\" z-wave module is unavailable. Many Pings didn't solve the problem\"","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":2450,"y":180,"wires":[["371b4f1197629d30"]]},{"id":"9ad4b90e09a36a0d","type":"api-call-service","z":"92da3f90.2062d","name":"Ping device","server":"5c29d263.09d2ac","version":5,"debugenabled":false,"domain":"button","service":"press","areaId":[],"deviceId":[],"entityId":["{{ping}}"],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":1670,"y":180,"wires":[["9e75f5158d501394"]]},{"id":"b8d5d79e4fa25ba6","type":"api-current-state","z":"92da3f90.2062d","name":"get friendly name","server":"5c29d263.09d2ac","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"{{original.topic}}","state_type":"str","blockInputOverrides":true,"outputProperties":[{"property":"data2","propertyType":"msg","value":"","valueType":"entity"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"}],"for":0,"forType":"num","forUnits":"minutes","x":2030,"y":180,"wires":[["2bf1e2f979441455"]]},{"id":"2bf1e2f979441455","type":"change","z":"92da3f90.2062d","name":"Define friendlyname","rules":[{"t":"set","p":"payload","pt":"msg","to":"data2.attributes.friendly_name","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":2240,"y":180,"wires":[["a75ab77c82fb9f37"]]},{"id":"454cac184e19551e","type":"comment","z":"92da3f90.2062d","name":"Revive z-wave module","info":"","x":1200,"y":60,"wires":[]},{"id":"5c29d263.09d2ac","type":"server","name":"Home Assistant","version":5,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":false,"cacheJson":true,"heartbeat":false,"heartbeatInterval":30,"areaSelector":"friendlyName","deviceSelector":"friendlyName","entitySelector":"friendlyName","statusSeparator":"at: ","statusYear":"hidden","statusMonth":"short","statusDay":"numeric","statusHourCycle":"h23","statusTimeFormat":"h:m","enableGlobalContextStore":true},{"id":"86158645.d19e98","type":"server","name":"Home Assistant","version":5,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true,"heartbeat":false,"heartbeatInterval":"30","areaSelector":"friendlyName","deviceSelector":"friendlyName","entitySelector":"friendlyName","statusSeparator":"at: ","statusYear":"hidden","statusMonth":"short","statusDay":"numeric","statusHourCycle":"h23","statusTimeFormat":"h:m","enableGlobalContextStore":true}]
It triggers whenever a node_status entities gets a problematic state. In that case it will fetch the parent device, for that parent device then get the list of entity_id’s, search amongst those for the ping entity, then call the ping entity. If that doesn’t help it will try many more times. If that still doesn’t solve it, you can at the end add your code to notify yourself.
ChatGPT helped me with generating the function node