mirror of
https://github.com/python-kasa/python-kasa.git
synced 2024-12-23 11:43:34 +00:00
7fd5c213e6
Addresses stability issues on older hw device versions - Handles module timeout errors better by querying modules individually on errors and disabling problematic modules like Firmware that go out to the internet to get updates. - Addresses an issue with the Led module on P100 hardware version 1.0 which appears to have a memory leak and will cause the device to crash after approximately 500 calls. - Delays updates of modules that do not have regular changes like LightPreset and LightEffect and enables them to be updated on the next update cycle only if required values have changed.
87 lines
2.9 KiB
Python
87 lines
2.9 KiB
Python
"""Child device implementation."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
import time
|
|
from typing import Any
|
|
|
|
from ..device_type import DeviceType
|
|
from ..deviceconfig import DeviceConfig
|
|
from ..smartprotocol import SmartProtocol, _ChildProtocolWrapper
|
|
from .smartdevice import SmartDevice
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
|
|
class SmartChildDevice(SmartDevice):
|
|
"""Presentation of a child device.
|
|
|
|
This wraps the protocol communications and sets internal data for the child.
|
|
"""
|
|
|
|
def __init__(
|
|
self,
|
|
parent: SmartDevice,
|
|
info,
|
|
component_info,
|
|
config: DeviceConfig | None = None,
|
|
protocol: SmartProtocol | None = None,
|
|
) -> None:
|
|
super().__init__(parent.host, config=parent.config, protocol=parent.protocol)
|
|
self._parent = parent
|
|
self._update_internal_state(info)
|
|
self._components = component_info
|
|
self._id = info["device_id"]
|
|
self.protocol = _ChildProtocolWrapper(self._id, parent.protocol)
|
|
|
|
async def update(self, update_children: bool = True):
|
|
"""Update child module info.
|
|
|
|
The parent updates our internal info so just update modules with
|
|
their own queries.
|
|
"""
|
|
await self._update(update_children)
|
|
|
|
async def _update(self, update_children: bool = True):
|
|
"""Update child module info.
|
|
|
|
Internal implementation to allow patching of public update in the cli
|
|
or test framework.
|
|
"""
|
|
req: dict[str, Any] = {}
|
|
for module in self.modules.values():
|
|
if mod_query := module.query():
|
|
req.update(mod_query)
|
|
if req:
|
|
self._last_update = await self.protocol.query(req)
|
|
self._last_update_time = time.time()
|
|
|
|
@classmethod
|
|
async def create(cls, parent: SmartDevice, child_info, child_components):
|
|
"""Create a child device based on device info and component listing."""
|
|
child: SmartChildDevice = cls(parent, child_info, child_components)
|
|
await child._initialize_modules()
|
|
return child
|
|
|
|
@property
|
|
def device_type(self) -> DeviceType:
|
|
"""Return child device type."""
|
|
child_device_map = {
|
|
"plug.powerstrip.sub-plug": DeviceType.Plug,
|
|
"subg.trigger.contact-sensor": DeviceType.Sensor,
|
|
"subg.trigger.temp-hmdt-sensor": DeviceType.Sensor,
|
|
"subg.trigger.water-leak-sensor": DeviceType.Sensor,
|
|
"kasa.switch.outlet.sub-fan": DeviceType.Fan,
|
|
"kasa.switch.outlet.sub-dimmer": DeviceType.Dimmer,
|
|
"subg.trv": DeviceType.Thermostat,
|
|
}
|
|
dev_type = child_device_map.get(self.sys_info["category"])
|
|
if dev_type is None:
|
|
_LOGGER.warning("Unknown child device type, please open issue ")
|
|
dev_type = DeviceType.Unknown
|
|
return dev_type
|
|
|
|
def __repr__(self):
|
|
return f"<{self.device_type} {self.alias} ({self.model}) of {self._parent}>"
|