Expose the light transition state change flag (#1745)

Bulbs and light strips can fade smoothly when their brightness or colour
changes, instead of snapping straight to the new value. The Tapo app
exposes this as "Smooth Transition". python-kasa cannot read or change
it today, so the setting is missing from Home Assistant even though the
device supports it.

This adds support for this feature as a switch:
- read `change_state` in `_post_update_hook`
- add a `change_transition` property and `set_change_transition()`
- register a `smooth_transition_change` switch feature when the device
reports the flag
This commit is contained in:
nopoz
2026-10-04 07:01:50 -07:00
committed by GitHub
parent dc0745ad93
commit effdf5a298
3 changed files with 81 additions and 1 deletions

View File

@@ -480,6 +480,12 @@ class FakeSmartTransport(BaseTransport):
info["get_on_off_gradually_info"]["off_state"]["duration"] = (
off_state["duration"]
)
elif (change_state := params.get("change_state")) and (
"get_on_off_gradually_info" in info
):
info["get_on_off_gradually_info"]["change_state"]["enable"] = change_state[
"enable"
]
return {"error_code": 0}
def _set_dynamic_light_effect(self, info, params):

View File

@@ -1,6 +1,7 @@
import pytest
from pytest_mock import MockerFixture
from kasa import Feature, Module
from kasa import Feature, KasaException, Module
from kasa.smart import SmartDevice
from ...device_fixtures import get_parent_and_child_modules, parametrize
@@ -20,6 +21,11 @@ light_transition_gt_v1 = parametrize(
),
protocol_filter={"SMART"},
)
light_transition_any = parametrize(
"has light transition",
component_filter="on_off_gradually",
protocol_filter={"SMART"},
)
@light_transition_v1
@@ -79,3 +85,33 @@ async def test_module_gt_v1(dev: SmartDevice, mocker: MockerFixture) -> None:
await light_transition.set_turn_off_transition(0)
await dev.update()
assert light_transition.enabled is False
@light_transition_any
async def test_change_transition(dev: SmartDevice, mocker: MockerFixture) -> None:
"""Test the state change transition flag, which only newer firmware reports."""
light_transition = next(get_parent_and_child_modules(dev, Module.LightTransition))
supported = isinstance(light_transition.data.get("change_state"), dict)
if not supported:
assert "smooth_transition_change" not in light_transition._module_features
with pytest.raises(KasaException, match="does not support state change"):
_ = light_transition.change_transition
return
feat = light_transition._module_features["smooth_transition_change"]
assert feat.type is Feature.Type.Switch
assert feat.value == light_transition.change_transition
call_spy = mocker.spy(light_transition, "call")
await light_transition.set_change_transition(True)
call_spy.assert_called_once_with(
"set_on_off_gradually_info", {"change_state": {"enable": True}}
)
await dev.update()
assert light_transition.change_transition is True
await light_transition.set_change_transition(False)
await dev.update()
assert light_transition.change_transition is False