Allow effect presets seen on light strips (#440)

* Make hue, saturation and color_temp optional for smartbulbpresets

* Adjust bulb preset attributes for effect mode

* Don't send None values on save_preset

* Add tests for save_preset payloads
This commit is contained in:
Teemu R 2023-04-01 16:15:58 +02:00 committed by GitHub
parent 4d514f983b
commit 505b63dd55
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 38 additions and 7 deletions

View File

@ -30,9 +30,16 @@ class SmartBulbPreset(BaseModel):
index: int index: int
brightness: int brightness: int
hue: int
saturation: int # These are not available for effect mode presets on light strips
color_temp: int hue: Optional[int]
saturation: Optional[int]
color_temp: Optional[int]
# Variables for effect mode presets
custom: Optional[int]
id: Optional[str]
mode: Optional[int]
class BehaviorMode(str, Enum): class BehaviorMode(str, Enum):
@ -174,7 +181,7 @@ class SmartBulb(SmartDevice):
Bulb configuration presets can be accessed using the :func:`presets` property: Bulb configuration presets can be accessed using the :func:`presets` property:
>>> bulb.presets >>> bulb.presets
[SmartBulbPreset(index=0, brightness=50, hue=0, saturation=0, color_temp=2700), SmartBulbPreset(index=1, brightness=100, hue=0, saturation=75, color_temp=0), SmartBulbPreset(index=2, brightness=100, hue=120, saturation=75, color_temp=0), SmartBulbPreset(index=3, brightness=100, hue=240, saturation=75, color_temp=0)] [SmartBulbPreset(index=0, brightness=50, hue=0, saturation=0, color_temp=2700, custom=None, id=None, mode=None), SmartBulbPreset(index=1, brightness=100, hue=0, saturation=75, color_temp=0, custom=None, id=None, mode=None), SmartBulbPreset(index=2, brightness=100, hue=120, saturation=75, color_temp=0, custom=None, id=None, mode=None), SmartBulbPreset(index=3, brightness=100, hue=240, saturation=75, color_temp=0, custom=None, id=None, mode=None)]
To modify an existing preset, pass :class:`~kasa.smartbulb.SmartBulbPreset` instance to :func:`save_preset` method: To modify an existing preset, pass :class:`~kasa.smartbulb.SmartBulbPreset` instance to :func:`save_preset` method:
@ -514,7 +521,7 @@ class SmartBulb(SmartDevice):
async def save_preset(self, preset: SmartBulbPreset): async def save_preset(self, preset: SmartBulbPreset):
"""Save a setting preset. """Save a setting preset.
You can either construct a preset object manually, or pass an existing one obtained You can either construct a preset object manually, or pass an existing one
obtained using :func:`presets`. obtained using :func:`presets`.
""" """
if len(self.presets) == 0: if len(self.presets) == 0:
@ -524,5 +531,5 @@ class SmartBulb(SmartDevice):
raise SmartDeviceException("Invalid preset index") raise SmartDeviceException("Invalid preset index")
return await self._query_helper( return await self._query_helper(
self.LIGHT_SERVICE, "set_preferred_state", preset.dict() self.LIGHT_SERVICE, "set_preferred_state", preset.dict(exclude_none=True)
) )

View File

@ -263,7 +263,7 @@ async def test_list_presets(dev: SmartBulb):
@bulb @bulb
async def test_modify_preset(dev: SmartBulb, mocker): async def test_modify_preset(dev: SmartBulb, mocker):
"""Verify that modifying preset calls the and exceptions are raised properly.""" """Verify that modifying preset calls the and exceptions are raised properly."""
if not dev.presets: if not dev.presets:
pytest.skip("Some strips do not support presets") pytest.skip("Some strips do not support presets")
@ -289,3 +289,27 @@ async def test_modify_preset(dev: SmartBulb, mocker):
await dev.save_preset( await dev.save_preset(
SmartBulbPreset(index=5, hue=0, brightness=0, saturation=0, color_temp=0) SmartBulbPreset(index=5, hue=0, brightness=0, saturation=0, color_temp=0)
) )
@bulb
@pytest.mark.parametrize(
("preset", "payload"),
[
(
SmartBulbPreset(index=0, hue=0, brightness=1, saturation=0),
{"index": 0, "hue": 0, "brightness": 1, "saturation": 0},
),
(
SmartBulbPreset(index=0, brightness=1, id="testid", mode=2, custom=0),
{"index": 0, "brightness": 1, "id": "testid", "mode": 2, "custom": 0},
),
],
)
async def test_modify_preset_payloads(dev: SmartBulb, preset, payload, mocker):
"""Test that modify preset payloads ignore none values."""
if not dev.presets:
pytest.skip("Some strips do not support presets")
query_helper = mocker.patch("kasa.SmartBulb._query_helper")
await dev.save_preset(preset)
query_helper.assert_called_with(dev.LIGHT_SERVICE, "set_preferred_state", payload)