Low battery level detection & notification for all battery sensors

Github Gist: https://gist.github.com/sbyx/1f6f434f0903b872b84c4302637d0890

Explanation

This is a different take on the whole low battery-level detection use case. Instead of manually listing one or more sensors this blueprint checks all sensors that have the attribute device_class set to ‘battery’ for either crossing below a threshold or being ‘on’ (low-battery binary sensors with class ‘battery’). This means whenever a sensor entity with device_class battery is added to HA it is automatically considered in the next check. Since this is a bit costly action and would probably cause reevaluation often if we were to use this as a trigger and I’m assuming we are dealing with battery lifetimes in the weeks or months range we are only testing this every day or every week at a given time.

Actions to run can be chosen freely and the names of the sensors are available through a template variable {{sensors}} e.g. you can use the following as data section for your notification action:
message: 'Low battery warning for: {{sensors}}'
Some notification providers (e.g. Telegram) expect messages to be valid Markdown. It may help to repace underscore possible underscore characters e.g. using {{sensors|replace("_"," ")}} instead of just {{sensors}}.

There is a target input for sensors you want to manually exclude from low-battery detection. It will only work for entities. If you select a device, you need to expand it so the underlying sensor is selected.

Given the nature of this automation this approach has a few gotchas too:

  • You may get a notification up to 1 day (or 1 week, if configured) after a sensor actually crossed the threshold.
  • You can only apply one threshold for all sensors of class battery, exclusions of sensors are possible based on the exclusion input or by using the customization feature of HA and defining a different device_class for them.
  • Similarly if your sensor does not have a device_class of ‘battery’ set it is not considered here. Again using HA’s customization you can manually set a device_class attribute to ‘battery’
  • Since the companion app also registers the battery level of the phone you may be default get a notification of your phone being low-battery at the configured time. To avoid this either disable the sensor in the companion app or use manual exclusion or customizations to override the device_class to something other than ‘battery’.
  • This currently only works if your battery-level or low-battery state is the actual state of a sensor entity. If your entities just expose the battery level as an attribute this is currently not considered but could be extended to do this.

Blueprint Code

Click the badge to import this Blueprint: (needs Home Assistant Core 2021.3 or higher)

Open your Home Assistant instance and show the blueprint import dialog with a specific blueprint pre-filled.

Or import this Blueprint by using the forum topic / Gist URL:

blueprint:
  name: Low battery level detection & notification for all battery sensors
  description: Regularly test all sensors with 'battery' device-class for crossing
    a certain battery level threshold and if so execute an action.
  domain: automation
  input:
    threshold:
      name: Battery warning level threshold
      description: Battery sensors below threshold are assumed to be low-battery (as
        well as binary battery sensors with value 'on').
      default: 20
      selector:
        number:
          min: 5.0
          max: 100.0
          unit_of_measurement: '%'
          mode: slider
          step: 5.0
    time:
      name: Time to test on
      description: Test is run at configured time
      default: '10:00:00'
      selector:
        time: {}
    day:
      name: Weekday to test on
      description: 'Test is run at configured time either everyday (0) or on a given
        weekday (1: Monday ... 7: Sunday)'
      default: 0
      selector:
        number:
          min: 0.0
          max: 7.0
          mode: slider
          step: 1.0
    exclude:
      name: Excluded Sensors
      description: Battery sensors (e.g. smartphone) to exclude from detection. Only entities are supported, devices must be expanded!
      default: {entity_id: []}
      selector:
        target:
          entity:
            device_class: battery
    actions:
      name: Actions
      description: Notifications or similar to be run. {{sensors}} is replaced with
        the names of sensors being low on battery.
      selector:
        action: {}
  source_url: https://gist.github.com/sbyx/1f6f434f0903b872b84c4302637d0890
variables:
  day: !input 'day'
  threshold: !input 'threshold'
  exclude: !input 'exclude'
  sensors: >-
    {% set result = namespace(sensors=[]) %}
    {% for state in states.sensor | selectattr('attributes.device_class', '==', 'battery') %}
      {% if 0 <= state.state | int(-1) < threshold | int and not state.entity_id in exclude.entity_id %}
        {% set result.sensors = result.sensors + [state.name ~ ' (' ~ state.state ~ ' %)'] %}
      {% endif %}
    {% endfor %}
    {% for state in states.binary_sensor | selectattr('attributes.device_class', '==', 'battery') | selectattr('state', '==', 'on') %}
      {% if not state.entity_id in exclude.entity_id %}
        {% set result.sensors = result.sensors + [state.name] %}
      {% endif %}
    {% endfor %}
    {{result.sensors|join(', ')}}
trigger:
- platform: time
  at: !input 'time'
