Add light presets common module to devices. (#907)

Adds light preset common module for switching to presets and saving presets.
Deprecates the `presets` attribute and `save_preset` method from the `bulb` 
interface in favour of the modular approach.  Allows setting preset for `iot` 
which was not previously supported.
This commit is contained in:
Steven B
2024-05-19 11:20:18 +01:00
committed by GitHub
parent 1ba5c73279
commit 273c541fcc
20 changed files with 612 additions and 73 deletions

View File

@@ -1,8 +1,9 @@
import pytest
from pytest_mock import MockerFixture
from kasa import Device, Module
from kasa import Device, LightState, Module
from kasa.tests.device_fixtures import (
bulb_iot,
dimmable_iot,
dimmer_iot,
lightstrip_iot,
@@ -33,6 +34,12 @@ dimmable_smart = parametrize(
)
dimmable = parametrize_combine([dimmable_smart, dimmer_iot, dimmable_iot])
light_preset_smart = parametrize(
"has light preset smart", component_filter="preset", protocol_filter={"SMART"}
)
light_preset = parametrize_combine([light_preset_smart, bulb_iot])
@led
async def test_led_module(dev: Device, mocker: MockerFixture):
@@ -130,3 +137,80 @@ async def test_light_brightness(dev: Device):
with pytest.raises(ValueError):
await light.set_brightness(feature.maximum_value + 10)
@light_preset
async def test_light_preset_module(dev: Device, mocker: MockerFixture):
"""Test light preset module."""
preset_mod = dev.modules[Module.LightPreset]
assert preset_mod
light_mod = dev.modules[Module.Light]
assert light_mod
feat = dev.features["light_preset"]
call = mocker.spy(light_mod, "set_state")
preset_list = preset_mod.preset_list
assert "Not set" in preset_list
assert preset_list.index("Not set") == 0
assert preset_list == feat.choices
assert preset_mod.has_save_preset is True
await light_mod.set_brightness(33) # Value that should not be a preset
assert call.call_count == 0
await dev.update()
assert preset_mod.preset == "Not set"
assert feat.value == "Not set"
if len(preset_list) == 1:
return
second_preset = preset_list[1]
await preset_mod.set_preset(second_preset)
assert call.call_count == 1
await dev.update()
assert preset_mod.preset == second_preset
assert feat.value == second_preset
last_preset = preset_list[len(preset_list) - 1]
await preset_mod.set_preset(last_preset)
assert call.call_count == 2
await dev.update()
assert preset_mod.preset == last_preset
assert feat.value == last_preset
# Test feature set
await feat.set_value(second_preset)
assert call.call_count == 3
await dev.update()
assert preset_mod.preset == second_preset
assert feat.value == second_preset
with pytest.raises(ValueError):
await preset_mod.set_preset("foobar")
assert call.call_count == 3
@light_preset
async def test_light_preset_save(dev: Device, mocker: MockerFixture):
"""Test saving a new preset value."""
preset_mod = dev.modules[Module.LightPreset]
assert preset_mod
preset_list = preset_mod.preset_list
if len(preset_list) == 1:
return
second_preset = preset_list[1]
if preset_mod.preset_states_list[0].hue is None:
new_preset = LightState(brightness=52)
else:
new_preset = LightState(brightness=52, color_temp=3000, hue=20, saturation=30)
await preset_mod.save_preset(second_preset, new_preset)
await dev.update()
new_preset_state = preset_mod.preset_states_list[0]
assert (
new_preset_state.brightness == new_preset.brightness
and new_preset_state.hue == new_preset.hue
and new_preset_state.saturation == new_preset.saturation
and new_preset_state.color_temp == new_preset.color_temp
)