2020-07-19 20:32:17 +00:00
|
|
|
"""Module for light strips (KL430)."""
|
2022-03-21 21:10:12 +00:00
|
|
|
from typing import Any, Dict, List, Optional
|
2020-07-19 20:32:17 +00:00
|
|
|
|
2023-09-13 13:46:38 +00:00
|
|
|
from .credentials import Credentials
|
2022-03-21 21:10:12 +00:00
|
|
|
from .effects import EFFECT_MAPPING_V1, EFFECT_NAMES_V1
|
2020-07-19 20:32:17 +00:00
|
|
|
from .smartbulb import SmartBulb
|
2022-03-21 21:10:12 +00:00
|
|
|
from .smartdevice import DeviceType, SmartDeviceException, requires_update
|
2020-07-19 20:32:17 +00:00
|
|
|
|
|
|
|
|
|
|
|
class SmartLightStrip(SmartBulb):
|
|
|
|
"""Representation of a TP-Link Smart light strip.
|
|
|
|
|
|
|
|
Light strips work similarly to bulbs, but use a different service for controlling,
|
2023-10-29 22:15:42 +00:00
|
|
|
and expose some extra information (such as length and active effect).
|
|
|
|
This class extends :class:`SmartBulb` interface.
|
2020-07-19 20:32:17 +00:00
|
|
|
|
2023-10-29 22:15:42 +00:00
|
|
|
Examples:
|
2020-07-19 20:32:17 +00:00
|
|
|
>>> import asyncio
|
|
|
|
>>> strip = SmartLightStrip("127.0.0.1")
|
|
|
|
>>> asyncio.run(strip.update())
|
|
|
|
>>> print(strip.alias)
|
|
|
|
KL430 pantry lightstrip
|
|
|
|
|
|
|
|
Getting the length of the strip:
|
|
|
|
|
|
|
|
>>> strip.length
|
|
|
|
16
|
|
|
|
|
|
|
|
Currently active effect:
|
|
|
|
|
|
|
|
>>> strip.effect
|
|
|
|
{'brightness': 50, 'custom': 0, 'enable': 0, 'id': '', 'name': ''}
|
|
|
|
|
|
|
|
.. note::
|
|
|
|
The device supports some features that are not currently implemented,
|
|
|
|
feel free to find out how to control them and create a PR!
|
|
|
|
|
|
|
|
|
|
|
|
See :class:`SmartBulb` for more examples.
|
|
|
|
"""
|
|
|
|
|
|
|
|
LIGHT_SERVICE = "smartlife.iot.lightStrip"
|
|
|
|
SET_LIGHT_METHOD = "set_light_state"
|
|
|
|
|
2023-09-13 13:46:38 +00:00
|
|
|
def __init__(
|
|
|
|
self,
|
|
|
|
host: str,
|
|
|
|
*,
|
|
|
|
port: Optional[int] = None,
|
|
|
|
credentials: Optional[Credentials] = None,
|
2023-10-07 18:58:00 +00:00
|
|
|
timeout: Optional[int] = None,
|
2023-09-13 13:46:38 +00:00
|
|
|
) -> None:
|
2023-10-07 18:58:00 +00:00
|
|
|
super().__init__(host, port=port, credentials=credentials, timeout=timeout)
|
2020-07-19 20:32:17 +00:00
|
|
|
self._device_type = DeviceType.LightStrip
|
|
|
|
|
|
|
|
@property # type: ignore
|
|
|
|
@requires_update
|
|
|
|
def length(self) -> int:
|
|
|
|
"""Return length of the strip."""
|
|
|
|
return self.sys_info["length"]
|
|
|
|
|
|
|
|
@property # type: ignore
|
|
|
|
@requires_update
|
|
|
|
def effect(self) -> Dict:
|
|
|
|
"""Return effect state.
|
|
|
|
|
|
|
|
Example:
|
|
|
|
{'brightness': 50,
|
|
|
|
'custom': 0,
|
|
|
|
'enable': 0,
|
|
|
|
'id': '',
|
|
|
|
'name': ''}
|
|
|
|
"""
|
|
|
|
return self.sys_info["lighting_effect_state"]
|
|
|
|
|
2022-03-21 21:10:12 +00:00
|
|
|
@property # type: ignore
|
|
|
|
@requires_update
|
|
|
|
def effect_list(self) -> Optional[List[str]]:
|
|
|
|
"""Return built-in effects list.
|
|
|
|
|
|
|
|
Example:
|
|
|
|
['Aurora', 'Bubbling Cauldron', ...]
|
|
|
|
"""
|
|
|
|
return EFFECT_NAMES_V1 if self.has_effects else None
|
|
|
|
|
2020-07-19 20:32:17 +00:00
|
|
|
@property # type: ignore
|
|
|
|
@requires_update
|
|
|
|
def state_information(self) -> Dict[str, Any]:
|
|
|
|
"""Return strip specific state information."""
|
|
|
|
info = super().state_information
|
|
|
|
|
|
|
|
info["Length"] = self.length
|
2022-03-21 21:10:12 +00:00
|
|
|
if self.has_effects:
|
|
|
|
info["Effect"] = self.effect["name"]
|
2020-07-19 20:32:17 +00:00
|
|
|
|
|
|
|
return info
|
2022-03-21 21:10:12 +00:00
|
|
|
|
|
|
|
@requires_update
|
|
|
|
async def set_effect(
|
2023-02-18 17:03:54 +00:00
|
|
|
self,
|
|
|
|
effect: str,
|
|
|
|
*,
|
|
|
|
brightness: Optional[int] = None,
|
|
|
|
transition: Optional[int] = None,
|
2022-03-21 21:10:12 +00:00
|
|
|
) -> None:
|
|
|
|
"""Set an effect on the device.
|
|
|
|
|
2023-10-29 22:15:42 +00:00
|
|
|
If brightness or transition is defined,
|
|
|
|
its value will be used instead of the effect-specific default.
|
2023-02-18 17:03:54 +00:00
|
|
|
|
2023-10-29 22:15:42 +00:00
|
|
|
See :meth:`effect_list` for available effects,
|
|
|
|
or use :meth:`set_custom_effect` for custom effects.
|
2023-02-18 17:03:54 +00:00
|
|
|
|
2022-03-21 21:10:12 +00:00
|
|
|
:param str effect: The effect to set
|
2023-01-20 23:25:59 +00:00
|
|
|
:param int brightness: The wanted brightness
|
2023-02-18 17:03:54 +00:00
|
|
|
:param int transition: The wanted transition time
|
2022-03-21 21:10:12 +00:00
|
|
|
"""
|
|
|
|
if effect not in EFFECT_MAPPING_V1:
|
|
|
|
raise SmartDeviceException(f"The effect {effect} is not a built in effect.")
|
2023-01-20 23:25:59 +00:00
|
|
|
effect_dict = EFFECT_MAPPING_V1[effect]
|
|
|
|
if brightness is not None:
|
|
|
|
effect_dict["brightness"] = brightness
|
2023-02-18 17:03:54 +00:00
|
|
|
if transition is not None:
|
|
|
|
effect_dict["transition"] = transition
|
|
|
|
|
2023-01-20 23:25:59 +00:00
|
|
|
await self.set_custom_effect(effect_dict)
|
2022-03-21 21:10:12 +00:00
|
|
|
|
|
|
|
@requires_update
|
|
|
|
async def set_custom_effect(
|
|
|
|
self,
|
|
|
|
effect_dict: Dict,
|
|
|
|
) -> None:
|
|
|
|
"""Set a custom effect on the device.
|
|
|
|
|
|
|
|
:param str effect_dict: The custom effect dict to set
|
|
|
|
"""
|
|
|
|
if not self.has_effects:
|
|
|
|
raise SmartDeviceException("Bulb does not support effects.")
|
|
|
|
await self._query_helper(
|
|
|
|
"smartlife.iot.lighting_effect",
|
|
|
|
"set_lighting_effect",
|
|
|
|
effect_dict,
|
|
|
|
)
|