Make Light and Fan a common module interface (#911)

This commit is contained in:
Steven B
2024-05-13 17:34:44 +01:00
committed by GitHub
parent d7b00336f4
commit 33d839866e
32 changed files with 544 additions and 342 deletions

View File

@@ -16,6 +16,7 @@ from .firmware import Firmware
from .frostprotection import FrostProtection
from .humiditysensor import HumiditySensor
from .led import Led
from .light import Light
from .lighteffect import LightEffect
from .lighttransition import LightTransition
from .reportmode import ReportMode
@@ -41,6 +42,7 @@ __all__ = [
"Fan",
"Firmware",
"Cloud",
"Light",
"LightEffect",
"LightTransition",
"ColorTemperature",

View File

@@ -2,16 +2,10 @@
from __future__ import annotations
from typing import TYPE_CHECKING
from ...feature import Feature
from ..smartmodule import SmartModule
if TYPE_CHECKING:
from ..smartdevice import SmartDevice
BRIGHTNESS_MIN = 1
BRIGHTNESS_MIN = 0
BRIGHTNESS_MAX = 100
@@ -20,8 +14,11 @@ class Brightness(SmartModule):
REQUIRED_COMPONENT = "brightness"
def __init__(self, device: SmartDevice, module: str):
super().__init__(device, module)
def _initialize_features(self):
"""Initialize features."""
super()._initialize_features()
device = self._device
self._add_feature(
Feature(
device,
@@ -47,8 +44,11 @@ class Brightness(SmartModule):
"""Return current brightness."""
return self.data["brightness"]
async def set_brightness(self, brightness: int):
"""Set the brightness."""
async def set_brightness(self, brightness: int, *, transition: int | None = None):
"""Set the brightness. A brightness value of 0 will turn off the light.
Note, transition is not supported and will be ignored.
"""
if not isinstance(brightness, int) or not (
BRIGHTNESS_MIN <= brightness <= BRIGHTNESS_MAX
):
@@ -57,6 +57,8 @@ class Brightness(SmartModule):
f"(valid range: {BRIGHTNESS_MIN}-{BRIGHTNESS_MAX}%)"
)
if brightness == 0:
return await self._device.turn_off()
return await self.call("set_device_info", {"brightness": brightness})
async def _check_supported(self):

126
kasa/smart/modules/light.py Normal file
View File

@@ -0,0 +1,126 @@
"""Module for led controls."""
from __future__ import annotations
from ...exceptions import KasaException
from ...interfaces.light import HSV, ColorTempRange
from ...interfaces.light import Light as LightInterface
from ...module import Module
from ..smartmodule import SmartModule
class Light(SmartModule, LightInterface):
"""Implementation of a light."""
def query(self) -> dict:
"""Query to execute during the update cycle."""
return {}
@property
def is_color(self) -> bool:
"""Whether the bulb supports color changes."""
return Module.Color in self._device.modules
@property
def is_dimmable(self) -> bool:
"""Whether the bulb supports brightness changes."""
return Module.Brightness in self._device.modules
@property
def is_variable_color_temp(self) -> bool:
"""Whether the bulb supports color temperature changes."""
return Module.ColorTemperature in self._device.modules
@property
def valid_temperature_range(self) -> ColorTempRange:
"""Return the device-specific white temperature range (in Kelvin).
:return: White temperature range in Kelvin (minimum, maximum)
"""
if not self.is_variable_color_temp:
raise KasaException("Color temperature not supported")
return self._device.modules[Module.ColorTemperature].valid_temperature_range
@property
def hsv(self) -> HSV:
"""Return the current HSV state of the bulb.
:return: hue, saturation and value (degrees, %, %)
"""
if not self.is_color:
raise KasaException("Bulb does not support color.")
return self._device.modules[Module.Color].hsv
@property
def color_temp(self) -> int:
"""Whether the bulb supports color temperature changes."""
if not self.is_variable_color_temp:
raise KasaException("Bulb does not support colortemp.")
return self._device.modules[Module.ColorTemperature].color_temp
@property
def brightness(self) -> int:
"""Return the current brightness in percentage."""
if not self.is_dimmable: # pragma: no cover
raise KasaException("Bulb is not dimmable.")
return self._device.modules[Module.Brightness].brightness
async def set_hsv(
self,
hue: int,
saturation: int,
value: int | None = None,
*,
transition: int | None = None,
) -> dict:
"""Set new HSV.
Note, transition is not supported and will be ignored.
:param int hue: hue in degrees
:param int saturation: saturation in percentage [0,100]
:param int value: value between 1 and 100
:param int transition: transition in milliseconds.
"""
if not self.is_color:
raise KasaException("Bulb does not support color.")
return await self._device.modules[Module.Color].set_hsv(hue, saturation, value)
async def set_color_temp(
self, temp: int, *, brightness=None, transition: int | None = None
) -> dict:
"""Set the color temperature of the device in kelvin.
Note, transition is not supported and will be ignored.
:param int temp: The new color temperature, in Kelvin
:param int transition: transition in milliseconds.
"""
if not self.is_variable_color_temp:
raise KasaException("Bulb does not support colortemp.")
return await self._device.modules[Module.ColorTemperature].set_color_temp(temp)
async def set_brightness(
self, brightness: int, *, transition: int | None = None
) -> dict:
"""Set the brightness in percentage.
Note, transition is not supported and will be ignored.
:param int brightness: brightness in percent
:param int transition: transition in milliseconds.
"""
if not self.is_dimmable: # pragma: no cover
raise KasaException("Bulb is not dimmable.")
return await self._device.modules[Module.Brightness].set_brightness(brightness)
@property
def has_effects(self) -> bool:
"""Return True if the device supports effects."""
return Module.LightEffect in self._device.modules