blueprint: name: Unavailable entity detection & notification description: > Regularly test all entities' status to check for unavailability. Supports exclusion by entities, devices, areas, and labels for flexible filtering. domain: automation source_url: https://github.com/gmlupatelli/blueprints_repo/blob/master/unavailable_entities_notification/unavailable_entities_notification.yaml input: time: name: Time to test on description: Test is run at configured time default: '10:00:00' selector: time: {} monday_enabled: name: Monday default: true selector: boolean: {} tuesday_enabled: name: Tuesday default: true selector: boolean: {} wednesday_enabled: name: Wednesday default: true selector: boolean: {} thursday_enabled: name: Thursday default: true selector: boolean: {} friday_enabled: name: Friday default: true selector: boolean: {} saturday_enabled: name: Saturday default: true selector: boolean: {} sunday_enabled: name: Sunday default: true selector: boolean: {} exclude: name: Excluded Entities description: Entities (e.g. smartphone) to exclude. Entities, devices, areas, and labels are supported! default: {} selector: target: {} include: name: Included Entities description: Entities (e.g. smartphone) to include. Entities, devices, areas, and labels are supported! default: {} selector: target: {} actions: name: Actions description: Notifications or similar to be run. {{entities}} is replaced with a formatted list. default: [] selector: action: {} variables: monday_enabled: !input monday_enabled tuesday_enabled: !input tuesday_enabled wednesday_enabled: !input wednesday_enabled thursday_enabled: !input thursday_enabled friday_enabled: !input friday_enabled saturday_enabled: !input saturday_enabled sunday_enabled: !input sunday_enabled current_day: '{{ now().weekday() | int }}' exclude: !input exclude include: !input include excluded_entities: > {% set excluded = [] %} {% if exclude.entity_id is defined %} {% set excluded = excluded + ( [exclude.entity_id] if exclude.entity_id is string else exclude.entity_id ) %} {% endif %} {% if exclude.device_id is defined %} {% for d in ([exclude.device_id] if exclude.device_id is string else exclude.device_id) %} {% set excluded = excluded + device_entities(d) %} {% endfor %} {% endif %} {% if exclude.area_id is defined %} {% for a in ([exclude.area_id] if exclude.area_id is string else exclude.area_id) %} {% set excluded = excluded + area_entities(a) %} {% for d in area_devices(a) %} {% set excluded = excluded + device_entities(d) %} {% endfor %} {% endfor %} {% endif %} {% if exclude.label_id is defined %} {% for l in ([exclude.label_id] if exclude.label_id is string else exclude.label_id) %} {% set excluded = excluded + label_entities(l) %} {% endfor %} {% endif %} {{ excluded }} # Build included list included_entities_raw: > {{ label_entities('monitored') }} # Collect ALL unavailable entities (no filtering yet) unavailable_entities: > {% set unavail = states | selectattr('state','eq','unavailable') | map(attribute='entity_id') | list %} {{ unavail }} # Apply include/exclude filtering only here final_unavailable_entities: > {% set ns = namespace(final=[]) %} {% set included_list = included_entities_raw %} {% set excluded_list = excluded_entities %} {% for entity in unavailable_entities %} {% set dev_id = device_id(entity) %} {% if entity in included_list and not entity in excluded_list and (not device_attr(dev_id,'disabled_by')) %} {% set ns.final = ns.final + [state_attr(entity,'friendly_name') ~ ' (' ~ entity ~ ')'] %} {% endif %} {% endfor %} {{ ns.final }} entities: "{{ '- ' }}{{ final_unavailable_entities | join('\n- ') }}" trigger: - platform: time at: !input time condition: - condition: template value_template: > {{ (current_day == 0 and monday_enabled) or (current_day == 1 and tuesday_enabled) or (current_day == 2 and wednesday_enabled) or (current_day == 3 and thursday_enabled) or (current_day == 4 and friday_enabled) or (current_day == 5 and saturday_enabled) or (current_day == 6 and sunday_enabled) }} - condition: template value_template: '{{ final_unavailable_entities | length > 0 }}' action: !input actions mode: single max_exceeded: silent