Add `color_temp_plateau_morning` and `color_temp_plateau_evening` (seconds,
default 0, max 12h). They keep `max_color_temp` for that long before / after
solar noon, and compress the ramp from/to `min_color_temp` at sunrise/sunset so
the curve stays continuous and smooth. Each side is independent, only the
color temperature is affected (not brightness, sleep mode or the night), and the
default (0) is bit-for-bit identical to the previous behavior. Each plateau is
clamped to 90% of the half-day so the ramp never collapses.
* feat: add expand_light_groups option
Some light group entities act as a proxy that must receive a single combined
`light.turn_on` call to function correctly — virtual mixers like
<https://github.com/mion00/color-temperature-light-mixer> for instance,
that blend a warm and a cold white channel into one entity. In such setups the
individual member entities only expose `ColorMode.BRIGHTNESS`, so sending
separate per-member commands bypasses the mixing logic.
Setting `expand_light_groups: false` keeps the group entity in `self.lights`
instead of expanding it to its members. Adaptation commands go to the group,
and the interceptor no longer skips group entities for that switch.
Default is `true` — no behaviour change for existing configurations.
* tests: regression test for expand_light_groups=False
_switches_with_lights was expanding the incoming entity_id globally,
causing the switch to never be found when expand_light_groups=False
* Resolve group targets consistently across adaptation paths
* Discard delayed group events after target changes
* Stabilize delayed group target regression test
---------
Co-authored-by: Bas Nijholt <bas@nijho.lt>
* feat: add `adapt_only_on_ha_turn_on` to skip adapting externally turned-on lights
When a light turns on from `off` via a source outside Home Assistant — a
physical wall switch or a hub/manufacturer scene (e.g. Lutron) — and
`detect_non_ha_changes` is enabled, Adaptive Lighting adapts the light on the
resulting `off` → `on` event, overriding the brightness/color the external
source just set. Disabling `detect_non_ha_changes` avoids this but also stops
detection of manual changes to already-on lights; the two behaviors were
coupled to a single flag.
Add `adapt_only_on_ha_turn_on` (default `false`, requires `take_over_control`).
When enabled, an `off` → `on` transition with no matching HA `light.turn_on`
context is marked `manual_control` and left untouched, independent of
`detect_non_ha_changes`, decoupling the two behaviors.
The off→on guard reduces to the previous expression when the option is `false`,
so existing configurations are unaffected. Includes a parametrized regression
test, docs, and regenerated strings/services/README via
scripts/update-generated-content.
Refs #435
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* Shorten generated turn-on option description
* Document shared turn-on policy limitations
* Name external turn-on policy after manual-control behavior
* Clarify settings needed to adapt unmatched turn-ons
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Bas Nijholt <bas@nijho.lt>
* Implement collapsible sections for options flow
Replace single-form options flow with collapsible sections:
- Basic options always visible (9 fields)
- Advanced options in collapsed section (collapsed by default)
- Single form, no multi-step navigation needed
Changes:
- const.py: Add BASIC_OPTIONS set defining which options are basic
- config_flow.py: Use section() from data_entry_flow to wrap advanced options
- strings.json: Restructure with sections.advanced for section translations
- tests: Update to handle nested section input format
* Update README.md, strings.json, and services.yaml
* Fix: Use vol.Required for section to render properly
* Fix section structure: separate basic and advanced fields in strings.json
* Remove accidentally added files
* Add local directories to gitignore
* Update README.md, strings.json, and services.yaml
* Preserve options behavior with collapsible sections
* Test serialized advanced options section
* fix: preserve config metadata when retrying options
* fix: keep options form defaults serializable
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
* feat: add option to duplicate existing lighting instance
A menu step in the config flow was added that allows a user to create a
new instance or duplicate the options of an existing one.
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* Add type annotation, tests, and translations for duplicate feature
- Add type annotation for source_options class attribute
- Add menu step translations to en.json
- Add tests for menu display, new instance creation, and duplication
* Simplify source_options access with class-level default
---------
Co-authored-by: Bas Nijholt <bas@nijho.lt>
* Update .devcontainer
* Drop support for ≤2023.6
* Add .vscode/settings.json
* Use async_process_ha_core_config
* Fix for HA ≤2023.10
* pop normalized_name
* Add comments
* use . instead of source
* set pytest args
* set country
* use py3.13 for dev branch of core
* set country in test_adaptive_lighting_time_zones_with_default_settings
* Add comment
* build: dev container
Add a VS Code Dev Container from the blueprint at bceaae212f
* build: dev container test setup
Add support for unit testing in the dev container environment with debugging and code coverage.
* ci: adjust to dev container test restructuring
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* ci: fix coverage collection
* build: add dummy light to HA config
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* build: update dev container to Python 3.11 (for HA 2023.6)
* Add VS Code tasks
* Use pre-commit hooks for linting
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* Unpin HA version
---------
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Bas Nijholt <basnijholt@gmail.com>