mirror of
https://github.com/python-kasa/python-kasa.git
synced 2024-12-23 03:33:35 +00:00
64da736717
This adds a generic interface for all device classes to introspect available device features, that is necessary to make it easier to support a wide variety of supported devices with different set of features. This will allow constructing generic interfaces (e.g., in homeassistant) that fetch and change these features without hard-coding the API calls. `Device.features()` now returns a mapping of `<identifier, Feature>` where the `Feature` contains all necessary information (like the name, the icon, a way to get and change the setting) to present and change the defined feature through its interface.
104 lines
3.2 KiB
Python
104 lines
3.2 KiB
Python
"""Module for smart plugs (HS100, HS110, ..)."""
|
|
import logging
|
|
from typing import Any, Dict, Optional
|
|
|
|
from ..device_type import DeviceType
|
|
from ..deviceconfig import DeviceConfig
|
|
from ..feature import Feature, FeatureType
|
|
from ..protocol import BaseProtocol
|
|
from .iotdevice import IotDevice, requires_update
|
|
from .modules import Antitheft, Cloud, Schedule, Time, Usage
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
|
|
class IotPlug(IotDevice):
|
|
r"""Representation of a TP-Link Smart Switch.
|
|
|
|
To initialize, you have to await :func:`update()` at least once.
|
|
This will allow accessing the properties using the exposed properties.
|
|
|
|
All changes to the device are done using awaitable methods,
|
|
which will not change the cached values,
|
|
but you must await :func:`update()` separately.
|
|
|
|
Errors reported by the device are raised as :class:`SmartDeviceException`\s,
|
|
and should be handled by the user of the library.
|
|
|
|
Examples:
|
|
>>> import asyncio
|
|
>>> plug = IotPlug("127.0.0.1")
|
|
>>> asyncio.run(plug.update())
|
|
>>> plug.alias
|
|
Kitchen
|
|
|
|
Setting the LED state:
|
|
|
|
>>> asyncio.run(plug.set_led(True))
|
|
>>> asyncio.run(plug.update())
|
|
>>> plug.led
|
|
True
|
|
|
|
For more examples, see the :class:`SmartDevice` class.
|
|
"""
|
|
|
|
def __init__(
|
|
self,
|
|
host: str,
|
|
*,
|
|
config: Optional[DeviceConfig] = None,
|
|
protocol: Optional[BaseProtocol] = None,
|
|
) -> None:
|
|
super().__init__(host=host, config=config, protocol=protocol)
|
|
self._device_type = DeviceType.Plug
|
|
self.add_module("schedule", Schedule(self, "schedule"))
|
|
self.add_module("usage", Usage(self, "schedule"))
|
|
self.add_module("antitheft", Antitheft(self, "anti_theft"))
|
|
self.add_module("time", Time(self, "time"))
|
|
self.add_module("cloud", Cloud(self, "cnCloud"))
|
|
|
|
self._add_feature(
|
|
Feature(
|
|
device=self,
|
|
name="LED",
|
|
icon="mdi:led-{state}",
|
|
attribute_getter="led",
|
|
attribute_setter="set_led",
|
|
type=FeatureType.Switch,
|
|
)
|
|
)
|
|
|
|
@property # type: ignore
|
|
@requires_update
|
|
def is_on(self) -> bool:
|
|
"""Return whether device is on."""
|
|
sys_info = self.sys_info
|
|
return bool(sys_info["relay_state"])
|
|
|
|
async def turn_on(self, **kwargs):
|
|
"""Turn the switch on."""
|
|
return await self._query_helper("system", "set_relay_state", {"state": 1})
|
|
|
|
async def turn_off(self, **kwargs):
|
|
"""Turn the switch off."""
|
|
return await self._query_helper("system", "set_relay_state", {"state": 0})
|
|
|
|
@property # type: ignore
|
|
@requires_update
|
|
def led(self) -> bool:
|
|
"""Return the state of the led."""
|
|
sys_info = self.sys_info
|
|
return bool(1 - sys_info["led_off"])
|
|
|
|
async def set_led(self, state: bool):
|
|
"""Set the state of the led (night mode)."""
|
|
return await self._query_helper(
|
|
"system", "set_led_off", {"off": int(not state)}
|
|
)
|
|
|
|
@property # type: ignore
|
|
@requires_update
|
|
def state_information(self) -> Dict[str, Any]:
|
|
"""Return switch-specific state information."""
|
|
return {}
|