Automate ZwaveJS Ping Dead Nodes?

i think it is working now, after change my sensor to:

image

let me test it

regards

I implemented this today, but it did not work until I changed the sensor’s state value to include a “default”. Until I did that, the sensor was always “unavailable”. Thanks to Rob C. for the fix!

- sensor:
  - name: "Dead ZWave Devices"
    unique_id: dead_zwave_devices
    state: >-
      {{ states | selectattr("entity_id", "search", "node_status") |
         selectattr('state', 'in', 'dead, unavailable, unknown') |
         map(attribute='entity_id') | default('Nothing', True) | list }}
1 Like

PSA:

The zwave_js.ping service is now deprecated in favor of a new ping button entity. You can replace any zwave_js.ping service calls in your automation with a button.press call against the new entity with no change in functionality.

The zwave_js.ping service will be removed in a future release of Home Assistant.

So I attempted to do your suggestion and unfortunately just changing the service doesn’t seem to work. When I change them I get notified about the dead mode but now the ping does not occur. I think it is because you have to call the button entity now but I am not 100% sure. The previous solution still works. Did you get this to work correctly in your scripts?

Hey. Who are you directing that to? I haven’t updated mine to use the new button yet and am still using the service approach.

You as you said we can now use the button call.

Gotcha. Sorry, I just wanted to mention that since when I read it in the release notes I knew it would impact this workaround automation (that I rely on).
I’ll try it this evening myself.

I don’t quite follow exactly what you tested though. You did or didn’t change it to the button press? The 3rd sentence seems to indicate you haven’t yet but the first sentence indicates you did. I may be misreading it.

Yeah I gave it a try by just changing zwave_js.press to the button command as described in the link you suggested. Did not work. Nodes stayed dead.

fwiw, in stead of iterating all states, do

{{ expand(integration_entities('Z-Wave JS') )| selectattr("entity_id", "search", "node_status") |
    selectattr('state', 'in', 'dead, unavailable, unknown') |
         map(attribute='entity_id')| list }}

to preselect the entities.

secondly, How could Pinging a list (which is what the automation does) work at all? Shouldn’t it ping the individual device(s)? Or rephrased, build a list of buttons to ping?
needing something like:

{% set list = 
expand(integration_entities('Z-Wave JS') )| selectattr('entity_id', 'search', 'node_status') |
    selectattr('state', 'in', ['dead', 'unavailable', 'unknown']) |
         map(attribute='entity_id')| list %}

{% set ns = namespace(buttons=[]) %}
{% for d in list %}
{% set ns.buttons = ns.buttons + 
  ['button.' ~ (states[d].object_id.split('_node')[0]) ~ '_ping'] %}
    
{% endfor %}
{{ns.buttons}}

as target in the automation service?

Thanks for the preselect improvement. That works fine.

Pinging the list of node_status entities works just fine. It appears that whoever created the integration made the service quite flexible. My request is that the ping service be left exactly as it is, and not be removed, as it is extremely useful. Removing it in favor of the button is a step backward, in my opinion.

Why remove functionality? Especially functionality that people are using, and that simplifies the automation.

1 Like

Another issue: the sensor.state string variable is limited to 255 characters, so this sensor is pretty much useless unless it’s limited to returning only a few dead nodes at a time.

This is now working for me:

- sensor:
  - name: "Dead ZWave Devices"
    unique_id: dead_zwave_devices
    state: >- 
      {% set deadlist = 
        expand(integration_entities('Z-Wave JS') ) | selectattr("entity_id", "search", "node_status") |
        selectattr('state', 'in', 'dead, unavailable, unknown') |
        map(attribute='entity_id') 
      %}
      {{ "[" }}
      {% for entity_id in deadlist %}
        {% if loop.index0 < 4 %}
          {{ '"' + entity_id + '",' }}
        {% endif %}
      {% endfor %}
      {{ "]" }}

I’d rather stuff the full list into a state attribute, but try as I might, I cannot find any way to do that.

1 Like

well, just jot that complete template (the full list)) in an attribute eg, entity_id, and replace this state: with let’s say a counter

   {{expand(integration_entities('Z-Wave JS') ) | selectattr("entity_id", "search", "node_status") |
        selectattr('state', 'in', 'dead, unavailable, unknown') |
        map(attribute='entity_id')|list|length }}

though, if your list of dead nodes is so long, you have other troubles to worry about :wink:

Yes - the service was well thought out:

“Entity (or list of entities) to ping. At least one entity_id, device_id, or area_id must be provided.”

I got to looking at the button.press that is a “like for like replacement” but am not sold on that yet.
Are we going to need to create a button group that is a list of all the ‘ping’ buttons of all the dead nodes and then call that button group in the button.press service?

I think I see what you are asking. I only have two zwave devices at the moment so I have just put them both in the action. I am waiting for one of the devices to die to see if this works. Then I could try grouping them?

      failed_zwave:
        value_template: >
          {% set ns = namespace(break = false) %}
          {% for state in states -%}
            {%- if (state.name | regex_search('Node Status'))%}
              {%- if (is_state(state.entity_id, 'dead') and ns.break == false) %}
                {%- set ns.break = true %}
                true       
              {%- endif -%}
            {%- endif -%}
          {%- endfor %}
- id: alert_on_failed_zwave_nodes
  alias: Alert on failed Zwave Nodes
  trigger:
  - platform: state
    entity_id: sensor.failed_zwave
    to: 'true'
  condition:
  action:
  - service: notify.gav_bullet
    data:
      message: Pinging dead node '{{ trigger.entity_id }}'
  - service: button.press
    target:
      entity_id: button.nano_dimmer_ping
  - service: button.press
    target:
      entity_id: button.dual_nano_switch_with_energy_metering_ping
  mode: queued

Yes, along those lines. Can we dynamically make a group of entities? That we would then iterate through. Seems messy though.

mine reports and try to ping both zwave sticks… I’m not able to disable these node statuses…

  - sensor.z_stick_gen5_usb_controller_node_status
  - sensor.z_stick_gen5_usb_controller_node_status_2

Node status is Unavailable…

that’s because they are no longer available. the Zwave controllers are supposed to be available always…you should delete those sensor entities

Thank you for sharing this. I had to modify your code just a bit to be able to create the automation. Now waiting for a node to go dead to see if it works.

Has anyone came up with a way to send a list of dead nodes in a notification or to a log file?

Thanks again

description: Ping
trigger:
  - platform: state
    entity_id: sensor.failed_zwave
condition:
  - condition: template
    value_template: '{{ states.sensor.failed_zwave.state != "[]" }}'
action:
  - service: zwave_js.ping
    data: {}
    target:
      entity_id: '{{ states.sensor.failed_zwave.state }}'
  - service: notify.mobile_app_bill_pixel_3
    data:
      message: Ping dead nodes
mode: single

Sure, just modify your last line to include the string.

  message: 'Pinging dead nodes: {{ states.sensor.failed_zwave.state }}'

This is very cool. In addition to the node being reported as dead, it can be helpful to also detects nodes that have not sent expected data. For example, if the sensor is sending temperature data every 10 minutes and 30 minutes have gone by without receiving data something is wrong. I’ve seen this happen and the node is still alive. Hence I use a combination of the node status and a latency calculation to determine if the node is working. There are zwavejs events that report each update even if is the same value,