Listing sensors with battery state lower than input number helper

Hello,

I am having an issue creating a sensor to list all sensors with a battery state lower than a number defined by an input number helper. This code works fine if I put it in the template editor in the Developer Tools section. However if I create a sensor template, the state becomes “unknown” if more than 1 low battery is detected. Works fine if only 1 low battery is detected.

This is the code in my sensor.yaml file

- platform: template
  sensors:
    low_batteries:
      value_template: >
        {% set threshold = states('input_number.battery_warning_threshold') %}
        {% set entities = states.sensor 
          | selectattr('entity_id', 'search', 'battery')
          | rejectattr('entity_id', 'search', '(ups|s21|backyard|doorbell|driveway|tablet|sm|thp)')
          | map(attribute = 'entity_id') | list %}
        {% if (entities != '') %}
          {% for sensor in entities if states(sensor) != 'unknown' and states(sensor) != 'unavailable'
          and states(sensor) != 'None' and states(sensor) | int(default=0) <= int(threshold) %}
            {{ state_attr(sensor, 'friendly_name') | replace(" Battery", "") | replace(" Level", "") | replace(" power", "") | replace(" Power", "") }} ({{ states(sensor) }} %)
          {% endfor %}
        {% endif %}
      attribute_templates:
        low_battery_count: >
          {% set threshold = states('input_number.battery_warning_threshold') %}
          {% set lowbatcount = states.sensor
            | selectattr('entity_id', 'search', 'battery')
            | selectattr('state', 'lessthan', threshold)
            | rejectattr('state', 'equalto', '100')
            | rejectattr('state', 'equalto', '100.0')
            | rejectattr('entity_id', 'search', '(ups|s21|backyard|doorbell|driveway|tablet|sm|thp)')
            | list | count %} {{ lowbatcount }}

Not looked at your code but… did you see this one?
maxwroc/battery-state-card: Battery state card for Home Assistant (github.com)

This works a treat
https://community.home-assistant.io/t/low-battery-level-detection-notification-for-all-battery-sensors/258664

Add |int() filter + default value to your threshold, e.g.


states('input_number.battery_warning_threshold')|int(25)

and adjust the following line:


          and states(sensor) != 'None' and states(sensor) | int(default=0) <= threshold %}

I tried this and unfortunately the sensor state still reports as ‘unknown’ if more than 1 battery is lower than the threshold.

I want to draw your attention to the following:

{% set threshold = states('input_number.battery_warning_threshold') %} #<-- this is a string value
{% set lowbatcount = states.sensor
  | selectattr('entity_id', 'search', 'battery')
  | selectattr('state', 'lessthan', threshold) #<-- this is performing a string comparison

Your template is not performing a numeric comparison but a string comparison.

The threshold variable contains a string not a number. In other words, if the input_number’s value is 50 then threshold contains '50' which is a numeric string but not a number.

The following line is comparing the sensor’s state value, which is a numeric string, to the threshold value which is also a numeric string. Comparing numeric strings doesn’t behave the same way as comparing numbers.

selectattr('state', 'lessthan', threshold)

For example, when comparing the numeric string '9' to the numeric string '85' it’s not less than '85'.

All this to say that selectattr('state', 'lessthan', threshold) may not be working the way you think it is.

Have you altered the input number slider after adjusting the code and reloading? I tested it with an input number set to 100:

Besides that, your attributes template won’t work that way. Try this one:


      attribute_templates:
        low_battery_count: >
          {% set threshold = states('input_number. battery_warning_threshold')|int(25) %}
          {% set lowbatcount = states.sensor
            |rejectattr('entity_id', 'search', 'xyz')
            |selectattr('entity_id', 'search', 'battery')
            |map(attribute='state')
            |map('int', -1) |select('le', threshold)
            |list |count %}
          {{ lowbatcount }}

1 Like