Commit graph

85 commits

Author SHA1 Message Date
Bas Nijholt
e61a018616
Fix regression: lights not adapting when turned on by automation (#1380)
## Summary

- Fixes regression in v1.30.0 where lights turned on by automations were incorrectly marked as "manually controlled"
- Makes `adapt_only_on_bare_turn_on` respect individual attribute tracking from #1356

## Root Cause

PR #1356 added a call to `update_manually_controlled_from_event()` in the `turn_on_off_event_listener.on()` handler for ALL `light.turn_on` events, including when turning a light on from OFF state.

When an automation turns on a light with brightness/color attributes, this incorrectly marked the light as "manually controlled", preventing Adaptive Lighting from adapting it.

## Fix

1. Only call `update_manually_controlled_from_event()` when the light was **already ON** before the turn_on event. Turning on from OFF is handled by `_respond_to_off_to_on_event()`.

2. Make `adapt_only_on_bare_turn_on` respect `take_over_control_mode`:
   - With `PAUSE_CHANGED`: Only pause adaptation of specified attributes, continue adapting unspecified ones
   - With `PAUSE_ALL`: Pause all adaptation (existing behavior)

## Expected Behavior After Fix

| Scenario | `adapt_only_on_bare_turn_on` | `take_over_control_mode` | Result |
|----------|------------------------------|--------------------------|--------|
| Turn on from OFF with brightness | `false` | Either | NOT manually controlled |
| Turn on from OFF with brightness | `true` | `PAUSE_ALL` | All adaptation paused |
| Turn on from OFF with brightness | `true` | `PAUSE_CHANGED` | Only brightness paused, color adapts |
| Turn on from OFF without attributes | Either | Either | NOT manually controlled |
| Change brightness while ON | Either | Either | Brightness manually controlled |

## Test plan

- [x] Turn on light via automation with brightness/color (`adapt_only_on_bare_turn_on=false`) - should adapt
- [x] Turn on light via scene (`adapt_only_on_bare_turn_on=true`, `PAUSE_ALL`) - should pause all adaptation
- [x] Turn on light with brightness only (`adapt_only_on_bare_turn_on=true`, `PAUSE_CHANGED`) - should adapt color
- [x] Both intercept=True and intercept=False paths tested for consistency
- [x] CI tests pass

Fixes #1378

Co-authored-by: Mario Guggenberger <mg@protyposis.net>
2026-01-12 13:40:55 +01:00
Bas Nijholt
49f9da14fe
docs: clarify Docker test setup requirements (#1383) 2026-01-11 21:57:52 +01:00
Mario Guggenberger
f84ee445b7
Individual manual control of brightness and color (#1356)
* 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
2025-12-22 22:55:16 -08:00
Mario Guggenberger
5886eee04c
Code cleanup (#1348) 2025-12-12 13:37:42 -08:00
Bas Nijholt
94b91a0ddc
fix: use correct entity and context in service interceptor (#1349) 2025-12-12 13:05:01 -08:00
edgimar
4aeb50bfe3
feat: add option to duplicate existing lighting instance (#1329)
* 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>
2025-12-05 04:15:24 -08:00
Bas Nijholt
d95f0d4bc6
Fix xfail and skipped tests to properly pass (#1307) 2025-11-27 18:52:11 +00:00
Bas Nijholt
4feaf2c291
Add bidirectional color mode change detection (issue #1275) (#1299)
Extract _has_color_mode_changed() function that checks original attributes
BEFORE conversion, enabling detection of all mode switches:
- color_temp → RGB ✓
- color_temp → XY ✓
- RGB → color_temp ✓
- RGB → XY ✓
- XY → color_temp ✓
- XY → RGB ✓

This improves on PR #1282 by detecting mode changes in both directions.
2025-11-27 10:02:50 -08:00
Bas Nijholt
68e243c87e
Fix infinite loop when disabling SimpleSwitch entities (#1296)
* Add regression tests for SimpleSwitch initial state bug

Adds tests that verify SimpleSwitch._state is set immediately in __init__
rather than waiting for async_added_to_hass(). These tests currently FAIL
because _state is None after __init__, which causes an infinite loop in
_setup_listeners when the entity is disabled (since async_added_to_hass
is never called for disabled entities).

Regression tests for: https://github.com/basnijholt/adaptive-lighting/issues/1264

* Fix infinite loop when disabling SimpleSwitch entities

The issue was that SimpleSwitch._state was initialized to None in __init__,
but only set to a boolean value in async_added_to_hass(). When an entity
is disabled, async_added_to_hass() is never called, so _state stayed None.

The _setup_listeners() method has a while loop that waits for
_state is not None for all SimpleSwitch children (sleep_mode_switch,
adapt_brightness_switch, adapt_color_switch). With _state stuck at None,
this created an infinite loop.

The fix sets _state to initial_state directly in __init__ instead of
waiting for async_added_to_hass() to set it. The async_added_to_hass()
will still properly restore state from the last session or set based
on initial_state as before.

Fixes: https://github.com/basnijholt/adaptive-lighting/issues/1264
2025-11-27 09:30:01 -08:00
Bas Nijholt
e8af7a485e
Bump to 1.27.0 for fixes in 2025.12 (#1293) 2025-11-27 09:06:41 -08:00
Bas Nijholt
b1aca6408d
Skip broken test (#1226)
Also see https://github.com/basnijholt/adaptive-lighting/pull/1159
2025-06-15 22:16:31 -07:00
Bas Nijholt
cb67a4cb9c
Fix test_light_switch_in_specific_area (#1225) 2025-06-15 22:12:48 -07:00
Bas Nijholt
ded439e6f7
Fix Docker setup and CI installation (#1212) 2025-06-15 21:31:51 -07:00
pre-commit-ci[bot]
9aee234955
[pre-commit.ci] pre-commit autoupdate (#972)
* [pre-commit.ci] pre-commit autoupdate

updates:
- [github.com/pre-commit/pre-commit-hooks: v4.5.0 → v5.0.0](https://github.com/pre-commit/pre-commit-hooks/compare/v4.5.0...v5.0.0)
- [github.com/astral-sh/ruff-pre-commit: v0.3.5 → v0.8.4](https://github.com/astral-sh/ruff-pre-commit/compare/v0.3.5...v0.8.4)
- [github.com/psf/black: 24.3.0 → 24.10.0](https://github.com/psf/black/compare/24.3.0...24.10.0)

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Fix issues

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Bas Nijholt <bas@nijho.lt>
2025-01-01 23:28:15 -08:00
Bas Nijholt
935b913bc7
Fix test_proactive_adaptation_with_separate_commands (#1158) 2025-01-01 22:49:58 -08:00
Bas Nijholt
f8719994a6
use uv, fix devcontainer, and drop support for HA ≤2023.6 (#1151)
* 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
2025-01-01 16:11:22 -08:00
Bas Nijholt
d23f6ec63a
Fix test_proactive_adaptation_with_separate_commands (#970)
* Add link script

* Set run_immediately=False

* Add await hass.async_block_till_done()

* Use scripts/link

* Rename scripts

* Links in devcontainer

* Install from setup script
2024-04-07 14:01:05 +02:00
Bas Nijholt
47cbda5c5e
Add versions to matrix and fix area test (#967) 2024-04-06 19:05:18 +02:00
Bas Nijholt
9eae1501d3
Test HA core v2023.6 until v2024.2 (#942)
* Test HA core v2023.6 until v2024.2

* Use Python 3.12

* Add components.ffmpeg

* Revert "VS Code Dev Container (dev & test environment) (#605)"

This reverts commit 6283158ff7.

* Fix

* revert

* fi

* simplify

* Fix

* fixes

* fix

* rev

* Rename test

* fix

* fix all

* fix

* revert
2024-04-06 10:14:54 +02:00
Bas Nijholt
f2a124c30f
Update Ruff to be used in tests (#943)
* Update Ruff config

* Rerun ruff
2024-03-03 15:09:18 -08:00
pre-commit-ci[bot]
95a59438b6
[pre-commit.ci] pre-commit autoupdate (#882)
* [pre-commit.ci] pre-commit autoupdate

updates:
- [github.com/astral-sh/ruff-pre-commit: v0.1.6 → v0.2.0](https://github.com/astral-sh/ruff-pre-commit/compare/v0.1.6...v0.2.0)
- [github.com/psf/black: 23.11.0 → 24.1.1](https://github.com/psf/black/compare/23.11.0...24.1.1)

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2024-02-05 14:13:13 -08:00
Bas Nijholt
68feb3d931
Make instantaneous light.turn_on adaptation configurable with intercept (#750)
* Make intercept configurable

* Update README.md, strings.json, and services.yaml

* import

* skip

* split

* do not pass config_entry

* add to conf

* Update README.md, strings.json, and services.yaml

* spacing

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-08-15 12:23:56 -07:00
Bas Nijholt
435b2ce5d0
Fix adapt_only_on_bare_turn_on and apply does not result in manual_control (#729)
* Fix adapt_only_on_bare_turn_on and apply does not result in manual_control

Closes #723

* fix style
2023-08-09 21:48:18 +00:00
Bas Nijholt
f8e7880a96
Split up SunLightSettings and improve https://basnijholt.github.io/adaptive-lighting/ (#719)
* Split up SunLightSettings

* Renames

* factor out SunEvents

* more renames

* rewrite

* rewrite more

* simpler

* refactor

* refact

* raise

* refact

* rename

* move method

* clean

* Move to new module 'sun.py'

* make sun independent of HA

* rename

* Move to webapp/homeassistant_util_color.py

* Rework app

* Add link

* new plotting

* app changes

* fix tests

* test clean

* tz fixes

* fix

* use sed

* verbose

* fix tz

* fix

* tiem
2023-08-08 21:31:17 +00:00
Bas Nijholt
cb9ae39ee4
Fix adaptive_lighting.change_switch_settings service (#712)
* Fix adaptive_lighting.change_switch_settings service

Closes #623

* filter defaults

* fix mutable

* Revert debugging logs
2023-08-06 11:15:14 -07:00
Bas Nijholt
d44cb66148
Add adapt_only_on_bare_turn_on which instantly triggers manual_control when turning on with brightness or color (#709) 2023-08-05 20:56:32 -07:00
Bas Nijholt
a1cec19351
feat: add different brightness ramping mechanisms (#699)
* feat: add different brightness ramping mechanisms

* Rephrase

* Fix curves

* update images

* link to other graphs

* update images
2023-08-05 20:14:21 +00:00
Bas Nijholt
1ef7ed507e
Implement call intercept for multiple lights (#679)
* Implement call intercept for multiple lights

* remove comment

* skip if no eids

* add comment

* fix type

* Fix skipped

* indentation

* Add logging and fix error

* Fix for HA ≤2023.04

* simplify

* remove unused ignores

* Debug mode

* Add test

* Make test failing

* rename switch

* rename lights

* Fix tests

* Rename lights in tests

* Remove unused dependencies

* Improve tests

* More tests

* Remove the DEBUG_MODE

* Add doc-string

* Extra test

* assert

* extra test

* Comments

* fix

* fix

* expand light groups

* more logging

* sort

* Revert is_proactively_adapting checks
This reverts commit 39fd8f2be0.

* simplify the mapping

* Revert "Revert is_proactively_adapting checks"

This reverts commit 18803e8e50.

* test

* no light groups

* do not expand

* Do not expand_light_groups in intercept

* more logging

* Fix

* add comment

* Add multi_light_intercept config option

* Update README.md, strings.json, and services.yaml

* add light group

* fix platform

* add simple test

* turn off again

* Test without take over control

* improve test and fix it in one way

* Fixes

* add cleanup fixture

* format

* Update test_switch.py

* add __str__

* remove unneeded call

* simplify service_data construction

* Generalize is_our_context

* Fix multi_light_intercept: false

* add comments

* add docs

* Update README.md, strings.json, and services.yaml

* Add feature line

* move function

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-08-03 17:47:09 -07:00
Bas Nijholt
e0e04da0f6
Before scheduling turn_on do a last-minute check if lights are off (#671)
* Before scheduling turn_on do a last-minute check if lights are off

* Pass force

* add comment

* fix for proactive

* commetn

* No default for force

* rm newline

* no force

* Return bool
2023-08-02 23:11:45 -07:00
Bas Nijholt
e513393653
Keep on and off state tracking in Manager and listen to toggle (#689)
* Keep on and off state tracking in Manager

* Move manual_control code

* add todo

* check is_on

* Track toggle

* handle toggle

* fix debug

* test

* add comment

* better log

* Fix comment

* log

* test

* get

* check

* cancel early

* rephrase

* add assert

* Remove check
2023-07-31 18:40:32 -07:00
Bas Nijholt
d588a5984a
Refactor _update_attrs_and_maybe_adapt_lights (#688)
* Do not call self.manager.significant_change when not needed

* refact

* fix

* fix

* Add more logging to tests

* remove
2023-07-31 04:57:30 +00:00
Bas Nijholt
f4d872a540
Make sure that SimpleSwitches are added before AdaptiveSwitch (#686) 2023-07-30 20:01:08 +00:00
Bas Nijholt
68985199f6
Rename lights in tests (#681)
* Rename lights in tests

* Remove unused dependencies
2023-07-30 04:48:45 +00:00
Bas Nijholt
5c897f76da
More typing fixes (#675) 2023-07-29 00:17:26 +00:00
Bas Nijholt
89c90adde0
Only start adapting on light.turn_on when detect_non_ha_changes: false to prevent unwanted light turn ons (#663)
* 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>
2023-07-28 15:17:17 -07:00
Bas Nijholt
8696092879
Avoid adapting lights with nothing in service_data, closes #661 (#662) 2023-07-26 02:17:11 +00:00
Bas Nijholt
f9b6753e6d
Ensure that interpolation is in [0, 1], fixes #624 (#660)
* Ensure that interpolation is in [0, 1], fixes #624

* Bump to 1.17.1

* Add assert

* Interpolate via HSV space

* Add test
2023-07-25 10:46:34 -07:00
Bas Nijholt
97f388608a
With transition_until_sleep and sleep_rgb, after sunset, use RGB colors (#656)
* With transition_until_sleep and sleep_rgb, after sunset, use RGB colors

Closes #624

* Add comment

* Add test
2023-07-23 13:40:03 -07:00
Bas Nijholt
c1528ec10a
Refactor, simplify code, rename, and set minimal HA core ≥2022.11 (#655)
* Rename TurnOnOffListener to AdaptiveLightingManager

* Bump Python version

* Refactor and unify methods that are called once

* Simplify adaptation_utils.py

* Improve readability in adaptation_utils.py

* More renames

* Simplify

* More renames and simplifications

* fix test

* simplify _supported_features

* rename

* walrus

* drop old astral support

* Only support HA  ≥2021.06

* Require 2016.06

* Try 2023.1

* even more old versions

* test

* more versions

* verify that only ≥2022.11 works

* named args

* setdefault

* no astral v1

* var

* simplify

* no need to pass adapt_brightness and adapt_color

* Add comment
2023-07-22 21:19:01 -07:00
Bas Nijholt
69592938db
Rename TurnOnOffListener to AdaptiveLightingManager (#654)
* Rename TurnOnOffListener to AdaptiveLightingManager

* Bump Python version
2023-07-22 17:57:49 -07:00
Bas Nijholt
49857632cc
Fix multiple switches controlling one light (reactive path) (#644)
* Fix multiple switches controlling one light

* WIP

* Keep length in AdaptationData

* Do not proceed if there is nothing to do

* Simplify

* Set tasks correctly

* log more

* WIP

* realize that intercept and double switch not possible

* Remove which from find_switch_for_lights

* Rephrase

* Check which one to cancel

* length -> max_length

* Implement test_two_switches_for_single_light

* Clean up

* Simplify is_color_brightness_or_both

* Improve test

* no wait

* logging

* just block

* make test such that it fails on main
2023-07-21 14:46:18 -07:00
Bas Nijholt
19d503b4d7
Revert supported_features from #565 and #575, fixes #601 (#637) 2023-07-20 13:59:19 -07:00
Mario Guggenberger
ed80bd7829
feat: service call adaptation (#628)
* feat: service call adaptation

* feat: toggle-on service call adaptation

* feat: prefer service call transition
2023-07-19 09:10:21 +02:00
Mario Guggenberger
72e140e293
feat: skip redundant adaptation commands (#615)
* feat: skip redundant adaptation commands

* update README

* style

* Remove "experimental"

---------

Co-authored-by: Bas Nijholt <basnijholt@gmail.com>
Co-authored-by: Bas Nijholt <bas@nijho.lt>
2023-07-02 15:26:07 -07:00
Mario Guggenberger
6283158ff7
VS Code Dev Container (dev & test environment) (#605)
* 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>
2023-06-11 15:33:07 -07:00
Mario Guggenberger
2c8a45604a
feat: brightness prioritization (#598)
* feat: optional brightness prioritization

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Remove config flag and change default split order

* Fix test

* Fix edge case

* Add tests

* Backwards compatiblity

* Fix another edge case

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2023-06-08 16:01:19 -07:00
Benjamin Auquite
47c5ea93e0
Add test_supported_features and fix the problem introduced in #565 (#575)
* Update test_switch.py

* Update test_switch.py

* test is now done.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* fix the test only.

test is backwards compatible with the old method.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* fix _supported_to_attributes

everything works now.

* pre-commit fixes

cannot fix the `function too complex` problem.

* ignore test_switch.py in `pre-commit-config.yaml`

* Add ignore C901 to test_supported_features

* remove commented out code

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Bas Nijholt <basnijholt@gmail.com>
Co-authored-by: Bas Nijholt <bas@nijho.lt>
2023-04-27 12:56:49 -07:00
Bas Nijholt
fe7bdd3940
Add auto_reset_time_remaining attribute (#558)
* Add auto_reset_time_remaining attribute

* fix attr

* Add test
2023-04-08 05:39:08 -05:00
Bas Nijholt
c0c363136b
Test multiple Home Assistant releases and the dev branch (#552)
* Test for multiple Home Assistant versions

* Install ulid-transform

* remove unnecessary unsafe `async_set` from test

* Skip test_state_change_handlers in <2023.4

* Revert "Skip test_state_change_handlers in <2023.4"

This reverts commit 8d01b6ec4e.

---------

Co-authored-by: Benjamin Auquite <halomastar@gmail.com>
2023-04-06 16:36:57 -07:00
Bas Nijholt
59877a0343
Make sure context_id is 26 chars and partially conform to ULID standard (#550) 2023-04-06 12:37:02 -07:00