Howto create battery alert without creating a template for every device

I’m not sure this works with packages. Try placing it in the normal customize section.

Ok, so my battery_alert_disabled is in the normal customize section. The code I copied from @NotoriousBDG github is in a package.

Post a screenshot of your sensor.dans_ipad_battery_level entity from the dev-states panel please.

It is about 10 posts up. And thank you for your help @petro and @sjabby.

@pdobrien3, can you paste what you get from this on your templates page? This should list every entity_id that’s considered a battery.

{%- for item in states.sensor if (
  (
    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')
    )
  ) -%}
  {{ item.entity_id }}
  battery_alert_disabled: {{ is_state_attr(item.entity_id, 'battery_alert_disabled', true) }}
  name: {{ item.name }}
  state: {{ item.state }}
{% endfor -%}

It does, as well as accurately list the battery_alert_disabled status (true or false) for each entity_id that’s considered a battery. It also lists the friendly name and battery percentage. I don’t think it is anything wrong with your code. I think it has something to do with my setup. What else, within my setup could affect this? Does it matter where the package include is listed in the config.yaml?
Like this doesn’t seem right but it is the only way it passes the config check:

homeassistant
  customize: !include customize.yaml
  packages: !include_dir_named packages
group: !include groups.yaml
automation: !include automations.yaml

That looks correct.

Do you have an automation in another package or in automations.yaml that could be notifying you?

No sir…

I’m at a loss. I’ve reviewed the code, and it definitely looks correct. I personally use that feature, and it’s working perfectly. Your sensor has the attribute needed to prevent it from being included in the notification. Since you don’t have duplicate sensors or other automations notifying you of batteries, I can’t think of what else could be causing it.

I’ve just tested and doesn’t work for me either. Shows the battery_alert_disabled as true but devices still displayed.

On 74.2, and now 75.1

Well that is promising. Maybe we can figure it out together.

Seems to be an error in the code. Once I am sure I fixed it I’ll submit a patch, but have what looks like a fix now…

That’s great to hear. Please let us know what you’ve found.

Here’s what’s working for me. I am using your auto-group automation modified to respect the entities flagged to ignore and that as the group to use for the notification triggers. For some reason I had to duplicate the macros to eliminate some undefined errors which I’m still tracking down. Are macros scope just to the automation defined or global?

- alias: battery_notification
  initial_state: True

  trigger:
    - platform: template
      value_template: >-
        {%- macro battery_level() -%}
          {% for entity_id in states.group.battery_status.attributes.entity_id if states(entity_id) | int < states.input_number.battery_alert_threshold_max.state | int %}
           {%- set domain, device = entity_id.split('.') -%}
           {{ states[domain][device].name }} ({{ states[domain][device].state }}%)             
          {% endfor %}
        {%- endmacro -%}
        {{ battery_level() | trim != "" }}

  condition:
    - condition: template
      value_template: "{{ not is_state('persistent_notification.low_battery_alert', 'notifying') }}"
 
  action:
    - service: persistent_notification.create
      data_template:
        title: "Low Battery levels"
        notification_id: low_battery_alert
        message: &message >-
          {%- macro battery_level() -%}
            {% for entity_id in states.group.battery_status.attributes.entity_id if states(entity_id) | int < states.input_number.battery_alert_threshold_max.state | int %}
             {%- set domain, device = entity_id.split('.') -%}
             {{ states[domain][device].name }} ({{ states[domain][device].state }}%)             
            {% endfor %}
          {%- endmacro -%}
          {{ battery_level() }}

    - wait_template: "{{ is_state('script.notify_ios_engine' , 'off') }}"
      timeout: '00:00:30'

    - service: script.notify_ios_engine
      data_template:
        message: *message
        who: "john"

#######################################################

- alias: battery_notification_clear
  initial_state: True

  trigger:
     - platform: template
       value_template: >-
        {%- macro battery_level() -%}
          {% for entity_id in states.group.battery_status.attributes.entity_id if states(entity_id) | int < states.input_number.battery_alert_threshold_max.state | int %}
           {%- set domain, device = entity_id.split('.') -%}
           {{ states[domain][device].name }} ({{ states[domain][device].state }}%)             
          {% endfor %}
        {%- endmacro -%}
        {{ battery_level() | trim == "" }}

  condition:
    - condition: template
      value_template: "{{ is_state('persistent_notification.low_battery_alert', 'notifying') }}"
    
  action:
    - service: persistent_notification.dismiss
      data:
        notification_id: low_battery_alert

#######################################################    

