* 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>
* Register service actions in async_setup for Bronze tier compliance
- Move 'apply' and 'set_manual_control' service registration from async_setup_entry to async_setup.
- Move service handlers to module-level functions in switch.py.
- Update apply_service_schema to support dynamic defaults for transition duration.
- Clean up related unused imports and fix Python 3.10 syntax compatibility.
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* Clean up and add tests
* [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
* Fix lint errors
* Automated update of generated docs
* Re-add types
* Make transition not required again
* fix: validate global service targets
* fix: document optional apply transition
* fix: derive service docs from schema markers
* docs: clarify service target options
* fix: preserve entity service target handling
---------
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Bas Nijholt <bas@nijho.lt>
* refactor: introduce light control parameter enum
* refactor: replace manual control flag with parameter enum
* test: update deprecated color temp attribute
* build: set execution bits on task scripts
* feat: individual manual control of brightness and color
* test: add tests for individual manual control evaluation
* fix: sequential manual changes not always detected
If multiple attributes of a light were changed within an interval, only the last change was detected because the check in the interval only used the latest event. For example, if there was a brightness change and a following color change, only the color attribute was detected as manually controlled. To fix this, the manual control attribute flags are now set directly from the event handler so that all events are processed.
* fix: invalid service description
* docs: fix missing space in config description
* refactor: pluralize multivalued bitmask enum name
* Change the order of options in config flow
* Update README.md, strings.json, and services.yaml
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
* Fixes in maybe_cancel_adjusting to possibly fix accidental turn on
* simplify logic in maybe_cancel_adjusting
* Add logging statements
* only control if turn_on called
* more logs
* add TODO
* Add _state_event_is_from_our_turn_on
* Ignore off->on state switches that are not accociated with light.turn_on
* improve logging
* rename
* Update docs
* Update README.md, strings.json, and services.yaml
* Add caution message to README
* Change order of emojis
* Update README.md, strings.json, and services.yaml
* Check that platform is not None
* log the call
* fix args
* Do not re-add already added configs
* Do not re-add already added configs
* Use async_remove
* remove unused code
* [pre-commit.ci] pre-commit autoupdate (#627)
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.0.279 → v0.0.280](https://github.com/astral-sh/ruff-pre-commit/compare/v0.0.279...v0.0.280)
- [github.com/psf/black: 23.3.0 → 23.7.0](https://github.com/psf/black/compare/23.3.0...23.7.0)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Bas Nijholt <basnijholt@gmail.com>
* Extra logging statement
* Add to README
* log context_id
* return right indent
* move comment
* Skip on self.manager.is_proactively_adapting
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
* added #274
* attempt getSwitchFromLightId()
* Update switch.py
* changed from register_entity_service to hass.services.async_register
* Update switch.py
* Update switch.py
* Update switch.py
* Update switch.py
* Update switch.py
* Update switch.py
* Update services.yaml
* Update switch.py
* test
* test builds ready
* target selector may not be possible with current syntax
priority is backwards-compatibility as I know most people will smash that update button
* expanded light groups
* test builds ready
* add feature #104
* Update custom_components/adaptive_lighting/switch.py
Co-authored-by: Chris <firstof9@gmail.com>
* Might as well type both. No reason not to.
Co-authored-by: Chris <firstof9@gmail.com>
* Might as well type both. No reason not to.
Co-authored-by: Chris <firstof9@gmail.com>
* Reformatted debug messages.
Reimported ServiceCall as suggested
* Multiple switches allowed again in services.
Apparently this was possible before.
With this change, the `lights` argument must not be passed with multiple switches, or the integration has no way of knowing what the user wants to do. Integration did not make this check in prior versions.
Also reformatted the debug messages.
Removed `automerge.yaml` (my apologies)
* Reload config without restart.
You can now reload any changes to the yaml file without restarting your home assistant. Should show a 'reload' button in your integrations page or you can call the homeassistant reload integration service call.
See https://community.home-assistant.io/t/how-to-allow-custom-compontent-for-yaml-configuration-reloading/391190/4
* Use snake_case for function name 'parseServiceArgs'
* Slight rephrase
* Small style changes
* Rephrased debug messages.
Removed `integration_entities` as we rewrote the code from that function already in parse_service_args. Reference function now above parse_service_args.
* removed: `these_switches = data = None`
* Factor out _find_switch_with_lights
* Rename function and add log statement
* Remove pylint marker
* Handle multiple switches found
* Small changes
* Rename _parse_service_args to _get_switches_from_service_call
* Rephrase log messages
* Add type hint
---------
Co-authored-by: Chris <firstof9@gmail.com>
Co-authored-by: Bas Nijholt <bas@nijho.lt>
The apply service is meant to apply the adaptive lighting parameters to a specific set of light(s). This set of lights need to be passed to the service, even though each Adaptive Lighting switch already has this list configured on itself. While having the flexibility to apply to some, it also might be useful to apply to all lights that the switch manages.
This patch makes the lights paramater optional and defaults it to the lights configured on the corresponding configuration entry of the switch being called.