Skip to content
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
34 changes: 8 additions & 26 deletions kasa/smart/smartbulb.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@ def is_color(self) -> bool:
@property
def is_dimmable(self) -> bool:
"""Whether the bulb supports brightness changes."""
# TODO: this makes an assumption that only dimmables report this
return "brightness" in self._info
return "Brightness" in self.modules

@property
def is_variable_color_temp(self) -> bool:
Expand Down Expand Up @@ -188,6 +187,11 @@ async def set_color_temp(

return await self.protocol.query({"set_device_info": {"color_temp": temp}})

def _raise_for_invalid_brightness(self, value: int):
"""Raise error on invalid brightness value."""
if not isinstance(value, int) or not (1 <= value <= 100):
raise ValueError(f"Invalid brightness value: {value} (valid range: 1-100%)")

async def set_brightness(
self, brightness: int, *, transition: Optional[int] = None
) -> Dict:
Expand All @@ -201,25 +205,12 @@ async def set_brightness(
if not self.is_dimmable: # pragma: no cover
raise KasaException("Bulb is not dimmable.")

self._raise_for_invalid_brightness(brightness)

return await self.protocol.query(
{"set_device_info": {"brightness": brightness}}
)

# Default state information, should be made to settings
"""
"info": {
"default_states": {
"re_power_type": "always_on",
"type": "last_states",
"state": {
"brightness": 36,
"hue": 0,
"saturation": 0,
"color_temp": 2700,
},
},
"""

async def set_effect(
self,
effect: str,
Expand All @@ -229,15 +220,6 @@ async def set_effect(
) -> None:
"""Set an effect on the device."""
raise NotImplementedError()
# TODO: the code below does to activate the effect but gives no error
return await self.protocol.query(
{
"set_device_info": {
"dynamic_light_effect_enable": 1,
"dynamic_light_effect_id": effect,
}
}
)

@property
def presets(self) -> List[BulbPreset]:
Expand Down
2 changes: 1 addition & 1 deletion kasa/tests/smart/features/test_brightness.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ async def test_brightness_component(dev: SmartDevice):
# Test getting the value
feature = dev.features["brightness"]
assert isinstance(feature.value, int)
assert feature.value > 0 and feature.value <= 100
assert feature.value > 1 and feature.value <= 100

# Test setting the value
await feature.set_value(10)
Expand Down
25 changes: 24 additions & 1 deletion kasa/tests/test_smartdevice.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@

from kasa import KasaException
from kasa.exceptions import SmartErrorCode
from kasa.smart import SmartDevice
from kasa.smart import SmartBulb, SmartDevice

from .conftest import (
bulb_smart,
device_smart,
)

Expand Down Expand Up @@ -103,3 +104,25 @@ async def test_update_module_queries(dev: SmartDevice, mocker: MockerFixture):
full_query = {**full_query, **mod.query()}

query.assert_called_with(full_query)


@bulb_smart
async def test_smartdevice_brightness(dev: SmartBulb):
"""Test brightness setter and getter."""
assert isinstance(dev, SmartDevice)
assert "brightness" in dev._components

# Test getting the value
feature = dev.features["brightness"]
assert feature.minimum_value == 1
assert feature.maximum_value == 100

await dev.set_brightness(10)
await dev.update()
assert dev.brightness == 10

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

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