fix(hass): driveway lights ignore TV mode, ramped evening dimming, bump to 2026.9.3
CI Images / Plan (pull_request) Failing after 2s
CI Images / Build ${{ matrix.key }} (pull_request) Skipped

The sunset automation required TV mode off, so an afternoon of TV skipped
the driveway string lights entirely (Sep 22 and 23) - not an outage. The
driveway now has its own sunset -1h automation, with catch-up on restart
or switch reconnect before 23:00.

Evening brightness lives in one script (evening_lights_apply) that blends
between the old step levels; a 5-minute ramp from 20:30 eases lights that
are on and leaves alone any a person has changed by hand. The Dining Hall
no longer bumps to 50% at 21:30.

TV off after 23:30 now only turns off the living room glow instead of
bringing the whole house back to full brightness, and TV on/off leave the
lights alone in daylight. Lights-out moves to 23:30, and a 01:00 sweep
catches anything switched back on at the wall.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Bastian de Byl
2026-09-25 12:42:33 -04:00
co-authored by Claude Opus 5.5
parent 15a8ec693e
commit fd985e014c
5 changed files with 237 additions and 397 deletions
+158 -396
View File
@@ -192,7 +192,8 @@
mode: single mode: single
- id: '1762116115638' - id: '1762116115638'
alias: Light - TV On alias: Light - TV On
description: '' description: TV mode on; once it's dark, dim the living room and turn off the
lights that glare on the TV
triggers: triggers:
- type: turned_on - type: turned_on
device_id: 18a9bb7a2a32be4371da447767ef50a9 device_id: 18a9bb7a2a32be4371da447767ef50a9
@@ -204,28 +205,32 @@
- action: input_boolean.turn_on - action: input_boolean.turn_on
target: target:
entity_id: input_boolean.tv_mode entity_id: input_boolean.tv_mode
- action: light.turn_on - if:
metadata: {} - condition: or
data: conditions:
brightness_pct: 5 - condition: sun
target: after: sunset
area_id: living_room after_offset: "-01:00:00"
- type: turn_off - condition: sun
device_id: 03a12d2360d9954aed19c2449070725a before: sunrise
entity_id: 7c1e7db73799cc3f90948b5118596985 then:
domain: light - action: light.turn_on
- type: turn_off data:
device_id: 800eddbeeda071225f181a14cb9527e0 brightness_pct: 5
entity_id: 521a92ddd8be76c7eddfc544f81f6020 target:
domain: light area_id: living_room
- type: turn_off - action: light.turn_off
device_id: 3f7f65571d9bb0833433996f1f6725bd target:
entity_id: 7407afe14783543252c666d5ff7c5d5c entity_id:
domain: light - light.kitchen_wall_light
- light.dining_hall
- light.bathroom_hallway
mode: single mode: single
- id: new_tv_off - id: new_tv_off
alias: Light - TV Off - Restore alias: Light - TV Off - Restore
description: Restores appropriate lighting level when TV turns off based on time description: Evening (sunset -1h to 23:30) brings the lights back to the
scheduled level; late night (23:30 to sunrise) only turns off the TV glow;
daytime leaves the lights alone
triggers: triggers:
- type: turned_off - type: turned_off
device_id: 18a9bb7a2a32be4371da447767ef50a9 device_id: 18a9bb7a2a32be4371da447767ef50a9
@@ -239,399 +244,156 @@
entity_id: input_boolean.tv_mode entity_id: input_boolean.tv_mode
- choose: - choose:
- conditions: - conditions:
- condition: sun
after: sunset
after_offset: "-01:00:00"
- condition: time - condition: time
after: '22:30:00' before: '23:30:00'
before: '23:45:00'
sequence: sequence:
# Late dim levels - action: script.evening_lights_apply
- type: turn_on data:
device_id: f31e4f9bf8fa3687a07aeb4430eaef38 apply: force
entity_id: b79934d97f3bb9d8a3da47c76d03ded4
domain: light
brightness_pct: 1
- type: turn_on
device_id: 03a12d2360d9954aed19c2449070725a
entity_id: 7c1e7db73799cc3f90948b5118596985
domain: light
brightness_pct: 1
- type: turn_on
device_id: 800eddbeeda071225f181a14cb9527e0
entity_id: 521a92ddd8be76c7eddfc544f81f6020
domain: light
brightness_pct: 25
- type: turn_on
device_id: 3f7f65571d9bb0833433996f1f6725bd
entity_id: 7407afe14783543252c666d5ff7c5d5c
domain: light
brightness_pct: 10
- type: turn_on
device_id: 21eb2bd28aba2ee361a22af92e8b2d16
entity_id: 81c486d682afcc94e98e377475cc92fc
domain: light
brightness_pct: 10
- conditions: - conditions:
- condition: time - condition: or
after: '21:30:00' conditions:
before: '22:30:00' - condition: time
after: '23:30:00'
- condition: sun
before: sunrise
sequence: sequence:
# Mid dim levels - action: light.turn_off
- type: turn_on target:
device_id: f31e4f9bf8fa3687a07aeb4430eaef38 area_id: living_room
entity_id: b79934d97f3bb9d8a3da47c76d03ded4
domain: light
brightness_pct: 25
- type: turn_on
device_id: 03a12d2360d9954aed19c2449070725a
entity_id: 7c1e7db73799cc3f90948b5118596985
domain: light
brightness_pct: 25
- type: turn_on
device_id: 800eddbeeda071225f181a14cb9527e0
entity_id: 521a92ddd8be76c7eddfc544f81f6020
domain: light
brightness_pct: 50
- type: turn_on
device_id: 3f7f65571d9bb0833433996f1f6725bd
entity_id: 7407afe14783543252c666d5ff7c5d5c
domain: light
brightness_pct: 25
- type: turn_on
device_id: 21eb2bd28aba2ee361a22af92e8b2d16
entity_id: 81c486d682afcc94e98e377475cc92fc
domain: light
brightness_pct: 25
- conditions:
- condition: time
after: '21:00:00'
before: '21:30:00'
sequence:
# Early dim levels
- type: turn_on
device_id: 03a12d2360d9954aed19c2449070725a
entity_id: 7c1e7db73799cc3f90948b5118596985
domain: light
brightness_pct: 50
- type: turn_on
device_id: f31e4f9bf8fa3687a07aeb4430eaef38
entity_id: b79934d97f3bb9d8a3da47c76d03ded4
domain: light
brightness_pct: 50
- type: turn_on
device_id: 3f7f65571d9bb0833433996f1f6725bd
entity_id: 7407afe14783543252c666d5ff7c5d5c
domain: light
brightness_pct: 50
- type: turn_on
device_id: 21eb2bd28aba2ee361a22af92e8b2d16
entity_id: 81c486d682afcc94e98e377475cc92fc
domain: light
brightness_pct: 50
default:
# Full brightness (before 21:00 after sunset)
- type: turn_on
device_id: 800eddbeeda071225f181a14cb9527e0
entity_id: 521a92ddd8be76c7eddfc544f81f6020
domain: light
brightness_pct: 25
- type: turn_on
device_id: f31e4f9bf8fa3687a07aeb4430eaef38
entity_id: b79934d97f3bb9d8a3da47c76d03ded4
domain: light
brightness_pct: 100
- type: turn_on
device_id: 03a12d2360d9954aed19c2449070725a
entity_id: 7c1e7db73799cc3f90948b5118596985
domain: light
brightness_pct: 100
- type: turn_on
device_id: 3f7f65571d9bb0833433996f1f6725bd
entity_id: 7407afe14783543252c666d5ff7c5d5c
domain: light
brightness_pct: 75
- type: turn_on
device_id: 21eb2bd28aba2ee361a22af92e8b2d16
entity_id: 81c486d682afcc94e98e377475cc92fc
domain: light
brightness_pct: 100
mode: single mode: single
- id: 'sunset_lights_on' - id: driveway_lights_on
alias: Lights - Sunset On alias: Driveway String Lights On
description: Turn on lights 1 hour before sunset description: On 1 hour before sunset whether or not the TV is on. Also catches
up if Home Assistant restarts or the switch reconnects before the 23:00 off
triggers: triggers:
- trigger: sun - trigger: sun
event: sunset event: sunset
offset: "-01:00:00" offset: "-01:00:00"
id: sunset
- trigger: homeassistant
event: start
- trigger: state
entity_id: switch.driveway_string_lights
from: unavailable
to: 'off'
conditions: conditions:
- condition: state - condition: state
entity_id: input_boolean.tv_mode entity_id: switch.driveway_string_lights
state: 'off' state: 'off'
- condition: or
conditions:
- condition: trigger
id: sunset
- condition: and
conditions:
- condition: sun
after: sunset
after_offset: "-01:00:00"
- condition: time
before: '23:00:00'
actions: actions:
- type: turn_on - action: switch.turn_on
device_id: 1fa1aca8f90daf94a2a7baf8a3abc158 target:
entity_id: 58d101e63456fd8e088d3a3b63f3a0f9 entity_id: switch.driveway_string_lights
domain: switch
- type: turn_on
device_id: 800eddbeeda071225f181a14cb9527e0
entity_id: 521a92ddd8be76c7eddfc544f81f6020
domain: light
brightness_pct: 25
- type: turn_on
device_id: f31e4f9bf8fa3687a07aeb4430eaef38
entity_id: b79934d97f3bb9d8a3da47c76d03ded4
domain: light
brightness_pct: 100
- type: turn_on
device_id: 03a12d2360d9954aed19c2449070725a
entity_id: 7c1e7db73799cc3f90948b5118596985
domain: light
brightness_pct: 100
- type: turn_on
device_id: 3f7f65571d9bb0833433996f1f6725bd
entity_id: 7407afe14783543252c666d5ff7c5d5c
domain: light
brightness_pct: 75
- type: turn_on
device_id: 21eb2bd28aba2ee361a22af92e8b2d16
entity_id: 81c486d682afcc94e98e377475cc92fc
domain: light
brightness_pct: 100
mode: single mode: single
- id: 'evening_dim_2100' - id: 'sunset_lights_on'
alias: Lights - Evening Dim (21:00) alias: Lights - Sunset On
description: Dim lights at 21:00 - only affects lights that are ON description: Turn on lights 1 hour before sunset. If the TV is on, the living
room gets the TV glow and the lights that glare on the TV stay off
triggers: triggers:
- trigger: time - trigger: sun
at: "21:00:00" event: sunset
conditions: offset: "-01:00:00"
- condition: state
entity_id: input_boolean.tv_mode
state: 'off'
actions:
- if:
- condition: device
device_id: 03a12d2360d9954aed19c2449070725a
domain: light
entity_id: 7c1e7db73799cc3f90948b5118596985
type: is_on
then:
- type: turn_on
device_id: 03a12d2360d9954aed19c2449070725a
entity_id: 7c1e7db73799cc3f90948b5118596985
domain: light
brightness_pct: 50
- if:
- condition: device
device_id: f31e4f9bf8fa3687a07aeb4430eaef38
domain: light
entity_id: b79934d97f3bb9d8a3da47c76d03ded4
type: is_on
then:
- type: turn_on
device_id: f31e4f9bf8fa3687a07aeb4430eaef38
entity_id: b79934d97f3bb9d8a3da47c76d03ded4
domain: light
brightness_pct: 50
- if:
- condition: device
device_id: 3f7f65571d9bb0833433996f1f6725bd
domain: light
entity_id: 7407afe14783543252c666d5ff7c5d5c
type: is_on
then:
- type: turn_on
device_id: 3f7f65571d9bb0833433996f1f6725bd
entity_id: 7407afe14783543252c666d5ff7c5d5c
domain: light
brightness_pct: 50
- if:
- condition: device
device_id: 21eb2bd28aba2ee361a22af92e8b2d16
domain: light
entity_id: 81c486d682afcc94e98e377475cc92fc
type: is_on
then:
- type: turn_on
device_id: 21eb2bd28aba2ee361a22af92e8b2d16
entity_id: 81c486d682afcc94e98e377475cc92fc
domain: light
brightness_pct: 50
mode: single
- id: 'mid_dim_2130'
alias: Lights - Mid Dim (21:30)
description: Dim lights at 21:30 - only affects lights that are ON
triggers:
- trigger: time
at: "21:30:00"
conditions:
- condition: state
entity_id: input_boolean.tv_mode
state: 'off'
actions:
- if:
- condition: device
device_id: f31e4f9bf8fa3687a07aeb4430eaef38
domain: light
entity_id: b79934d97f3bb9d8a3da47c76d03ded4
type: is_on
then:
- type: turn_on
device_id: f31e4f9bf8fa3687a07aeb4430eaef38
entity_id: b79934d97f3bb9d8a3da47c76d03ded4
domain: light
brightness_pct: 25
- if:
- condition: device
device_id: 03a12d2360d9954aed19c2449070725a
domain: light
entity_id: 7c1e7db73799cc3f90948b5118596985
type: is_on
then:
- type: turn_on
device_id: 03a12d2360d9954aed19c2449070725a
entity_id: 7c1e7db73799cc3f90948b5118596985
domain: light
brightness_pct: 25
- if:
- condition: device
device_id: 800eddbeeda071225f181a14cb9527e0
domain: light
entity_id: 521a92ddd8be76c7eddfc544f81f6020
type: is_on
then:
- type: turn_on
device_id: 800eddbeeda071225f181a14cb9527e0
entity_id: 521a92ddd8be76c7eddfc544f81f6020
domain: light
brightness_pct: 50
- if:
- condition: device
device_id: 3f7f65571d9bb0833433996f1f6725bd
domain: light
entity_id: 7407afe14783543252c666d5ff7c5d5c
type: is_on
then:
- type: turn_on
device_id: 3f7f65571d9bb0833433996f1f6725bd
entity_id: 7407afe14783543252c666d5ff7c5d5c
domain: light
brightness_pct: 25
- if:
- condition: device
device_id: 21eb2bd28aba2ee361a22af92e8b2d16
domain: light
entity_id: 81c486d682afcc94e98e377475cc92fc
type: is_on
then:
- type: turn_on
device_id: 21eb2bd28aba2ee361a22af92e8b2d16
entity_id: 81c486d682afcc94e98e377475cc92fc
domain: light
brightness_pct: 25
mode: single
- id: 'late_dim_2230'
alias: Lights - Late Dim (22:30)
description: Dim lights at 22:30 - only affects lights that are ON
triggers:
- trigger: time
at: "22:30:00"
conditions:
- condition: state
entity_id: input_boolean.tv_mode
state: 'off'
actions:
- if:
- condition: device
device_id: f31e4f9bf8fa3687a07aeb4430eaef38
domain: light
entity_id: b79934d97f3bb9d8a3da47c76d03ded4
type: is_on
then:
- type: turn_on
device_id: f31e4f9bf8fa3687a07aeb4430eaef38
entity_id: b79934d97f3bb9d8a3da47c76d03ded4
domain: light
brightness_pct: 1
- if:
- condition: device
device_id: 03a12d2360d9954aed19c2449070725a
domain: light
entity_id: 7c1e7db73799cc3f90948b5118596985
type: is_on
then:
- type: turn_on
device_id: 03a12d2360d9954aed19c2449070725a
entity_id: 7c1e7db73799cc3f90948b5118596985
domain: light
brightness_pct: 1
- if:
- condition: device
device_id: 800eddbeeda071225f181a14cb9527e0
domain: light
entity_id: 521a92ddd8be76c7eddfc544f81f6020
type: is_on
then:
- type: turn_on
device_id: 800eddbeeda071225f181a14cb9527e0
entity_id: 521a92ddd8be76c7eddfc544f81f6020
domain: light
brightness_pct: 25
- if:
- condition: device
device_id: 3f7f65571d9bb0833433996f1f6725bd
domain: light
entity_id: 7407afe14783543252c666d5ff7c5d5c
type: is_on
then:
- type: turn_on
device_id: 3f7f65571d9bb0833433996f1f6725bd
entity_id: 7407afe14783543252c666d5ff7c5d5c
domain: light
brightness_pct: 10
- if:
- condition: device
device_id: 21eb2bd28aba2ee361a22af92e8b2d16
domain: light
entity_id: 81c486d682afcc94e98e377475cc92fc
type: is_on
then:
- type: turn_on
device_id: 21eb2bd28aba2ee361a22af92e8b2d16
entity_id: 81c486d682afcc94e98e377475cc92fc
domain: light
brightness_pct: 10
mode: single
- id: 'lights_out_2345'
alias: Lights - Out (23:45)
description: Turn off all lights at 23:45
triggers:
- trigger: time
at: "23:45:00"
conditions: [] conditions: []
actions: actions:
- type: turn_off - action: script.evening_lights_apply
device_id: 3f7f65571d9bb0833433996f1f6725bd data:
entity_id: 7407afe14783543252c666d5ff7c5d5c apply: force
domain: light - if:
- type: turn_off - condition: state
device_id: f31e4f9bf8fa3687a07aeb4430eaef38 entity_id: input_boolean.tv_mode
entity_id: b79934d97f3bb9d8a3da47c76d03ded4 state: 'on'
domain: light then:
- type: turn_off - action: light.turn_on
device_id: 03a12d2360d9954aed19c2449070725a data:
entity_id: 7c1e7db73799cc3f90948b5118596985 brightness_pct: 5
domain: light target:
- type: turn_off area_id: living_room
device_id: 800eddbeeda071225f181a14cb9527e0 mode: single
entity_id: 521a92ddd8be76c7eddfc544f81f6020 - id: evening_dim_ramp
domain: light alias: Lights - Evening Dim Ramp
- type: turn_off description: Every 5 minutes from 20:30 to 23:30, ease the lights that are on
device_id: 03eb359bf2344a58bebfe1e9c5bcfadd toward the schedule in script.evening_lights_apply
entity_id: a30b2da3cd80a5b4c927e1608b91eb65 triggers:
domain: light - trigger: time_pattern
- type: turn_off minutes: /5
device_id: 21eb2bd28aba2ee361a22af92e8b2d16 conditions:
entity_id: 81c486d682afcc94e98e377475cc92fc - condition: time
domain: light after: '20:30:00'
before: '23:30:00'
actions:
- action: script.evening_lights_apply
data:
apply: ramp
mode: single
- id: 'lights_out_2345'
alias: Lights - Out (23:30)
description: Turn off all lights at 23:30. While the TV is on the living room
is left as it is
triggers:
- trigger: time
at: "23:30:00"
conditions: []
actions:
- action: light.turn_off
target:
entity_id:
- light.kitchen_lights
- light.kitchen_wall_light
- light.dining_hall
- light.dining_room
- light.bathroom_hallway
- if:
- condition: state
entity_id: input_boolean.tv_mode
state: 'off'
then:
- action: light.turn_off
target:
entity_id: light.living_room
mode: single
- id: lights_sweep_0100
alias: Lights - Sweep (01:00)
description: Catch anything turned back on after lights-out. While the TV is
on the living room is left as it is
triggers:
- trigger: time
at: "01:00:00"
conditions: []
actions:
- action: light.turn_off
target:
entity_id:
- light.kitchen_lights
- light.kitchen_wall_light
- light.dining_hall
- light.dining_room
- light.bathroom_hallway
- action: switch.turn_off
target:
entity_id: switch.driveway_string_lights
- if:
- condition: state
entity_id: input_boolean.tv_mode
state: 'off'
then:
- action: light.turn_off
target:
entity_id: light.living_room
mode: single mode: single
- id: '1768862300896' - id: '1768862300896'
alias: Bedroom On alias: Bedroom On
@@ -23,6 +23,7 @@ homeassistant:
media: /share media: /share
automation: !include automations.yaml automation: !include automations.yaml
script: !include scripts.yaml
input_boolean: input_boolean:
tv_mode: tv_mode:
@@ -0,0 +1,76 @@
evening_lights_apply:
alias: Evening Lights - Apply Schedule
description: >-
Sets each evening light to its scheduled brightness for the current time,
blending linearly between the points in `schedule`. apply=force turns the
lights on (sunset, TV off); apply=ramp only eases lights that are already
on, and leaves alone any light someone has changed by hand. While TV mode
is on the living room and the lights that glare on the TV are left alone.
mode: queued
fields:
apply:
description: "force: turn lights on at the target. ramp: only adjust lights that are already on."
example: ramp
selector:
select:
options:
- force
- ramp
variables:
# [minute of day, brightness %] - 1230 = 20:30, 1260 = 21:00,
# 1290 = 21:30, 1350 = 22:30. Before the first point a light sits at the
# first value; after the last it holds the last value until lights-out.
schedule:
light.kitchen_lights: [[1230, 100], [1260, 50], [1290, 25], [1350, 1]]
light.kitchen_wall_light: [[1230, 100], [1260, 50], [1290, 25], [1350, 1]]
light.bathroom_hallway: [[1230, 75], [1260, 50], [1290, 25], [1350, 10]]
light.living_room: [[1230, 100], [1260, 50], [1290, 25], [1350, 10]]
light.dining_hall: [[1290, 25], [1350, 15]]
tv_mode_lights:
- light.living_room
- light.kitchen_wall_light
- light.dining_hall
- light.bathroom_hallway
apply_mode: "{{ apply | default('ramp') }}"
sequence:
- repeat:
for_each: "{{ schedule.keys() | list }}"
sequence:
- variables:
light: "{{ repeat.item }}"
# [target now, target 5 minutes ago - what the last ramp tick set]
levels: >-
{%- macro at(pts, t) -%}
{%- if t <= pts[0][0] -%}{{ pts[0][1] }}
{%- elif t >= pts[-1][0] -%}{{ pts[-1][1] }}
{%- else -%}
{%- for i in range(pts | length - 1) if pts[i][0] <= t < pts[i + 1][0] -%}
{{ (pts[i][1] + (pts[i + 1][1] - pts[i][1]) * (t - pts[i][0]) / (pts[i + 1][0] - pts[i][0])) | round(0) | int }}
{%- endfor -%}
{%- endif -%}
{%- endmacro -%}
{%- set t = now().hour * 60 + now().minute -%}
{{ [at(schedule[repeat.item], t) | int, at(schedule[repeat.item], t - 5) | int] }}
current: "{{ ((state_attr(repeat.item, 'brightness') or 0) / 2.55) | round(0) | int }}"
skip: "{{ is_state('input_boolean.tv_mode', 'on') and repeat.item in tv_mode_lights }}"
- choose:
- conditions: "{{ not skip and apply_mode == 'force' }}"
sequence:
- action: light.turn_on
target:
entity_id: "{{ light }}"
data:
brightness_pct: "{{ levels[0] }}"
transition: 2
# A light more than 10 points off the last tick was set by hand; the
# biggest scheduled change in 5 minutes is ~8
- conditions: >-
{{ not skip and apply_mode == 'ramp' and is_state(light, 'on')
and (current - levels[1]) | abs <= 10 and current != levels[0] }}
sequence:
- action: light.turn_on
target:
entity_id: "{{ light }}"
data:
brightness_pct: "{{ levels[0] }}"
transition: 60
@@ -25,6 +25,7 @@
loop: loop:
- configuration.yaml - configuration.yaml
- automations.yaml - automations.yaml
- scripts.yaml
- name: flush handlers - name: flush handlers
ansible.builtin.meta: flush_handlers ansible.builtin.meta: flush_handlers
+1 -1
View File
@@ -39,7 +39,7 @@
- import_tasks: containers/home/hass.yml - import_tasks: containers/home/hass.yml
vars: vars:
image: ghcr.io/home-assistant/home-assistant:2026.8.3 image: ghcr.io/home-assistant/home-assistant:2026.9.3
tags: hass tags: hass
- import_tasks: containers/home/partsy.yml - import_tasks: containers/home/partsy.yml