How to recognize when devices are offline?

Hi all, I have 2 Aeotec Switches that I’d like to be alerted if the power to them goes out (they’re connected to GFCI outlets), but when power is cut to them Home Assistant/Zwave JS just keeps reporting that they’re “On” and are never recognized as going offline. How do I monitor them so their status is properly reflected?

There is a node status sensor that you can use to notify you if a node is dead.

the sensor is disabled by default so you will need to go to the device in the zwavejs integration and enable the sensor.

then if the node is dead the sensor state will show as “dead”.

1 Like

I do a combination of things. Most importantly I verify that the device is up and responding. Here are my templates / automations.

Every 10 minutes and at HA startup it polls the switch state. When a response to the poll occurs, regardless of whether it’s state changes a zwave_js.value_updated event fires. This guarantees that the switch is alive and responding. That event triggers an update to the last_updated template sensor that captures the current time. Then there is a latency sensor that determine how long ago in seconds that update happened. Then a binary sensor that trigger if latency exceeds 2x the poll time ( polls are dropped infrequently) or if node status indicated a problem. Finally I have an input boolean to control whether an alert should be generated and a txt sent to my phone. In replicate this for all my switches by doing string substitution (sed scripts).


# switch_2
# switch.switch_2_switch to monitor
# 1200

input_boolean:
  zwave_switch_2_alarm_enable:

template:
  - trigger:
      - platform: homeassistant
        event: start
      - platform: zwave_js.value_updated
        entity_id:
          - switch.switch_2_switch
        command_class: 37
        property: currentValue
    sensor:
      - name: "switch_2_last_updated"
        state: "{{ now() }} "

sensor:
  - platform: template
    sensors:
      zwave_switch_2_latency:
        unit_of_measurement: secs
        value_template: >-
          {%- if as_timestamp(states("sensor.switch_2_last_updated"),0) == 0 %}
          0
          {%- else %}
          {{ ((as_timestamp(now(), 0) | int(0)) - as_timestamp(states('sensor.switch_2_last_updated'),0) | int(0)) }}
          {%- endif %}
binary_sensor:
  - platform: template
    sensors:
      zwave_switch_2_online:
        value_template: >-
          {{ ( 1200 - (states('sensor.zwave_switch_2_latency') | int(0))) > 0  and
               states('sensor.switch_2_node_status') != 'dead' and
               states('sensor.switch_2_node_status') != 'unavailable' and
               states('sensor.switch_2_node_status') != 'unknown'
          }}
      zwave_switch_2_alert:
        value_template: '{{ is_state("binary_sensor.zwave_switch_2_online", "on") and is_state("input_boolean.zwave_switch_2_alarm_enable", "on") }}'

alert:
  zwave_switch_2:
    name: zwave switch_2 alert
    message: '{{ state_attr("zone.home","friendly_name") }} zwave switch_2 offline - Latency: {{ states("sensor.zwave_switch_2_latency") }} Node {{ states("sensor.zwave_switch_2_node_status") }}'
    done_message: '{{ state_attr("zone.home","friendly_name") }} zwave switch_2 online'
    entity_id: binary_sensor.zwave_switch_2_alert
    state: "on"
    repeat: 240
    can_acknowledge: true
    skip_first: false
    notifiers:
      - sms_notifiers_all

recorder:
  include:
    entities:
      - binary_sensor.zwave_switch_2_online
      - binary_sensor.zwave_switch_2_alert
      - sensor.switch_2_node_status
      - input_boolean.zwave_switch_2_alarm_enable
      - alert.zwave_switch_2
      - sensor.zwave_switch_2_latency

- id: "switch_2 poll switch state"
  alias: switch_2 poll switch state
  description: "Automation to periodically poll switches"
  trigger:
    - platform: time_pattern
      minutes: "/10"
    - platform: homeassistant
      event: start
  action:
    - delay:
        seconds: "{{ range(0, 60)|random|int }}"
    - service: zwave_js.refresh_value
      data:
        entity_id: switch.switch_2_switch

1 Like

Wow! that’s pretty involved.

It seems like overkill to me since I rarely have issues with my zwave stuff but if it works for you… :+1:

Thanks, it looks like that sensor is already enabled for me and unfortunately it didn’t detect that the node had no power and would be dead.

Thanks, I’ll have to try something like this, maybe something not as complex.

Sounds good. Nice part is that logic is debugged and working. Hard part is figuring out the command class to listen to. Every time I add a zwave device, I add it to this script which then autogenerates the packages.


TARGET="/mnt/c/github/ha"

zwave_js_health_template()
# ZWAVE Entity
# ENTITY_ID to monitor 
# TIMEOUT
# COMMAND_CLASS
# PROPERTY_NAME
# Output file
{
   sed "s/multisensor_1/$1/g" zwave_js_health_template_multisensor_1_package.yaml | 
   sed "s/ENTITY_ID/$2/g" | sed "s/TIMEOUT/$3/g" | sed "s/COMMAND_CLASS/$4/g" | sed "s/PROPERTY_NAME/$5/g" > $TARGET/packages/$6
}

zwave_js_health_template multisensor_1 sensor.multisensor_1_temperature 480 49 "Air temperature" zwave_js_health_template_multisensor_1_package.yaml
zwave_js_health_template basement_sensor sensor.basement_temperature 480 49 "Air temperature" zwave_js_health_template_basement_sensor_package.yaml
zwave_js_health_template switch_1 switch.switch_1_switch 1200 37 currentValue zwave_js_health_template_switch_1_package.yaml
zwave_js_health_template switch_2 switch.switch_2_switch 1200 37 currentValue zwave_js_health_template_switch_2_package.yaml
zwave_js_health_template switch_3 switch.switch_3_switch 1200 37 currentValue zwave_js_health_template_switch_3_package.yaml
zwave_js_health_template oldwell switch.oldwell 1200 37 currentValue zwave_js_health_template_switch_oldwell_package.yaml
zwave_js_health_template newwell switch.newwell 1200 37 currentValue zwave_js_health_template_switch_newwell_package.yaml
zwave_js_health_template hvac_uv switch.hvac_uv 1200 37 currentValue zwave_js_health_template_switch_hvac_uv_package.yaml
zwave_js_health_template outdoor_switch switch.outdoor_switch 1200 37 currentValue zwave_js_health_template_outdoor_switch_package.yaml
zwave_js_health_template water_softener_switch switch.water_softener 1200 37 currentValue zwave_js_health_template_water_softener_switch_package.yaml
zwave_js_health_template bedroom_thermostat climate.bedroom_thermostat 1200 49 "Air temperature" zwave_js_health_template_bedroom_thermostat_package.yaml
zwave_js_health_template studio_thermostat climate.studio_thermostat 1200 49 "Air temperature" zwave_js_health_template_studio_thermostat_package.yaml
zwave_js_health_template bsmnt_bath sensor.bsmnt_bath_temperature 600 49 "Air temperature" zwave_js_health_template_bsmnt_bath_package.yaml
zwave_js_health_template garage_sensor sensor.garage_temperature 600 49 "Air temperature" zwave_js_health_template_garage_sensor_package.yaml

Happy to post the actual template files, if you want them.

The nodes don’t get marked as “dead” until they fail to respond to a command.

1 Like

Yes please if you don’t mind.

Makes sense, if I poll select devices every few minutes I imagine that would flip it to dead?

You can issue the zwave_js.ping service to ping a node, if it fails to respond it’ll be flagged dead.

1 Like