# School dates transcribed from the supplied Blackhawk 2026-2027 calendar. # Early-dismissal days are school days. May 4-6 are closed for kindergarten # only and are not excluded from the older children's schedule. template: # Fetch overlapping events together; calendar.message exposes only one event. - triggers: - trigger: homeassistant event: start - trigger: event event_type: event_template_reloaded - trigger: time at: '00:00:00' - trigger: time_pattern minutes: '/15' - trigger: state entity_id: calendar.family_events actions: - variables: requested_day: "{{ now().date().isoformat() }}" agenda: {} - action: calendar.get_events continue_on_error: true target: entity_id: calendar.family_events data: start_date_time: "{{ today_at('00:00') }}" end_date_time: "{{ today_at('00:00') + timedelta(days=1) }}" response_variable: agenda - condition: template value_template: >- {{ agenda is defined and agenda is mapping and 'calendar.family_events' in agenda and 'events' in agenda['calendar.family_events'] }} sensor: - name: Family Day Events unique_id: family_day_events state: "{{ requested_day }}" attributes: refreshed_at: "{{ now().isoformat() }}" events: "{{ agenda['calendar.family_events']['events'] }}" - binary_sensor: - name: Family Schedule Ready unique_id: family_schedule_ready state: >- {{ has_value('calendar.family_events') and is_state('sensor.family_day_events', now().date().isoformat()) and as_timestamp(now()) - as_timestamp(state_attr('sensor.family_day_events', 'refreshed_at'), 0) < 1200 }} - name: Day Camp Today unique_id: family_day_camp_today availability: "{{ is_state('binary_sensor.family_schedule_ready', 'on') }}" state: >- {% set ns = namespace(camp=false) %} {% for event in state_attr('sensor.family_day_events', 'events') or [] %} {% set summary = event.summary | default('', true) | lower %} {% if summary | regex_search('\\bcamp\\b') and not summary | regex_search('\\b(no|cancelled|canceled)\\s+(day\\s+)?camp\\b|\\bcamp\\s+(is\\s+)?(cancelled|canceled)\\b') %} {% set ns.camp = true %} {% endif %} {% endfor %} {{ ns.camp }} - name: Family No School Today unique_id: family_no_school_today availability: "{{ is_state('binary_sensor.family_schedule_ready', 'on') }}" state: >- {% set ns = namespace(no_school=false) %} {% for event in state_attr('sensor.family_day_events', 'events') or [] %} {% set summary = event.summary | default('', true) | lower %} {% if summary | regex_search('\\b(no school|school closed|snow day)\\b') %} {% set ns.no_school = true %} {% endif %} {% endfor %} {{ ns.no_school }} - name: Girls At Home unique_id: family_girls_at_home availability: "{{ is_state('binary_sensor.family_schedule_ready', 'on') }}" state: >- {% set ns = namespace(home=false) %} {% for event in state_attr('sensor.family_day_events', 'events') or [] %} {% if event.summary | default('', true) | trim | lower == 'girls at home' %} {% set start = as_datetime(event.start | default(''), none) %} {% set end = as_datetime(event.end | default(''), none) %} {% if start is not none and end is not none %} {# All-day dates have no timezone; interpret them as local dates. #} {% if start.tzinfo is none %} {% set start = start.replace(tzinfo=now().tzinfo) %} {% endif %} {% if end.tzinfo is none %} {% set end = end.replace(tzinfo=now().tzinfo) %} {% endif %} {% if start <= now() < end %} {% set ns.home = true %} {% endif %} {% endif %} {% endif %} {% endfor %} {{ ns.home }} - name: Blackhawk Scheduled School Day unique_id: blackhawk_scheduled_school_day # Do not silently extend an old district calendar into a new school year. availability: >- {{ '2026-08-01' <= now().date().isoformat() <= '2027-07-31' }} state: >- {% set day = now().date().isoformat() %} {% set closed = [ '2026-09-07', '2026-10-12', '2026-11-11', '2026-11-24', '2026-11-25', '2026-11-26', '2026-11-27', '2026-11-30', '2026-12-23', '2026-12-24', '2026-12-25', '2026-12-28', '2026-12-29', '2026-12-30', '2026-12-31', '2027-01-01', '2027-01-18', '2027-02-15', '2027-03-25', '2027-03-26', '2027-03-29', '2027-05-07' ] %} {{ '2026-08-19' <= day <= '2027-05-27' and now().weekday() < 5 and day not in closed }} attributes: school_year: '2026-2027' first_day: '2026-08-19' last_day: '2027-05-27' calendar_valid_until: '2027-07-31' - name: Blackhawk School Day unique_id: blackhawk_school_day # Scheduled closures remain known even if the family calendar is down. # On regular school days, require fresh data for snow-day overrides. availability: >- {{ has_value('binary_sensor.blackhawk_scheduled_school_day') and (is_state('binary_sensor.blackhawk_scheduled_school_day', 'off') or has_value('binary_sensor.family_no_school_today')) }} state: >- {{ is_state('binary_sensor.blackhawk_scheduled_school_day', 'on') and is_state('binary_sensor.family_no_school_today', 'off') }} - name: Kids Summer Schedule Day unique_id: kids_summer_schedule_day availability: "{{ has_value('binary_sensor.blackhawk_school_day') }}" state: >- {% set day = now().date().isoformat() %} {{ now().weekday() < 5 and ('2026-08-01' <= day < '2026-08-19' or '2027-05-27' < day <= '2027-07-31') }} automation: - id: family_schedule_sync_legacy_camp_helper alias: Family Schedule - Sync Day Camp Helper description: Keep the existing camp helper compatible with the shared calendar sensor. triggers: - trigger: state entity_id: binary_sensor.day_camp_today to: - 'on' - 'off' actions: - action: "{{ 'input_boolean.turn_on' if is_state('binary_sensor.day_camp_today', 'on') else 'input_boolean.turn_off' }}" target: entity_id: input_boolean.day_camp_today mode: restart