Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Home Assistant Blueprint: Low battery level detection & notification for all battery sensors
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:
- '{{ sensors != '''' and (day | int == 0 or day | int == now().isoweekday()) }}'
action:
- choose: []
default: !input 'actions'
mode: single
@amitubale

This comment has been minimized.

Copy link

@amitubale amitubale commented Jan 6, 2021

Does this work for the 433MHZ sensors..that work though the Sonoff RF Bridge ?
THese sensors sen3 3 codes - Open, Close & Low Batt Code. Can this template be adapted for the Low Batt Code ?

@sbyx

This comment has been minimized.

Copy link
Owner Author

@sbyx sbyx commented Jan 6, 2021

Is the low-battery state exposed in HA and if so, how?

@amitubale

This comment has been minimized.

Copy link

@amitubale amitubale commented Jan 6, 2021

the 433MHz sensor send out 3 codes. I have seens on the forums users making thoer own automation to alert when the "Low Batt" code is recived from the Sensor via the RF Bridge.

example
12F70A - open
12F70E - closed
12F707 - tamper
12F706 - low battery
Ref: https://community.home-assistant.io/t/sonoff-dw1-433mhz-door-window-sensor-low-battery-warning-capable/43073/8
platform: mqtt
topic: rfbridge_A12345/tele/RESULT
condition:
condition: template
value_template: ‘"{{ trigger.payload_json.RfReceived.Sync > 10200 }}"’
condition: and
conditions:
condition: template
value_template: ‘"{{ trigger.payload_json.RfReceived.Data == ‘‘9CEA29’’ }}"’
action:
data:
message: change battery because sync is high for device code 9CEA29
service: notify.notify

@sbyx

This comment has been minimized.

Copy link
Owner Author

@sbyx sbyx commented Jan 6, 2021

I see right now only actual sensor entities in HA are supported, i.e. ones you can find under Settings - Entities.

@lsaranto

This comment has been minimized.

Copy link

@lsaranto lsaranto commented May 15, 2021

I used this on a system that uses 24-hour clock. I set the time option to 12:00 PM. The automation that was created had time value converted to 24:00:00. This did not work and broke the automation. Changing it to a valid value fixed it.

I don't know if it is a bug in this blueprint or in HA.

@AseKarlsson

This comment has been minimized.

Copy link

@AseKarlsson AseKarlsson commented Jun 25, 2021

Great Blueprint.
Not sure what to add to the "Actions" part, I want to get a notification if any device have low battery.
Notification in HA Notifications area is good enough.
Any advice?

//Ase

@colmbuckley

This comment has been minimized.

Copy link

@colmbuckley colmbuckley commented Jun 30, 2021

Great Blueprint.
Not sure what to add to the "Actions" part, I want to get a notification if any device have low battery.
Notification in HA Notifications area is good enough.

Action type: "Call Service"
Service: notify.notify
Fill in the message you want to be notified with.

(notify.persistent_notification to add a notification to the "notifications" section of the HAss app. notify.notify to send a push notification to your devices. you can also use something like notify.email to send emails.)

@Mollegarden

This comment has been minimized.

Copy link

@Mollegarden Mollegarden commented Jul 1, 2021

Great Blueprint.

To get all my 22 battery powered devices, including those that displays voltage instead of percent, I modified the sensors part with this code:

sensors: >-
{% set result = namespace(sensors=[]) %}
{% for state in states.sensor | selectattr('attributes.device_class', '==', 'battery') %}
{% if state.state | int < threshold and not state.state == 'unavailable' %}
{% set result.sensors = result.sensors + [state.name ~ ' (' ~ state.state ~ '%)'] %}
{% endif %}
{% endfor %}
{% for sensor in states.binary_sensor %}
{% if 'battery_level' in sensor.attributes %}
{% if ((state_attr(sensor.entity_id, 'battery_level')-2) |float/0.01)|round(1) | int < threshold and not sensor.state == 'unavailable' %}
{% set result.sensors = result.sensors + [sensor.name ~ ' (' ~ ((state_attr(sensor.entity_id, 'battery_level')-2)|float/0.01)|round(1) ~ '%)'] %}
{% endif %}
{% endif %}
{% endfor %}
{% for sensor in states.camera %}
{% if 'battery_level' in sensor.attributes %}
{% if state_attr(sensor.entity_id, 'battery_level') | int < threshold and not sensor.state == 'unavailable' %}
{% set result.sensors = result.sensors + [sensor.name ~ ' (' ~ state_attr(sensor.entity_id, 'battery_level')~ '%)'] %}
{% endif %}
{% endif %}
{% endfor %}
{{result.sensors|join('\n')}}

I also joined the result with '\n' instead of ', ' which displays one device per row when I do a persistent notification.

I have 2 actions:

service: persistent_notification.create
data:
title: Warning low battery level!
message: Low battery level{{ ':' }}{{ '\n' -}}{{sensors}}

service: notify.notify
data:
title: Warning low battery level!
message: 'Low battery level: {{sensors}}'

@AseKarlsson

This comment has been minimized.

Copy link

@AseKarlsson AseKarlsson commented Jul 1, 2021

Thanks Guys for helping me out, now both HA and email notification in place. So obvious after seeing your answers.

@justinlawrence

This comment has been minimized.

Copy link

@justinlawrence justinlawrence commented Jul 24, 2021

Great Blueprint.

To get all my 22 battery powered devices, including those that displays voltage instead of percent, I modified the sensors part with this code:

sensors: >-
{% set result = namespace(sensors=[]) %}
{% for state in states.sensor | selectattr('attributes.device_class', '==', 'battery') %}
{% if state.state | int < threshold and not state.state == 'unavailable' %}
{% set result.sensors = result.sensors + [state.name ~ ' (' ~ state.state ~ '%)'] %}
{% endif %}
{% endfor %}
{% for sensor in states.binary_sensor %}
{% if 'battery_level' in sensor.attributes %}
{% if ((state_attr(sensor.entity_id, 'battery_level')-2) |float/0.01)|round(1) | int < threshold and not sensor.state == 'unavailable' %}
{% set result.sensors = result.sensors + [sensor.name ~ ' (' ~ ((state_attr(sensor.entity_id, 'battery_level')-2)|float/0.01)|round(1) ~ '%)'] %}
{% endif %}
{% endif %}
{% endfor %}
{% for sensor in states.camera %}
{% if 'battery_level' in sensor.attributes %}
{% if state_attr(sensor.entity_id, 'battery_level') | int < threshold and not sensor.state == 'unavailable' %}
{% set result.sensors = result.sensors + [sensor.name ~ ' (' ~ state_attr(sensor.entity_id, 'battery_level')~ '%)'] %}
{% endif %}
{% endif %}
{% endfor %}
{{result.sensors|join('\n')}}

I also joined the result with '\n' instead of ', ' which displays one device per row when I do a persistent notification.

I have 2 actions:

service: persistent_notification.create
data:
title: Warning low battery level!
message: Low battery level{{ ':' }}{{ '\n' -}}{{sensors}}

service: notify.notify
data:
title: Warning low battery level!
message: 'Low battery level: {{sensors}}'

Super helpful, thank you!

@MrPlow254

This comment has been minimized.

Copy link

@MrPlow254 MrPlow254 commented Aug 1, 2021

Ecobee motion sensor puts the battery level in the attribute column not as a separate class. This blueprint does not work with this type of battery level logging.
image

@anarro

This comment has been minimized.

Copy link

@anarro anarro commented Aug 19, 2021

Great Blueprint.

To get all my 22 battery powered devices, including those that displays voltage instead of percent, I modified the sensors part with this code:

sensors: >-
{% set result = namespace(sensors=[]) %}
{% for state in states.sensor | selectattr('attributes.device_class', '==', 'battery') %}
{% if state.state | int < threshold and not state.state == 'unavailable' %}
{% set result.sensors = result.sensors + [state.name ~ ' (' ~ state.state ~ '%)'] %}
{% endif %}
{% endfor %}
{% for sensor in states.binary_sensor %}
{% if 'battery_level' in sensor.attributes %}
{% if ((state_attr(sensor.entity_id, 'battery_level')-2) |float/0.01)|round(1) | int < threshold and not sensor.state == 'unavailable' %}
{% set result.sensors = result.sensors + [sensor.name ~ ' (' ~ ((state_attr(sensor.entity_id, 'battery_level')-2)|float/0.01)|round(1) ~ '%)'] %}
{% endif %}
{% endif %}
{% endfor %}
{% for sensor in states.camera %}
{% if 'battery_level' in sensor.attributes %}
{% if state_attr(sensor.entity_id, 'battery_level') | int < threshold and not sensor.state == 'unavailable' %}
{% set result.sensors = result.sensors + [sensor.name ~ ' (' ~ state_attr(sensor.entity_id, 'battery_level')~ '%)'] %}
{% endif %}
{% endif %}
{% endfor %}
{{result.sensors|join('\n')}}

I also joined the result with '\n' instead of ', ' which displays one device per row when I do a persistent notification.

I have 2 actions:

service: persistent_notification.create
data:
title: Warning low battery level!
message: Low battery level{{ ':' }}{{ '\n' -}}{{sensors}}

service: notify.notify
data:
title: Warning low battery level!
message: 'Low battery level: {{sensors}}'

Hi,

I made the modifications in a blueprint but when I receive the notification (Telegram) it shows me in a single line, how can I see it in two rows?

image

It's possible?

Thank you.

@anarro

This comment has been minimized.

Copy link

@anarro anarro commented Aug 20, 2021

Great Blueprint.
To get all my 22 battery powered devices, including those that displays voltage instead of percent, I modified the sensors part with this code:
sensors: >-
{% set result = namespace(sensors=[]) %}
{% for state in states.sensor | selectattr('attributes.device_class', '==', 'battery') %}
{% if state.state | int < threshold and not state.state == 'unavailable' %}
{% set result.sensors = result.sensors + [state.name ~ ' (' ~ state.state ~ '%)'] %}
{% endif %}
{% endfor %}
{% for sensor in states.binary_sensor %}
{% if 'battery_level' in sensor.attributes %}
{% if ((state_attr(sensor.entity_id, 'battery_level')-2) |float/0.01)|round(1) | int < threshold and not sensor.state == 'unavailable' %}
{% set result.sensors = result.sensors + [sensor.name ~ ' (' ~ ((state_attr(sensor.entity_id, 'battery_level')-2)|float/0.01)|round(1) ~ '%)'] %}
{% endif %}
{% endif %}
{% endfor %}
{% for sensor in states.camera %}
{% if 'battery_level' in sensor.attributes %}
{% if state_attr(sensor.entity_id, 'battery_level') | int < threshold and not sensor.state == 'unavailable' %}
{% set result.sensors = result.sensors + [sensor.name ~ ' (' ~ state_attr(sensor.entity_id, 'battery_level')~ '%)'] %}
{% endif %}
{% endif %}
{% endfor %}
{{result.sensors|join('\n')}}
I also joined the result with '\n' instead of ', ' which displays one device per row when I do a persistent notification.
I have 2 actions:
service: persistent_notification.create
data:
title: Warning low battery level!
message: Low battery level{{ ':' }}{{ '\n' -}}{{sensors}}
service: notify.notify
data:
title: Warning low battery level!
message: 'Low battery level: {{sensors}}'

Hi,

I made the modifications in a blueprint but when I receive the notification (Telegram) it shows me in a single line, how can I see it in two rows?

image

It's possible?

Thank you.

Hi,

I can get it with:

image

@colmbuckley

This comment has been minimized.

Copy link

@colmbuckley colmbuckley commented Aug 20, 2021

I don't use Telegram for notifications, but the screenshot you shared looks very much as though you had written '/n' instead of '\n' in your join(). Are you sure the new version is the one which is being used?

@cweakland

This comment has been minimized.

Copy link

@cweakland cweakland commented Sep 1, 2021

the 433MHz sensor send out 3 codes. I have seens on the forums users making thoer own automation to alert when the "Low Batt" code is recived from the Sensor via the RF Bridge.

example
12F70A - open
12F70E - closed
12F707 - tamper
12F706 - low battery
Ref: https://community.home-assistant.io/t/sonoff-dw1-433mhz-door-window-sensor-low-battery-warning-capable/43073/8
platform: mqtt
topic: rfbridge_A12345/tele/RESULT
condition:
condition: template
value_template: ‘"{{ trigger.payload_json.RfReceived.Sync > 10200 }}"’
condition: and
conditions:
condition: template
value_template: ‘"{{ trigger.payload_json.RfReceived.Data == ‘‘9CEA29’’ }}"’
action:
data:
message: change battery because sync is high for device code 9CEA29
service: notify.notify

Not sure if you figured this out, but you need to create a binary_sensor for these mqtt style battery high/low sensors. This is what one will look like:

  • platform: mqtt
    name: family_motion_battery
    state_topic: 'rtl_433/9b13b3f4-rtl433/devices/Interlogix-Security/motion/4cf72a/battery_ok'
    payload_off: "1"
    payload_on: "0"
    device_class: battery
@amitubale

This comment has been minimized.

Copy link

@amitubale amitubale commented Sep 6, 2021

12F706

you have 433MHz sensor working via Sonoff RF Bridge ? and this binary_sensor config is working for you ?..On my RF bridge......the code it sends out for low batt is XXXX06 (XXXX is unique to a sensor, XXXX0A for Open/On & XXXX0E for closed/Off)..if you say its working for you then i will giv e it a try..but i dont see this topic sent out by my Tasmotized Sonoff RF Bridge "rtl_433/9b13b3f4-rtl433/devices/Interlogix-Security/motion/4cf72a/battery_ok"

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