Skip to content

Allow effect presets seen on light strips #440

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions kasa/smartbulb.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,16 @@ class SmartBulbPreset(BaseModel):

index: int
brightness: int
hue: int
saturation: int
color_temp: int

# These are not available for effect mode presets on light strips
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):
Expand Down Expand Up @@ -174,7 +181,7 @@ class SmartBulb(SmartDevice):
Bulb configuration presets can be accessed using the :func:`presets` property:

>>> 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:

Expand Down Expand Up @@ -514,7 +521,7 @@ def presets(self) -> List[SmartBulbPreset]:
async def save_preset(self, preset: SmartBulbPreset):
"""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`.
"""
if len(self.presets) == 0:
Expand All @@ -524,5 +531,5 @@ async def save_preset(self, preset: SmartBulbPreset):
raise SmartDeviceException("Invalid preset index")

return await self._query_helper(
self.LIGHT_SERVICE, "set_preferred_state", preset.dict()
self.LIGHT_SERVICE, "set_preferred_state", preset.dict(exclude_none=True)
)
26 changes: 25 additions & 1 deletion kasa/tests/test_bulb.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ async def test_list_presets(dev: SmartBulb):

@bulb
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:
pytest.skip("Some strips do not support presets")

Expand All @@ -289,3 +289,27 @@ async def test_modify_preset(dev: SmartBulb, mocker):
await dev.save_preset(
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)