Howto create battery alert without creating a template for every device

Your screenshot showed that the attribute was set correctly. Can you confirm you’re running the latest code from github? Can you also search the attributes column on your states page (http://hassio.local:8123/dev-state) for the friendly name of sensor.my_iphone_battery_level to make sure you don’t have a duplicate sensor created by MQTT discovery?

Perfect. That’s one of the main reasons I added that feature.

I rarely use the Home Assistant UI, so I haven’t even looked at lovelace yet. I’ll set it up so I can see if I can figure out what’s happening there.

Thank you for your assistance with this. I am running the latest code and only one of the sensors shows up on the states page. I know I have said it before but I want to make sure, I am not using MQTT discovery. Everything else but…I am also using notify.notify instead of slack but the sensors show up in both notify and persistent notifications. Are you using the battery_alert_disabled: true in your setup?

I also found out the the input_number errors on lovelace are related to using safari or firefox. When I use Chrome there are no errors. The issue has already been reported.

Thanks for confirming. I need to review the code again to see if there is a bug somewhere. I need to see your screenshot showing the attributes again so I can try to repro the problem. It looks like it’s been deleted.

Yes, I use it to disable alerts for my phone battery, just like you’re attempting to do.

Good to hear that it’s not an issue with the package.

I’m a little late to the thread, but you can simply your macro by not even calling out the domains because your for loop that searches for battery_level will remove every domain that doesn’t have that attribute:

{%- for item in states if (item.attributes.battery_level is defined) %}
{{ item.name }} #Do your message stuff here.
{%- endfor -%}

Capture

I no longer loop through all domains looking for battery_level attributes in the current version, so that doesn’t really apply anymore. That’s a useful tip though. I definitely have a use case for it.

You can see the latest code at Home-AssistantConfig/packages/battery_alert.yaml at master · notoriousbdg/Home-AssistantConfig · GitHub.

Yeah, I stumbled across your previous post after I posted my response. Looks good.

1 Like

Fantastic script. Do you know why xiaomi sensors doesn’t appear?
Regards,

his script handles just about everything. What does your xiaomi sensors look like? Do they have the battery device_class?

It works! Sorry its my fault :frowning:
Seems that xiaomi devices took some time to appear
Regards,

1 Like

I think the device needs to have a state change for it to be recognized. I noticed that a little late in the game. When I get a minute, I am going to try and take the mdi:battery off of one of my sensors and see if I can’t generate a state change for it to be recognized.

Here is the screen shot.

@petro, I played around today with the template editor and your code. It hit on all the right entities. Any chance you could help me make it into something similar to what NotoriousBDG has done but simplified. I am just looking for some simple automation to notify me when a battery gets low. I only have like 5 batteries and they all came up with:

{%- for item in states if (item.attributes.battery_level is defined) %}
{{ item.name }} 
{%- endfor -%}

Just not really sure where to go from there. Once started and understood, I could build on it.

Thanks

Yeah, it can be tough.

automation:
- alias: battery notifier
  trigger:
    - platform: time
      minutes: '/15'
      seconds: 00
  condition:
    - condition: template
      value_template: >
        # this is the threshold, if the battery goes below 10, the alert will occur.
        {% set battery_alert_threshold = 10 %}
        # the next templateline is complicated.  It selects
        # the any objects that have the battery attribute.  Then compares the battery
        # attribute to the battery_alert_threshold.  If the battery is less than the threshold
        # it adds the item to a list.  If the list is greater than or equal to 1 item, 
        # the template will return True, otherwise false.
        {{ states | selectattr('attributes.battery_level', 'defined') | selectattr('attributes.battery_level','<', battery_alert_threshold ) | list | length >= 1 }}
  action:
    - service: notify.notify
      data_template:
        title: "Batteries low"
        message: >
          {% set low_batteries = states | selectattr('attributes.battery_level', 'defined') | selectattr('attributes.battery_level','<', battery_alert_threshold ) | map(attribute='name') | list | join(', ') %}
          Low batteries in the following devices: {{ low_batteries }}

Looking at it now, it doesn’t seem much simpler. But it should send you messages.

Thank you @petro

Any other ideas @NotoriousBDG?

Ok, I have been playing around with the template editor. If everything was correct with my battery_alert_disabled: true setup, shouldn’t this template report true?

   {% macro battery_level() %}
    {%- for item in states.sensor if (
    (
    is_state_attr('item.entity_id', 'battery_alert_disabled', 'true')
    )
    ) -%}
    {% endfor -%}
    {% endmacro %}
    {{ battery_level() | trim != ""}}

that is all sorts of wrong.

in @NotoriousBDG’s file, he’s using a input_boolean to decide weather or not to send the notification.

The is_state_attr() method looks inside the states and returns an entitys attribute specified in the call.

The first requirement is the entity_id, the second is the attribute, and the 3rd is the result of what you expect it to be.

You are feeding it a string ‘item.entity_id’ and a result string of ‘true’. I can guarentee you don’t have a entity id that is ‘item.entity_id’. If you are trying to grab the variable item (coming from the for loop), then you need to remove the quotes on that.

Second, you are evaluating a true/false, you need to evaluate against true/false, not a string of true or a string of false. So remove the quotes from that.

Third, the ‘battery_alert_disabled’ attribute will only be used if you customize the entity to have that attribute. Did you do that?

Lastly, why aren’t you just following @NotoriousBDG’s installation process and using his code in the link he supplied? Copy and Paste? It should work without you having to deal with all this…

I did copy and paste his code. It works for everything but the items in customize that I have put battery_alert_disabled: true.

So I am trying to figure out why.

Because that disables the alert… So it won’t work on those? That’s the point of that customization. Turn that to false and they will work.

But I don’t want them to work and they do!!!

can you post your customization?

sensor.dans_ipad_battery_level:
  battery_alert_disabled: true

and here is my package:

homeassistant:
  customize:
    ################################################
    ## Node Anchors
    ################################################

    package.node_anchors:
      customize: &customize
        package: 'battery_alert'
        
    ################################################
    ## Group
    ################################################

    group.battery_alert:
      <<: *customize
      friendly_name: "Battery Alert"
      icon: mdi:steam
      
    group.battery_status:
      <<: *customize
      friendly_name: "Battery Status"
      icon: mdi:battery-charging     
      control: hidden

    ################################################
    ## Automation
    ################################################

    automation.battery_notification:
      <<: *customize
      friendly_name: "Battery Notification"
      icon: mdi:comment-alert-outline

    automation.battery_notification_clear:
      <<: *customize
      friendly_name: "Battery Notification Clear"
      icon: mdi:comment-remove-outline

    automation.battery_notification_text:
      <<: *customize
      friendly_name: "Battery Notification Text"
      icon: mdi:comment-alert-outline

    automation.update_battery_status_group_members:
      <<: *customize
      friendly_name: "Update Battery Status Group Members"
      icon: mdi:group

################################################
## Group
################################################

group:
  battery_alert:
    control: hidden
    entities:
      - input_number.battery_alert_threshold_min
      - input_number.battery_alert_threshold_max
      - automation.battery_notification
      - automation.battery_notification_clear
      - automation.battery_notification_text
#      - automation.update_battery_status_group_members

################################################
## Input Number
################################################

input_number:
  battery_alert_threshold_max:
    name: "Max Alert Threshold"
    icon: mdi:arrow-collapse-up
    mode: slider
    min: -1
    max: 100
    # initial: 40

  battery_alert_threshold_min:
    name: "Min Alert Threshold"
    icon: mdi:arrow-collapse-down
    mode: slider
    min: -1
    max: 100
    # initial: -1

################################################
## Automation
################################################

automation:
- alias: battery_notification
  trigger:
    - platform: time
      minutes: '/15'
      seconds: 00
    - platform: state
      entity_id:
        - input_number.battery_alert_threshold_min
        - input_number.battery_alert_threshold_max
  condition:
    - condition: template
      value_template: "{{ not is_state('persistent_notification.low_battery_alert', 'notifying') }}"
  action:
    - condition: template
      value_template: &low_battery_check >
        {% macro battery_level() %}
        {%- for item in states.sensor if (
          (
            not is_state_attr(item.entity_id, 'battery_alert_disabled', true)
          ) and (
            is_state_attr(item.entity_id, 'device_class', 'battery')
            ) or (
              is_state_attr(item.entity_id, 'icon', 'mdi:battery')
            ) or (
              is_state_attr(item.entity_id, 'icon', 'mdi:battery-alert')
            ) or (
              is_state_attr(item.entity_id, 'icon', 'mdi:battery-unknown')
            ) or (
              'battery' in item.entity_id | lower
              and item.attributes.icon is defined
              and 'battery' in item.attributes.icon | lower
            ) or (
              'battery' in item.name | lower
              and item.attributes.icon is defined
              and 'battery' in item.attributes.icon | lower
            ) or (
              (item.entity_id | lower).endswith('_bat')
            ) or (
              (item.name | lower).endswith('_bat')
            )
          ) and (
            (
              (
                item.state is number
                or item.state | length == item.state | int | string | length
                or item.state | length == item.state | float | string | length
              )
              and item.state | int < states.input_number.battery_alert_threshold_max.state | int
              and item.state | int > states.input_number.battery_alert_threshold_min.state | int
            )
            or item.state | lower == 'low'
            or item.state | lower == 'unknown'
          ) -%}
          {{ item.name }} ({{ item.state }})
        {% endfor -%}
        {% endmacro %}
        {{ battery_level() | trim != "" }}
    - service: persistent_notification.create
      data_template:
        title: "Low Battery Levels"
        notification_id: low_battery_alert
        message: &message >
          {% macro battery_level() %}
          {%- for item in states.sensor if (
            (
              not is_state_attr(item.entity_id, 'battery_alert_disabled', true)
            ) and (
              is_state_attr(item.entity_id, 'device_class', 'battery')
              ) or (
                is_state_attr(item.entity_id, 'icon', 'mdi:battery')
              ) or (
                is_state_attr(item.entity_id, 'icon', 'mdi:battery-alert')
              ) or (
                is_state_attr(item.entity_id, 'icon', 'mdi:battery-unknown')
              ) or (
                'battery' in item.entity_id | lower
                and item.attributes.icon is defined
                and 'battery' in item.attributes.icon | lower
              ) or (
                'battery' in item.name | lower
                and item.attributes.icon is defined
                and 'battery' in item.attributes.icon | lower
              ) or (
                (item.entity_id | lower).endswith('_bat')
              ) or (
                (item.name | lower).endswith('_bat')
              )
            ) and (
              (
                (
                  item.state is number
                  or item.state | length == item.state | int | string | length
                  or item.state | length == item.state | float | string | length
                )
                and item.state | int < states.input_number.battery_alert_threshold_max.state | int
                and item.state | int > states.input_number.battery_alert_threshold_min.state | int
              )
              or item.state | lower == 'low'
              or item.state | lower == 'unknown'
            ) -%}
            {{ item.name }} ({{ item.state }})
          {% endfor -%}
          {% endmacro %}
          {{ battery_level() }}

- alias: battery_notification_clear
  trigger:
    - platform: time
      minutes: '/15'
      seconds: 00
    - platform: state
      entity_id:
        - input_number.battery_alert_threshold_min
        - input_number.battery_alert_threshold_max
  action:
    - condition: template
      value_template: &low_battery_clear >
        {% macro battery_level() %}
        {%- for item in states.sensor if (
          (
            not is_state_attr(item.entity_id, 'battery_alert_disabled', true)
          ) and (
            is_state_attr(item.entity_id, 'device_class', 'battery')
            ) or (
              is_state_attr(item.entity_id, 'icon', 'mdi:battery')
            ) or (
              is_state_attr(item.entity_id, 'icon', 'mdi:battery-alert')
            ) or (
              is_state_attr(item.entity_id, 'icon', 'mdi:battery-unknown')
            ) or (
              'battery' in item.entity_id | lower
              and item.attributes.icon is defined
              and 'battery' in item.attributes.icon | lower
            ) or (
              'battery' in item.name | lower
              and item.attributes.icon is defined
              and 'battery' in item.attributes.icon | lower
            ) or (
              (item.entity_id | lower).endswith('_bat')
            ) or (
              (item.name | lower).endswith('_bat')
            )
          ) and (
            (
              (
                item.state is number
                or item.state | length == item.state | int | string | length
                or item.state | length == item.state | float | string | length
              )
              and item.state | int < states.input_number.battery_alert_threshold_max.state | int
              and item.state | int > states.input_number.battery_alert_threshold_min.state | int
            )
            or item.state | lower == 'low'
            or item.state | lower == 'unknown'
          ) -%}
          {{ item.name }} ({{ item.state }})
        {% endfor -%}
        {% endmacro %}
        {{ battery_level() | trim == "" }}
    - service: persistent_notification.dismiss
      data:
        notification_id: low_battery_alert

- alias: battery_notification_text
  trigger:
    - platform: time
      at: '10:00:00'
    - platform: time
      at: '18:00:00'
    - platform: state
      entity_id:
        - input_number.battery_alert_threshold_min
        - input_number.battery_alert_threshold_max
  action:
    - condition: template
      value_template: *low_battery_check
    - service: notify.dandm
      data_template:
        message: *message
        title: "Silly Humans - Low Battery Levels"