Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save kurohouou/880fdbffc697ef872cf8a793dc3fb72b to your computer and use it in GitHub Desktop.
Save kurohouou/880fdbffc697ef872cf8a793dc3fb72b to your computer and use it in GitHub Desktop.
Home Assistant Blueprint: Low battery level detection & notification for all battery sensors
blueprint:
name: Low Battery and Device Unavailable Check
description: Regularly test all sensors with 'battery' device-class for crossing
a certain battery level threshold as well as if it is unavailable.
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: Removed Battery only selection to select any entity like switches. Only entities are supported, devices must be expanded!
default: {entity_id: []}
selector:
target:
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.sensor | selectattr('attributes.device_class', 'defined') | selectattr('attributes.device_class', '==', 'battery') %}
{% if "unavailable" in state | string 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 %}
{% for state in states.binary_sensor | selectattr('attributes.device_class', 'defined') | selectattr('attributes.device_class', '==', 'battery') %}
{% if "unavailable" in state | string and not state.entity_id in exclude.entity_id %}
{% set result.sensors = result.sensors + [ state.name ~ ' (' ~ state.state ~ ')'] %}
{% endif %}
{% endfor %}
{% for state in states.switch | selectattr('state','eq','unavailable') %}
{% if state.entity_id not in exclude.entity_id %}
{% set result.sensors = result.sensors + [ state.name ~ ' (' ~ state.state ~ ')'] %}
{% endif %}
{% endfor %}
{{result.sensors|join(', ')}}
trigger:
- platform: time
at: !input 'time'
condition:
- '{{ sensors != '''' and (day | int == 0 or day | int == now().isoweekday()) }}'
action:
- choose: []
default: !input 'actions'
mode: single
@kurohouou
Copy link
Author

I was not able to find a good blueprint for doing both a battery level check and a device unavailable check, so I basically combined code from multiple blueprints I found. This one lets you know what devices are below the threshold as well as if it is unavailable which is good for detected dead devices! Why HA doesn't build this into their service is crazy imo, this is a must have feature.

@kurohouou
Copy link
Author

Made a change to the entity selection when I noticed an outlet/switch device I don't use except for at Christmas time was showing unavailable. I removed the device type battery and just made it able to select any entity. Works great now with my outlets/switches that might say unavailable if not plugged in.

@andyblac
Copy link

andyblac commented May 27, 2023

can you add an option to use "Included" instead for selecting all battery sensors, just my Aqara Roller Shade E1 motors do not operate below 55% batttery and I would like a notification when those get below 60%.

@andyblac
Copy link

andyblac commented May 27, 2023

coded myself, here is code if you want to use it

blueprint:
  name: Low Battery and Device Unavailable Check
  description:
    Regularly test all sensors with 'battery' device-class for crossing
    a certain battery level threshold as well as if it is unavailable.
  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
    include:
      name: Included Sensors
      description:
        Battery sensors (e.g. smartphone) to use only these entities. 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/kurohouou/880fdbffc697ef872cf8a793dc3fb72b
variables:
  day: !input day
  threshold: !input threshold
  exclude: !input exclude
  include: !input include
  sensors: >-
    {% if include.entity_id|count > 0 %}
      {% for state in states.sensor | selectattr('attributes.device_class', '==', 'battery') %}
        {% if 0 <= state.state | int(-1) < threshold | int and state.entity_id in include.entity_id %}
          {% set result.sensors = result.sensors + [ state.name ~ ' (' ~ state.state ~ ' %)'] %}
        {% endif %}
      {% endfor %}
      {% for state in states.sensor | selectattr('attributes.device_class', 'defined') | selectattr('attributes.device_class', '==', 'battery') %}
        {% if "unavailable" in state | string  and state.entity_id in include.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 state.entity_id in include.entity_id %}
          {% set result.sensors = result.sensors + [ state.name] %}
        {% endif %}
      {% endfor %} 
      {% for state in states.binary_sensor | selectattr('attributes.device_class', 'defined') | selectattr('attributes.device_class', '==', 'battery') %}
        {% if "unavailable" in state | string and state.entity_id in include.entity_id %}
          {% set result.sensors = result.sensors + [ state.name ~ ' (' ~ state.state ~ ')'] %}
        {% endif %}
      {% endfor %} 
      {% for state in states.switch | selectattr('state','eq','unavailable') %}    
        {% if state.entity_id in include.entity_id %}
          {% set result.sensors = result.sensors + [ state.name ~ ' (' ~ state.state ~ ')'] %}   
        {% endif %}
      {% endfor %}
    {% else %}
      {% 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.sensor | selectattr('attributes.device_class', 'defined') | selectattr('attributes.device_class', '==', 'battery') %}
        {% if "unavailable" in state | string  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 %} 
      {% for state in states.binary_sensor | selectattr('attributes.device_class', 'defined') | selectattr('attributes.device_class', '==', 'battery') %}
        {% if "unavailable" in state | string and not state.entity_id in exclude.entity_id %}
          {% set result.sensors = result.sensors + [ state.name ~ ' (' ~ state.state ~ ')'] %}
        {% endif %}
      {% endfor %} 
      {% for state in states.switch | selectattr('state','eq','unavailable') %}    
        {% if state.entity_id not in exclude.entity_id %}
          {% set result.sensors = result.sensors + [ state.name ~ ' (' ~ state.state ~ ')'] %}   
        {% endif %}
      {% endfor %}
    {% endif %}
    {{result.sensors|join(',')}}
trigger:
  - platform: time
    at: !input time
condition:
  - "{{ sensors != '''' and (day | int == 0 or day | int == now().isoweekday()) }}"
