blueprint: name: Occupancy Lighting with Manual Override description: > Turns lights on when any presence sensor, motion sensor, or door sensor indicates occupancy. Turns lights off when all sensors are inactive for the configured delay. A physical switch input (e.g. Shelly in detached mode) toggles the light and suppresses sensor-based automation for a configurable period using a timer helper. Create one timer helper per room and pass it to the blueprint. domain: automation input: light_target: name: Light selector: target: entity: domain: light presence_sensors: name: Presence sensors default: [] selector: entity: domain: binary_sensor multiple: true motion_sensors: name: Motion sensors default: [] selector: entity: domain: binary_sensor multiple: true door_sensors: name: Door sensors default: [] selector: entity: domain: binary_sensor multiple: true switch_input: name: Physical switch input selector: entity: domain: binary_sensor override_timer: name: Override timer selector: entity: domain: timer override_duration: name: Override duration (seconds) default: 1800 selector: number: min: 60 max: 86400 step: 60 mode: box unit_of_measurement: seconds off_delay: name: Off delay (seconds) default: 5 selector: number: min: 0 max: 300 step: 1 mode: box unit_of_measurement: seconds mode: restart variables: presence_entities: !input presence_sensors motion_entities: !input motion_sensors door_entities: !input door_sensors timer_entity: !input override_timer trigger: - id: occupancy_change platform: state entity_id: !input presence_sensors - id: occupancy_change platform: state entity_id: !input motion_sensors - id: occupancy_change platform: state entity_id: !input door_sensors - id: manual_switch platform: state entity_id: !input switch_input from: "off" to: "on" - id: timer_finished platform: event event_type: timer.finished event_data: entity_id: !input override_timer action: - variables: override_active: "{{ is_state(timer_entity, 'active') }}" occupied: > {{ (presence_entities | length > 0 and expand(presence_entities) | selectattr('state', 'eq', 'on') | list | count > 0) or (motion_entities | length > 0 and expand(motion_entities) | selectattr('state', 'eq', 'on') | list | count > 0) or (door_entities | length > 0 and expand(door_entities) | selectattr('state', 'eq', 'on') | list | count > 0) }} - choose: - conditions: - condition: template value_template: "{{ trigger.id == 'manual_switch' }}" sequence: - action: light.toggle target: !input light_target - action: timer.start target: entity_id: !input override_timer data: duration: !input override_duration - conditions: - condition: template value_template: "{{ trigger.id == 'occupancy_change' and override_active }}" sequence: [] - conditions: - condition: template value_template: "{{ occupied }}" sequence: - action: light.turn_on target: !input light_target default: - delay: seconds: !input off_delay - condition: template value_template: > {{ not occupied and not is_state(timer_entity, 'active') }} - action: light.turn_off target: !input light_target