I updated my post. For friendly names, just use item.attributes.friendly_name instead of item.name.
I honestly don’t know how often it’ll run, probably every single event loop (i.e. a lot). I don’t know how to reduce that without either specifying every entity to track in the template sensor or duplicating the template in both the condition and action. Maybe we can get the template sensor updated to allow a config option that specifies how often it should update.
In this example, input_boolean.update_low_battery will toggle states every 30 minutes, which then triggers sensor.low_battery to update. You could also set it up to update just before your alert automation runs as well if you wanted. That way you only update the sensor right before the automation runs to check for low battery.
@tboyce1, thanks so much! That’s definitely a lot cleaner and I like having that persistent notification. I made a few (mostly cosmetic) tweaks to what you sent. The trigger on your “Update Low Battery” automation needs a seconds: 00 attribute to keep it from running every second when the minutes match. I changed the condition on the automation to prevent empty alerts when there are no batteries. Finally, I added the current battery level to the notification.
I’ve got a few more ideas that can make this better, but I wanted to share the latest code that’s working for me.
input_boolean:
battery_status_update:
name: Battery Status Update
sensor:
- platform: template
sensors:
battery_status:
friendly_name: "Battery Status"
entity_id:
- input_boolean.battery_status_update
value_template: >
{%- set threshold = 40 -%}
{%- set domains = ['light', 'switch', 'sensor', 'zwave', 'lock'] -%}
{%- for domain in domains -%}
{%- for item in states[domain] if ((item.attributes.battery_level is defined and item.attributes['battery_level'] | int < threshold) or ("battery" in item.name | lower and ((item.state | int < threshold and item.state|int != 0) or item.state | lower == "low" or item.state | lower == "unknown"))) -%}
{%- if (item.attributes.battery_level is defined and item.attributes['battery_level'] | int < threshold) -%}
{{ item.name }} ({{ item.attributes['battery_level'] }}){%- if not loop.last %}, {% endif -%}{% endif -%}
{%- if "battery" in item.name | lower and ((item.state | int < threshold and item.state|int != 0) or item.state | lower == "low" or item.state | lower == "unknown") -%}
{{ item.name }} ({{ item.state }}){%- if not loop.last %}, {% endif -%} {% endif -%}
{%- endfor -%}
{%- endfor -%}
automation:
- alias: Battery Status Update
trigger:
- platform: time
minutes: '/5'
seconds: 00
action:
- alias: Battery Status Update
service: input_boolean.toggle
data:
entity_id: input_boolean.battery_status_update
- alias: 'Battery Alert'
trigger:
- platform: time
at: '10:00:00'
- platform: time
at: '18:00:00'
condition:
condition: template
value_template: "{% if states('sensor.battery_status') %}{{ true }}{% else %}{{ false }}{% endif %}"
action:
- service: persistent_notification.create
data_template:
title: Low Battery levels
message: "{{ states('sensor.battery_status') }}"
notification_id: low-battery-alert
- service: notify.slack_notify
data_template:
message: >-
These devices have low battery levels: {{ states('sensor.battery_status') }}
I took the last change from @NotoriousBDG and converted it into a package that can pretty much just be dropped in and will work. Just update the notification to your preference.
Node Anchors is used to simplify your configurations and avoid repetitions of settings. So instead of repeting all settings for each entity you just add an anchor to the setting. Example:
################################################
## With Node Anchors and Merge Key Tags
################################################
homeassistant:
customize:
package.node_anchors: # This is just a dummy entry
customize: &customize # Also a dummy entry that allows us to define the node anchor
package: 'philips_hue'
light.back_porch:
<<: *customize # This merges the keys/values from "&customize"
friendly_name: "Back Porch"
light.chandelier:
<<: *customize
friendly_name: "Chandelier"
light.dining_room:
<<: *customize
friendly_name: "Dining Room"
light.entry_lamp:
<<: *customize
friendly_name: "Entry Lamp"
light.front_porch:
<<: *customize
friendly_name: "Front Porch"
@Maaniac, I think i found the issue. The notification was missing commas between domains. Can you try out this updated package below?
@thundergreen, Yes, it shouldn’t be difficult to add. If your device_tracker entity has an attribute named battery_level, you’d only need to add device_tracker to the list of domains. Can you provide more details how your device_tracker entity tracks it’s battery?
################################################################
## Packages / Battery levels
################################################################
################################################
## Customize
################################################
homeassistant:
customize:
################################################
## Node Anchors
################################################
package.node_anchors:
customize: &customize
package: 'battery_alert'
expose: &expose
<<: *customize
haaska_hidden: false
homebridge_hidden: false
################################################
## Group
################################################
group.battery_alert:
<<: *customize
friendly_name: "Battery Alert"
icon: mdi:steam
################################################
## Automation
################################################
automation.battery_alert:
<<: *customize
friendly_name: "Battery Alert"
automation.battery_alert_clear:
<<: *customize
friendly_name: "Battery Alert Clear"
################################################
## Group
################################################
group:
battery_alert:
control: hidden
entities:
- automation.battery_alert
- automation.battery_alert_clear
################################################
## Automation
################################################
automation:
- alias: battery_alert
trigger:
- platform: time
at: '10:00:00'
- platform: time
at: '18:00:00'
condition:
- condition: template
value_template: >
{%- set threshold = 40 -%}
{% macro battery_level() %}
{% set domains = ['light', 'switch', 'sensor', 'zwave', 'lock'] %}
{% for domain in domains -%}
{% for item in states[domain] if ((item.attributes.battery_level is defined and item.attributes['battery_level'] | int < threshold) or ("battery" in item.name | lower and ((item.state | int < threshold and item.state|int != 0) or item.state | lower == "low" or item.state | lower == "unknown"))) -%}
{% if (item.attributes.battery_level is defined and item.attributes['battery_level'] | int < threshold) -%}
{{ item.name }}{% endif -%}
{% if "battery" in item.name | lower and ((item.state | int < threshold and item.state|int != 0) or item.state | lower == "low" or item.state | lower == "unknown") -%}
{{ item.name }}{% endif -%}
{% endfor %}
{%- endfor %}
{% endmacro %}
{{ battery_level() |trim != "" }}
action:
- service: persistent_notification.create
data_template:
title: "Low Battery levels"
notification_id: low-battery-alert
message: >
{%- set threshold = 40 -%}
{% macro battery_level(domain) %}
{%- for item in states[domain] if ((item.attributes.battery_level is defined and item.attributes['battery_level'] | int < threshold) or ("battery" in item.name | lower and ((item.state | int < threshold and item.state|int != 0) or item.state | lower == "low" or item.state | lower == "unknown"))) -%}
{% if (item.attributes.battery_level is defined and item.attributes['battery_level'] | int < threshold) -%}
{{ item.name }} ({{ item.attributes['battery_level'] }}){%- if not loop.last %}, {% endif -%}{%- endif -%}
{%- if "battery" in item.name | lower and ((item.state | int < threshold and item.state|int != 0) or item.state | lower == "low" or item.state | lower == "unknown") -%}
{{ item.name }} ({{ item.state }}){% if not loop.last %}, {% endif %}{% endif -%}
{%- endfor -%}
{% endmacro %}
{%- set domains = ['light', 'switch', 'sensor', 'zwave', 'lock'] -%}
{%- for domain in domains if battery_level(domain) |trim != ""-%}
{{ battery_level(domain) }}{%- if not loop.last %}, {% endif -%}
{%- endfor -%}
- service: notify.slack_notify
data_template:
message: "Low Battery Levels"
data:
attachments:
- color: '#52c0f2'
title: "These devices have low battery levels"
text: >
{%- set threshold = 40 -%}
{% macro battery_level(domain) %}
{%- for item in states[domain] if ((item.attributes.battery_level is defined and item.attributes['battery_level'] | int < threshold) or ("battery" in item.name | lower and ((item.state | int < threshold and item.state|int != 0) or item.state | lower == "low" or item.state | lower == "unknown"))) -%}
{% if (item.attributes.battery_level is defined and item.attributes['battery_level'] | int < threshold) -%}
{{ item.name }} ({{ item.attributes['battery_level'] }}){%- if not loop.last %}, {% endif -%}{%- endif -%}
{%- if "battery" in item.name | lower and ((item.state | int < threshold and item.state|int != 0) or item.state | lower == "low" or item.state | lower == "unknown") -%}
{{ item.name }} ({{ item.state }}){% if not loop.last %}, {% endif %}{% endif -%}
{%- endfor -%}
{% endmacro %}
{%- set domains = ['light', 'switch', 'sensor', 'zwave', 'lock'] -%}
{%- for domain in domains if battery_level(domain) |trim != ""-%}
{{ battery_level(domain) }}{%- if not loop.last %}, {% endif -%}
{%- endfor -%}
- alias: battery_alert_clear
trigger:
- platform: time
minutes: '/30'
seconds: 00
condition:
- condition: template
value_template: >
{%- set threshold = 40 -%}
{% macro battery_level() %}
{% set domains = ['light', 'switch', 'sensor', 'zwave', 'lock'] %}
{% for domain in domains -%}
{% for item in states[domain] if ((item.attributes.battery_level is defined and item.attributes['battery_level'] | int < threshold) or ("battery" in item.name | lower and ((item.state | int < threshold and item.state|int != 0) or item.state | lower == "low" or item.state | lower == "unknown"))) -%}
{% if (item.attributes.battery_level is defined and item.attributes['battery_level'] | int < threshold) -%}
{{ item.name }}{% endif -%}
{% if "battery" in item.name | lower and ((item.state | int < threshold and item.state|int != 0) or item.state | lower == "low" or item.state | lower == "unknown") -%}
{{ item.name }}{% endif -%}
{% endfor %}
{%- endfor %}
{% endmacro %}
{{ battery_level() |trim == "" }}
action:
- service: persistent_notification.dismiss
data:
notification_id: low-battery-alert
Is it possible to create sensors for all battery powered devices? I got a tip about this thread but i used to use Script to track all devices with a battery_level but in that thread the author also indicates that it will not be used when he created a PR because they said use templating. So my question would be how can one still do that? Example output that thread would create:
(in all fairness this template does a better job at finding all battery powered devices) would be sweet to have a similar look too. (its better to get a feeling on battery levels by looking at them every now and then to know when the time is getting close to replace them)