Automation: Is it possible to use the condition result in an action

I need an automation that sends an MQTT message when a Z-Wave device is dead after a reboot. Some devices react to ping, but I have found that instead of pinging I can call a refresh of CC 112 (configuration), which will work on every single device. The MQTT action is like this:

action: mqtt.publish
metadata: {}
data:
  evaluate_payload: false
  qos: 0
  topic: zwave/_CLIENTS/ZWAVE_GATEWAY-zwave-js-ui/api/refreshCCValues/set
  payload: "{     \"args\": [43, 112] }"

The 43 in arguments is the node number. Then I have the trigger, which is a simple “every minute” trigger. And finally I have the condition. The reason I would like to use the condition result is that otherwise I’d have to make one automation for each node, even for those that are dead on startup maybe once a month (yes, I have tried re-adding and healing and refreshing routes). But if this can be done, I will have only one automation and then conditions for all the different nodes. I assume that will (in addition to declutter) tax the system less than having around 50 automations running every minute. So this is the condition for two of my devices:

condition: or
conditions:
  - condition: device
    device_id: 40a10659aa6dc3adbd1e049d449dba57
    domain: zwave_js
    type: node_status
    status: dead
  - condition: device
    device_id: 135cb73086262ffece1b65c233765345
    domain: zwave_js
    type: node_status
    status: dead

So what I was hoping to achive was that when one of the conditions are true, that I could use that to get the node number in the action. But is that even possible? I think the “OR” condition means that it skips the later conditions in the block, but if not I need a way to stop after the first true condition.

Is the node number a part of any entity of the device?

I would try and use a template instead of condition.
I have this as a trigger in one of my automations that dynamically finds all entities that comes from one integration and filters it.

I realize the seen variable should probably be renamed, but I was trying to use the entities called last_seen first and then swapped to pending updates.

{% set ns = namespace(trigger = false) %}
{% for seen in  integration_entities("open_epaper_link") |select('match','sensor\..*pending_updates')|list -%}
{% if states(seen) | int > 0 -%}
{% set ns.trigger = true %}
{% endif -%}
{%- endfor -%}

{{ ns.trigger }}

I’m not saying this will work for you but perhaps there are some tweaks that can be done?
I don’t have Z2M so I can’t help much more than this.

Thanks for answering! Honestly, I didn’t really understand much of that, I think it’s a bit over my head. :blush:

You mean you want to know which of the “or” conditions passed? There isn’t a way to do that.

Do you have entity IDs for these devices?

1 Like

No, I just want the first conditions in the list to pass, no matter what, so the next time that condition will fail and go to the next in the list, until they are all alive again.

And yes, they have entity IDs, here’s one of them. This is a condition based on the entity ID being unavailable. If I can get the node number out of that in a way, that is just as well. Maybeit can be set as a variable, or something?

condition: state
entity_id: light.lysror_over_kjokkenbenken
state:
  - unavailable

Edit: That may actually be to say what condition that passed, when I think about it…

So you want to “round-robin” through the list every second?

Am I understanding right that you have a different node number for each of the device_ids?

If so, probably a better way to do this would be to define all of the device_ids and node numbers that you need in a dictionary. For example:

- variables:
    devices:
      # This assumes that the node for this device_id is 43
      40a10659aa6dc3adbd1e049d449dba57: 43
      other_device_id: other_node_number
- repeat:
    for_each: "{{ devices.keys() | list }}"
    sequence:
      - action: mqtt.publish
        metadata: {}
        data:
          evaluate_payload: false
          qos: 0
          topic: zwave/_CLIENTS/ZWAVE_GATEWAY-zwave-js-ui/api/refreshCCValues/set
          payload: "{     \"args\": [{{devices[repeat.item]}}, 112] }"
      - delay: 
          seconds: 1

I would use mode: single and probably trigger it less often. If you have 50 devices, maybe every minute, since each run would take about 50 seconds.

EDIT: But also, and maybe this is what you were referring to at the end of your post, if you get unavailable as the state for the entity when it dies, maybe a more direct way would be to trigger on changes to that state? You can use trigger IDs to figure out which entity is unavailable. Then the automation doesn’t have to constantly round-robin.

Thanks! But the round-robin would be every minute, actually. And the point was to trigger only on the devices that were unavailable. I think your sample would trigger on all devices, no matter if they are available or not.

The problem is that on startup the devices do not change to unavailable, they are already unavailable so they don’t trigger anything. I tried a state trigger, and it didn’t work when that happened. I may have made a mistake, but at least the way I understand it that won’t work, it only triggers when the state changes.

Okay, that clarifies things a little bit.

In that case, maybe this approach would work. Your automation triggers on the entity states as well as on homeassistant startup. In the body of the automation, you can have a loop that goes through all the entities, checks their state using an if condition, and then sends the MQTT message if the state is unavailable. That’s a little bit less efficient than ideal since you won’t be looking up your trigger ID directly to figure out which device is dead and instead checking the full set each time, but that’s really not a big deal.

Can you post the device_ids for the 2 devices? This can be done with a simple template

Thank you! That sounds very interesting! Here are three, when I got the way of doing it I wanted to expand it to the whole setup, so no matter what device messes up, it will be fixed:

40a10659aa6dc3adbd1e049d449dba57
135cb73086262ffece1b65c233765345
dc6d18d59fe9244c4c28f64c4eaf2ee3

You can run this script whenever

sequence:
- variables:
    dead_nodes: >
      {% set devices = integration_entities('zwave_js') | map('device_id') | unique | list %}
      [{% for device in devices %}
        {% set identifier = device_attr(device, 'identifiers') | list | first | last %}
        {% set node = identifier.split('-')[1] %}
        {% set entity = device | device_entities | select('search', 'node_status') | first | default %}
        {% set state = is_state(entity, 'dead') %}
        {% if state %}
          {{ dict(node=node | int, entity=entity, state=states(entity)) }},
        {% endif %}
      {% endfor %}]
- condition: template
  value_template: "{{ dead_nodes | count > 0 }}"
- repeat:
    for_each: "{{ dead_nodes }}"
    sequence:
      - action: mqtt.publish
        metadata: {}
        data:
          evaluate_payload: false
          qos: 0
          topic: zwave/_CLIENTS/ZWAVE_GATEWAY-zwave-js-ui/api/refreshCCValues/set
          payload: "{     \"args\": [{{ repeat.item.node }}, 112] }"
      - delay: 
          seconds: 1

Just understand that this may not work for all entities because they aren’t guarenteed to have CC 112.

You can change the first line in the template to just use the device_ids you listed.

2 Likes

Thank you very much, @petro! That worked perfectly! Great idea to drop the device ID’s and use it on the complete integration! :grin: I’ll set an automation to run it on startup and then every five minutes or so. I couldn’t see any increase in CPU usage when running it, so it can’t be heavy on the system.

Edit: Note to self, and in case anybody reads this and wants to implement it, to run it when Z-Wave JS UI is restarted and Home Assistant is not restarted I added a trigger with an MQTT message that comes on every start of Z-Wave JS UI. Then I added a minute delay before the action. That is at least on my system enough for the mesh to settle down after startup.

trigger: mqtt
topic: zwave/_CLIENTS/ZWAVE_GATEWAY-zwave-js-ui/version