Skip to content

Instantly share code, notes, and snippets.

@jsternadel
Last active August 12, 2018 20:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jsternadel/29ed6a6e245629e77a59a232b08956b5 to your computer and use it in GitHub Desktop.
Save jsternadel/29ed6a6e245629e77a59a232b08956b5 to your computer and use it in GitHub Desktop.
Battery Notification with custom MQTT topic and HTML5 nofitications
################################################################
## Packages / Battery Alert
################################################################
################################################################
## Changelog
################################################################
##
## 1.0.0 (2018-02-14)
## Added
## - Added version number to enable better tracking
##
## 1.0.1 (2018-02-15)
## Added
## - Added battery_sensor_creation_disabled attibute to skip
## creating a battery sensor even when an battery attribute
## exists.
##
## 1.0.2 (2018-04-06)
## Added
## - Added battery icon to sensors.
##
## 1.0.3 (2018-05-10)
## Changed
## - Change device_class to battery and remove icon, which
## allows dynamic icons in 0.69.
##
## 1.0.4 (2018-05-11)
## Changed
## - Fixed condition battery_sensor_creation_disabled condition
## Added
## - Documented a jinja template that can be use to assist
## with creating a group containing all battery sensors.
##
## 1.0.5 (2018-05-14)
## Changed
## - Changed formatting of notifications to improve readability
## - Nofity via Slack immediately when thresholds are modified
## Added
## - Entities with device_class of battery no longer need
## battery in their friendly name to be monitored
## - Don't create a battery sensor from an entity if
## device_class is battery
##
## 1.0.6 (2018-05-14)
## Changed
## - Added object_id to notifications
## - Updated Battery Status group jinja code to check for
## battery device_class
##
## 1.0.7 (2018-05-16)
## Added
## - Added unique_id to disambiguate sensors with duplicate
## names
## - Added source info to mqtt config topic
## - Consider friendly names and entity_ids that end with _bat
## as a battery sensor (needed for rflink battery sensors)
## - Consider entities with icon of battery, battery-alert, or
## battery-unknown as a battery sensor regardles of its name
## - Consider entity_ids containing battery as a battery sensor
## Changed
## - Reduce code duplication using yaml anchors and references
## - Changed MQTT topic to be based on entity_id
## - Improve method of filtering non-battery devices that have
## battery in their name. Detection is now based on icon
## rather than keywords.
##
## 1.0.8 (2018-06-01)
## Added
## - Add support for defining battery_template attibute to
## allow manipulation of value of battery sensor
## - Support battery attributes that contain strings
## Removed
## - Cleaned up notifications by removing object id
##
## 1.0.9 (2018-06-08)
## Added
## - Automatically create Battery Status group containing all
## discovered batteries
## Removed
## - Removed sample jinja to create battery status group yaml
##
## 1.0.10 (2018-06-08)
## Added
## - Moved group.update_battery_status_group_members to Battery
## Alert group
##
## 1.1.0 (2018-08-09)
## 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
## Breaking Changes
## - The attribute additions requires restarting Home Assistant
## after the first state change or clearing retained MQTT topics
##
## 1.1.1 (2018-08-11)
## Added
## - Added input text box named `MQTT Topic to Clear`, which can be used
## to clear MQTT topics with retained messages
## - Set initial_state to on for all automations to ensure they are enabled
## on startup
## Changed
## - Consider entities with battery in their entity_id or friendly_name a
## battery sensor if neither an icon nor a device class is defined
## - Consolidated the battery_sensor_from_* automations into a single
## automation
##
################################################################
################################################################
## Install Instructions
################################################################
##
## 1. Enable MQTT using your preferred MQTT broker
## https://home-assistant.io/components/mqtt/
##
## 2. Enable MQTT Discovery by adding `discovery: true` and
## `discovery_prefix: homeassistant` under the `mqtt:` section
## of your configuration.yaml
##
## mqtt:
## discovery: true
## discovery_prefix: homeassistant
##
## 3. Save this file as CONFIGDIR/packages/battery_alert.yaml
##
## 4. Add `packages: !include_dir_named packages` under the
## `homeassistant:` section of your configuration.yaml
##
## homeassistant:
## packages: !include_dir_named packages
##
## 5. Restart Home Assistant
##
## 6. Adjust Min Alert Threshold slider to the minimum battery
## level to alert on. Note: the input slider requires the
## recorder component to keep it's state through restarts.
## If recorder is not enabled, the threshold can be set by
## un-remarking `initial` and setting the preferred default.
##
## 7. Adjust Max Alert Threshold slider to the maximum battery
## level to alert on. Note: the input slider requires the
## recorder component to keep it's state through restarts.
## If recorder is not enabled, the threshold can be set by
## un-remarking `initial` and setting the preferred default.
##
## 8. To disable alerts for a specific entity, use customize to
## set `battery_alert_disabled` to `true`
##
## homeassistant:
## customize:
## sensor.sensor_name_to_ignore_battery:
## battery_alert_disabled: true
##
## 9. To disable creating a sensor from battery attributes for a specific entity, use customize to
## set `battery_sensor_creation_disabled` to `true`
##
## homeassistant:
## customize:
## sensor.sensor_with_battery_attibute:
## battery_sensor_creation_disabled: true
##
## 10. If a battery attribute requires a template to convert it into a usable percent
## or string, use customize to add `battery_template` with the necessary template.
## The template should result in either a percentage or a string ("Low" will
## trigger low battery notification).
##
## This example will create a battery sensor with the value of battery_level * 2
##
## homeassistant:
## customize:
## sensor.sensor_with_battery_attibute_template:
## battery_template: "{{ value_json.value | int * 2 }}"
##
## This example will create a battery sensor that contains "Low" if battery_level
## is less than 2
##
## homeassistant:
## customize:
## sensor.sensor_with_battery_attibute_template:
## battery_template: >-
## {%- if value < 2 -%}
## "Low"
## {%- else -%}
## "Full"
## {%- endif -%}
##
################################################################
################################################
## Customize
################################################
homeassistant:
customize:
################################################
## Node Anchors
################################################
package.node_anchors:
customize: &customize
package: 'battery_alert'
################################################
## Group
################################################
group.battery_view:
<<: *customize
friendly_name: "Batteries"
icon: mdi:battery-alert
group.battery_alert:
<<: *customize
friendly_name: "Battery Alert"
icon: mdi:steam
control: hidden
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_slack:
<<: *customize
friendly_name: "Battery Notification Slack"
icon: mdi:comment-alert-outline
automation.battery_notification_telegram:
<<: *customize
friendly_name: "Battery Notification Telegram"
icon: mdi:comment-alert-outline
automation.battery_notification_pushover:
<<: *customize
friendly_name: "Battery Notification Pushover"
icon: mdi:comment-alert-outline
automation.battery_notification_html5:
<<: *customize
friendly_name: "Battery Notification HTML5"
icon: mdi:comment-alert-outline
automation.battery_notification_join:
<<: *customize
friendly_name: "Battery Notification Join"
icon: mdi:comment-alert-outline
automation.battery_sensor_from_attributes:
<<: *customize
friendly_name: "Create Battery Sensor from Attributes"
icon: mdi:battery-charging-wireless-outline
automation.update_battery_status_group_members:
<<: *customize
friendly_name: "Update Battery Status Group Members"
icon: mdi:group
automation.clear_mqtt_topic:
<<: *customize
friendly_name: "Clear a Retained MQTT Topic"
icon: mdi:server-remove
################################################
## Group
################################################
group:
battery_view:
view: yes
entities:
- group.battery_status
- group.battery_alert
battery_alert:
control: hidden
entities:
- input_number.battery_alert_threshold_min
- input_number.battery_alert_threshold_max
- input_text.mqtt_topic
- input_text.clear_mqtt_topic
- input_text.html5_notify_name
- automation.battery_notification
- automation.battery_notification_clear
- automation.battery_notification_slack
- automation.battery_notification_telegram
- automation.battery_notification_pushover
- automation.battery_notification_html5
- automation.battery_notification_join
- automation.battery_sensor_from_attributes
- automation.update_battery_status_group_members
- automation.clear_mqtt_topic
################################################
## 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
################################################
## Input Text
################################################
input_text:
mqtt_topic:
name: MQTT Discovery Topic
mode: text
# initial: 'homeassistant'
clear_mqtt_topic:
name: MQTT Topic to Clear
mode: text
# initial: ''
html5_notify_name:
name: HTML5 Notifier Name
mode: text
# initial: ''
################################################
## Automation
################################################
automation:
- alias: battery_notification
initial_state: 'on'
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_check >
{% macro battery_level() %}
{% for entity_id in states.group.battery_status.attributes.entity_id if (
not is_state_attr(entity_id, 'battery_alert_disabled', true)
and (
(
(
states(entity_id) is number
or states(entity_id) | length == states(entity_id)| int | string | length
or states(entity_id) | length == states(entity_id)| float | string | length
)
and states(entity_id) | int < states.input_number.battery_alert_threshold_max.state | int
and states(entity_id) | int > states.input_number.battery_alert_threshold_min.state | int
)
or states(entity_id) | lower == 'low'
or states(entity_id) | lower == 'unknown'
)
) -%}
{{ state_attr(entity_id, "friendly_name") }} ({{ states(entity_id) }})
{% 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 entity_id in states.group.battery_status.attributes.entity_id if (
not is_state_attr(entity_id, 'battery_alert_disabled', true)
and (
(
(
states(entity_id) is number
or states(entity_id) | length == states(entity_id)| int | string | length
or states(entity_id) | length == states(entity_id)| float | string | length
)
and states(entity_id) | int < states.input_number.battery_alert_threshold_max.state | int
and states(entity_id) | int > states.input_number.battery_alert_threshold_min.state | int
)
or states(entity_id) | lower == 'low'
or states(entity_id) | lower == 'unknown'
)
) -%}
{{ state_attr(entity_id, "friendly_name") }} ({{ states(entity_id) }})
{% endfor -%}
{% endmacro %}
{{ battery_level() }}
- alias: battery_notification_clear
initial_state: 'on'
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 entity_id in states.group.battery_status.attributes.entity_id if (
not is_state_attr(entity_id, 'battery_alert_disabled', true)
and (
(
(
states(entity_id) is number
or states(entity_id) | length == states(entity_id)| int | string | length
or states(entity_id) | length == states(entity_id)| float | string | length
)
and states(entity_id) | int < states.input_number.battery_alert_threshold_max.state | int
and states(entity_id) | int > states.input_number.battery_alert_threshold_min.state | int
)
or states(entity_id) | lower == 'low'
or states(entity_id) | lower == 'unknown'
)
) -%}
{{ state_attr(entity_id, "friendly_name") }} ({{ states(entity_id) }})
{% endfor -%}
{% endmacro %}
{{ battery_level() | trim == "" }}
- service: persistent_notification.dismiss
data:
notification_id: low_battery_alert
- alias: battery_notification_slack
initial_state: 'on'
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.slack_notify
data_template:
message: "Low Battery Levels"
data:
attachments:
- color: '#52c0f2'
title: "These devices have low battery levels"
text: *message
- alias: battery_notification_telegram
initial_state: 'on'
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.telegram
data_template:
title: "Low Battery Levels"
message: *message
- alias: battery_notification_pushover
initial_state: 'on'
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: "Low Battery Levels"
message: *message
- alias: battery_notification_html5
initial_state: 'on'
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_template: >
{% if states.input_text.html5_notify_name.state != "" %}
notify.{{ states.input_text.html5_notify_name.state }}
{% else %}
notify.notify
{% endif %}
data_template:
title: "Low Battery Levels"
message: *message
- alias: battery_notification_join
initial_state: 'on'
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.joaoapps_join
data_template:
title: "Low Battery Levels"
message: *message
- alias: battery_sensor_from_attributes
initial_state: 'on'
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.old_state 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: "{{ 'battery' not in trigger.event.data.new_state.name | lower }}"
- condition: template
value_template: "{{ not is_state_attr(trigger.event.data.entity_id, 'device_class', 'battery') }}"
- condition: template
value_template: "{{ not is_state_attr(trigger.event.data.entity_id, 'battery_sensor_creation_disabled', true) }}"
- condition: or
conditions:
- condition: template
value_template: "{{ trigger.event.data.new_state.attributes.battery_level is defined }}"
- condition: template
value_template: "{{ trigger.event.data.new_state.attributes.battery is defined }}"
- condition: template
value_template: "{{ trigger.event.data.new_state.attributes['Battery numeric'] is defined }}"
action:
- service: mqtt.publish
data_template:
# topic: "homeassistant/sensor/{{ trigger.event.data.entity_id.split('.')[1] }}_battery/config"
topic: "{{ states.input_text.mqtt_topic.state }}/sensor/{{ trigger.event.data.entity_id.split('.')[1] }}_battery/config"
retain: true
payload: &config_payload >-
{
"device_class": "battery",
"name": "{{ trigger.event.data.new_state.name }} Battery",
"state_topic": "{{ states.input_text.mqtt_topic.state }}/sensor/{{ trigger.event.data.entity_id.split('.')[1] }}_battery/state",
"unit_of_measurement": "%",
{% if trigger.event.data.new_state.attributes.battery_template is defined -%}
"value_template": "{{ trigger.event.data.new_state.attributes.battery_template }}",
{% else -%}
"value_template": "{{ "{{" }} value_json.value | int {{ "}}" }}",
{% endif -%}
"unique_id": "{{ trigger.event.data.entity_id.split('.')[1] }}_battery",
"json_attributes": [
"entity_id",
"attribute",
"mqtt_config_topic",
"mqtt_state_topic"
]
}
- service: mqtt.publish
data_template:
topic: "{{ states.input_text.mqtt_topic.state }}/sensor/{{ trigger.event.data.entity_id.split('.')[1] }}_battery/state"
retain: true
payload: >-
{
{% if trigger.event.data.new_state.attributes.battery_level is defined -%}
{%- set attrib = trigger.event.data.new_state.attributes.battery_level -%}
{%- elif trigger.event.data.new_state.attributes.battery is defined -%}
{%- set attrib = trigger.event.data.new_state.attributes.battery -%}
{%- elif trigger.event.data.new_state.attributes['Battery numeric'] is defined -%}
{%- set attrib = (trigger.event.data.new_state.attributes['Battery numeric'] | int + 1) * 10 -%}
{%- else -%}
{%- set attrib = "unknown" -%}
{%- endif -%}
"value": {%- if attrib is number
or attrib | length == attrib | int | string | length
or attrib | length == attrib | float | string | length
-%}
{{ attrib | int }}
{%- else -%}
"{{ attrib }}"
{%- endif %},
"entity_id": "{{ trigger.event.data.entity_id }}",
{% if trigger.event.data.new_state.attributes.battery_level is defined -%}
"attribute": "battery_level",
{%- elif trigger.event.data.new_state.attributes.battery is defined -%}
"attribute": "battery",
{%- elif trigger.event.data.new_state.attributes['Battery numeric'] is defined -%}
"attribute": "Battery numeric",
{%- else -%}
"attribute": "unknown",
{%- endif %}
"mqtt_config_topic": "{{ states.input_text.mqtt_topic.state }}/sensor/{{ trigger.event.data.entity_id.split('.')[1] }}_battery/config",
"mqtt_state_topic": "{{ states.input_text.mqtt_topic.state }}/sensor/{{ trigger.event.data.entity_id.split('.')[1] }}_battery/state"
}
- alias: update_battery_status_group_members
initial_state: 'on'
trigger:
- platform: homeassistant
event: start
- platform: time
minutes: '/5'
seconds: 00
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')
or 'battery' in item.attributes.icon | lower
or (item.entity_id | lower).endswith('_bat')
or (item.name | lower).endswith('_bat')
) or (
(
'battery' in item.entity_id | lower
or 'battery' in item.name | lower
) and (
item.attributes.icon is not defined
)
)
-%}
{{ item.entity_id }}{% if not loop.last %}, {% endif %}
{%- endfor -%}
- alias: clear_mqtt_topic
initial_state: 'on'
trigger:
- platform: state
entity_id:
- input_text.clear_mqtt_topic
condition:
- condition: template
value_template: "{{ '{{ states.input_text.mqtt_topic.state }}/sensor/' in states.input_text.clear_mqtt_topic.state }}"
action:
- service: mqtt.publish
data_template:
topic: "{{ states.input_text.clear_mqtt_topic.state }}"
retain: true
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment