Commit graph

1,120 commits

Author SHA1 Message Date
Bas Nijholt
fdce4c9102
fix: keep adaptation updates from restarting manual-control timers (#1525)
* Fix autoreset timeout during partial adaptation

* Test manual timeout renewal for mixed light requests
2026-09-06 10:45:08 +02:00
Marijn Eken
8f78233e11
docs: clarify that UI setup needs no YAML entry (#1031)
* Fixed outdated info in README.md

The README says to always add an adaptive_lighting: entry in the YAML, where this seems to be no longer needed (or even preferred).

* docs: clarify YAML is optional for UI setup

---------

Co-authored-by: Bas Nijholt <basnijholt@users.noreply.github.com>
Co-authored-by: Bas Nijholt <bas@nijho.lt>
2026-09-06 10:43:37 +02:00
allcontributors[bot]
edc8f70996
docs: add davidgeiger as a contributor for bug (#1529)
* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
Co-authored-by: Bas Nijholt <bas@nijho.lt>
2026-09-06 10:38:49 +02:00
allcontributors[bot]
ee12752927
docs: add callistoprime as a contributor for bug (#1528)
* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
Co-authored-by: Bas Nijholt <bas@nijho.lt>
2026-09-06 10:37:50 +02:00
allcontributors[bot]
66e6d5ff5f
docs: add kasiom as a contributor for translation (#1527)
* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
Co-authored-by: Bas Nijholt <bas@nijho.lt>
2026-09-06 10:36:25 +02:00
Bas Nijholt
efa64d01be
fix: allow negative service offsets (#1524) 2026-09-06 10:35:35 +02:00
Bas Nijholt
17d9b39700
fix: restore Czech options placeholders (#1523) 2026-09-06 10:35:30 +02:00
allcontributors[bot]
c03a19c5a3
docs: add marijneken as a contributor for doc (#1526)
* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2026-09-06 10:34:44 +02:00
Bas Nijholt
c7339678a6
ci: check out the workflow commit during test setup (#1522) 2026-09-06 10:32:01 +02:00
proscar87
a2186ecf22
perf: stagger periodic adaptation updates (#1500)
Spread recurring updates with a deterministic per-switch offset while keeping turn-on adaptation immediate. Register the delayed listener on Home Assistant's event loop and cover cancellation, reconfiguration, and cadence with real timer tests.

Closes #939.

Co-authored-by: Bas Nijholt <basnijholt@gmail.com>
2026-09-06 01:12:28 -07:00
mueslo
68c0e4db69
fix: preserve Home Assistant area target exclusions (#1511)
* Exclude 'service' lights (entity_category) from area intercept turn-on

Fixes #1510

When Adaptive Lighting intercepts an area/label-targeted light.turn_on, the
intercept rewrites the call to target only the managed lights (see
modify_service_data), so Home Assistant's own handler turns on only those.
AL then re-issues light.turn_on for the remaining 'skipped' (unmanaged)
entities so they still come on.

The problem: HA excludes entities with an entity_category (config/diagnostic,
e.g. the Home Assistant Voice LED ring) from area/label expansion, but AL's
re-issue did not, so AL was the sole thing turning these service lights on.

Changes:
- Keep re-issuing skipped lights so unmanaged normal lights still come on,
  but filter out 'service' lights (entity_category set) from that re-issue.
- Add _is_service_light helper (registry-based) and divert a *managed*
  service light to 'skipped' in _separate_entity_ids, so it is excluded from
  the intercept turn-on while still being adapted when on.

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

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

* Add toggle regression test for service light exclusion from area intercept

Mirrors test_service_light_excluded_from_area_intercept_turn_on but uses
light.toggle: a service light (entity_category set) in an area must remain
off when AL intercepts an area toggle. The managed lights still toggle on.

Refs #1510, PR #1511.

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

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

* Only exclude service lights from indirect (area/device/label) expansion

Previously _is_service_light filtered service lights unconditionally, which
also excluded a service light explicitly named in `entity_id`. Home
Assistant only excludes such lights from indirect area/device/label expansion
and turns them on when directly targeted, so AL must mirror that: service
lights are now excluded from the intercept/re-issue only when not directly
targeted (`direct_entity_ids`).

Adds a regression test for the direct-target case.

Refs #1510, PR #1511.

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

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

* Use if/elif/else for indirect service-light exclusion; inline check

Address review: collapse the two separate `if is_service`/"if not
is_service" into an `if/elif/else` chain (ruff PLR5501) and inline the
service check as `self._is_service_light(...) and entity_id not in
direct_entity_ids`, which conceptually is `is_indirect_service`.
Matches HA's indirect-only exclusion and keeps the flow simple.

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

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

* Filter service lights directly in _get_entity_list expansion

Move service-light filtering to the single expansion site
AdaptiveLightingManager._get_entity_list. Area/device expansion is the
only place where HA excludes entity_category lights, so filtering there
mirrors HA and makes the later direct_entity_ids / skipped_normal guards
unnecessary. Explicit entity_id targets bypass expansion and therefore
still turn on service lights, matching HA.

Fully reverts the direct_entity_ids / skipped_normal addition per review.

---------

Co-authored-by: mueslo <mueslo@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Bas Nijholt <basnijholt@gmail.com>
2026-09-06 01:04:50 -07:00
Jared Jensen
e453541a78
feat: expose per-attribute manual-control state (#1469)
Adds two new read-only state attributes on the AdaptiveSwitch entity:

- manual_control_brightness: list of light entity_ids whose brightness
  axis is currently in manual override (i.e. AL is paused for brightness
  on those lights).
- manual_control_color: same, for the color axis.

These mirror the existing 'manual_control' attribute (which is a
union of both axes) but expose the LightControlAttributes bitfield
that AL already tracks internally per-light.

Why: the existing 'manual_control' state attribute and the
adaptive_lighting.manual_control event are useful, but neither lets
a template or dashboard see which axis is paused without subscribing
to events. This is especially important with take_over_control_mode:
pause_changed, where one axis can be manual while the other still
adapts. Now a Lovelace card or template sensor can display
brightness/color manual state directly via state_attr().

Test: extends test_manual_control to assert the new attributes
reflect the bitfield correctly.

No new platform, no breaking changes.

Co-authored-by: Bas Nijholt <basnijholt@gmail.com>
2026-09-06 00:59:38 -07:00
allcontributors[bot]
61896eb86a
docs: credit mueslo for code contributions (#1521)
* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2026-09-06 00:55:27 -07:00
allcontributors[bot]
9b0f03045b
docs: credit jaredjxyz for code contributions (#1520)
* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2026-09-06 00:54:58 -07:00
Bas Nijholt
cc99067c73
fix: keep adapting during polar night and midnight sun (#1489)
Handle missing polar sunrise and sunset with a shared fallback. Bound offsets between actual solar anchors while preserving the daily lighting cycle and configured time behavior.

Co-authored-by: Oscar Pacheco <oscar@gigadefense.com.mx>
2026-09-06 00:23:21 -07:00
proscar87
55f871fd0c
Adopt has_entity_name to fix duplicated entity ids on HA 2026.4+ (#1499)
* Adopt has_entity_name to fix duplicated entity ids on HA 2026.4+

Since HA core 2026.4 (PR 166246) composes entity names as device name +
entity name, and only strips the device prefix when the entity name
starts with it. Adaptive Lighting's names ('Adaptive Lighting Sleep
Mode: stairs' on device 'Adaptive Lighting: stairs') never match, so
new installs get ids like
switch.adaptive_lighting_stairs_adaptive_lighting_sleep_mode_stairs.

Adopt has_entity_name: the main switch takes the device name
('Adaptive Lighting: <name>'), the simple switches use their role
('Sleep Mode', 'Adapt Brightness', 'Adapt Color'). Unique ids are
unchanged, so existing installs keep their entity ids via the registry.

Fixes #1459

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Test the new entity ids and that existing ones survive

The renamed constants were defined but never asserted, so neither the
fresh-install ids nor the registry-preservation claim were covered.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* test: keep the apply-service test light on

Avoid generating brightness zero in the attribute-change helper, which turns the light off and makes the test depend on the current adaptive brightness.

---------

Co-authored-by: proscar87 <proscar87@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Bas Nijholt <bas@nijho.lt>
Co-authored-by: Bas Nijholt <basnijholt@gmail.com>
2026-09-06 09:18:49 +02:00
proscar87
67d4a2f657
fix: clamp() collapsed to minimum when min_brightness > max_brightness (#1507)
* fix: clamp() collapsed to minimum when min_brightness > max_brightness

A user can intentionally set min_brightness > max_brightness (or the
equivalent for color temperature) for an inverted timescale -- e.g. a
porch light that should be brighter at night than during the day.
clamp()'s max(minimum, min(value, maximum)) assumed minimum <= maximum;
when inverted, min(value, maximum) is always <= maximum < minimum, so
max(minimum, ...) always returns minimum. linear and tanh brightness
modes -- both of which end in a clamp(brightness, min_brightness,
max_brightness) call -- got stuck returning one fixed value regardless
of the time of day.

Fixes #1421

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

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

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

* test: accept current Home Assistant brightness validation errors

Keep asserting the maximum brightness limit without depending on the validation library's dictionary-path wording.

---------

Co-authored-by: Oscar Pacheco <proscar@MacBook-Pro-de-Oscar.local>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Bas Nijholt <bas@nijho.lt>
Co-authored-by: Bas Nijholt <basnijholt@gmail.com>
2026-09-06 00:10:21 -07:00
Dennis Dekker
c620d1480a
fix: re-adapt lights right after the auto-reset timer fires (#1506)
When the auto-reset timer fired, its callback called manager.reset(),
which pops the timer and calls timer.cancel() - cancelling the very task
that was running the callback. The manual_control flag was cleared, but
the re-adaptation that should follow was silently cancelled, so the light
only changed on the next interval pass (with the normal transition).

_AsyncSingleShotTimer.cancel() now never cancels the task that is
currently running its own callback. The trailing assert in the callback
is removed because it is reachable now and could trip when a new manual
change comes in while the re-adaptation is still running. The existing
auto-reset test also checks that a light.turn_on with the 'autoreset'
context is sent.

Fixes #1233

Co-authored-by: Dennis-Dekker <>
Co-authored-by: Bas Nijholt <bas@nijho.lt>
2026-09-06 07:01:50 +00:00
Samson Brock
68c66a0ff3
Fix options flow changes silently discarded for pre-refactor UI entries (#1504)
* Fix options flow changes being silently discarded for UI-configured entries

validate() merges config_entry.options then config_entry.data, on the
assumption that data only ever holds YAML-imported settings (which should
win) or, for UI-created entries, just the entry name (harmless to apply
last).

That assumption doesn't hold for entries created before data/options were
split: their data still carries the full settings snapshot from initial
setup. Applying it after options means any change made through the options
flow for a key that already exists in data (e.g. adding a light) is
silently ignored, even though the options flow reports success and the
entry reloads without error.

Reproduced on a real entry: added a light via the options flow, entry
reloaded cleanly, but the light was never picked up by the switch's
service-call interceptor ("No switch found for entity_id=...") because
data still held the old light list and clobbered the updated options.

Fix: only let data win over options for genuinely YAML-imported entries
(config_entry.source == SOURCE_IMPORT), matching the existing use of that
check elsewhere in this file. For UI-configured entries, apply options
last so changes made through the options flow actually take effect.

* Add focused tests for the data/options merge order in validate()

Covers both source-specific contracts the merge logic relies on, per
review feedback on this PR:

- SOURCE_USER: options must win over data (this PR's actual fix - proven
  to fail against the pre-fix code, verified locally by reverting
  switch.py and re-running).
- SOURCE_IMPORT: data must keep winning over options (the existing,
  intentional YAML-precedence behavior - unchanged by this PR, verified
  to already pass against the pre-fix code too).

Verified against a real Home Assistant instance's test harness
(pytest-homeassistant-custom-component + the actual installed
homeassistant package), not just reasoned about statically.

---------

Co-authored-by: Bas Nijholt <bas@nijho.lt>
2026-09-06 00:00:02 -07:00
Corey Peruffo
6d46b82313
fix: use quantization-aware comparison in skip_redundant_commands filter (#1513)
* fix: use quantization-aware comparison in skip_redundant_commands filter

_remove_redundant_attributes() compared target values against light state
with exact equality, but many targets can never round-trip exactly through
a device with coarser resolution:

- brightness: HA's 0-255 scale vs the 0-99 Z-Wave Multilevel Switch scale
  leaves 156 of 255 targets that never converge (e.g. 230 -> 89 -> 229),
- color_temp_kelvin: the kelvin -> mired -> kelvin round trip leaves most
  kelvin targets off by up to ~21 K at 6500 K (e.g. 5500 -> 182 -> 5495).

Such attributes survived the filter and were re-sent every interval
forever, which on larger Z-Wave meshes is enough to jam the controller.

Compare brightness with a tolerance of 2 (the exact worst case of the
0-99 scale) and color temperature in mired space, where devices actually
quantize and where the comparison is exact at every kelvin value. Both
are far below the manual-control detection thresholds
(BRIGHTNESS_CHANGE = 25, COLOR_TEMP_CHANGE = 100), so they cannot mask a
genuine user change.

Fixes #1512

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017P2wLQYGQH6npY5op5CKVD

* fix: tolerate one mired to cover both floor- and round-based conversions

The previous exact mired equality assumed round-based kelvin<->mired
conversion, but HA core's color_temperature_kelvin_to_mired() and
color_temperature_mired_to_kelvin() both use math.floor, under which a
target like 5500 K comes back as 5524 K in a different rounded mired
bucket and would never be filtered. Flooring in the comparison instead
would merely flip the failure onto integrations that round.

Comparing with a tolerance of one mired converges for both conversion
schemes (verified by brute force over 1000-10000 K: zero stuck targets
under either pipeline) and can hide at most ~2 mireds, far below the
~5.5 mired just-noticeable difference for color temperature.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017P2wLQYGQH6npY5op5CKVD

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Bas Nijholt <bas@nijho.lt>
2026-09-06 06:53:06 +00:00
renovate[bot]
5df9b30d32
⬆️ Update actions/checkout action to v7 (#1479)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Bas Nijholt <bas@nijho.lt>
2026-09-06 08:45:48 +02:00
allcontributors[bot]
cc93af84de
docs: add proscar87 as a contributor for code (#1519)
* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
Co-authored-by: Bas Nijholt <basnijholt@gmail.com>
2026-09-06 08:37:57 +02:00
allcontributors[bot]
efee60cb9a
docs: add Dennis-Dekker as a contributor for code (#1518)
* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
Co-authored-by: Bas Nijholt <basnijholt@gmail.com>
2026-09-06 08:37:34 +02:00
allcontributors[bot]
dce34134b6
docs: add imwithsam as a contributor for code (#1517)
* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
Co-authored-by: Bas Nijholt <basnijholt@gmail.com>
2026-09-06 08:37:09 +02:00
allcontributors[bot]
a9fd62a110
docs: add cperuffo3 as a contributor for code (#1516)
* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2026-09-06 08:35:50 +02:00
renovate[bot]
19dd9723a3
⬆️ Update python to v3.14.7 (#1419) 2026-09-06 08:30:13 +02:00
renovate[bot]
afb447c4e8
⬆️ Update pytz to v2026 (#1436) 2026-09-06 08:29:53 +02:00
renovate[bot]
928d57f8be
⬆️ Update actions/setup-python action to v7 (#1493) 2026-09-06 08:28:58 +02:00
renovate[bot]
f3af35f95e
⬆️ Update astral-sh/setup-uv action to v10 (#1501) 2026-09-06 08:28:48 +02:00
renovate[bot]
4a87b5ef54
⬆️ Update astral-sh/setup-uv action to v9 (#1496)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-07-29 14:02:37 -07:00
Bas Nijholt
7afdf5bc5c
Update manifest.json to v1.31.0 (#1486) v1.31.0 2026-07-07 09:38:26 -07:00
Bas Nijholt
3638fb3013
fix: don't cancel adaptation when a light group turns on via a member with a reused context (#1483)
* fix: don't cancel adaptation when a light group turns on via a member with a reused context (#1378)

When a member of a light group is turned on (e.g., by a motion sensor
automation) while the group is off, the group turns on as a side effect,
but Home Assistant may reuse the context of the earlier turn_off call for
the group's state change. just_turned_off() saw matching context IDs and
treated the state change as a polling artifact, cancelling adaptation.

- Check whether the off->on state change comes from a light.turn_on call
  before the matching-context polling-artifact check, so automations that
  turn a light off and back on with a single (automation) context adapt
  correctly.
- For light groups, allow adaptation when a member's turn_on event falls
  between the group's on->off and off->on state changes, bounded on both
  sides so stale member events are never treated as explanatory.
- Document that integration-level groups (e.g., Zigbee2MQTT groups) should
  not be nested inside HA Light Groups managed by Adaptive Lighting.

* fix: time-bound the same-context turn_on check instead of reordering

Address review findings:

- Reordering the turn_on-service check above the matching-context check
  reintroduced stale-event false negatives: turn_on_event entries are never
  cleaned up, so a 'turn_on -> delay -> turn_off(transition)' automation
  (one shared context) would defeat the polling-artifact guard and AL could
  turn a light back on right after it was turned off. Restore main's check
  order and instead add a time-bounded own-turn_on check inside the
  matching-context branch, symmetric with the group-member check. This
  also avoids emitting the 'should not happen' warning for self-context
  polling artifacts.
- Add a regression test for the stale same-context turn_on case.
- Add an end-to-end test driving the event-bus listeners for the #1378
  scenario (group kept in manager.lights, as in the reported setups).
- Docs: drop the inaccurate 'expands only one level deep' claim; explain
  that integration-level groups cannot be expanded and nested groups make
  tracking unpredictable.
2026-07-02 08:08:14 -07:00
Bas Nijholt
d4d3d50ada
fix: replace deprecated get_astral_location with get_astral_observer (#1482)
* fix: replace deprecated get_astral_location with get_astral_observer (#1481)

HA 2026.7 deprecates homeassistant.helpers.sun.get_astral_location
(removal planned for 2027.7) in favor of get_astral_observer, causing a
deprecation warning in the HA logs.

- Switch SunEvents/SunLightSettings from astral.location.Location to
  astral.Observer, using the astral.sun module functions (which return
  UTC times by default, matching the previous local=False calls).
- Use get_astral_observer in switch.py, with a fallback for HA < 2026.7
  that constructs the Observer directly from the HA config.
- Update tests and the webapp simulator accordingly.

* ci: handle removal of requirements_test_all.txt in HA 2026.8 dev

HA core removed requirements_test_all.txt (home-assistant/core#171530),
which made test_dependencies.py crash with FileNotFoundError and broke
the dev pytest job and the Docker builds. Fall back to
requirements_all.txt, which carries the same per-integration
'# homeassistant.components.x' annotations. Also extend the
aiohasupervisor pin lookup in scripts/setup-dependencies accordingly.

* test: support modern template light config for HA 2026.6+

HA 2026.6 removed the legacy `light: platform: template` YAML format
(home-assistant/core#169615), so setup_lights found no template platform
on HA dev and every test using it failed with IndexError. Detect legacy
support at runtime (PLATFORM_SCHEMA presence) and fall back to the
modern `template:` config format. The group platform is set up before
the template integration in the modern path, because setting up
`template` also sets up the `light` domain, which would make a later
async_setup_component(hass, LIGHT_DOMAIN, ...) a no-op.
2026-07-01 23:00:35 -07:00
renovate[bot]
ddaf851be3
⬆️ Update release-drafter/release-drafter action to v7
Squash merge Renovate GitHub Actions update.

Validation:
- Fixed PR-time Release Drafter v7 execution by using dry-run for pull_request events.
- GitHub Actions checks for PR #1445 passed before merge.
2026-04-24 14:55:04 -07:00
renovate[bot]
89b5e9a14f
⬆️ Update docker/setup-qemu-action action to v4
Squash merge Renovate GitHub Actions update.

Validation:
- GitHub Actions checks for PR #1438 passed before merge.
2026-04-24 14:23:26 -07:00
Florian
830c5589f7
fix: reduce log verbosity for self-triggered off-to-on warning (#1433) (#1434)
* fix: reduce log verbosity for self-triggered off-to-on warning (#1433)

Move full event object dump from warning to debug level in
_off_to_on_state_event_is_from_turn_on() (switch.py:2717).

For lights with large effect_list attributes (e.g. Govee lights
with 130+ effects), the warning dumped the entire Event object
including both old_state and new_state, creating log entries
thousands of characters long.

The warning now logs only entity_id and context.id, while the
full event remains available at debug level for troubleshooting.

Fixes #1433

* fix: correct indentation for _LOGGER.debug block

* fix: correct indentation for _LOGGER.warning and _LOGGER.debug

* fix: remove unintended encoding corruption, keep only log level change

Reset switch.py to main and re-apply only the intended change:
move the full event object from warning to debug level in
_off_to_on_state_event_is_from_turn_on().

Addresses reviewer feedback about unintended Unicode corruption
(→ and ≈ characters were corrupted to mojibake).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Florian Horner <florianhorner@Mac.fritz.box>
Co-authored-by: Bas Nijholt <basnijholt@users.noreply.github.com>
2026-04-24 13:30:18 -07:00
renovate[bot]
7dcad99d81
⬆️ Update docker/setup-buildx-action action to v4 (#1439)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-24 13:13:53 -07:00
renovate[bot]
cb4eb7ef49
⬆️ Update actions/deploy-pages action to v5 (#1453)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-24 13:13:34 -07:00
renovate[bot]
17e43e0427
⬆️ Update astral-sh/setup-uv action to v8 (#1468)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-24 13:13:15 -07:00
Florian
b787c533bf
fix: make setup-dependencies portable on macOS (#1463)
Two issues prevented the script from running on macOS without manual intervention:

1. `sed -i` requires a backup suffix on macOS BSD sed. Replace with a
   portable `grep -v | mv` idiom that works on both macOS and Linux.

2. `python` is not in PATH on macOS by default. Replace with `python3`.

Co-authored-by: Florian Horner <florianhorner@macbook-pro-von-florian.tail6f28f8.ts.net>
Co-authored-by: Bas Nijholt <basnijholt@users.noreply.github.com>
2026-04-24 13:12:20 -07:00
renovate[bot]
c8c31be573
⬆️ Update actions/upload-pages-artifact action to v5 (#1467)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-24 13:12:01 -07:00
renovate[bot]
86091de0e7
⬆️ Update docker/login-action action to v4 (#1437)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-24 12:00:21 -07:00
renovate[bot]
31762ba78d
⬆️ Update docker/metadata-action action to v6 (#1440)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-24 12:00:10 -07:00
renovate[bot]
0a305a7a4c
⬆️ Update docker/build-push-action action to v7 (#1441)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-04-24 11:59:38 -07:00
Bas Nijholt
c4b8e28ea8
fix: restore hassfest and Home Assistant CI
## Summary
- fix hassfest validation by replacing raw options-description URLs with Home Assistant translation placeholders
- extend the pytest CI matrix to cover the latest patch release for each Home Assistant month, plus dev
- align CI/dev container Python versions and tests with newer Home Assistant behavior

## Validation
- GitHub Actions pytest matrix passed for 2024.12.5 through 2026.4.3 plus dev
- Docker passed for linux/amd64 and linux/arm64
- hassfest, HACS validation, pre-commit, pre-commit.ci, markdown-code-runner, docs build, and Release Drafter passed
2026-04-24 11:31:53 -07:00
Roee Hendel
6cebe14a69
fix: merge last_service_data across split calls to fix detect_non_ha_changes with separate_turn_on_commands (#1426)
* test: regression test — AL must not override manual brightness with separate_turn_on_commands

End-to-end scenario: user adjusts brightness via a directly-bound Zigbee
switch (e.g. IKEA RODRET).  No HA service call is made; ZHA reports the new
brightness via async_update_entity.  On the next adaptation interval AL must
detect the change and stop overriding the user's brightness.

The test verifies the user-visible symptom: after two adaptation cycles
following a simulated direct-Zigbee brightness change, the light's brightness
must still be the manually set value — not AL's own target.

NOTE: this test FAILS on the current code.  It is committed here to document
the bug before the fix is applied in the next commit.

* fix: merge last_service_data across split calls to fix detect_non_ha_changes with separate_turn_on_commands

When separate_turn_on_commands=True, each adaptation cycle makes two
light.turn_on calls (brightness, then color_temp).  Previously each call
overwrote last_service_data[light], so after the cycle only the color_temp
key remained.  _attributes_have_changed() then saw old_brightness=None and
silently skipped the brightness comparison, so a manually-set brightness was
never detected and AL kept overriding it.

Fix: merge instead of overwrite so all split-call attributes accumulate:

    self.manager.last_service_data[light] = {
        **self.manager.last_service_data.get(light, {}),
        **service_data,
    }

* test: add intermediate assertions to regression test

Two assertions were promised in the PR description but missing:
1. After the force-adapt, assert that last_service_data contains BOTH
   brightness AND color — directly proving the merge fix works.
2. After the first non-forced update, assert that BRIGHTNESS is in
   manual_control — proving detection fired, not just that the final
   state is right.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

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

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

* refactor: remove spurious comments, trim test docstring and assertions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* refactor: strip verbose comments from test, trim assert messages

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

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

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

* test: add message to bare assert
2026-03-16 15:54:53 -07:00
Bas Nijholt
f9ccc946ee
Migrate to markdown-code-runner's built-in include_section() (#1417) 2026-01-26 09:01:50 +01:00
renovate[bot]
74a795d907
⬆️ Update actions/checkout action to v6.0.2 (#1411)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-01-22 23:02:25 +00:00
allcontributors[bot]
e9f7d4925f
docs: add Esspel as a contributor for translation (#1409)
* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2026-01-20 03:20:18 -08:00
allcontributors[bot]
ec33670b3f
docs: add Yllelder as a contributor for translation (#1408)
* docs: update README.md

* docs: update .all-contributorsrc

---------

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2026-01-20 03:19:00 -08:00