Howto create battery alert without creating a template for every device

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:

image

(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)

No, this won’t create the template sensors for you, but if you do create them, it should automatically alert on them if entity’s name contains battery.

One thing that could be done is to create a single template sensor similar to @tboyce1’s suggestion in Howto create battery alert without creating a template for every device, but make it include all entities that have betteries instead of just ones that are low. This wouldn’t be a clean as your screenshot, but it would give you a single place to look to see current battery status of everything.

I’ll give it a shot, i do like having both options. If i can manage, i’ll post it too of course. Have not done much with the templates :slight_smile:

It’s probably possible with either an automation, custom component, or python script that runs every so often and creates/updates template sensors for any sensor that has a battery level attribute. I may play around with this when I have some time if nobody comes up with a better solution before then.

If the custom component from the other thread works for what you want, there’s really nothing wrong with just keeping it in your custom components for personal use. You could possibly modify it to pick up the same battery levels as the templates.

I tried this and it is great.
Only got one problem.
I have sensors always reporting battery level 0. They don’t use battery.
Is there a way to not exclude those sensors? Like, set the minimum value to 1?

@xydix, Try this. I don’t have any devices that have 0, so I can’t fully test it.


################################################################
## 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_high = 40 -%}
        {%- set threshold_low = 0 -%}
        {% 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_high and item.attributes['battery_level'] | int > threshold_low) or ("battery" in item.name | lower and ((item.state | int < threshold_high and item.state | int > threshold_low 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_high and item.attributes['battery_level'] | int > threshold_low) -%}
        {{ item.name }}{% endif -%}
        {% if "battery" in item.name | lower and ((item.state | int < threshold_high and item.state | int > threshold_low 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_high = 40 -%}
          {%- set threshold_low = 0 -%}
          {% macro battery_level(domain) %}
          {%- for item in states[domain] if ((item.attributes.battery_level is defined and item.attributes['battery_level'] | int < threshold_high and item.attributes['battery_level'] | int > threshold_low) or ("battery" in item.name | lower and ((item.state | int < threshold_high 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_high and item.attributes['battery_level'] | int > threshold_low) -%}
          {{ item.name }} ({{ item.attributes['battery_level'] }}){%- if not loop.last %}, {% endif -%}{%- endif -%}
          {%- if "battery" in item.name | lower and ((item.state | int < threshold_high and item.state | int > threshold_low 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_high = 40 -%}
              {%- set threshold_low = 0 -%}
              {% macro battery_level(domain) %}
              {%- for item in states[domain] if ((item.attributes.battery_level is defined and item.attributes['battery_level'] | int < threshold_high and item.attributes['battery_level'] | int > threshold_low) or ("battery" in item.name | lower and ((item.state | int < threshold_high 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_high and item.attributes['battery_level'] | int > threshold_low) -%}
              {{ item.name }} ({{ item.attributes['battery_level'] }}){%- if not loop.last %}, {% endif -%}{%- endif -%}
              {%- if "battery" in item.name | lower and ((item.state | int < threshold_high and item.state | int > threshold_low 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_high = 40 -%}
        {%- set threshold_low = 0 -%}
        {% 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_high and item.attributes['battery_level'] | int > threshold_low) or ("battery" in item.name | lower and ((item.state | int < threshold_high and item.state | int > threshold_low 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_high and item.attributes['battery_level'] | int > threshold_low) -%}
        {{ item.name }}{% endif -%}
        {% if "battery" in item.name | lower and ((item.state | int < threshold_high and item.state | int > threshold_low 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
5 Likes

Thanks.
It solved my problem.
Now it is as expected.

1 Like

@NotoriousBDG

As a Newbie, and not a programmer, I pasted your code where I thought it was ment to be. It off course crashed the Rasp.Pi.

Think I missed this:
“…need to add device_tracker to the list of domains”.

How do I do this?

Please advise.

Create a folder under your config directory called packages. Save the yaml from Howto create battery alert without creating a template for every device as battery_alert.yaml, then add an include line under the homeassistant: section of your configuration.yaml. The documentation for packages is available at https://home-assistant.io/docs/configuration/packages/ if you need additional info.

homeassistant:
  packages: !include_dir_named packages

To add device_trackers, change every instance of this:

{% set domains = ['light', 'switch', 'sensor', 'zwave', 'lock'] %}

to this:

{% set domains = ['light', 'switch', 'sensor', 'zwave', 'lock', 'device_tracker'] %}
3 Likes

Thanks for you helping out.

I have a Fibaro Water Sensor (Vannsensor) and a Fibaro Smoke Sensor in my setup.
Your code shows this (looks like the Smoke Sensor is not present: Maybe battery level ok? ):

And when running “Confirguration - General - Check Config”, error is reported:
2017-12-19 22:28:25 INFO (MainThread) [homeassistant.setup] Setting up updater
2017-12-19 22:28:25 ERROR (MainThread) [homeassistant.config] Invalid config for [automation]: required key not provided @ data[‘action’]. Got None
required key not provided @ data[‘trigger’]. Got None. (See ?, line ?). Please check the docs at https://home-assistant.io/components/automation/
2017-12-19 22:28:26 ERROR (MainThread) [homeassistant.config] Invalid config for [automation]: not a valid value for dictionary value @ data[‘condition’][0][‘condition’]. Got None
required key not provided @ data[‘condition’][0][‘entity_id’]. Got None. (See ?, line ?). Please check the docs at https://home-assistant.io/components/automation/
2017-12-19 22:28:26 INFO (MainThread) [homeassistant.setup] Setting up sensor

(Hassio 0.60.0)

Yes, that’s likely. It should only complain about sensors that have low batteries.

This is complaining about an automation, but without seeing the config and corresponding line numbers it’s hard to say what’s wrong.

I have deleted the content in the battery_alert.yaml and pasted the code in once again. Still getting errors in the log(?)

My overview displays:
2017-12-20_11-31-09

My battery_alert.yaml and error log are attached:
Error log
Yaml
configuration.yaml

is the line in your “condition” statements just wrapping due to formatting in drop drop display or did you actually put in a before the word(s) “lower”?

There should be no there.

No wrapping.
If you download the yaml-file and open it in Notepad++, then it looks good.

Can you post a sanitized version of your configuration.yaml? The battery_alert.yaml looks fine. I’m wondering if the issue is how the package is being included.

Configuration file added to my post with the other files.

Maybe" packages: !include_dir_named packages" has to be directly under “homeassistant:”?
Updated: - Nope. That did not help

Here is the Hassio log:

I’m still not seeing anything that could cause that error. Do you have any automations in your automations.yaml? If you remove the package, does your config validate ok?

My automations.yaml is emty. When commenting out packages (#…packages: !include_dir_named packages), the Configuration Validation goes all fine (I am sorry to say)

I think I found the culprit. It’s the fact that you’ve got an empty automations.yaml file. Try adding an automation to that file then retry.

Here’s a simple one that I used to get your config to validate successfully.

- alias: Home Assistant Startup
  id: Home_Assistant_Startup
  trigger:
  - platform: homeassistant
    event: start
  action:
  - service: notify.slack_notify
    data:
      message: Home Assistant is up

You are absolutely right. This fixed the issue. All smiles.
Thanks so much!

My overview looks now like:

Just one thing, what does the “Automation - Home Assistant Startup” do?

1 Like