Template for triggered condition (is this possible?)

I’m attempting to cut down on the vast number of automations that I’ve accumulated over the many many years… Oh, October 2019 you say? Wow 2020 HAS sucked! Anyhow, I’ve removed all of my previous individual low-battery notifications and consolidated them into one automation that runs at a set time each evening (giving me a window of time that I can actually DO something about said low batteries) with each sensor added to an ‘OR’ condition. Instead of attempting to describe it, I’ll just post the code below:

- id: '1589688330541'
  alias: General - Low Battery - Alert
  description: Alert on low battery
  trigger:
  - at: '18:00:00'
    platform: time
  condition:
  - condition: or
    conditions:
    - below: '100'
      condition: numeric_state
      entity_id: sensor.august_asl_03_smart_lock_battery_level
    - below: '20'
      condition: numeric_state
      entity_id: sensor.dryer_battery
    - below: '20'
      condition: numeric_state
      entity_id: sensor.washer_battery
    - condition: numeric_state
      entity_id: sensor.livingroom_motion_battery
      below: '20'
    - condition: numeric_state
      entity_id: sensor.ecolink_door_window_sensor_battery_level
      below: '50'
  action:
  - data:
      message: Check battery for Home Assistant things.
      title: Low Battery
    service: notify.mobile_app_phone
  mode: single

Now what I’d REALLY love to know is if there is some way to use a template to show me SPECIFICALLY which condition triggered. Something along the lines of:

  action:
  - data:
      message: The following device(s) have a low battery: {{ state_attr('automation.alert_on_low_battery', 'which_condition_triggered_me') }}
      title: Low Battery
    service: notify.mobile_app_phone

Is this even possible in HA as it stands today? And if not, is this something that other folks even want? Just curious on if anyone else has had this thought before.

A condition doesn’t ‘trigger’. It’s simply a filter (another level of checking that is performed before proceeding to the action).

The action has access to the Trigger State Object but it represents the trigger.

What you are trying to do can’t be done with the way you have structured the automation.

I suggest creating a Template Sensor that reports all low-battery devices. Your automation simply runs at 18:00 and reports whatever the Template Sensor has found.

Let me know if you need help creating the Template Sensor.

1 Like

That’s actually a really good point, thanks! One of those nuggets that I kinda remember starting out, but didn’t quite remember in this case. I’ve been poking around and think I’m (maybe) on the right track. Essentially what I’m messing around in the dev tools looks like this and would be thrown into the message field (once things are working):

{%- set sensors = [
  'sensor.august_asl_03_smart_lock_battery_level',
  'sensor.dryer_battery',
  'sensor.washer_battery',
  'sensor.livingroom_motion_battery',
  'sensor.ecolink_door_window_sensor_battery_level'
] %}
{%- for sensor in sensors -%}
  {% if (states(sensor) | int) >= 20 %}
    {{ sensors.remove(sensor) }}
  {%- endif %}
{%- endfor %}
{% for sensor in sensors -%}
    {% if loop.first %}The following device(s) have a low battery: {% elif loop.last %}{% else %}{% endif %}
    {{ state_attr(sensor, 'friendly_name').replace(' Level', '') }} {{ states(sensor) | int }}%
{%- endfor %}

The problem I’m running into with this is that I get the following error:

SecurityError: access to attribute 'remove' of 'list' object is unsafe.

Whomp whomp! Any ideas on how I’d be able to only display the sensors that are actually lower than my threshold? I suspect I need a more convoluted loop syntax, but not really sure what to do on that front. If I take out the line to remove the list entry, I end up with output that looks like this:

The following device(s) have a low battery: 
    August ASL-03 Smart Lock Battery 100%
    Dryer Battery 60%
    Washer Battery 44%
    Living Room Motion Battery 0%
    Back Gate Battery 99%

This is exactly what I’m trying to go for, however WITHOUT all of the sensors that are above my threshold (once I get a single value working for all of them, I’ll add thresholds for each type of sensor to align with my automation conditions). Thanks in advance for any light you can shed :slight_smile:

Here’s what I suggest you do.

  • Create a custom attribute called battery_threshold for each sensor and set it to the desired level.
  • Create a group to hold all five battery-powered sensors.
  • Create an automation that runs at 18:00, examines the group, determines which sensors have a low battery level, and reports them (if any) via a notification.

1. Create custom attributes for each battery-powered sensor.

Begin by allowing Home Assistant to use a customization file (you may already have done this in the past).

In configuration.yaml under the existing homeassistant domain add the following key:

homeassistant:
  customize: !include customize.yaml

In the same directory as configuration.yaml create a new file called customize.yaml. Add the following information to the file and save it.

sensor.august_asl_03_smart_lock_battery_level:
  battery_threshold: 100
sensor.dryer_battery:
  battery_threshold: 20
sensor.washer_battery:
  battery_threshold: 20
sensor.livingroom_motion_battery:
  battery_threshold: 20
sensor.ecolink_door_window_sensor_battery_level:
  battery_threshold: 50

2. Create a group containing the five battery-powered sensors.

Create a new group, called batteries, in the groups.yaml file containing the following:

  batteries:
    - sensor.august_asl_03_smart_lock_battery_level
    - sensor.dryer_battery
    - sensor.washer_battery
    - sensor.livingroom_motion_battery
    - sensor.ecolink_door_window_sensor_battery_level

After saving the file, execute Configuration > Server Controls > Check Configuration. If it reports no errors, restart Home Assistant.

If you now check Developer tools > States, you’ll see that all five of your battery-powered sensors have a custom attribute called battery_threshold. There is also a group called group.batteries containing the five sensors. This information will be used by the automation’s template.

3. Create an automation that determines which sensors have low batteries and reports them via a notification.

Create the following automation:

- id: '1589688330541'
  alias: General - Low Battery - Alert
  description: Alert on low battery
  trigger:
  - platform: time
    at: '18:00:00'
  action:
  - variables:
      low_batteries: >
        {% set ns = namespace(y=[]) %}
        {% for x in expand('group.batteries') if x.state|float < x.attributes.battery_threshold %}
          {% set ns.y = ns.y + [x.name] %}
        {% endfor %}
        {{ ns.y | join(', ') }}
  - condition: template
    value_template: '{{ low_batteries | length > 0 }}'
  - service: notify.mobile_app_phone
    data:
      title: Low Battery Alert
      message: "{{ low_batteries }}"

How the template works:
The template expands the group and filters it based on each sensor’s state falling below its threshold value. It adds each low-battery sensor (if any) to a list. Specifically, it adds the sensor’s friendly_name. The resulting list is displayed as a comma-separated string.

1 Like

This new learning amazes me! Next you’ll be telling me how to employ sheep bladders to prevent earthquakes! :rofl:
But seriously, thanks a bunch! This was super helpful!

1 Like