Include device_on in set_brightness, set_color_temp, and set_hsv#1680
Include device_on in set_brightness, set_color_temp, and set_hsv#1680fluffyspace wants to merge 5 commits intopython-kasa:masterpython-kasa/python-kasa:masterfrom fluffyspace:fix-device-on-light-commandsfluffyspace/python-kasa:fix-device-on-light-commandsCopy head branch name to clipboard
Conversation
Some Tapo devices (confirmed on L900-5 LED strip) treat power state and brightness/color as independent parameters. When set_device_info is called with only brightness or color parameters (without device_on), the device accepts the command, updates its internal state, and reports success — but the LEDs do not physically turn on. This causes a particularly bad failure mode: the device enters a "zombie state" where it reports on/brightness=100 to all queries while the LEDs remain off. The device stays in this state until power cycled, and python-kasa has no way to detect the discrepancy since every protocol response indicates success. Adding device_on: True to set_brightness(), set_color_temp(), and set_hsv() ensures the device always receives an explicit power state with light property changes. This matches the behavior of set_state() which already includes device_on, and is consistent with how the official Tapo app sends commands. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Update test_light_effect_brightness assertions in both test_light_effect.py and test_light_strip_effect.py to match the new set_brightness payload that includes device_on: True. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #1680 +/- ##
==========================================
+ Coverage 93.22% 93.24% +0.02%
==========================================
Files 157 157
Lines 9815 9822 +7
Branches 1003 1006 +3
==========================================
+ Hits 9150 9159 +9
Misses 472 472
+ Partials 193 191 -2 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Forcing device_on: True unconditionally in set_brightness, set_color_temp, and set_hsv fixed the L900-5 zombie state but reintroduced the python-kasa#1532 regression: users who want to change brightness on an off device without turning it on as a side-effect. Now device_on: True is injected only when self._device.is_on is already true. That still re-asserts the power state for devices in the zombie state (they report on, so the flag is still sent and the LEDs physically come up), while leaving a deliberately-off device alone. Tests parametrize all three setters over is_on=[True, False] to lock in both branches.
|
Updated in 85d8d38 to address the regression risk against #1532 / #1066. Original approach forced New approach: PR description updated with the full matrix; new parametrized tests in |
Fixes mypy: `dev` is typed as `Device` (the abstract base) which has no `_info` attribute. Patching the public `is_on` property has the same effect on the brightness module's logic and is type-clean.
Summary
device_on: Truein theset_device_infopayload fromset_brightness(),set_color_temp(), andset_hsv()— only whenself._device.is_onis already true.Problem
Some Tapo devices (confirmed on the L900-5 LED light strip) do not implicitly turn on when receiving brightness or color commands via
set_device_info. The device:error_code: 0)device_on: true,brightness: 100when queried)This creates a "zombie state" where the device reports it's on but the LEDs are off. The state persists until the device is power-cycled. Since every protocol response indicates success, python-kasa (and Home Assistant) have no way to detect the failure.
Root cause
Brightness.set_brightness()sent{"brightness": N}— nodevice_onColorTemperature.set_color_temp()sent{"color_temp": N}— nodevice_onColor.set_hsv()sent{"hue": N, "saturation": N}— nodevice_onMeanwhile,
Light.set_state()always includesdevice_onin the payload, and works correctly.Fix
Include
"device_on": Truein all three methods'set_device_infopayloads, only when the device is currently on. This re-asserts the power state for the zombie-state case (the device thinks it's on, so the flag is still sent and the LEDs physically come up) while leaving a deliberately-off device alone.is_ondevice_onsent?TrueTrueFalseThis matches the spirit of
set_state()(which sendsdevice_onexplicitly) without contradicting the "set brightness without turning on" use case from #1532 / #1066.Testing
Tested on a Tapo L900-5 (firmware current, KLAP v2 transport) controlled via Home Assistant's tplink integration:
light.turn_onwithbrightness_pct=100→ device reports on, LEDs stay offlight.turn_onwithbrightness_pct=100→ device reports on, LEDs turn onUnit tests
New
tests/smart/modules/test_light_device_on_payload.pyparametrizesset_brightness,set_color_temp, andset_hsvoveris_on=[True, False]and locks in:is_on=True→ payload includesdevice_on: Trueis_on=False→ payload omitsdevice_on(no regression for Regression? Latest kasa cli turns light on when setting brightness. #1532)Updated existing
test_light_effect_brightnesscases to forcedev._info["device_on"] = Trueso the asserted payload is deterministic across fixtures (some havedevice_on: falsebaked in).Closes the regression risk for #1532 / #1066.
🤖 Generated with Claude Code