Use a template for entity ids in a state automation trigger

I have this template to get a list of all entitiy ids with an attribute “battery” (filtering some of them out based on their name):

{% set liste = namespace(value='') %}
{% for state in states -%}
{%- if state.attributes.battery and not 'illuminance' in state.entity_id and not 'available' in state.entity_id and not 'batter' in state.entity_id and not 'calibration' in state.entity_id and not 'timeout' in state.entity_id and not 'temperature' in state.entity_id and not 'tamper' in state.entity_id and not 'sensitivity' in state.entity_id and not 'duration' in state.entity_id and not 'indication' in state.entity_id %} {% set liste.value = liste.value + ', ' + state.entity_id %} {% endif -%}
{%- endfor %}
{{ liste.value.split(', ') | reject('equalto', '') | list }}

I would love to have an automation that notifies me when batteries are getting low without me needing to add every new entity with a battery to that automation. As far as I can tell, I can’t use a template in a state automation trigger for the entity id. Is there a reason for that because it seems really useful (for my use case anyways)?

I found this post that suggests I can make a state_changed event automation and then use a template condition to test the trigger entity id against my list. But with several hundred entities it seems like overkill to run this automation every time a state changes.

Does anyone have another idea how I can implement my automation?

If there is no technical or security reason to not allow templates for the entity id, I could also (try to) implement this feature myself and create a Pull Request.

there was a battery alert package posted a while back by a user ( @NotoriousBDG ) that I still use as a basis for my battery alerts. But it is highly modified to fit my needs.

maybe you can do the same.

basically in my use it automatically updates a group with all of my battery devices and notifies me if any of the entities in the group goes below the setpoint created in the package.

1 Like

I didn’t know you could create groups like this, but in the end, this also relies on a state_changed event automation to notify about low battery levels - which I’m trying to avoid.

I’m not sure why this is an issue.

literally everything in HA relies on a “state changed” event.

every automation trigger, UI status update, etc, everything relies on the event bus which is driven by the state machine (or maybe the other way around but you get the idea…)

Yeah, maybe I’m overthinking this, but it feels wrong to trigger an automation on a state change of every entity when I only need it to trigger for a handful of entities…

like I said I have modified the package to my needs but looking thru my automations in that package I never trigger anything off of any state change for every entity. I haven’t looked at the original in a long time so I don’t remember how it did things.

my low battery notification automation runs every 15 minutes and only checks the entities in the battery alerts group against the setpoints created by the package.

the battery alert group runs once an hour to check all the sensors for certain defined characteristics (mostly it is “do they have ‘battery_level’ in the entity_id”) and then the group is created with only those entities. So if you ad or remove any battery powered entities the group is automatically updated every hour.

if you would like to see my updated automations I could post them here.

Ah, a time based trigger. That actually sounds like a good idea and much better then a trigger for every state change. If you don’t mind, I would love to see your automation and how you use the group in it.

Automation to set the battery entities group members:

- alias: update_battery_status_group_members
    initial_state: 'on'
    trigger:
      - platform: time_pattern
        hours: '/1'
        seconds: 00
    action:
      - service: group.set
        data:
          object_id: "battery_status"
          entities: >-
            {%- for item in states.sensor 
              if 
                ( 
                  not is_state_attr(item.entity_id, 'hidden', true)
                  and not is_state_attr(item.entity_id, 'battery_alert_disabled', true)
                  and (is_state_attr(item.entity_id, 'device_class', 'battery') or (item.entity_id | lower).endswith('_battery_level'))
                )
            -%}
              {{ item.entity_id }}{% if not loop.last %}, {% endif %}
            {%- endfor -%}

