############################################################################### # PACKAGE: Lounge Blinds - Sunrise / Sunset Automation ############################################################################### # # VERSION: # v1.2 - 2026-05-08 # - Updated input_boolean.lounge_blinds control logic. # - input_boolean.lounge_blinds ON now closes the blinds. # - input_boolean.lounge_blinds OFF now opens the blinds. # - Removed the sync guard helper. # - Added state checks so cover feedback does not create command loops. # # v1.1 - 2026-05-08 # - Added input_boolean.lounge_blinds as a manual control/status helper. # - Added cover state sync back to input_boolean.lounge_blinds. # # v1.0 - 2026-05-08 # - Initial package. # - Opens lounge blinds at sunrise. # - Closes lounge blinds at sunset. # - Includes sunrise/sunset minute offsets. # - Includes repeated command attempts for Zigbee reliability. # - Opens blinds in list order: A, B, C. # - Closes blinds in reverse list order: C, B, A. # # NOTES: # - input_boolean.lounge_blinds is treated as: # ON = blinds closed # OFF = blinds open # # - Turning input_boolean.lounge_blinds ON will close the blinds. # - Turning input_boolean.lounge_blinds OFF will open the blinds. # - If all blinds are closed by another method, the boolean will turn ON. # - If all blinds are opened by another method, the boolean will turn OFF. # - If blinds are in a mixed/partial state, the boolean is left unchanged. # # - The blind entity list is inside: # script.lounge_blinds_run_sequence # script.lounge_blinds_sync_status # automation.lounge_blinds_control_from_input_boolean # # - If you add more blinds, update the blind list in those three places. # ############################################################################### input_boolean: lounge_blinds: name: Lounge Blinds Closed icon: mdi:blinds input_number: lounge_blinds_sunrise_offset_minutes: name: Lounge Blinds Sunrise Offset icon: mdi:weather-sunset-up min: -180 max: 180 step: 1 mode: box unit_of_measurement: min initial: 0 lounge_blinds_sunset_offset_minutes: name: Lounge Blinds Sunset Offset icon: mdi:weather-sunset-down min: -180 max: 180 step: 1 mode: box unit_of_measurement: min initial: 0 lounge_blinds_per_blind_delay_seconds: name: Lounge Blinds Per-Blind Delay icon: mdi:timer-outline min: 0 max: 60 step: 1 mode: box unit_of_measurement: sec initial: 2 lounge_blinds_command_repeats: name: Lounge Blinds Command Repeats icon: mdi:repeat min: 1 max: 5 step: 1 mode: box initial: 2 lounge_blinds_retry_delay_seconds: name: Lounge Blinds Retry Delay icon: mdi:timer-refresh-outline min: 0 max: 120 step: 1 mode: box unit_of_measurement: sec initial: 10 input_datetime: lounge_blinds_next_open_time: name: Lounge Blinds Next Open Time has_date: true has_time: true lounge_blinds_next_close_time: name: Lounge Blinds Next Close Time has_date: true has_time: true script: lounge_blinds_update_sun_times: alias: Lounge Blinds - Update Sun Times mode: single sequence: - variables: sunrise_offset_seconds: > {{ states('input_number.lounge_blinds_sunrise_offset_minutes') | int(0) * 60 }} sunset_offset_seconds: > {{ states('input_number.lounge_blinds_sunset_offset_minutes') | int(0) * 60 }} next_sunrise_timestamp: > {{ as_timestamp(state_attr('sun.sun', 'next_rising')) + sunrise_offset_seconds }} next_sunset_timestamp: > {{ as_timestamp(state_attr('sun.sun', 'next_setting')) + sunset_offset_seconds }} - action: input_datetime.set_datetime target: entity_id: input_datetime.lounge_blinds_next_open_time data: datetime: > {{ next_sunrise_timestamp | timestamp_custom('%Y-%m-%d %H:%M:%S', true) }} - action: input_datetime.set_datetime target: entity_id: input_datetime.lounge_blinds_next_close_time data: datetime: > {{ next_sunset_timestamp | timestamp_custom('%Y-%m-%d %H:%M:%S', true) }} lounge_blinds_run_sequence: alias: Lounge Blinds - Run Open/Close Sequence mode: queued fields: blind_action: name: Blind Action description: Use open or close. required: true selector: select: options: - open - close sequence: - variables: blind_list: - cover.lounge_blind_a_xbl11 - cover.lounge_blind_b_xbl12 - cover.lounge_blind_c_xbl13 command_repeats: > {{ states('input_number.lounge_blinds_command_repeats') | int(2) }} retry_delay_seconds: > {{ states('input_number.lounge_blinds_retry_delay_seconds') | int(10) }} per_blind_delay_seconds: > {{ states('input_number.lounge_blinds_per_blind_delay_seconds') | int(2) }} - repeat: count: "{{ command_repeats }}" sequence: - choose: - conditions: - condition: template value_template: "{{ blind_action == 'open' }}" sequence: - repeat: for_each: "{{ blind_list }}" sequence: - action: cover.open_cover target: entity_id: "{{ repeat.item }}" - delay: seconds: "{{ per_blind_delay_seconds }}" - conditions: - condition: template value_template: "{{ blind_action == 'close' }}" sequence: - repeat: for_each: "{{ blind_list | reverse | list }}" sequence: - action: cover.close_cover target: entity_id: "{{ repeat.item }}" - delay: seconds: "{{ per_blind_delay_seconds }}" - if: - condition: template value_template: "{{ repeat.index < command_repeats }}" then: - delay: seconds: "{{ retry_delay_seconds }}" - action: script.lounge_blinds_sync_status lounge_blinds_sync_status: alias: Lounge Blinds - Sync Status mode: queued sequence: - variables: blind_list: - cover.lounge_blind_a_xbl11 - cover.lounge_blind_b_xbl12 - cover.lounge_blind_c_xbl13 blind_states: > {{ expand(blind_list) | map(attribute='state') | list }} all_blinds_closed: > {{ blind_states | select('eq', 'closed') | list | count == blind_list | count }} all_blinds_open: > {{ blind_states | select('eq', 'open') | list | count == blind_list | count }} - choose: - conditions: - condition: template value_template: > {{ all_blinds_closed and is_state('input_boolean.lounge_blinds', 'off') }} sequence: - action: input_boolean.turn_on target: entity_id: input_boolean.lounge_blinds - conditions: - condition: template value_template: > {{ all_blinds_open and is_state('input_boolean.lounge_blinds', 'on') }} sequence: - action: input_boolean.turn_off target: entity_id: input_boolean.lounge_blinds automation: - id: lounge_blinds_update_sun_times alias: Lounge Blinds - Update Sun Times mode: restart trigger: - platform: homeassistant event: start - platform: time at: "00:05:00" - platform: state entity_id: - input_number.lounge_blinds_sunrise_offset_minutes - input_number.lounge_blinds_sunset_offset_minutes action: - action: script.lounge_blinds_update_sun_times - id: lounge_blinds_open_at_sunrise alias: Lounge Blinds - Open At Sunrise mode: single trigger: - platform: time at: input_datetime.lounge_blinds_next_open_time action: - action: script.lounge_blinds_run_sequence data: blind_action: open - id: lounge_blinds_close_at_sunset alias: Lounge Blinds - Close At Sunset mode: single trigger: - platform: time at: input_datetime.lounge_blinds_next_close_time action: - action: script.lounge_blinds_run_sequence data: blind_action: close - id: lounge_blinds_control_from_input_boolean alias: Lounge Blinds - Control From Input Boolean mode: restart trigger: - platform: state entity_id: input_boolean.lounge_blinds to: "on" - platform: state entity_id: input_boolean.lounge_blinds to: "off" action: - variables: blind_list: - cover.lounge_blind_a_xbl11 - cover.lounge_blind_b_xbl12 - cover.lounge_blind_c_xbl13 blind_states: > {{ expand(blind_list) | map(attribute='state') | list }} all_blinds_closed: > {{ blind_states | select('eq', 'closed') | list | count == blind_list | count }} all_blinds_open: > {{ blind_states | select('eq', 'open') | list | count == blind_list | count }} - choose: - conditions: - condition: state entity_id: input_boolean.lounge_blinds state: "on" - condition: template value_template: "{{ not all_blinds_closed }}" sequence: - action: script.lounge_blinds_run_sequence data: blind_action: close - conditions: - condition: state entity_id: input_boolean.lounge_blinds state: "off" - condition: template value_template: "{{ not all_blinds_open }}" sequence: - action: script.lounge_blinds_run_sequence data: blind_action: open - id: lounge_blinds_sync_input_boolean_from_cover_states alias: Lounge Blinds - Sync Input Boolean From Cover States mode: restart trigger: - platform: homeassistant event: start - platform: state entity_id: - cover.lounge_blind_a_xbl11 - cover.lounge_blind_b_xbl12 - cover.lounge_blind_c_xbl13 to: "open" - platform: state entity_id: - cover.lounge_blind_a_xbl11 - cover.lounge_blind_b_xbl12 - cover.lounge_blind_c_xbl13 to: "closed" action: - action: script.lounge_blinds_sync_status