Automate ZwaveJS Ping Dead Nodes?

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 ?

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)

1 Like

Here -

Zwave-js NVM backup/restore zwave 500->700 - Configuration / Z-Wave - Home Assistant Community (home-assistant.io)

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.

2 Likes

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.

1 Like

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
1 Like

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 }}
3 Likes

@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

1 Like

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 }}
1 Like

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.

2 Likes

So, I followed the process here as far as directory structure goes:

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
4 Likes

@Karson Not sure why, but with this code, the sensor shows 0 dead devices even though I have 2.

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 :slight_smile:

5 Likes

I also encountered this invalid slug zwave-ping problem, which I initially thought was related to a power outage bad SD card.

thanks to all for developing this code :grinning:

You sir made my day! Thanks :slight_smile:

1 Like