Howto create battery alert without creating a template for every device

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

That’s great news.

It sends a notification via Slack when Home Assistant starts

I’ve created a few templates for battery status and they’re working fine, but I tried implementing “Battery Status” to roll everything up into one and I get “(unknown)” for everything.

I think the cuplrit may be that there’s an issue with my input_boolean.battery_status_update as I cannot see it in the drop-down when creating an automation to add the toggle for checking status. However, I do see it under dev tools > States. So I’m not sure about that…

Any ideas on what to check?

input_boolean: !include includes/input_boolean.yaml

battery_status_update:
  name: Battery Status Update

sensor: !include includes/sensors/templates.yaml

- 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', 'device_tracker'] -%}
        {%- 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 | l$
        {%- 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 -%}

image

Many thanks!

@gohassgo, it looks like a couple lines of your sensor yaml are cutoff. Can you try pasting it again?

One issue I can see is your “Battery Status” sensor is including itself, which is not desirable. You should add an additional test to exclude sensors named “Battery Status” near the test for sensors that have “battery” in their name. That doesn’t account for the other unknowns though…

Thanks…

I did find that some of the template config was missing a few pieces from your post earlier in this thread. I must’ve got the code from another thread… I updated it and here’s what’s there now:

    batt_status:
      friendly_name: "Batt Status"
      entity_id:
      - input_boolean.battery_status_update
      value_template: >
        {%- set threshold = 40 -%}
        {%- set domains = ['light', 'switch', 'sensor', 'zwave', 'lock', 'device_tracker'] -%}
        {%- 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 -%}

image

It’s also only showing the templates I manually created and none of the other devices that have a battery_level.

Your code seems to work fine on my system. Can you go to the states page (http://HOSTNAME/dev-state) filter for “battery”, then paste a screenshot here?

I’m not seeing what could be causing the issue. I’ve replaced your template with the latest version that I’m using. Can you try the code below? If it still doesn’t work, can you paste the jinja code below the value_template line into the Templated Dev page (http://HOSTNAME/dev-template) and let me know if you get the same thing?

    batt_status:
      friendly_name: "Batt Status"
      entity_id:
      - input_boolean.battery_status_update
      value_template: >
        {%- set threshold_high = 40 -%}
        {%- set threshold_low = -1 -%}
        {% 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 not "voltage" in item.name | lower and not "runtime" in item.name | lower and ((item.state | int < threshold_high and item.state | int > threshold_low) 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) 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', 'device_tracker'] -%}
        {%- for domain in domains if battery_level(domain) |trim != ""-%}
        {{ battery_level(domain) }}{%- if not loop.last %}, {% endif -%}
        {%- endfor -%}

The front end looks the same, but the code pasted into the dev-template page picks up one of the sensors. I manually deleted the remnant “Battery Status” sensor that was in customize.yaml.

image

Do you have an automation that’s forcing input_boolean.battery_status_update to toggle periodically? Since you’re referencing it in the template, it won’t update unless that input_boolean changes state.

Also, I found some issues with the code above that didn’t handle strings correctly. Here’s an updated version to try.

    batt_status:
      friendly_name: "Batt Status"
      entity_id:
      - input_boolean.battery_status_update
      value_template: >
        {%- set threshold_high = 40 -%}
        {%- set threshold_low = -1 -%}
        {% macro battery_level(domain) %}
        {%- for item in states[domain] if (item.attributes['battery_level'] is defined or ("battery" in item.name | lower and not "voltage" in item.name | lower and not "runtime" in item.name | lower )) -%}
        {% if (item.attributes['battery_level'] is defined and (item.attributes['battery_level'] is number or item.attributes['battery_level'] | length == item.attributes['battery_level'] | int | string | length) 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 != item.state | string and item.state | int < threshold_high and item.state | int > threshold_low) 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', 'device_tracker'] -%}
        {%- for domain in domains if battery_level(domain) |trim != ""-%}
        {{ battery_level(domain) }}{%- if not loop.last %}, {% endif -%}
        {%- endfor -%}
1 Like

For anyone using the package version of the alert, I’ve fixed some issues handling strings and some general cleanup.

Here is the latest version of the package:

################################################################
## 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 = -1 -%}
        {% macro battery_level() %}
        {% set domains = ['light', 'switch', 'sensor', 'zwave', 'lock', 'device_tracker'] %}
        {% for domain in domains -%}
        {%- for item in states[domain] if (item.attributes['battery_level'] is defined or ("battery" in item.name | lower and not "voltage" in item.name | lower and not "runtime" in item.name | lower )) -%}
        {% if (item.attributes['battery_level'] is defined and (item.attributes['battery_level'] is number or item.attributes['battery_level'] | length == item.attributes['battery_level'] | int | string | length) 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 is number or item.state | length == item.state | int | string | length) and item.state | int < threshold_high and item.state | int > threshold_low) 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 = -1 -%}
          {% macro battery_level(domain) %}
          {%- for item in states[domain] if (item.attributes['battery_level'] is defined or ("battery" in item.name | lower and not "voltage" in item.name | lower and not "runtime" in item.name | lower )) -%}
          {% if (item.attributes['battery_level'] is defined and (item.attributes['battery_level'] is number or item.attributes['battery_level'] | length == item.attributes['battery_level'] | int | string | length) 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 is number or item.state | length == item.state | int | string | length) and item.state | int < threshold_high and item.state | int > threshold_low) 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', 'device_tracker'] -%}
          {%- 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 = -1 -%}
              {% macro battery_level(domain) %}
              {%- for item in states[domain] if (item.attributes['battery_level'] is defined or ("battery" in item.name | lower and not "voltage" in item.name | lower and not "runtime" in item.name | lower )) -%}
              {% if (item.attributes['battery_level'] is defined and (item.attributes['battery_level'] is number or item.attributes['battery_level'] | length == item.attributes['battery_level'] | int | string | length) 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 is number or item.state | length == item.state | int | string | length) and item.state | int < threshold_high and item.state | int > threshold_low) 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', 'device_tracker'] -%}
              {%- 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 = -1 -%}
        {% macro battery_level() %}
        {% set domains = ['light', 'switch', 'sensor', 'zwave', 'lock', 'device_tracker'] %}
        {% for domain in domains -%}
        {%- for item in states[domain] if (item.attributes['battery_level'] is defined or ("battery" in item.name | lower and not "voltage" in item.name | lower and not "runtime" in item.name | lower )) -%}
        {% if (item.attributes['battery_level'] is defined and (item.attributes['battery_level'] is number or item.attributes['battery_level'] | length == item.attributes['battery_level'] | int | string | length) 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 is number or item.state | length == item.state | int | string | length) and item.state | int < threshold_high and item.state | int > threshold_low) 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
3 Likes

I do not have an automation for that.

That’s likely the issue then. The template won’t update if you don’t have the automation.

Alternatively, you can use the package version, which creates a persistent notification when batteries are low. It’s not quite the same as what you’re attempting to do, but maybe it’s good enough…