mirror of
https://github.com/python-kasa/python-kasa.git
synced 2026-10-07 05:13:49 +00:00
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
118 lines
4.2 KiB
Python
118 lines
4.2 KiB
Python
import pytest
|
|
from pytest_mock import MockerFixture
|
|
|
|
from kasa import Feature, KasaException, Module
|
|
from kasa.smart import SmartDevice
|
|
|
|
from ...device_fixtures import get_parent_and_child_modules, parametrize
|
|
from ...fixtureinfo import ComponentFilter
|
|
|
|
light_transition_v1 = parametrize(
|
|
"has light transition",
|
|
component_filter=ComponentFilter(
|
|
component_name="on_off_gradually", maximum_version=1
|
|
),
|
|
protocol_filter={"SMART"},
|
|
)
|
|
light_transition_gt_v1 = parametrize(
|
|
"has light transition",
|
|
component_filter=ComponentFilter(
|
|
component_name="on_off_gradually", minimum_version=2
|
|
),
|
|
protocol_filter={"SMART"},
|
|
)
|
|
light_transition_any = parametrize(
|
|
"has light transition",
|
|
component_filter="on_off_gradually",
|
|
protocol_filter={"SMART"},
|
|
)
|
|
|
|
|
|
@light_transition_v1
|
|
async def test_module_v1(dev: SmartDevice, mocker: MockerFixture) -> None:
|
|
"""Test light transition module."""
|
|
assert isinstance(dev, SmartDevice)
|
|
light_transition = next(get_parent_and_child_modules(dev, Module.LightTransition))
|
|
assert light_transition
|
|
assert "smooth_transitions" in light_transition._module_features
|
|
assert "smooth_transition_on" not in light_transition._module_features
|
|
assert "smooth_transition_off" not in light_transition._module_features
|
|
|
|
await light_transition.set_enabled(True)
|
|
await dev.update()
|
|
assert light_transition.enabled is True
|
|
|
|
await light_transition.set_enabled(False)
|
|
await dev.update()
|
|
assert light_transition.enabled is False
|
|
|
|
|
|
@light_transition_gt_v1
|
|
async def test_module_gt_v1(dev: SmartDevice, mocker: MockerFixture) -> None:
|
|
"""Test light transition module."""
|
|
assert isinstance(dev, SmartDevice)
|
|
light_transition = next(get_parent_and_child_modules(dev, Module.LightTransition))
|
|
assert light_transition
|
|
assert "smooth_transitions" not in light_transition._module_features
|
|
assert "smooth_transition_on" in light_transition._module_features
|
|
assert "smooth_transition_off" in light_transition._module_features
|
|
|
|
await light_transition.set_enabled(True)
|
|
await dev.update()
|
|
assert light_transition.enabled is True
|
|
|
|
await light_transition.set_enabled(False)
|
|
await dev.update()
|
|
assert light_transition.enabled is False
|
|
|
|
await light_transition.set_turn_on_transition(5)
|
|
await dev.update()
|
|
assert light_transition.turn_on_transition == 5
|
|
# enabled is true if either on or off is enabled
|
|
assert light_transition.enabled is True
|
|
|
|
await light_transition.set_turn_off_transition(10)
|
|
await dev.update()
|
|
assert light_transition.turn_off_transition == 10
|
|
assert light_transition.enabled is True
|
|
|
|
max_on = light_transition._module_features["smooth_transition_on"].maximum_value
|
|
assert max_on < Feature.DEFAULT_MAX
|
|
max_off = light_transition._module_features["smooth_transition_off"].maximum_value
|
|
assert max_off < Feature.DEFAULT_MAX
|
|
|
|
await light_transition.set_turn_on_transition(0)
|
|
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
|