Initial support for tapos with child devices (#720)

* Add ChildDevice and ChildProtocolWrapper

* Initialize & update children

* Fix circular imports

* Add dummy_protocol fixture and tests for unwrapping responseData

* Use dummy_protocol for existing smartprotocol tests

* Move _ChildProtocolWrapper to smartprotocol.py

* Use dummy_protocol for test multiple requests

* Use device_id instead of position for selecting the child

* Fix wrapping for regular requests

* Remove unused imports

* tweak

* rename child_device to childdevice

* Fix import
This commit is contained in:
Teemu R
2024-01-29 17:11:29 +01:00
committed by GitHub
parent b479b6d84d
commit 1ad2a05b65
6 changed files with 280 additions and 43 deletions

View File

@@ -5,11 +5,11 @@ from datetime import datetime, timedelta, timezone
from typing import Any, Dict, List, Optional, Set, cast
from ..aestransport import AesTransport
from ..device_type import DeviceType
from ..deviceconfig import DeviceConfig
from ..emeterstatus import EmeterStatus
from ..exceptions import AuthenticationException, SmartDeviceException
from ..modules import Emeter
from ..protocol import BaseProtocol
from ..smartdevice import SmartDevice, WifiNetwork
from ..smartprotocol import SmartProtocol
@@ -24,17 +24,27 @@ class TapoDevice(SmartDevice):
host: str,
*,
config: Optional[DeviceConfig] = None,
protocol: Optional[BaseProtocol] = None,
protocol: Optional[SmartProtocol] = None,
) -> None:
_protocol = protocol or SmartProtocol(
transport=AesTransport(config=config or DeviceConfig(host=host)),
)
super().__init__(host=host, config=config, protocol=_protocol)
self.protocol: SmartProtocol
self._components_raw: Optional[Dict[str, Any]] = None
self._components: Dict[str, int]
self._state_information: Dict[str, Any] = {}
self._discovery_info: Optional[Dict[str, Any]] = None
self.modules: Dict[str, Any] = {}
async def _initialize_children(self):
children = self._last_update["child_info"]["child_device_list"]
# TODO: Use the type information to construct children,
# as hubs can also have them.
from .childdevice import ChildDevice
self.children = [
ChildDevice(parent=self, child_id=child["device_id"]) for child in children
]
self._device_type = DeviceType.Strip
async def update(self, update_children: bool = True):
"""Update the device."""
@@ -51,6 +61,10 @@ class TapoDevice(SmartDevice):
await self._initialize_modules()
extra_reqs: Dict[str, Any] = {}
if "child_device" in self._components:
extra_reqs = {**extra_reqs, "get_child_device_list": None}
if "energy_monitoring" in self._components:
extra_reqs = {
**extra_reqs,
@@ -81,8 +95,15 @@ class TapoDevice(SmartDevice):
"time": self._time,
"energy": self._energy,
"emeter": self._emeter,
"child_info": resp.get("get_child_device_list", {}),
}
if self._last_update["child_info"]:
if not self.children:
await self._initialize_children()
for child in self.children:
await child.update()
_LOGGER.debug("Got an update: %s", self._data)
async def _initialize_modules(self):