automations to trigger the notification & clear it when no longer low:

  - alias: battery_persistent_notification
    initial_state: 'on'
    trigger:
      - platform: time_pattern
        minutes: '/15'
        seconds: 00
      - platform: state
        entity_id:
          - input_number.battery_alert_threshold_min
          - input_number.battery_alert_threshold_max
    action:
      - condition: template
        value_template: &low_battery_check >
          {% macro battery_level() %}
          {% for entity_id in states.group.battery_status.attributes.entity_id if (
            not is_state_attr(entity_id, 'battery_alert_disabled', true)
            and states(entity_id) is not none
            and entity_id not in expand('group.battery_notification_excluded') | map(attribute='entity_id') | list
            and (
              (
                (
                  states(entity_id) is number
                  or states(entity_id) | length == states(entity_id)| int | string | length
                  or states(entity_id) | length == states(entity_id)| float | string | length
                )
                and states(entity_id) | int < states.input_number.battery_alert_threshold_max.state | int
                and states(entity_id) | int > states.input_number.battery_alert_threshold_min.state | int
              )
              or states(entity_id) | lower == 'low'
              or states(entity_id) | lower == 'unknown'
              or states(entity_id) | lower == 'unavailable'
            )
          ) -%}
            {{ state_attr(entity_id, "friendly_name") }} ({{ states(entity_id) }})
          {% endfor -%}
          {% endmacro %}
          {{ battery_level() | trim != "" }}
      - service: input_boolean.turn_on
        data:
          entity_id: input_boolean.low_batteries
      - service: persistent_notification.create
        data:
          title: "Low Battery Levels"
          notification_id: low_battery_alert
          message: &message >
            {% macro battery_level() %}
            {% for entity_id in states.group.battery_status.attributes.entity_id if (
              not is_state_attr(entity_id, 'battery_alert_disabled', true)
              and states(entity_id) is not none
              and entity_id not in expand('group.battery_notification_excluded') | map(attribute='entity_id') | list
              and (
                (
                  (
                    states(entity_id) is number
                    or states(entity_id) | length == states(entity_id)| int | string | length
                    or states(entity_id) | length == states(entity_id)| float | string | length
                  )
                  and states(entity_id) | int < states.input_number.battery_alert_threshold_max.state | int
                  and states(entity_id) | int > states.input_number.battery_alert_threshold_min.state | int
                )
                or states(entity_id) | lower == 'low'
                or states(entity_id) | lower == 'unknown'
                or states(entity_id) | lower == 'unavailable'
              )
            ) -%}
              {{ state_attr(entity_id, "friendly_name") }} ({{ states(entity_id) }})
            {% endfor -%}
            {% endmacro %}
            {{ battery_level() }}

  - alias: battery_persistent_notification_clear
    initial_state: 'on'
    trigger:
      - platform: time_pattern
        minutes: '/15'
        seconds: 00
      - platform: state
        entity_id:
          - input_number.battery_alert_threshold_min
          - input_number.battery_alert_threshold_max
    action:
      - condition: template
        value_template: &low_battery_clear >
          {% macro battery_level() %}
          {% for entity_id in states.group.battery_status.attributes.entity_id if (
            not is_state_attr(entity_id, 'battery_alert_disabled', true)
            and states(entity_id) is not none
            and entity_id not in expand('group.battery_notification_excluded') | map(attribute='entity_id') | list
            and (
              (
                (
                  states(entity_id) is number
                  or states(entity_id) | length == states(entity_id)| int | string | length
                  or states(entity_id) | length == states(entity_id)| float | string | length
                )
                and states(entity_id) | int < states.input_number.battery_alert_threshold_max.state | int
                and states(entity_id) | int > states.input_number.battery_alert_threshold_min.state | int
              )
              or states(entity_id) | lower == 'low'
              or states(entity_id) | lower == 'unknown'
              or states(entity_id) | lower == 'unavailable'
            )
          ) -%}
            {{ state_attr(entity_id, "friendly_name") }} ({{ states(entity_id) }})
          {% endfor -%}
          {% endmacro %}
          {{ battery_level() | trim == "" }}
      - service: input_boolean.turn_off
        data:
          entity_id: input_boolean.low_batteries
      - service: persistent_notification.dismiss
        data:
          notification_id: low_battery_alert

there are some things that might be able to be cleaned up and stream-lined. But it works as is for me so I never dug into it any further.

And there are couple of other parts in the rest of the package so these might not be able to be used as standalone automations

Thank you for posting your config.
If I am reading this correctly, you are getting a notification every 15 minutes if one of your batteries is low, right? So even if you were to dismiss the notification it would be right back - that sounds a little annoying. I was looking for a way to get a one time notification when a batterie passes a certain threshold but I might settle with this solution for now.
Thanks again.

Edit: I just realized that you are using HA’s notification, not something external, so it’s not that annoying. I wanted a notification for the companion app, which sounds less appealing every 15 minutes.