Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save Ltek/0c9cecf632b9c32915130680d834bcf7 to your computer and use it in GitHub Desktop.

Select an option

Save Ltek/0c9cecf632b9c32915130680d834bcf7 to your computer and use it in GitHub Desktop.
Home Assistant Blueprint: Offline Devices Report
blueprint:
name: "⛔ Offline Devices Report with Notification Actions"
description: |
⛔ Offline Devices Report with Notification Actions
🚀 Version 2026.02.23.45c
- ADDED: Custom Actions option to run only when offline devices are detected
- Recent Fixes... Debug triggers, Template syntax errors, To-Do list output, Empty notifications, Button trigger fix
- Important Update... Real-Time Debug trigger happened with every entity change so the trigger code is now commented out. If you want to use it you will need to modify the code to add it back in. Change made since lower-powered systems would see high CPU use with this code running.
📖 Community Discussion, Help, and Details... https://community.home-assistant.io/t/offline-devices-report-easy-customize-includes-excludes-notifications-more/887859
***Features***
📱 Device Notifications
- Send alerts to mobile devices via mobile_app integration
- iOS and Android specific notification options
- Configurable interruption levels and sounds
📢 Persistent Web UI Notifications
- Dashboard notifications for offline devices
- Optional "no issues" confirmation messages
⚡ Execution methods
- Schedule Time and Day(s)
- Manual trigger via button
- Debug mode for immediate offline/unknown state changes
🚫️ Entity exclusion options
- Directly select specific entities
- Pattern-based exclusions using text strings
- Case-sensitive matching for precise control
- Checkbox to exclude Hidden Entities
- **Note: Disabled entities are automatically excluded** (they are not loaded into the system)
📈 Flexible display formats
- Friendly names only
- Entity IDs only
- Combined format (Friendly Name + Entity ID)
🎬 Custom actions after report
- Add offline devices to To-Do list automatically
- Action buttons in notifications for manual control
- Custom automation actions integration
- {{ offline_devices }} variable returns a formatted list of offline devices
- {{ offline_devices_count }} variable returns the count of offline devices
📡 Smart device detection
- Automatic battery sensor identification
- Switch monitoring for offline states
- Combined or separate reporting options
📖 Logging
- Debug to Logbook
- Easy troubleshooting configuration
🐛 Real-Time Debug Mode (Short-term troubleshooting only - must enable in code, not just in the UI)
- Trigger on entity state changes to offline/unknown
- Configurable delay to confirm persistent offline state
- Uses same exclusions as scheduled reports
📡 Monitored Domains
Monitors all sources... Zigbee, Z-Wave, WiFi, etc.
Will list entities from these domains...
- sensor.*
- binary_sensor.*
- switch.*
These domains are NOT monitored at all...
- climate.*
- light.*
- media_player.*
- device_tracker.*
- input_*
- automation.*
- script.*
- scene.*
- weather.*
- camera.*
- person.*
- zone.*
- sun.*
- timer.*
- counter.*
- calendar.*
domain: automation
input:
trigger_settings:
name: ⚙️ Trigger Settings
collapsed: true
input:
include_button:
name: Use Button Trigger?
default: disable_button_trigger
selector:
select:
options:
- label: Enabled
value: enable_button_trigger
- label: Disabled
value: disable_button_trigger
button_entity:
name: Set Button Trigger
default:
selector:
entity:
domain: [input_button, button]
multiple: false
include_time:
name: Use an Automatic Reoccuring Report?
default: time_disabled
selector:
select:
options:
- label: Enabled
value: time_enabled
- label: Disabled
value: time_disabled
time:
name: Set Reoccuring Time
default: "05:00:00"
selector:
time: {}
weekday_options:
name: Set Reoccuring Days
default: [mon, tue, wed, thu, fri, sat, sun]
selector:
select:
multiple: true
mode: list
options:
- {label: Monday, value: mon}
- {label: Tuesday, value: tue}
- {label: Wednesday, value: wed}
- {label: Thursday, value: thu}
- {label: Friday, value: fri}
- {label: Saturday, value: sat}
- {label: Sunday, value: sun}
device_settings:
name: "🚫 Exclusion Settings"
collapsed: true
input:
exclude_hidden_entities:
name: Exclude Hidden Entities
default: true
selector:
boolean: {}
exclude_entities:
name: Individual Entities
default: []
selector:
entity:
multiple: true
exclude_strings:
name: Text Pattern Exclusions
default: ''
selector:
text:
multiline: true
notification_settings:
name: "📢 Notification Settings"
collapsed: true
input:
include_easy_notify:
name: Device Notifications
default: disabled_easy_notify
selector:
select:
options:
- {label: Disabled, value: disabled_easy_notify}
- {label: Enabled - notify only if offline devices found, value: enable_easy_notify}
- {label: Enabled - notify even if no offline devices found, value: enable_easy_okay_notify}
notify_device:
name: Devices to Notify
default: []
selector:
device:
integration: mobile_app
multiple: true
notify_title:
name: Notification Title
default: Offline Devices Report
selector:
text: {}
notify_message:
name: Message Format
default: all_sensors
selector:
select:
options:
- {label: All Offline Devices, value: all_sensors}
- {label: Only Battery Sensors, value: sensors}
- {label: Only Switches, value: switches}
notify_okay_message:
name: Message when No Offline Devices found
default: No offline devices detected
selector:
text: {}
notify_interruption_level:
name: iOS Interruption Level
default: active
selector:
select:
options:
- {label: Default, value: active}
- {label: Critical Notifications, value: critical}
- {label: Time Sensitive, value: time-sensitive}
- {label: Quiet, value: passive}
notify_sound:
name: iOS Notification Sound
default: ''
selector:
text: {}
notify_data:
name: Android Options
default: []
selector:
select:
multiple: true
options:
- {label: High Priority, value: high_priority}
- {label: Sticky Notification, value: sticky}
- {label: Notification Channel, value: channel}
notify_channel:
name: Android Notification Channel
default: ''
selector:
text: {}
include_persistent_notification:
name: Persistent UI Notifications
default: disabled_persistent_notification
selector:
select:
options:
- {label: Disabled, value: disabled_persistent_notification}
- {label: Notify only when offline devices are found, value: enable_persistent_notification}
- {label: Notify always - even if no offline devices found, value: enable_persistent_okay_notification}
display_options:
name: Display Options
default: friendly_names
selector:
select:
options:
- {label: Entity IDs, value: entity_ids}
- {label: Friendly Names, value: friendly_names}
- {label: Both, value: both}
action_buttons_settings:
name: "🚀 Action Buttons"
collapsed: true
input:
auto_add_to_do:
name: Automatically Add to To-Do List
default: disable_auto_add_to_do
selector:
select:
options:
- {label: Disabled, value: disable_auto_add_to_do}
- {label: Enabled, value: enable_auto_add_to_do}
notify_tag:
name: Notification Action Tag
default: offline_devices_report_action
selector:
text: {}
notify_action_buttons:
name: Action Buttons
default: disabled_notify_action_buttons
selector:
select:
options:
- {label: Disabled, value: disabled_notify_action_buttons}
- {label: Add To-Do Button, value: enable_to_do_list_button}
- {label: Add To-Do with Confirmation, value: enable_to_do_list_button_and_confirmation}
to_do_list:
name: To-Do List
default: []
selector:
entity:
domain: [todo]
multiple: false
to_do_task_title:
name: Task Title
default: Check Offline Devices
selector:
text: {}
action_button_to_do:
name: Action Button Text
default: Add to To-Do List
selector:
text: {}
action_button_cancel:
name: Cancel Button Text
default: Cancel
selector:
text: {}
action_button_confirmation_title:
name: Confirmation Title
default: Action Confirmation
selector:
text: {}
action_button_confirmation_message:
name: Confirmation Message
default: Task added to To-Do list
selector:
text: {}
cancel_action_button_confirmation_message:
name: Cancel Confirmation Message
default: Action cancelled
selector:
text: {}
custom_actions_settings:
name: ⚡ Custom Actions
collapsed: true
input:
include_custom_actions:
name: Enable Custom Actions
default: disable_custom_actions
selector:
select:
options:
- {label: Never, value: disable_custom_actions}
- {label: Only when offline devices are found, value: enable_custom_actions_offline_only}
- {label: Always (even if no offline devices found), value: enable_custom_actions_always}
custom_actions:
name: Custom Actions
default: []
selector:
action: {}
global_conditions_settings:
name: "🌍 Global Conditions"
collapsed: true
input:
global_conditions:
name: Conditions
default: []
selector:
condition: {}
debug_settings:
name: "🐛 Debug Settings"
collapsed: true
input:
include_debug:
name: Real-Time Debug Mode?
default: debug_disabled
selector:
select:
options:
- {label: Enabled, value: debug_enabled}
- {label: Disabled, value: debug_disabled}
debug_offline_delay:
name: Wait Time Confirmation
default: "00:03:00"
selector:
duration: {}
include_logbook_debug:
name: Logbook Debug Messages
default: logbook_realtime_only
selector:
select:
options:
- {label: Enabled (All Runs), value: logbook_enabled_all}
- {label: Real-Time Debug Only, value: logbook_realtime_only}
- {label: Disabled, value: logbook_disabled}
include_system_log_debug:
name: System Log Debug Messages
default: systemlog_realtime_only
selector:
select:
options:
- {label: Enabled (All Runs), value: systemlog_enabled_all}
- {label: Real-Time Debug Only, value: systemlog_realtime_only}
- {label: Disabled, value: systemlog_disabled}
include_debug_persistent_notification:
name: Persistent UI Notifications
default: persistent_realtime_only
selector:
select:
options:
- {label: Enabled, value: persistent_realtime_only}
- {label: Disabled, value: persistent_disabled}
variables:
include_button: !input include_button
button_entity: !input button_entity
include_time: !input include_time
include_debug: !input include_debug
debug_offline_delay: !input debug_offline_delay
include_logbook_debug: !input include_logbook_debug
include_system_log_debug: !input include_system_log_debug
include_debug_persistent_notification: !input include_debug_persistent_notification
debug_offline_delay_seconds: >
{% set delay = debug_offline_delay %}
{% if delay is string %}
{% set parts = delay.split(':') %}
{% set hours = parts[0] | int %}
{% set minutes = parts[1] | int if parts|length > 1 else 0 %}
{% set seconds = parts[2] | int if parts|length > 2 else 0 %}
{{ (hours * 3600 + minutes * 60 + seconds) | int }}
{% elif delay is mapping and 'hours' in delay %}
{{ (delay.hours * 3600 + delay.minutes * 60 + delay.seconds) | int }}
{% else %}
180
{% endif %}
weekday_options: !input weekday_options
exclude_hidden_entities: !input exclude_hidden_entities
exclude_entities: !input exclude_entities
exclude_strings: !input exclude_strings
display_options: !input display_options
include_easy_notify: !input include_easy_notify
notify_device: !input notify_device
notify_title: !input notify_title
notify_message: !input notify_message
notify_okay_message: !input notify_okay_message
notify_interruption_level: !input notify_interruption_level
notify_sound: !input notify_sound
notify_data: !input notify_data
notify_channel: !input notify_channel
include_persistent_notification: !input include_persistent_notification
notify_action_buttons: !input notify_action_buttons
auto_add_to_do: !input auto_add_to_do
notify_tag: !input notify_tag
to_do_list: !input to_do_list
to_do_task_title: !input to_do_task_title
action_button_to_do: !input action_button_to_do
action_button_cancel: !input action_button_cancel
action_button_confirmation_title: !input action_button_confirmation_title
action_button_confirmation_message: !input action_button_confirmation_message
cancel_action_button_confirmation_message: !input cancel_action_button_confirmation_message
include_custom_actions: !input include_custom_actions
exclude_regex: >
{% if exclude_strings is defined %}
{% set patterns = exclude_strings.split('\n') | map('trim') | reject('eq', '') | list %}
{{ patterns | join('|') if patterns else 'a^' }}
{% else %}
a^
{% endif %}
all_exclude_entities: >
{{ exclude_entities if exclude_entities is defined else [] }}
_offline_devices: >
{% set exclude_entities_list = all_exclude_entities %}
{# Disabled entities are automatically excluded as they don't appear in states #}
{% set entities = states | map(attribute='entity_id') | reject('search', 'cloud') | reject('in', exclude_entities_list) | reject('search', exclude_regex) | list %}
{% if exclude_hidden_entities == true %}
{% set entities = entities | reject('is_hidden_entity') | list %}
{% endif %}
{% set sensors = entities | select('search', '^(sensor|binary_sensor)') | list %}
{% set battery_entities = sensors | select('is_state_attr', 'device_class', 'battery') | reject('has_value') | list %}
{% set switches = entities | select('search', '^switch') | reject('has_value') | list %}
{% set offline_entities = (battery_entities + switches) | unique %}
{% if display_options == 'entity_ids' %}
{{ offline_entities | list }}
{% elif display_options == 'friendly_names' %}
{{ offline_entities | map('state_attr', 'friendly_name') | list }}
{% elif display_options == 'both' %}
{% set result = namespace(items=[]) %}
{% for e in offline_entities %}
{% set friendly_name = state_attr(e, 'friendly_name') %}
{% set item = friendly_name ~ ' (' ~ e ~ ')' if friendly_name else e %}
{% set result.items = result.items + [item] %}
{% endfor %}
{{ result.items }}
{% else %}
[]
{% endif %}
offline_devices: >
{% if _offline_devices | length > 0 %}
{{ '- ' ~ (_offline_devices | sort | join('\n- ')) }}
{% else %}
No offline devices detected.
{% endif %}
offline_devices_count: >
{{ _offline_devices | length }}
_battery_sensors: >
{% set exclude_entities_list = all_exclude_entities %}
{# Disabled entities are automatically excluded as they don't appear in states #}
{% set entities = states | map(attribute='entity_id') | reject('search', 'cloud') | reject('in', exclude_entities_list) | reject('search', exclude_regex) | list %}
{% if exclude_hidden_entities == true %}
{% set entities = entities | reject('is_hidden_entity') | list %}
{% endif %}
{% set sensors = entities | select('search', '^(sensor|binary_sensor)') | list %}
{% set battery_entities = sensors | select('is_state_attr', 'device_class', 'battery') | reject('has_value') | list %}
{{ battery_entities }}
_switches: >
{% set exclude_entities_list = all_exclude_entities %}
{# Disabled entities are automatically excluded as they don't appear in states #}
{% set entities = states | map(attribute='entity_id') | reject('search', 'cloud') | reject('in', exclude_entities_list) | reject('search', exclude_regex) | list %}
{% if exclude_hidden_entities == true %}
{% set entities = entities | reject('is_hidden_entity') | list %}
{% endif %}
{% set switches = entities | select('search', '^switch') | reject('has_value') | list %}
{{ switches }}
all_sensors: >
{% if _offline_devices | length > 0 %}
{{ offline_devices_count ~ ' Offline Devices\n\n' ~ ('- ' ~ (_offline_devices | sort | join('\n- '))) }}
{% else %}
''
{% endif %}
sensors: >
{% if _battery_sensors | length > 0 %}
{{ '🔋 ' ~ _battery_sensors | length ~ ' Offline Battery Sensor(s):\n\n' ~ ('- ' ~ (_battery_sensors | sort | join('\n- '))) }}
{% else %}
''
{% endif %}
switches: >
{% if _switches | length > 0 %}
{{ '🔌 ' ~ _switches | length ~ ' Offline Switch(es):\n\n' ~ ('- ' ~ (_switches | sort | join('\n- '))) }}
{% else %}
''
{% endif %}
easy_notify_message: >
{% if notify_message == 'all_sensors' %}
{{ all_sensors }}
{% elif notify_message == 'sensors' %}
{{ sensors }}
{% elif notify_message == 'switches' %}
{{ switches }}
{% else %}
''
{% endif %}
to_do_description: >
{% set device_list = _offline_devices | join(', ') %}
{% set cleaned = device_list | regex_replace('\\s*\\([^)]+\\)', '') %}
{% if cleaned | length > 250 %}
{{ cleaned[:250] ~ '...' }}
{% else %}
{{ cleaned }}
{% endif %}
sensors_names: >
{% if _battery_sensors | length > 0 %}
{{ (_battery_sensors | list | sort | join('\n')) }}
{% else %}
''
{% endif %}
switches_names: >
{% if _switches | length > 0 %}
{{ (_switches | list | sort | join('\n')) }}
{% else %}
''
{% endif %}
device_message_data: >
{% set message = namespace(data={}) %}
{% set push = namespace(data={}) %}
{% if notify_interruption_level in ['active', 'critical', 'time-sensitive', 'passive'] %}
{% set push.data = dict(push.data, **{ 'interruption-level': notify_interruption_level }) %}
{% endif %}
{% if notify_sound != '' %}
{% set push.data = dict(push.data, **{ 'sound': notify_sound }) %}
{% endif %}
{% if push.data %}
{% set message.data = dict(message.data, **{ 'push': push.data }) %}
{% endif %}
{% if 'high_priority' in notify_data %}
{% set message.data = dict(message.data, **{ 'ttl': 0, 'priority': 'high' }) %}
{% endif %}
{% if 'channel' in notify_data %}
{% set message.data = dict(message.data, **{ 'channel': notify_channel }) %}
{% endif %}
{% if 'sticky' in notify_data %}
{% set message.data = dict(message.data, **{ 'sticky': "true" }) %}
{% endif %}
{% set message.data = dict(message.data, **{ 'tag': notify_tag }) %}
{{ message.data }}
device_message_data_action_button: >
{% set message = namespace(data={}) %}
{% set push = namespace(data={}) %}
{% if notify_interruption_level in ['active', 'critical', 'time-sensitive', 'passive'] %}
{% set push.data = dict(push.data, **{ 'interruption-level': notify_interruption_level }) %}
{% endif %}
{% if notify_sound != '' %}
{% set push.data = dict(push.data, **{ 'sound': notify_sound }) %}
{% endif %}
{% if push.data %}
{% set message.data = dict(message.data, **{ 'push': push.data }) %}
{% endif %}
{% if 'high_priority' in notify_data %}
{% set message.data = dict(message.data, **{ 'ttl': 0, 'priority': 'high' }) %}
{% endif %}
{% if 'channel' in notify_data %}
{% set message.data = dict(message.data, **{ 'channel': notify_channel }) %}
{% endif %}
{% if 'sticky' in notify_data %}
{% set message.data = dict(message.data, **{ 'sticky': "true" }) %}
{% endif %}
{% set actions = [{'action': action_button_to_do, 'title': action_button_to_do}, {'action': action_button_cancel, 'title': action_button_cancel}] %}
{% set message.data = dict(message.data, **{ 'actions': actions, 'tag': notify_tag }) %}
{{ message.data }}
device_confirmation_message_data: >
{% set message = namespace(data={}) %}
{% set push = namespace(data={}) %}
{% if notify_interruption_level in ['active', 'critical', 'time-sensitive', 'passive'] %}
{% set push.data = dict(push.data, **{ 'interruption-level': notify_interruption_level }) %}
{% endif %}
{% if notify_sound != '' %}
{% set push.data = dict(push.data, **{ 'sound': notify_sound }) %}
{% endif %}
{% if push.data %}
{% set message.data = dict(message.data, **{ 'push': push.data }) %}
{% endif %}
{% if 'high_priority' in notify_data %}
{% set message.data = dict(message.data, **{ 'ttl': 0, 'priority': 'high' }) %}
{% endif %}
{% if 'channel' in notify_data %}
{% set message.data = dict(message.data, **{ 'channel': notify_channel }) %}
{% endif %}
{% if 'sticky' in notify_data %}
{% set message.data = dict(message.data, **{ 'sticky': "true" }) %}
{% endif %}
{% set message.data = dict(message.data, **{ 'tag': notify_tag }) %}
{{ message.data }}
trigger:
###############################
# Real-Time Debug Code #
###############################
# - platform: event
# event_type: state_changed
# event_data: {}
# id: debug_trigger
###############################
- platform: time
at: !input time
id: time_trigger
- platform: event
event_type: state_changed
id: button_trigger
condition:
- condition: or
conditions:
- condition: and
conditions:
- condition: trigger
id: button_trigger
- condition: template
value_template: '{{ include_button == "enable_button_trigger" }}'
- condition: template
value_template: '{{ button_entity is not none and button_entity != "" and trigger.event.data.entity_id == button_entity }}'
- condition: template
value_template: '{{ trigger.event.data.new_state.state not in ["unknown", "unavailable", "off"] }}'
- condition: and
conditions:
- condition: trigger
id: time_trigger
- condition: template
value_template: '{{ include_time == "time_enabled" }}'
- condition: template
value_template: '{{ now().strftime("%a").lower() in weekday_options }}'
- condition: and
conditions:
- condition: trigger
id: debug_trigger
- condition: template
value_template: '{{ include_debug == "debug_enabled" }}'
- condition: template
value_template: >
{{ trigger.event.data.new_state is not none
and trigger.event.data.new_state.state in ["unavailable", "unknown"]
and (trigger.event.data.old_state is none
or trigger.event.data.old_state.state not in ["unavailable", "unknown"]) }}
- condition: and
conditions: !input global_conditions
action:
- choose:
- conditions:
- condition: trigger
id: debug_trigger
- condition: template
value_template: '{{ include_debug == "debug_enabled" }}'
sequence:
- if:
- condition: template
value_template: '{{ include_system_log_debug in ["systemlog_enabled_all", "systemlog_realtime_only"] }}'
then:
- service: system_log.write
data:
message: "Debug mode triggered by state_changed event"
level: warning
- variables:
debug_entity: "{{ trigger.event.data.entity_id }}"
debug_entity_state: "{{ trigger.event.data.new_state.state }}"
debug_entity_name: '{{ trigger.event.data.new_state.attributes.friendly_name or trigger.event.data.entity_id }}'
old_state: "{{ trigger.event.data.old_state.state if trigger.event.data.old_state else '' }}"
- if:
- condition: template
value_template: '{{ include_system_log_debug in ["systemlog_enabled_all", "systemlog_realtime_only"] }}'
then:
- service: system_log.write
data:
message: "Debug checking entity: {{ debug_entity }}, new_state: {{ debug_entity_state }}, old_state: {{ old_state }}"
level: warning
- if:
- condition: template
value_template: '{{ debug_entity_state not in ["unknown", "unavailable"] or old_state in ["unknown", "unavailable"] }}'
then:
- if:
- condition: template
value_template: '{{ include_system_log_debug in ["systemlog_enabled_all", "systemlog_realtime_only"] }}'
then:
- service: system_log.write
data:
message: "Debug stopped: Not a change TO unknown/unavailable for {{ debug_entity }}"
level: info
- stop: 'Not a change TO unknown/unavailable state'
- variables:
entity_excluded: >
{% if debug_entity in all_exclude_entities %}
true
{% elif exclude_regex != 'a^' and debug_entity is search(exclude_regex) %}
true
{% elif exclude_hidden_entities == true and is_hidden_entity(debug_entity) %}
true
{% elif debug_entity is search('cloud') %}
true
{% else %}
false
{% endif %}
- if:
- condition: template
value_template: '{{ include_system_log_debug in ["systemlog_enabled_all", "systemlog_realtime_only"] }}'
then:
- service: system_log.write
data:
message: "Debug exclusion check for {{ debug_entity }}: excluded={{ entity_excluded }}"
level: info
- if:
- condition: template
value_template: '{{ entity_excluded == true }}'
then:
- if:
- condition: template
value_template: '{{ include_logbook_debug in ["logbook_enabled_all", "logbook_realtime_only"] }}'
then:
- service: logbook.log
data:
name: Offline Devices Debug Mode
message: 'Debug ignored: {{ debug_entity_name }} is excluded'
- if:
- condition: template
value_template: '{{ include_system_log_debug in ["systemlog_enabled_all", "systemlog_realtime_only"] }}'
then:
- service: system_log.write
data:
message: "Debug ignored: {{ debug_entity_name }} ({{ debug_entity }}) is excluded from monitoring"
level: info
- if:
- condition: template
value_template: '{{ include_debug_persistent_notification == "persistent_realtime_only" }}'
then:
- service: persistent_notification.create
data:
title: "🐛 Debug: Entity Excluded"
message: 'Debug ignored: {{ debug_entity_name }} is excluded from monitoring'
notification_id: 'debug_excluded_{{ debug_entity | replace(".", "_") }}'
- stop: 'Entity excluded from debug'
- if:
- condition: template
value_template: '{{ include_logbook_debug in ["logbook_enabled_all", "logbook_realtime_only"] }}'
then:
- service: logbook.log
data:
name: Offline Devices Debug Mode
message: 'Debug triggered: {{ debug_entity_name }} ({{ debug_entity }}) changed from {{ old_state }} to {{ debug_entity_state }}'
- if:
- condition: template
value_template: '{{ include_system_log_debug in ["systemlog_enabled_all", "systemlog_realtime_only"] }}'
then:
- service: system_log.write
data:
message: "🐛 DEBUG ALERT: {{ debug_entity_name }} ({{ debug_entity }}) went {{ debug_entity_state }}"
level: warning
- if:
- condition: template
value_template: '{{ include_debug_persistent_notification in ["persistent_enabled_all", "persistent_realtime_only"] }}'
then:
- service: persistent_notification.create
data:
title: "🐛 Debug: Entity Offline Detected"
message: '{{ debug_entity_name }} ({{ debug_entity }}) changed from {{ old_state }} to {{ debug_entity_state }}'
notification_id: 'debug_trigger_{{ debug_entity | replace(".", "_") }}'
- wait_template: '{{ states(debug_entity) in ["unknown","unavailable"] }}'
timeout: '{{ debug_offline_delay_seconds }}'
continue_on_timeout: false
- choose:
- conditions:
- condition: template
value_template: '{{ wait is defined and wait.timed_out == true }}'
sequence:
- if:
- condition: template
value_template: '{{ include_logbook_debug in ["logbook_enabled_all", "logbook_realtime_only"] }}'
then:
- service: logbook.log
data:
name: Offline Devices Debug Mode
message: '{{ debug_entity_name }} ({{ debug_entity }}) stayed {{ debug_entity_state }} for {{ debug_offline_delay }}'
- if:
- condition: template
value_template: '{{ include_debug_persistent_notification in ["persistent_enabled_all", "persistent_realtime_only"] }}'
then:
- service: persistent_notification.create
data:
title: "🐛 Debug: Entity Confirmed Offline"
message: '{{ debug_entity_name }} ({{ debug_entity }}) stayed {{ debug_entity_state }} for {{ debug_offline_delay }}'
notification_id: 'debug_confirmed_{{ debug_entity | replace(".", "_") }}'
- stop: 'Debug complete - entity stayed offline'
- conditions:
- condition: template
value_template: '{{ wait is defined and wait.timed_out == false }}'
sequence:
- if:
- condition: template
value_template: '{{ include_logbook_debug in ["logbook_enabled_all", "logbook_realtime_only"] }}'
then:
- service: logbook.log
data:
name: Offline Devices Debug Mode
message: '{{ debug_entity_name }} ({{ debug_entity }}) came back online during wait period'
- if:
- condition: template
value_template: '{{ include_debug_persistent_notification in ["persistent_enabled_all", "persistent_realtime_only"] }}'
then:
- service: persistent_notification.create
data:
title: "🐛 Debug: Entity Back Online"
message: '{{ debug_entity_name }} ({{ debug_entity }}) came back online during wait period'
notification_id: 'debug_online_{{ debug_entity | replace(".", "_") }}'
- stop: 'Debug cancelled - entity came back online'
- if:
- condition: template
value_template: '{{ include_logbook_debug == "logbook_enabled_all" or (include_logbook_debug == "logbook_realtime_only" and trigger.id == "debug_trigger") }}'
then:
- service: logbook.log
data:
name: Offline Devices Report Debug
message: |
Initial: include_easy_notify: {{ include_easy_notify | default('undefined') }},
include_persistent_notification: {{ include_persistent_notification | default('undefined') }},
notify_device: {{ notify_device | default('undefined') }},
offline_devices_count: {{ offline_devices_count | default('0') }},
_battery_sensors_count: {{ _battery_sensors | length | default('0') }},
_switches_count: {{ _switches | length | default('0') }},
easy_notify_message length: {{ easy_notify_message | default('') | length }},
to_do_description length: {{ to_do_description | default('') | length }},
to_do_list: {{ to_do_list | default('undefined') }},
exclude_hidden_entities: {{ exclude_hidden_entities | default('undefined') }}
- choose:
- alias: Use the easy notify options
conditions:
- condition: template
value_template: '{{ include_easy_notify == "enable_easy_notify" or include_easy_notify == "enable_easy_okay_notify" }}'
- condition: template
value_template: '{{ notify_device | length > 0 }}'
- condition: template
value_template: '{{ trigger.id != "debug_trigger" }}'
sequence:
- alias: Send a notification to each device
repeat:
for_each: '{{ notify_device | default([]) }}'
sequence:
- choose:
- alias: Offline devices have been found
conditions:
- condition: template
value_template: '{{ offline_devices_count > 0 }}'
sequence:
- choose:
- alias: Easy notify with no action button
conditions:
- condition: template
value_template: '{{ notify_action_buttons == "disabled_notify_action_buttons" or auto_add_to_do == "enable_auto_add_to_do" }}'
sequence:
- service: notify.mobile_app_{{ device_attr(repeat.item, 'name') | slugify }}
data:
title: !input notify_title
message: '{{ easy_notify_message }}'
data: '{{ device_message_data }}'
- if:
- condition: template
value_template: '{{ include_logbook_debug == "logbook_enabled_all" }}'
then:
- service: logbook.log
data:
name: Offline Devices Report Debug
message: 'Sent notification without action buttons to device: {{ device_attr(repeat.item, "name") | slugify }}, service: notify.mobile_app_{{ device_attr(repeat.item, "name") | slugify }}, tag: {{ notify_tag }}, message length: {{ easy_notify_message | length }}'
- alias: Easy notify with action button
conditions:
- condition: template
value_template: '{{ notify_action_buttons != "disabled_notify_action_buttons" and auto_add_to_do != "enable_auto_add_to_do" }}'
sequence:
- service: notify.mobile_app_{{ device_attr(repeat.item, 'name') | slugify }}
data:
title: !input notify_title
message: '{{ easy_notify_message }}'
data: '{{ device_message_data_action_button }}'
- if:
- condition: template
value_template: '{{ include_logbook_debug == "logbook_enabled_all" }}'
then:
- service: logbook.log
data:
name: Offline Devices Report Debug
message: 'Sent notification with action buttons to device: {{ device_attr(repeat.item, "name") | slugify }}, service: notify.mobile_app_{{ device_attr(repeat.item, "name") | slugify }}, tag: {{ notify_tag }}, actions: {{ device_message_data_action_button }}'
- alias: No offline devices have been found
conditions:
- condition: template
value_template: '{{ offline_devices_count == 0 }}'
- condition: template
value_template: '{{ include_easy_notify == "enable_easy_okay_notify" }}'
sequence:
- service: notify.mobile_app_{{ device_attr(repeat.item, 'name') | slugify }}
data:
title: !input notify_title
message: '{{ notify_okay_message }}'
data: '{{ device_message_data }}'
- if:
- condition: template
value_template: '{{ include_logbook_debug == "logbook_enabled_all" }}'
then:
- service: logbook.log
data:
name: Offline Devices Report Debug
message: 'Sent no-issues notification to device: {{ device_attr(repeat.item, "name") | slugify }}, service: notify.mobile_app_{{ device_attr(repeat.item, "name") | slugify }}, tag: {{ notify_tag }}, message: {{ notify_okay_message }}'
- choose:
- alias: Use the easy notify persistent notification options
conditions:
- condition: template
value_template: '{{ include_persistent_notification == "enable_persistent_notification" or include_persistent_notification == "enable_persistent_okay_notification" }}'
- condition: template
value_template: '{{ trigger.id != "debug_trigger" }}'
sequence:
- choose:
- alias: Offline devices have been found
conditions:
- condition: template
value_template: '{{ offline_devices_count > 0 }}'
sequence:
- service: persistent_notification.create
data:
title: "⛔ {{ notify_title }}"
message: '{{ easy_notify_message }}'
notification_id: offline_devices_report
- if:
- condition: template
value_template: '{{ include_logbook_debug == "logbook_enabled_all" }}'
then:
- service: logbook.log
data:
name: Offline Devices Report Debug
message: 'Created persistent notification, id: offline_devices_report, message length: {{ easy_notify_message | length }}'
- alias: No offline devices have been found
conditions:
- condition: template
value_template: '{{ offline_devices_count == 0 }}'
- condition: template
value_template: '{{ include_persistent_notification == "enable_persistent_okay_notification" }}'
sequence:
- service: persistent_notification.create
data:
title: "⛔ {{ notify_title }}"
message: '{{ notify_okay_message }}'
notification_id: offline_devices_report_ok
- if:
- condition: template
value_template: '{{ include_logbook_debug == "logbook_enabled_all" }}'
then:
- service: logbook.log
data:
name: Offline Devices Report Debug
message: 'Created persistent no-issues notification, id: offline_devices_report_ok, message: {{ notify_okay_message }}'
- choose:
- alias: Auto-add to To-Do list when enabled
conditions:
- condition: template
value_template: '{{ auto_add_to_do == "enable_auto_add_to_do" and to_do_description != "" }}'
- condition: template
value_template: '{{ to_do_list | length > 0 and is_state(to_do_list, "unknown") == false and is_state(to_do_list, "unavailable") == false }}'
- condition: template
value_template: '{{ trigger.id != "debug_trigger" }}'
sequence:
- service: todo.add_item
data:
entity_id: '{{ to_do_list }}'
item: !input to_do_task_title
description: '{{ to_do_description }}'
continue_on_error: true
- if:
- condition: template
value_template: '{{ include_logbook_debug == "logbook_enabled_all" }}'
then:
- service: logbook.log
data:
name: Offline Devices Report Debug
message: 'Auto-added To-Do item to {{ to_do_list }}: title={{ to_do_task_title }}, description length={{ to_do_description | length }}'
- choose:
- alias: Check if the To-Do action button is enabled
conditions:
- condition: template
value_template: '{{ include_easy_notify == "enable_easy_notify" or include_easy_notify == "enable_easy_okay_notify" }}'
- condition: template
value_template: '{{ notify_action_buttons == "enable_to_do_list_button" or notify_action_buttons == "enable_to_do_list_button_and_confirmation" }}'
- condition: template
value_template: '{{ auto_add_to_do != "enable_auto_add_to_do" }}'
- condition: template
value_template: '{{ notify_device | length > 0 }}'
- condition: template
value_template: '{{ to_do_list | length > 0 and is_state(to_do_list, "unknown") == false and is_state(to_do_list, "unavailable") == false }}'
- condition: template
value_template: '{{ trigger.id != "debug_trigger" }}'
sequence:
- alias: Wait for a response from the action buttons
wait_for_trigger:
- platform: event
event_type: mobile_app_notification_action
event_data:
action: '{{ action_button_to_do }}'
- platform: event
event_type: mobile_app_notification_action
event_data:
action: '{{ action_button_cancel }}'
timeout: 00:15:00
continue_on_timeout: true
- if:
- condition: template
value_template: '{{ include_logbook_debug == "logbook_enabled_all" }}'
then:
- service: logbook.log
data:
name: Offline Devices Report Debug
message: 'Wait for trigger result: {{ wait.trigger | default("no trigger received", true) }}, action: {{ wait.trigger.event.data.action if wait.trigger else "none" }}, tag: {{ notify_tag if wait.trigger else "none" }}, event_data: {{ wait.trigger.event.data if wait.trigger else "none" }}'
- choose:
- alias: Check if confirmation message is disabled
conditions:
- condition: template
value_template: '{{ notify_action_buttons == "enable_to_do_list_button" }}'
sequence:
- if:
- condition: template
value_template: '{{ wait.trigger is not none and wait.trigger.event.data.action == action_button_to_do }}'
then:
- service: todo.add_item
data:
entity_id: '{{ to_do_list }}'
item: !input to_do_task_title
description: '{{ to_do_description }}'
continue_on_error: true
- if:
- condition: template
value_template: '{{ include_logbook_debug == "logbook_enabled_all" }}'
then:
- service: logbook.log
data:
name: Offline Devices Report Debug
message: 'Added To-Do item to {{ to_do_list }}: title={{ to_do_task_title }}, description length={{ to_do_description | length }}'
- if:
- condition: template
value_template: '{{ wait.trigger is not none and wait.trigger.event.data.action == action_button_cancel }}'
then:
- if:
- condition: template
value_template: '{{ include_logbook_debug == "logbook_enabled_all" }}'
then:
- service: logbook.log
data:
name: Offline Devices Report Debug
message: 'Action cancelled for tag: {{ notify_tag }}'
- stop: 'Action cancelled'
- alias: Check if confirmation message is enabled
conditions:
- condition: template
value_template: '{{ notify_action_buttons == "enable_to_do_list_button_and_confirmation" }}'
sequence:
- if:
- condition: template
value_template: '{{ wait.trigger is not none and wait.trigger.event.data.action == action_button_to_do }}'
then:
- service: todo.add_item
data:
entity_id: '{{ to_do_list }}'
item: !input to_do_task_title
description: '{{ to_do_description }}'
continue_on_error: true
- if:
- condition: template
value_template: '{{ include_logbook_debug == "logbook_enabled_all" }}'
then:
- service: logbook.log
data:
name: Offline Devices Report Debug
message: 'Added To-Do item to {{ to_do_list }}: title={{ to_do_task_title }}, description length={{ to_do_description | length }}'
- repeat:
for_each: '{{ notify_device | default([]) }}'
sequence:
- service: notify.mobile_app_{{ device_attr(repeat.item, 'name') | slugify }}
data:
title: !input action_button_confirmation_title
message: !input action_button_confirmation_message
data: '{{ device_confirmation_message_data }}'
continue_on_error: true
- if:
- condition: template
value_template: '{{ include_logbook_debug == "logbook_enabled_all" }}'
then:
- service: logbook.log
data:
name: Offline Devices Report Debug
message: 'Sent confirmation notification to device: {{ device_attr(repeat.item, "name") | slugify }}, service: notify.mobile_app_{{ device_attr(repeat.item, "name") | slugify }}, tag: {{ notify_tag }}, message: {{ action_button_confirmation_message }}'
- if:
- condition: template
value_template: '{{ wait.trigger is not none and wait.trigger.event.data.action == action_button_cancel }}'
then:
- repeat:
for_each: '{{ notify_device | default([]) }}'
sequence:
- service: notify.mobile_app_{{ device_attr(repeat.item, 'name') | slugify }}
data:
title: !input action_button_confirmation_title
message: !input cancel_action_button_confirmation_message
data: '{{ device_message_data }}'
continue_on_error: true
- if:
- condition: template
value_template: '{{ include_logbook_debug == "logbook_enabled_all" }}'
then:
- service: logbook.log
data:
name: Offline Devices Report Debug
message: 'Sent cancel confirmation notification to device: {{ device_attr(repeat.item, "name") | slugify }}, service: notify.mobile_app_{{ device_attr(repeat.item, "name") | slugify }}, tag: {{ notify_tag }}, message: {{ cancel_action_button_confirmation_message }}'
- choose:
- alias: Perform the custom actions
conditions:
- condition: template
value_template: >-
{{ include_custom_actions == "enable_custom_actions_always" or
(include_custom_actions == "enable_custom_actions_offline_only" and offline_devices_count | int > 0) }}
- condition: template
value_template: '{{ trigger.id != "debug_trigger" }}'
sequence: !input custom_actions
mode: single

Comments are disabled for this gist.