action:
  - choose: []
    default: !input actions
mode: single

@kurohouou
Copy link
Author

can you add an option to use "Included" instead for selecting all battery sensors, just my Aqara Roller Shade E1 motors do not operate below 55% batttery and I would like a notification when those get below 60%.

Hi, thanks for checking out this blueprint. I am curious what the benefit of having an include list would be as all devices are automatically included and you just set the exclude list for ones you don't want.. or is it somehow missing a device? Or maybe you only want to monitor a couple devices maybe and don't want to have to select a bunch to exclude? Is that what your doing? I just figured people would want to monitor all battery based devices.

@andyblac
Copy link

andyblac commented May 27, 2023

I have 7 Aqara Roller Shade motors, but these have a battery level issue, where once they get below 55% they fail to operate correctly and Aqara refuses to fix the issue. So in my case it was easier to "include" just these sensors and have a automation to warning me once they reach 60%, rather than "exclude" all the other battery sensors (over 50 of them). So now i have 2 automation one with only these included and 60%, and another with these excluded with 20%.

Hope that make sense.

@kurohouou
Copy link
Author

Ah that makes sense, thanks for that clarification :) I'll try out your modifications soon

@andyblac
Copy link

andyblac commented Jul 15, 2023

added an option to list unavailable or not. here my gist https://gist.github.com/andyblac/35b4164355dbef4f998f358353278236 based on your code, hope you don't mind

Screenshot 2023-07-15 at 14 48 43

@chrissi5120
Copy link

added an option to list unavailable or not. here my gist https://gist.github.com/andyblac/35b4164355dbef4f998f358353278236 based on your code, hope you don't mind

Screenshot 2023-07-15 at 14 48 43

Logger: homeassistant.helpers.template
Source: helpers/template.py:2209
First occurred: 18:20:15 (4 occurrences)
Last logged: 18:22:47

Template variable warning: 'sensors' is undefined when rendering '{{sensors}}'

you got any idea how I screw this up?

image

@andyblac
Copy link

hi, sure thats np, here is my latest version, it now adds send message as default you only have to add the device(s)
Screenshot 2023-10-19 at 09 49 13

@andyblac
Copy link

andyblac commented Dec 1, 2023

Hi,

just fixed this issue in my gist here, it stops the error in logs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment