Add light presets common module to devices. (#907)

Adds light preset common module for switching to presets and saving presets.
Deprecates the `presets` attribute and `save_preset` method from the `bulb` 
interface in favour of the modular approach.  Allows setting preset for `iot` 
which was not previously supported.
This commit is contained in:
Steven B
2024-05-19 11:20:18 +01:00
committed by GitHub
parent 1ba5c73279
commit 273c541fcc
20 changed files with 612 additions and 73 deletions

View File

@@ -2,13 +2,15 @@
from .fan import Fan
from .led import Led
from .light import Light, LightPreset
from .light import Light, LightState
from .lighteffect import LightEffect
from .lightpreset import LightPreset
__all__ = [
"Fan",
"Led",
"Light",
"LightEffect",
"LightState",
"LightPreset",
]

View File

@@ -3,13 +3,24 @@
from __future__ import annotations
from abc import ABC, abstractmethod
from typing import NamedTuple, Optional
from pydantic.v1 import BaseModel
from dataclasses import dataclass
from typing import NamedTuple
from ..module import Module
@dataclass
class LightState:
"""Class for smart light preset info."""
light_on: bool | None = None
brightness: int | None = None
hue: int | None = None
saturation: int | None = None
color_temp: int | None = None
transition: bool | None = None
class ColorTempRange(NamedTuple):
"""Color temperature range."""
@@ -25,23 +36,6 @@ class HSV(NamedTuple):
value: int
class LightPreset(BaseModel):
"""Light configuration preset."""
index: int
brightness: int
# These are not available for effect mode presets on light strips
hue: Optional[int] # noqa: UP007
saturation: Optional[int] # noqa: UP007
color_temp: Optional[int] # noqa: UP007
# Variables for effect mode presets
custom: Optional[int] # noqa: UP007
id: Optional[str] # noqa: UP007
mode: Optional[int] # noqa: UP007
class Light(Module, ABC):
"""Base class for TP-Link Light."""
@@ -133,3 +127,7 @@ class Light(Module, ABC):
:param int brightness: brightness in percent
:param int transition: transition in milliseconds.
"""
@abstractmethod
async def set_state(self, state: LightState) -> dict:
"""Set the light state."""

View File

@@ -0,0 +1,76 @@
"""Module for LightPreset base class."""
from __future__ import annotations
from abc import abstractmethod
from typing import Sequence
from ..feature import Feature
from ..module import Module
from .light import LightState
class LightPreset(Module):
"""Base interface for light preset module."""
PRESET_NOT_SET = "Not set"
def _initialize_features(self):
"""Initialize features."""
device = self._device
self._add_feature(
Feature(
device,
id="light_preset",
name="Light preset",
container=self,
attribute_getter="preset",
attribute_setter="set_preset",
category=Feature.Category.Config,
type=Feature.Type.Choice,
choices_getter="preset_list",
)
)
@property
@abstractmethod
def preset_list(self) -> list[str]:
"""Return list of preset names.
Example:
['Off', 'Preset 1', 'Preset 2', ...]
"""
@property
@abstractmethod
def preset_states_list(self) -> Sequence[LightState]:
"""Return list of preset states.
Example:
['Off', 'Preset 1', 'Preset 2', ...]
"""
@property
@abstractmethod
def preset(self) -> str:
"""Return current preset name."""
@abstractmethod
async def set_preset(
self,
preset_name: str,
) -> None:
"""Set a light preset for the device."""
@abstractmethod
async def save_preset(
self,
preset_name: str,
preset_info: LightState,
) -> None:
"""Update the preset with *preset_name* with the new *preset_info*."""
@property
@abstractmethod
def has_save_preset(self) -> bool:
"""Return True if the device supports updating presets."""