GeezerVison is showing github.com — Add segment effect support for RGBIC light strips by shiner66 · Pull Request #1702 · python-kasa/python-kasa
Conversation
shiner66
commented
May 29, 2026
•
edited
Loading
Uh oh!
There was an error while loading. Please reload this page.
Summary
RGBIC light strips such as the L930 (also L920 / L430) expose a dedicated
segment_effect SMART component for the per-segment custom effects created in
the Tapo app (breathe, circulating, chasing, flicker, bloom, stacking, and the
static "none" paint). These
are a separate subsystem from the lighting_effect system handled by
LightStripEffect, and are activated with the apply_segment_effect_rule
method rather than set_lighting_effect. python-kasa currently has no support
for them.
This PR adds a SegmentEffect module:
REQUIRED_COMPONENT = "segment_effect"
- reads the active rule via
get_segment_effect_rule and the saved-effect list
from get_preset_rules (already fetched by LightPreset, so no extra query)
effect / effect_list / is_active / brightness / has_custom_effects
set_effect(name | "Off"), set_custom_effect(rule), set_brightness()
test(rule) / stop_test() for a churn-free live preview via
start_segment_effect_test / stop_segment_effect_test — plays a rule without
rewriting the device preset table (saving an effect makes the firmware/app
rewrite the preset list and evict effects no longer present)
- payload includes
deviceType: "strip" (required for custom effects) and
preserves speed (the firmware resets it to 0 / no animation if omitted)
The rule builder is hardened against the documented SegmentEffectData ranges
(decompiled from the Tapo Android app v3.18.506, cross-checked on a live L930):
- validates
type against the seven segment types (raises on anything else)
- clamps
brightness to 1-100 and speed to 1-10; speed: 0 is permitted only
for the static "none" paint (it freezes an animated type otherwise)
- normalises per-segment colours to the device's 4-int
[h, s, v, w] form and
reduces display_colors to the unique palette — start_segment_effect_test
rejects 3-int [h, s, v] colours with PARAMS_ERROR(-1008) (apply tolerates
them), so normalising keeps both code paths working
- the
segments field is dual-encoded by type: group sizes for the six
animated types, explicit LED indices for the static "none" paint
Also adds a FakeSmartTransport handler for apply_segment_effect_rule, tests,
and an L930 fixture (fw 1.4.3) that contains real saved segment effects.
Open question for maintainers
LightStripEffect names itself "LightEffect" on the assumption that a device
supports only one effect system, but RGBIC strips expose both
light_strip_lighting_effect and segment_effect. This PR therefore registers
the new module under its own name (Module.SegmentEffect) so the two coexist.
I'm happy to change the approach — e.g. unify both into the LightEffect
interface and route set_effect to the correct subsystem — if you prefer.
Notes on the fixture
The L930-5(EU)_1.0_1.4.3 fixture was captured from a real device. The region
suffix is assumed; the device brightness was normalised to a resting value and
the active segment rule set to enable: 0 (the two custom effects remain in the
preset slots). Happy to regenerate it with dump_devinfo if you'd rather.
Test plan
-
uv run pytest tests/smart/modules/test_segment_effect.py
-
uv run pytest -k "1.4.3" (full suite against the new fixture)
-
pre-commit run -a (ruff / mypy / generate-supported)
🤖 Generated with Claude Code
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
RGBIC strips such as the L930/L920/L430 expose a `segment_effect` component
for the per-segment custom effects created in the Tapo app (breathe,
circulating, chasing, flicker, bloom, stacking). These are separate from the
`lighting_effect` system handled by LightStripEffect and are activated with
the `apply_segment_effect_rule` method.
Add a SegmentEffect module exposing the saved-effect list (from preset rules),
the active effect, and set_effect/set_custom_effect, plus a fake-transport
handler for apply_segment_effect_rule and an L930 1.4.3 fixture.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
codecov
Bot
commented
May 29, 2026
•
edited
Loading
Uh oh!
There was an error while loading. Please reload this page.
|
❌ Patch coverage is 98.33333% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 93.30%. Comparing base (76d9f68) to head (56a7065).
⚠️ Report is 19 commits behind head on master.
Additional details and impacted files
@@ Coverage Diff @@
## master #1702 +/- ##
==========================================
+ Coverage 93.22% 93.30% +0.08%
==========================================
Files 157 158 +1
Lines 9815 9935 +120
Branches 1003 1018 +15
==========================================
+ Hits 9150 9270 +120
Misses 472 472
Partials 193 193
☔ View full report in Codecov by Harness.
📢 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.
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Add tests for set_custom_effect (with and without speed/carousel),
set_brightness (active and idle), the Off no-op path, the module
properties, and non-dict preset entries — bringing the module to 100%
coverage so the codecov patch check passes.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Harden the segment effect rule builder using the decompiled Tapo app
v3.18.506 `SegmentEffectData` bean (cross-checked on a live L930):
* Validate `type` against the seven segment types (now incl. the static
"none" paint) and raise on anything else.
* Clamp brightness to 1-100 and speed to 1-10; speed 0 is permitted only
for the static "none" paint (it freezes an animated type otherwise).
* Normalise per-segment colours to the device's 4-int [h, s, v, w] form
and reduce display_colors to the unique palette. start_segment_effect_test
rejects 3-int [h, s, v] colours with PARAMS_ERROR(-1008); apply tolerates
them, so normalising keeps both paths working.
Add test()/stop_test() backed by start/stop_segment_effect_test for a
churn-free live preview that does not rewrite the device preset table.
Expand the module docstring with the type/range table and the dual
`segments` encoding (group sizes for animated types, explicit LED indices
for "none"). Cover the new behaviour with four tests.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
|
Update — pushed 56a7065 hardening the rule builder against the documented SegmentEffectData ranges (decompiled from the Tapo Android app v3.18.506, cross-checked on a live L930):
- Validation & ranges —
type is validated against the seven segment types (now incl. the static none paint); brightness is clamped to 1–100 and speed to 1–10. speed: 0 is permitted only for none (it freezes an animated type otherwise).
- 4-int colours — per-segment colours are normalised to the device's
[h, s, v, w] form and display_colors is reduced to the unique palette. start_segment_effect_test rejects 3-int [h, s, v] colours with PARAMS_ERROR(-1008) while apply_segment_effect_rule tolerates them, so normalising keeps both code paths working.
- Live preview — new
test(rule) / stop_test() backed by start_segment_effect_test / stop_segment_effect_test. These play a rule without rewriting the device preset table, avoiding the churn where saving an effect makes the firmware/app rewrite the preset list and evict effects no longer present.
- Docs — the module docstring gains the type/range table and documents the dual
segments encoding: group sizes for the six animated types vs explicit LED indices for the static none paint.
+4 tests (clamping/normalisation, the none speed-0 exception, invalid-type, and the preview path). uv run ruff check & mypy clean; pytest tests/smart/modules/test_segment_effect.py → 72 passed, 12 skipped.
The PR description above has been updated to match.
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Assignees
No one assigned
Milestone
No milestone
Development
Successfully merging this pull request may close these issues.
Uh oh!
There was an error while loading. Please reload this page.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
|