Skip to content

Commit

Permalink
Add colortemp module (#814)
Browse files Browse the repository at this point in the history
Allow controlling the color temperature via features interface:
```
$ kasa --host 192.168.xx.xx feature color_temperature                                                                                                                             
Color temperature (color_temperature): 0

$ kasa --host 192.168.xx.xx feature color_temperature 2000
Setting color_temperature to 2000
Raised error: Temperature should be between 2500 and 6500, was 2000
Run with --debug enabled to see stacktrace

$ kasa --host 192.168.xx.xx feature color_temperature 3000
Setting color_temperature to 3000

$ kasa --host 192.168.xx.xx feature color_temperature                                                                                                                             
Color temperature (color_temperature): 3000
```
  • Loading branch information
rytilahti committed Mar 15, 2024
1 parent 270614a commit d63f43a
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 0 deletions.
11 changes: 11 additions & 0 deletions kasa/feature.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,17 @@ class Feature:
minimum_value: int = 0
#: Maximum value
maximum_value: int = 2**16 # Arbitrary max
#: Attribute containing the name of the range getter property.
#: If set, this property will be used to set *minimum_value* and *maximum_value*.
range_getter: Optional[str] = None

def __post_init__(self):
"""Handle late-binding of members."""
container = self.container if self.container is not None else self.device
if self.range_getter is not None:
self.minimum_value, self.maximum_value = getattr(
container, self.range_getter
)

@property
def value(self):
Expand Down
2 changes: 2 additions & 0 deletions kasa/smart/modules/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from .brightness import Brightness
from .childdevicemodule import ChildDeviceModule
from .cloudmodule import CloudModule
from .colortemp import ColorTemperatureModule
from .devicemodule import DeviceModule
from .energymodule import EnergyModule
from .firmware import Firmware
Expand All @@ -31,4 +32,5 @@
"Firmware",
"CloudModule",
"LightTransitionModule",
"ColorTemperatureModule",
]
55 changes: 55 additions & 0 deletions kasa/smart/modules/colortemp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
"""Implementation of color temp module."""
from typing import TYPE_CHECKING, Dict

from ...bulb import ColorTempRange
from ...feature import Feature
from ..smartmodule import SmartModule

if TYPE_CHECKING:
from ..smartdevice import SmartDevice


class ColorTemperatureModule(SmartModule):
"""Implementation of color temp module."""

REQUIRED_COMPONENT = "color_temperature"

def __init__(self, device: "SmartDevice", module: str):
super().__init__(device, module)
self._add_feature(
Feature(
device,
"Color temperature",
container=self,
attribute_getter="color_temp",
attribute_setter="set_color_temp",
range_getter="valid_temperature_range",
)
)

def query(self) -> Dict:
"""Query to execute during the update cycle."""
# Color temp is contained in the main device info response.
return {}

@property
def valid_temperature_range(self) -> ColorTempRange:
"""Return valid color-temp range."""
return ColorTempRange(*self.data.get("color_temp_range"))

@property
def color_temp(self):
"""Return current color temperature."""
return self.data["color_temp"]

async def set_color_temp(self, temp: int):
"""Set the color temperature."""
valid_temperature_range = self.valid_temperature_range
if temp < valid_temperature_range[0] or temp > valid_temperature_range[1]:
raise ValueError(
"Temperature should be between {} and {}, was {}".format(
*valid_temperature_range, temp
)
)

return await self.call("set_device_info", {"color_temp": temp})
Empty file.
File renamed without changes.
31 changes: 31 additions & 0 deletions kasa/tests/smart/features/test_colortemp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import pytest

from kasa.smart import SmartDevice
from kasa.tests.conftest import parametrize

brightness = parametrize("colortemp smart", component_filter="color_temperature")


@brightness
async def test_colortemp_component(dev: SmartDevice):
"""Test brightness feature."""
assert isinstance(dev, SmartDevice)
assert "color_temperature" in dev._components

# Test getting the value
feature = dev.features["color_temperature"]
assert isinstance(feature.value, int)
assert isinstance(feature.minimum_value, int)
assert isinstance(feature.maximum_value, int)

# Test setting the value
# We need to take the min here, as L9xx reports a range [9000, 9000].
new_value = min(feature.minimum_value + 1, feature.maximum_value)
await feature.set_value(new_value)
assert feature.value == new_value

with pytest.raises(ValueError):
await feature.set_value(feature.minimum_value - 10)

with pytest.raises(ValueError):
await feature.set_value(feature.maximum_value + 10)

0 comments on commit d63f43a

Please sign in to comment.