Add restore_manual_control option to keep manual control across restarts

A restart currently clears manual control for every light: the startup
adaptation resets the flags and force-adapts, so a light that was dimmed by
hand before the restart comes back at the adaptive values. With the new
opt-in option, manual control is written to storage as it changes (debounced,
one store per Home Assistant instance) and restored at startup. The restored
flags are resolved once at EVENT_HOMEASSISTANT_STARTED: kept while the light
is on and at least one profile controlling it has the option without
autoreset_control_seconds, dropped otherwise, and forgotten when no profile
controls the light anymore, so the outcome does not depend on the order the
profiles are set up in. Only a full restart restores; a config-entry reload
still clears manual control. Unloading the last entry writes a pending save.
Defaults stay unchanged and nothing is read or written unless a profile opts in.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EdXCHuaz4Yj932oEwtgouW
This commit is contained in:
Joe Neuman 2026-09-08 18:00:23 -07:00
commit b1729d906c
10 changed files with 586 additions and 4 deletions

View file

@ -138,6 +138,27 @@ adaptive_lighting:
manual_control_on_external_turn_on: true # leave unmatched off→on events unchanged
```
### restore_manual_control
By default a Home Assistant restart clears manual control: the startup adaptation brings every light back to the adaptive values. When enabled, manual control is saved to storage as it changes and restored at startup, so a light you dimmed before the restart stays where you left it. The option is off by default and nothing is written to storage until at least one profile enables it.
What is stored is the manual-control flag of every light your profiles control, with the same brightness and color detail the switch attributes show. It is written whenever a flag changes, whether you dimmed the light, called `adaptive_lighting.set_manual_control`, or turned the light off. Writes are debounced by two seconds and go to one `adaptive_lighting.manual_control` file per Home Assistant instance.
At startup the stored flags are pruned before anything adapts. A flag is kept only when the light is on. A light that was turned off while Home Assistant was down is not restored, because manual control normally clears on the off event that never reached Home Assistant. A light that is unavailable at startup is treated the same way, since its integration may bring it back in any state. A light that no profile controls anymore is forgotten entirely. Everything that is kept follows the usual rules from then on: off and on, an explicit reset, or a sleep mode change clears it.
Profiles with `autoreset_control_seconds` do not restore manual control, because their holds are meant to expire on their own. Manual control belongs to the light rather than to a profile, so when several profiles control the same light the flag is restored as long as one of those profiles has this option enabled without an autoreset. The result does not depend on the order in which the profiles are set up.
Only a full restart restores manual control. Reloading a config entry, or changing an option, still clears it the way it always has.
```yaml
adaptive_lighting:
- name: "Keep my dimming through restarts"
lights:
- light.living_room
take_over_control: true
restore_manual_control: true
```
## Checking Manual Control Status
You can see which lights are marked as manually controlled by checking the switch attributes:

View file

@ -68,6 +68,7 @@ All configuration options are listed below with their default values. These opti
| `adapt_only_on_bare_turn_on` | When turning lights on initially. If set to `true`, AL adapts only if `light.turn_on` is invoked without specifying color or brightness. ❌🌈 This e.g., prevents adaptation when activating a scene and marks the light as manually controlled. If `false`, AL adapts regardless of the presence of color or brightness in the initial `service_data`. Needs `take_over_control` enabled. 🕵️ | `False` | `bool` |
| `manual_control_on_external_turn_on` | Treat turn-ons without a matching Home Assistant `light.turn_on` context as manual control. Normal manual-control resets apply. Still allows `detect_non_ha_changes` for already-on lights. Needs `take_over_control` enabled. 🕵️ | `False` | `bool` |
| `reset_manual_control_on_sleep_mode_change` | Reset manual control when the sleep mode switch is toggled. Set to `false` to preserve manual control across sleep mode changes. 😴 | `True` | `bool` |
| `restore_manual_control` | Keep manual control across Home Assistant restarts. Manually controlled lights are saved to storage and restored at startup while they are still on, so the startup adaptation leaves them alone. Ignored when `autoreset_control_seconds` is set. 💾 | `False` | `bool` |
| `separate_turn_on_commands` | Use separate `light.turn_on` calls for color and brightness, needed for some light types. 🔀 | `False` | `bool` |
| `send_split_delay` | Delay (ms) between `separate_turn_on_commands` for lights that don't support simultaneous brightness and color setting. ⏲️ | `0` | `int` 0-10000 |
| `adapt_delay` | Wait time (seconds) between light turn on and Adaptive Lighting applying changes. Might help to avoid flickering. ⏲️ | `0` | `float > 0` |