Skip to content

Fix light effect not being turned off sometimes#733

Draft
TheJulianJES wants to merge 2 commits into
zigpy:devfrom
TheJulianJES:tjj/light_effect
Draft

Fix light effect not being turned off sometimes#733
TheJulianJES wants to merge 2 commits into
zigpy:devfrom
TheJulianJES:tjj/light_effect

Conversation

@TheJulianJES
Copy link
Copy Markdown
Contributor

DRAFT. Should be cleaned up further.

Proposed change

This fixes an issue where sending a light turn on command with a color temperature does not cause some lights to switch into color temperature mode if the "color loop" effect is currently active.

Previously, we only turned off the effect after sending color (temp) commands. Now, we also do it before, though only if we're certain that an effect is active, to not send unnecessary packets.

Notes

Lights continue to be one of the most complicated things to do 100% right. This is the one known issue that happens in some cases.

In general, the light class will be cleaned up soon a bit. I want to increase test coverage for all edge cases before, though.
This PR may be adjusted and merged only after that's done. We'll see.

Additional information

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 1, 2026

Codecov Report

❌ Patch coverage is 85.71429% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 97.66%. Comparing base (696ab1c) to head (aeb75e5).

Files with missing lines Patch % Lines
zha/application/platforms/light/__init__.py 85.71% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##              dev     #733      +/-   ##
==========================================
+ Coverage   97.63%   97.66%   +0.03%     
==========================================
  Files          62       62              
  Lines       10814    10825      +11     
==========================================
+ Hits        10558    10572      +14     
+ Misses        256      253       -3     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

TheJulianJES added a commit to TheJulianJES/zha that referenced this pull request Apr 1, 2026
Copy link
Copy Markdown
Collaborator

@zigpy-review-bot zigpy-review-bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment-only — the fix is correct and the new tests lock both paths. Noting it's DRAFT and author already flagged "should be cleaned up further"; this is mostly forward-looking observations rather than blockers.

What the fix does

  • Computes deactivate_effect_after_turn_on from the pre-deactivate state, then runs _async_deactivate_effect_before_turn_on (gated on self._state being truthy) so a stale colorloop is cleared before color-mode-changing commands.
  • The original elif (self._effect == EFFECT_COLORLOOP and effect != EFFECT_COLORLOOP) becomes the post-turn-on path, now gated on deactivate_effect_after_turn_on so it only fires when the light started off (preserves prior behavior for the colorloop-was-set-while-off case).
  • I ran the two new tests against aeb75e5 in a worktree and both pass; the full tests/test_light.py (22 tests) also passes. Real mypy in the venv (76 errors) matches the dev baseline — no regression.

Observations (none blocking on a DRAFT)

  1. started_on is self._state snapshotted. The early-deactivate path only mutates self._effect, not self._state, so not started_on and not self._state are equivalent here. Keeping the local is fine for intent — just noting it's not load-bearing.
  2. _async_deactivate_effect_before_turn_on and _async_deactivate_effect_after_turn_on are near-identical — only the guard differs. Could collapse into a single helper that takes the guard inline, or be called unconditionally with the guard at the call site. Worth folding into the cleanup pass.
  3. self._effect = EFFECT_OFF is set unconditionally after the deactivate ZCL call, regardless of result[1]. Same as the pre-PR code, so not a regression — but if the deactivate fails on the wire, ZHA now reports effect=off while the device may still be looping. The _check_result helper in #734 would let this raise and unwind. Out of scope here; flagging because it's the kind of thing the #734 cleanup is positioned to address cleanly.

Cross-PR

  • #734 already folds in this PR's logic — both the early-deactivate-while-on path and the post-deactivate-from-off path are present there, and #734 adds the same two test cases as locks. If #734 is the intended landing strategy, this one can probably be closed as superseded once #734 leaves draft. If #733 lands first (smaller, more focused), #734 will need a trivial rebase.
  • #767 (Fix on/off-only lights reverting to off after rapid turn_off/turn_on, non-draft) edits the same async_turn_off transition-time/flag-setting block. No textual conflict with this PR (this PR doesn't touch async_turn_off), but worth being aware of the merge ordering.

Title

Matches repo conventions — concise, no prefix, no trailing period.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[ZHA] Fix light effects not turning off sometimes

2 participants