- alias: update_battery_status_group_members
  initial_state: True

  trigger:
    - platform: event
      event_type: state_changed
      
  condition:
    - condition: template
      value_template: "{{ trigger.event.data is not none }}"
    - condition: template
      value_template: "{{ trigger.event.data.new_state is not none }}"
    - condition: template
      value_template: "{{ trigger.event.data.new_state.attributes is not none }}"
    - condition: template
      value_template: "{{ trigger.event.data.old_state is not none }}"
    - condition: or
      conditions:
        - condition: template
          value_template: "{{ is_state_attr(trigger.event.data.entity_id, 'device_class', 'battery') }}"
        - condition: template
          value_template: "{{ is_state_attr(trigger.event.data.entity_id, 'icon', 'mdi:battery') }}"
        - condition: template
          value_template: "{{ is_state_attr(trigger.event.data.entity_id, 'icon', 'mdi:battery-alert') }}"
        - condition: template
          value_template: "{{ is_state_attr(trigger.event.data.entity_id, 'icon', 'mdi:battery-unknown') }}"
        - condition: and
          conditions:
          - condition: template
            value_template: "{{ trigger.event.data.new_state.attributes.icon is defined }}"
          - condition: template
            value_template: "{{ 'battery' in trigger.event.data.new_state.attributes.icon | lower }}"
          - condition: or
            conditions:
            - condition: template
              value_template: "{{ 'battery' in trigger.event.data.entity_id | lower }}"
            - condition: template
              value_template: "{{ 'battery' in trigger.event.data.new_state.name | lower }}"
        - condition: template
          value_template: "{{ (trigger.event.data.entity_id | lower).endswith('_bat') }}"
        - condition: template
          value_template: "{{ (trigger.event.data.new_state.name | lower).endswith('_bat') }}"
       
  action:
    - service: group.set
      data_template:
        object_id: "battery_status"
        entities: >-
          {%- for item in states.sensor if (
            is_state_attr(item.entity_id, 'device_class', 'battery')
          ) and ( 
            not is_state_attr(item.entity_id, 'battery_alert_disabled', true )
          ) -%}
            {{ item.entity_id }}{% if not loop.last %}, {% endif %}
          {%- endfor -%}

Has anyone been able to create a Pushover notification with the newer code? I was successful in creating one when the code was simpler, but it’s over my head now.

Changes to use pushover:

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_pushover                    -   Remove old and add this line
      - automation.battery_sensor_from_battery_level_attribute
      - automation.battery_sensor_from_battery_attribute
      - automation.battery_sensor_from_battery_numeric_attribute
      - automation.update_battery_status_group_members

Change the automation:

- alias: battery_notification_pushover
  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.pushover
      data_template:
        title: "These devices have low battery levels"
        message: *message

and in the customize section:

    automation.battery_notification_pushover:
      <<: *customize
      friendly_name: "Battery Notification Pushover"
      icon: mdi:comment-alert-outline
1 Like

Release 1.1.0 is now available. I did quite a bit of refactoring in this release in an attempt to clean up the code a bit plus fix the issue discovered by @pdobrien3 and fix an issue with the Battery Status Group automation running more frequently than necessary.

There is a breaking change caused by the addition of attributes on the MQTT sensors. You’ll either need to clear the retained MQTT topics, uninstall/re-install the Mosquitto addon, or restart Home Assistant after the first state change on the existing battery sensors. These new attributes should make troubleshooting easier.

Battery sensors created by the package will now have 4 attributes.
entity_id: The entity_id that the sensor was created from
attribute: The attribute on the source entity_id that contains battery level state
mqtt_config_topic: The MQTT topic used for MQTT discovery
mqtt_state_topic: The MQTT topic that contains the sensor’s state

Full Changelog

Added

  • Added Batteries view
  • Added Telegram notification automation
  • Added Pushover notification automation
  • Added attributes to battery entities created via mqtt: entity_id, attribute, mqtt_config_topic, and mqtt_state_topic

Changed

  • Simplified trigger for update_battery_status_group_members automation
  • Refactored conditions on automations to rely on group.battery_status members

I was finally able to reproduce your issue, and I’ve incorporated the fix into the 1.1.0 release. I think I just needed to step back a bit and look at it with fresh eyes. Please let me know if you still have the problem.

I like your idea of relying on the group for the list of sensors. There’s no need to continually look for them since the group already does that. I’ve incorporated that into the 1.1.0 release.

The scope of a macro is only within a single template. I do use yaml anchors (&low_battery_check) and references (*low_battery_check) to eliminate some of the duplication.

I’ve incorporated this into the latest package. It’s essentially the same as what @sjabby posted above.

1 Like

@jwelter, I appreciate you working on this but now I am confused. Did you use @NotoriousBDG’s package and just substitute your automations?

Unfortunately I do not want to use MQTT to discover the battery sensors. I realize that is the position this thread has taken and by no means want to change what is working for a lot of people. I am trying to mesh both together and get something that works for me though.

The code I posted will work to auto create a group and set notifications/clear notifications if you have sensors setup to report the battery levels. These can be manually configured, use one of the other auto creation methods, or use the rest of the code in the package in this thread to use mqtt to set them up.