condition:
- condition: template
  value_template: '{{ sensors != '''' and (day | int == 0 or day | int == now().isoweekday()) }}'
action:
- choose: []
  default: !input 'actions'
mode: single

Changelog

  • 2020-12-26: Replace exclusion inputs with target selector and report battery level as well where available. Thanks to @CentralCommand @KlausDK
  • 2020-12-23: Added 10 exclusion inputs
  • 2020-12-22: Initial version

My blueprints

219 Likes

Thanks! I had a simlar automation that needed attention so this saved me a job :smile:

2 Likes

Edit: this was in response to a post asking about sending a Telegram message with the sensor name in it.

Sure under actions add a “call service” action with notify.xyz (or whatever is used for Telegram) and then under data add {{sensors}} wherever you like. It will be replaced with the name of the sensors that are low on battery, e.g.:

message: 'The battery of the sensor(s) {{sensors}} is low.'
10 Likes

Thanks for this, really useful!

Would be really good to have one for when devices become offline for more than x amount of time.

6 Likes

Great idea, wish we could add some sort of “exclusion” list so I can put my Car/phone but solid idea man thanks for sharing it

3 Likes

At first, thanks @Sbyx for your contribution! It’s really great.

Yes, this would be an awesome extension.

3 Likes

Really great idea. I can not get it to trigger on time. Tried both every day and today. Works well with manual execution.

1 Like

Not elegant but I updated the blueprint with 10 new optional inputs to exclude sensors (e.g. phones, cars, …) hope that is enough for most people. If not you can still use HA’s customization to reassign device_class of sensors you don’t want included.

@mrfoyl not sure what could be wrong there do normal automations with a time trigger work for you?

Rather than a finite number you could use a comma separated list?

But it is not as user friendly when using the GUI to set the automation up as they have to enter each entity id.

Yeah I think manual input would be too error-prone for a blueprint. Let’s hope we are getting some sort of proper list support in an upcoming HA version.

1 Like

My bad. I forgot time zone issues. Works now. :slight_smile:

1 Like

This was also my concern, but an alternative none-the-less.
Anyway great effort using it daily :smile:

1 Like

Hey @Sbyx,

first off, thanks for this great blueprint. I am running into one issue which could correlate with the latest update. I would like to use the automation to trigger a Telegram message which also tells me which battery is low. While the following payload works fine for a friend of mine

message: 'Low Battery {{sensors}}'

it does not send any notification while

message: 'Low Battery'

works perfectly fine. The only difference (apart from sensors) between his and my blueprint is, that he is using the version before todays update (without the exclude option).

Any idea what could go wrong?

2 Likes

Can you please check your logs for any errors e.g. regarding templates?
I’m using the latest version, just deleted and reimported from GIthub with

actions:
      - service: notify.mobile_app_sm_g955f
        data:
          message: 'Batteriewarnung für: {{sensors}}'

and it works fine.

In fact there is an error in the log in that regard:

  • Error sending message: Can’t parse entities: can’t find end of the entity starting at byte offset 202. Args: (1347055346, “Batterie schwach - Xiaomi Batterie, Xiaomi Batterie, K iPhone Battery Level, Katjas iPhone Battery Level, R iPhone Battery Level, Xiaomi Batterie, Schalte Batterie, Xiaomi Batterie, us_ws_ikea_motion Battery Level”), kwargs: {‘parse_mode’: ‘Markdown’, ‘disable_notification’: False, ‘disable_web_page_preview’: None, ‘reply_to_message_id’: None, ‘reply_markup’: None, ‘timeout’: None, ‘message_tag’: None}

Sensors in use:

  • Ikea 2 Button Switch
  • Ikea Motion Sensor
  • Hue Switch
  • Hue Motion Sensor
  • Xiaomi Aqara Temp/Humidity Sensors
  • 2 iPhones

I have the same trouble. If i use service notify.mobile_app, all work fine, but if i use service notify.telegram_chat message dont left and in logs i see this:

Error sending message: Can't parse entities: can't find end of the entity starting at byte offset 95. Args: (201732582, 'Battery low - MI PAD 4 Battery Level, iPhone Irina Battery Level, T-H-Balcony_battery'), kwargs: {'parse_mode': 'Markdown', 'disable_notification': False, 'disable_web_page_preview': None, 'reply_to_message_id': None, 'reply_markup': None, 'timeout': None, 'message_tag': None}

Thank you

It seems that Telegram expects the message to be valid markdown and I suppose if there are e.g. an odd number of _ characters it believes this to be invalid markdown. Not sure if the underscores are the only problem here, but you could first try {{sensors|replace("_"," ")}} instead of just {{sensors}} maybe that does the trick already.

1 Like

Thanks, that did it! Much appreciated. Schöne Weihnachten! :slight_smile:

1 Like

Good to know it worked. I will make a note in the original post.

Und danke ebenfalls! :wink:

1 Like

Works great. Many thanks :slight_smile:

I use the Action:

service: notify.google_cloud_notify
data:
  message: 'Low battery warning for: {{sensors}}'
1 Like