Automate ZwaveJS Ping Dead Nodes?

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

Glad that it can help you! It took me some time to make so this increases my return on investment :grinning_face_with_smiling_eyes:

Same here. I have several but the sensor shows 0.

If I run the template in dev tools it does show me all the ping buttons.
Leaving that open, going to zwavejs in another tab, pressing Ping there, I can see the result update. So it would appear the count is not updating?

Update: no, not that since entity_id is empty:

entity_id: []
unit_of_measurement: entities
friendly_name: Dead ZWave Devices

Strange that the template updates itself in dev tools but the sensor doesn’t.

As a test I added a trigger to the sensor for every 5 minutes. This successfully updated the entity_id list but the State value never changed from 0. Nor did the entity_id list change if I manually ping the nodes.
After another 5 minutes though, it did update the entity_id list and then it updated the State value to 4. At that time though I’d already pinged them all so the entity_id was empty.

Odd.

soooo, does anyone know the cause of the devices going dead? i implemented this because every once in a while, specially after some sort of reboot, a large number of my devices go dead. Not all, but a majority. sometimes the ping works, sometimes it doesn’t and i have to walk around the house pressing buttons on the devices for them to come back on. it’s really strange and there is no discernible pattern. Most reboots are just fine, just once in a while everything comes crashing down. I do have a 700 series stick, and have it patched to 7.17.2. Just trying to see if anyone has an idea on what’s going on…

1 Like

I have same problem. Patched to 7.17.2 and currently trying to implement ping script to mitigate as it keeps on occurring - well mainly for more distant z-wave devices (Aeotec ZW).

The problem is Z-wave 700 is hot garbage compared to Z-wave 500. Many will defend it but there’s really no excuse for the hoops we have to jump through just to get Z-wave 700 “working”.

The difficulty with 700 series stability lies in challenge of:

  1. Knowing the difference between the Z-wave JS integration, Z-wave JS addon, and Z-wave JS UI addon.
  2. Capturing logs at the time of failure
  3. Enabling and collecting the necessary logs.
  4. Having someone who actually knows what to look for within the logs determine the cause of the failure.

Step 0 is self explanatory. Spend any time in the #zwave Discord channel and you’ll know exactly why Step 0 exists.

Step 1 is a point of failure because by default, logging is not enabled at the necessary level regardless of the addon being used. In most cases, the initial report of dead nodes dies after someone asks, “What do the logs say?”

Step 2 is another point of failure. Unless you are running Z-waveJS UI from the get go, which many aren’t, by the time you experience step 1, you’ve subsequently been told to “Install JS UI” because logging is better/easier/faster.

Step 3, IMHO, is the single, most challenging point of failure because there are so few people who actually fit that description. Additionally, the people who do fit that description are making an educated guess based on your description. Much of their troubleshooting is reliant upon the strength of your communication abilities.

And if you fail to communicate your problem effectively, chances are you’ll end up being given one or more of the following summations:

  • RF Interference
  • Poor Network Construction
  • Lack of a USB extension cable/USB Hub
  • USB Passthrough is unstable (on everything except VMWare)

If you’re still having trouble, or if you’ve been met with any of the above, do yourself a favor and downgrade. If any of the above summations follow you to the 500 series stick, at least you’ll have eliminated Z-wave 700 as the cause. I’m willing to bet that won’t be the case.

But I digress…

To show that I’m not just a salty Z-wave user, I will contribute something useful to this thread. Here is an automation I created to notify me when a Z-Wave node goes dead. It includes a template that “should” provide the entity_id of the dead node, which should hasten the speed in which you can collect logs for sharing. I haven’t been able to test this automation as I haven’t had a dead node since I downgraded to Z-wave 500.

Please note - This automation assumes that you’ve set up one of the many notification services that exist for Home Assistant. I use Pushover.

alias: Zwave Node is dead!
description: ""
trigger:
  - platform: numeric_state
    entity_id: sensor.dead_zwave_devices
    above: "0"
    for:
      hours: 0
      minutes: 0
      seconds: 1
condition: []
action:
  - service: notify.pushover
    data:
      message: >-
        Zwave Node {{ state_attr('sensor.dead_zwave_devices','entity_id') }}
        just went dead or unavailable.
      title: Dead Zwave Node
mode: single

EDIT 1/23: For the first time since I downgraded back to Z-wave 500, my dead node notify automation kicked off. Here’s an example of what it looks like when a node goes dead.

As you can see, the notify automation now includes the node name. Hopefully this proves helpful to others.

3 Likes

Excellent job with this, worked perfectly. Well done to all involved :+1:t4:

Did you use a palette? i get “Unknown: calculator”

Yes I used this one: node-red-contrib-calc (node) - Node-RED
All that node does is to increase msg.limit by 1 so you can use that using existing nodes as well. I was just being lazy by using the simple calculator node :):slight_smile:

1 Like