#Numeric template trigger?

1 messages · Page 1 of 1 (latest)

hexed lintel
#

I'm trying to create a 'generic' automation which handles all of my motion lights by listening for state changes of any properly labeled motion sensor and then turning on the primary lights in the same area as that motion sensor. I've gotten the light action down, but I'm having trouble with the trigger.

These triggers only work with booleans, which means that this automation wouldn't be able to handle multiple motion lights at the same time (for example walking from one room to another)

The workaround I've seen presented as an excuse for not adding additional functionality to Home Assistant is to create a helper template sensor to monitor the count of sensors matching the criteria, however this completely negates the ability to act on the actual triggering entity because the triggering entity has turned into a single helper entity rather than the actual motion entity that caused the trigger to occur.

Basically, I'm looking for a way to trigger an automation when any entity of a certain domain and device_class changes state from ["on", "off"] to ["on", "off"]

#

If, for example, I could trigger an automation whenever this template changes at all, that would be perfect:

{{
  set(
    states.binary_sensor
    | selectattr('attributes.device_class', 'eq', 'motion')
    | selectattr('state','eq','on')
    | map(attribute='entity_id')
  ) | length
}}
#

i think a workaround would be to pass through the triggering entity id as an attribute but i can't figure out where to edit the helper entity yaml since it was created in gui, and template attributes aren't available to be configured in gui

hexed lintel
#

just tried to migrate it to the configuration.yaml and found out that attributes aren't a viable workaround since trigger data is only given if you use a trigger based sensor

hexed lintel
#

well that's fucking annoying:
https://github.com/home-assistant/core/pull/121451

what the hell even is the point of open source if when someone tries to add functionality that people want and doesn't have any workaround it just gets denied for "too much complexity"

"too much complexity" being checks notes 17 additional lines in the template trigger source to enable the new desired functionality

GitHub

Proposed change

Currently, template triggers only trigger when the template previously renders false and then renders true. This limits template triggers and forces users to create template entit...

#

The current workaround for this would be using a separate template sensor as a helper for the specific case outlined in the PR description.

except that's not a valid workaround because it doesn't expose the same triggering entity_id, from_state, and to_state information

#

@frozen grail Sorry for the ping but you mentioned:

"event sensors" with 8 pieces of information to get the triggering entity in a group of entities.

how do you create these sensors to get this info? i'd rather have to have created 8 sensors once and be able to scale my automations as much as i'd like in the future by just adding or removing labels to entities vs having to create and configure a new automation for each individual entity

hexed lintel
#

Here's a workaround:

alias: New automation
description: ""
triggers:
  - trigger: event
    event_type: state_changed
    event_data: {}
conditions:
  - condition: template
    value_template: "{{ trigger.event.data.entity_id.startswith('binary_sensor.') }}"
  - condition: template
    value_template: "{{ trigger.event.data.new_state.attributes.device_class == 'motion' }}"
  - condition: template
    value_template: >-
      {{ trigger.event.data.old_state.state == 'off' or
      trigger.event.data.old_state.state == 'on' }}
  - condition: template
    value_template: >-
      {{ trigger.event.data.new_state.state == 'off' or
      trigger.event.data.new_state.state == 'on' }}
actions:
  - action: >-
      light.{{ "turn_on" if trigger.event.data.new_state.state == "on" else
      "turn_off" }}
    target:
      entity_id: |-
        {{
          set(area_entities(area_id(trigger.event.data.entity_id))).intersection(label_entities('Primary Lighting'))
        }}
mode: parallel
max: 1000
#

i'm really not happy with having traces on the automation for every single state update though

#

makes debugging essentially impossible

odd merlin
#

The typical solution that is recommended is to create a trigger-based template sensor with the state as the count, and an attribute with the list of entities that can trigger the sensor, sorted by last_changed (so that the first one is always the one that caused the template sensor to change)

hexed lintel
#

annoying, but that seems like a better solution than listening to every single state change event

frozen grail
#

@hexed lintel the solution i've been using is a normal template entity where the main state outputs the last updated timestamp of the most recently updated entity. And an attribute that lists all the entities in order of last updated.

#
- name:  blah
  state: "{{ label_entities('labela') | select('is_state', 'on') | expand | sort(attribute='last_changed', reverse=True) | first | default }}"
  attributes:
   last_changed: >
    {{ label_entities('labela') | select('is_state', 'on') | expand | sort(attribute='last_changed', reverse=True) | map(attribute='entity_id') | list }}
#

very simple

hexed lintel
#

yeah that's about what i'm doing

#
      - name: "Detected Motion Sensors"
        state: >
          {{
            this.attributes.entities
            | default([])
            | expand
            | selectattr('state', 'eq', 'on')
            | list
            | length
          }}
        attributes:
          entities: >
            {{
                states.binary_sensor
                | selectattr('attributes.device_class', 'eq', 'motion')
                | sort(attribute='last_changed', reverse=true)
                | map(attribute='entity_id')
                | list
            }}
frozen grail
#

it likely will, however there's a chance for a non-update when 2 things change state at the exact same time

hexed lintel
#

it's been working fine with this automation:

alias: Motion Lights
description: ""
triggers:
  - trigger: state
    entity_id:
      - sensor.detected_motion_sensors
    from: null
    to: null
conditions:
  - condition: numeric_state
    entity_id: zone.home
    above: 0
  - condition: template
    value_template: >-
      {{ states('input_boolean.' ~ states[state_attr(trigger.entity_id,
      'entities')[0]].object_id ~ '_enabled') in ('unknown', 'on') }}
actions:
  - action: >-
      light.{{ 'turn_on' if trigger.to_state.state > trigger.from_state.state
      else 'turn_off' }}
    target:
      entity_id: |-
        {{
          set(area_entities(area_id(state_attr(trigger.entity_id, 'entities')[0]))).intersection(label_entities('Primary Lighting'))
        }}
mode: parallel
max: 1000
frozen grail
#

which is why the main state needs to be a timestamp