Automation trigger based on state change of dynamic entity list

Here is a way to trigger an automation based on state change of any entity in a dynamically generated list - without extra helper entities. My original motivation was to create a notification whenever any door, window, or lock is opened. I don't want to list them manually in the automation because I'm slowly but steadily adding new devices and I don't want to constantly update multiple places with every new device.
I have group entities aggregating each device class, but the group doesn't change state when e.g. the third window is opened - so a state trigger doesn't work. A Template Trigger can do the job of watching each individual entity by expanding the groups, but it's not obvious how to get a False->True edge on every state change. The trick I found is to extract the last_changed attribute and compare to the automation last_triggered time:

- alias: Dynamic Entity Test
  triggers:
  - trigger: template
    value_template: >
      {% set doors_windows = (
         expand("binary_sensor.all_doors")
         + expand("binary_sensor.all_windows")
         ) | list %}
      {% set last_changed_time = (doors_windows + (states.lock | list))
        | map(attribute="last_changed") | max %}
      {% set this_auto = states.automation.dynamic_entity_test %}
      {% set last_triggered_time = this_auto.attributes.last_triggered
         | default(as_datetime(0), true) %}
      {% set effective_trigger_time = max([
           last_triggered_time,
           this_auto.last_changed + timedelta(seconds=10)]) %}
      {{ last_changed_time > effective_trigger_time }}
  actions:
  - action: persistent_notification.create
    ...

The use of effective_trigger_time is a kludge to account for HA restarts, in order to force the template to evaluate false initially. The timedelta should essentially be set to the maximum variation between the last_changed values of all sensors and the automation itself after a restart. And consequently, it won't trigger in that timedelta after a restart and after editing/saving the automation.

1 Like

This kind of thing is one of the goals of the new "purpose-specific" triggers that are now available through Labs.

Once you have them enabled, they provide triggers based on domains (or collections of domains) that can be targeted like Actions:

triggers:
  - trigger: door.opened
    target:
      label_id: exterior_doors
    options:
      for: "00:00:00"
      behavior: any
  - trigger: window.opened
    target:
      floor_id:
        - first_floor
        - second_floor
    options:
      for: "00:00:00"
      behavior: any

If you want to make it fully automated, you can use the Label Management actions from Frenck's Spook integration to apply labels programmatically instead of using "group entities aggregating each device class".

2 Likes

Awesome, looking forward for that feature to be fully baked!