#:########################################################################################:# # Battery Notes Alerts Package # #:########################################################################################:# # # TITLE: # Battery Notes Alerts # # FILE: # packages/battery_notes_alerts.yaml # # VERSION: # V1.0.0 2026-08-25 # # PURPOSE: # Sends immediate and weekly Pushover alerts for non-temporary Battery Notes devices. # Device lists are generated from Battery Notes at runtime, so adding a note starts # monitoring the device without maintaining a second entity list. # # CONTROLS: # - Battery Notes - Immediate Alert and Battery Notes - Weekly Digest are independent # automation entities. Each can be enabled or disabled in Home Assistant Automations. # # DEPENDENCIES: # - Battery Notes integration # - packages/view_road_announcement_router.yaml # # VERSION HISTORY: # - V1.0.0 2026-08-25: Initial immediate and Thursday weekly battery alerts. # #:########################################################################################:# automation: - id: battery_notes_immediate_alert alias: "Battery Notes - Immediate Alert" description: > Sends a Pushover alert when a monitored Battery Notes device newly reports low battery or becomes unavailable. Temporary Battery Notes devices are ignored. mode: queued max: 10 triggers: - trigger: event event_type: state_changed conditions: - condition: template value_template: >- {{ trigger.event.data.entity_id is match('^(sensor|binary_sensor)\\..*_battery_plus(?:_low)?$') }} - condition: template value_template: >- {% set old = trigger.event.data.old_state %} {% set new = trigger.event.data.new_state %} {{ old is not none and new is not none and old.state not in ['unknown', 'unavailable'] and old.state != new.state }} - condition: template value_template: >- {% set note = trigger.event.data.new_state.attributes.note | default('', true) | lower %} {{ trigger.event.data.new_state.attributes.device_id is defined and 'temporary' not in note }} - condition: template value_template: >- {% set old = trigger.event.data.old_state %} {% set new = trigger.event.data.new_state %} {% set device_id = new.attributes.device_id %} {% set is_percentage = new.entity_id.startswith('sensor.') and new.entity_id.endswith('_battery_plus') %} {% set companion = namespace(percentage=none) %} {% for item in states %} {% if item.attributes.device_id | default('') == device_id and item.entity_id.startswith('sensor.') and item.entity_id.endswith('_battery_plus') %} {% set companion.percentage = item %} {% endif %} {% endfor %} {% set source = companion.percentage if companion.percentage else new %} {% set qualitative_id = source.entity_id | replace('_battery_plus_low', '_battery_state') | replace('_battery_plus', '_battery_state') %} {% set qualitative = states[qualitative_id] %} {% set qualitative_available = qualitative is not none and qualitative.state in ['high', 'medium', 'low'] %} {% set newly_low = (new.attributes.battery_low | default(false)) and not (old.attributes.battery_low | default(false)) %} {% set newly_binary_low = new.entity_id.startswith('binary_sensor.') and new.state == 'on' %} {% set newly_unavailable = new.state in ['unknown', 'unavailable'] and source.entity_id == new.entity_id and not qualitative_available %} {{ newly_low or newly_binary_low or newly_unavailable }} variables: alert_name: >- {% set new = trigger.event.data.new_state %} {{ new.attributes.device_name | default(new.attributes.friendly_name, true) | default(new.name, true) }} alert_type: >- {% set new = trigger.event.data.new_state %} {{ new.attributes.battery_type_and_quantity | default('Not recorded', true) }} alert_level: >- {% set new = trigger.event.data.new_state %} {% set device_id = new.attributes.device_id %} {% set level = namespace(value=none) %} {% for item in states %} {% if item.attributes.device_id | default('') == device_id and item.entity_id.startswith('sensor.') and item.entity_id.endswith('_battery_plus') and item.state not in ['unknown', 'unavailable'] %} {% set level.value = item.state %} {% endif %} {% endfor %} {{ level.value ~ '%' if level.value is not none else '' }} alert_line: >- {% set new = trigger.event.data.new_state %} {% if new.state in ['unknown', 'unavailable'] %} New Alert: {{ alert_name }}, Battery Unavailable {{ alert_type }} {% else %} New Alert: {{ alert_name }}, Battery Low {{ alert_level }} {{ alert_type }} {% endif %} alert_summary: &battery_notes_summary >- {% set monitored = namespace(device_ids=[], low=[], unavailable=[]) %} {% for item in states %} {% set note = item.attributes.note | default('', true) | lower %} {% set device_id = item.attributes.device_id | default('') %} {% if item.entity_id is match('^(sensor|binary_sensor)\\..*_battery_plus(?:_low)?$') and device_id and 'temporary' not in note and device_id not in monitored.device_ids %} {% set monitored.device_ids = monitored.device_ids + [device_id] %} {% set device = namespace(percentage=none, low_sensor=none) %} {% for candidate in states %} {% if candidate.attributes.device_id | default('') == device_id %} {% if candidate.entity_id.startswith('sensor.') and candidate.entity_id.endswith('_battery_plus') %} {% set device.percentage = candidate %} {% elif candidate.entity_id.startswith('binary_sensor.') and candidate.entity_id.endswith('_battery_plus_low') %} {% set device.low_sensor = candidate %} {% endif %} {% endif %} {% endfor %} {% set source = device.percentage if device.percentage else device.low_sensor %} {% set qualitative_id = source.entity_id | replace('_battery_plus_low', '_battery_state') | replace('_battery_plus', '_battery_state') %} {% set qualitative = states[qualitative_id] %} {% set qualitative_state = qualitative.state if qualitative is not none else '' %} {% set name = source.attributes.device_name | default(source.attributes.friendly_name, true) | default(source.name, true) %} {% set battery_type = source.attributes.battery_type_and_quantity | default('Not recorded', true) %} {% set low = source.attributes.battery_low | default(false) or (device.low_sensor is not none and device.low_sensor.state == 'on') or qualitative_state == 'low' %} {% set unavailable = source.state in ['unknown', 'unavailable'] and qualitative_state not in ['high', 'medium', 'low'] %} {% if low %} {% set level = source.state ~ '%' if device.percentage is not none and source.state not in ['unknown', 'unavailable'] else '' %} {% set monitored.low = monitored.low + [name ~ ' (' ~ level ~ (', ' if level else '') ~ battery_type ~ ')'] %} {% endif %} {% if unavailable %} {% set monitored.unavailable = monitored.unavailable + [name ~ ' (' ~ battery_type ~ ')'] %} {% endif %} {% endif %} {% endfor %} Summary: {{ monitored.device_ids | count }} Battery Notes devices, {{ monitored.unavailable | count }} unavailable, {{ monitored.low | count }} battery low. Low Battery Devices: {{ monitored.low | join(', ') if monitored.low else 'None' }} Unavailable Devices: {{ monitored.unavailable | join(', ') if monitored.unavailable else 'None' }} actions: - action: script.view_road_announcement data: channels: "pushover_zorruno" title: "Battery Alert" short_announcement: "{{ alert_line }}" long_announcement: >- {{ alert_line }} {{ alert_summary }} - id: battery_notes_weekly_digest alias: "Battery Notes - Weekly Digest" description: > Sends the Battery Notes health summary to Pushover every Thursday at 19:00. Temporary Battery Notes devices are excluded. mode: single triggers: - trigger: time at: "19:00:00" conditions: - condition: time weekday: - thu variables: alert_summary: *battery_notes_summary actions: - action: script.view_road_announcement data: channels: "pushover_zorruno" title: "Weekly Battery Digest" short_announcement: "Weekly Battery Digest" long_announcement: "{{ alert_summary }}"