2024-02-19 17:01:31 +00:00
|
|
|
"""Base class for IOT module implementations."""
|
2024-04-16 18:21:20 +00:00
|
|
|
|
2024-11-10 18:55:13 +00:00
|
|
|
from __future__ import annotations
|
|
|
|
|
2022-01-29 17:15:59 +00:00
|
|
|
import logging
|
2024-11-21 18:40:13 +00:00
|
|
|
from typing import TYPE_CHECKING, Any
|
2021-11-07 01:41:12 +00:00
|
|
|
|
2024-02-21 15:52:55 +00:00
|
|
|
from ..exceptions import KasaException
|
2024-02-19 17:01:31 +00:00
|
|
|
from ..module import Module
|
2021-11-07 01:41:12 +00:00
|
|
|
|
2022-01-29 17:15:59 +00:00
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
|
2024-11-21 18:40:13 +00:00
|
|
|
if TYPE_CHECKING:
|
|
|
|
from .iotdevice import IotDevice
|
|
|
|
|
2022-01-29 17:15:59 +00:00
|
|
|
|
2024-08-14 21:33:54 +00:00
|
|
|
def _merge_dict(dest: dict, source: dict) -> dict:
|
2021-11-07 01:41:12 +00:00
|
|
|
"""Update dict recursively."""
|
2024-08-14 21:33:54 +00:00
|
|
|
for k, v in source.items():
|
|
|
|
if k in dest and type(v) is dict: # noqa: E721 - only accepts `dict` type
|
|
|
|
_merge_dict(dest[k], v)
|
2021-11-07 01:41:12 +00:00
|
|
|
else:
|
2024-08-14 21:33:54 +00:00
|
|
|
dest[k] = v
|
|
|
|
return dest
|
|
|
|
|
|
|
|
|
|
|
|
merge = _merge_dict
|
2021-11-07 01:41:12 +00:00
|
|
|
|
|
|
|
|
2024-02-19 17:01:31 +00:00
|
|
|
class IotModule(Module):
|
|
|
|
"""Base class implemention for all IOT modules."""
|
2021-11-07 01:41:12 +00:00
|
|
|
|
2024-11-21 18:40:13 +00:00
|
|
|
_device: IotDevice
|
|
|
|
|
2024-11-10 18:55:13 +00:00
|
|
|
async def call(self, method: str, params: dict | None = None) -> dict:
|
2024-02-19 17:01:31 +00:00
|
|
|
"""Call the given method with the given parameters."""
|
2024-11-10 18:55:13 +00:00
|
|
|
return await self._device._query_helper(self._module, method, params)
|
2021-11-07 01:41:12 +00:00
|
|
|
|
2024-11-10 18:55:13 +00:00
|
|
|
def query_for_command(self, query: str, params: dict | None = None) -> dict:
|
2024-02-19 17:01:31 +00:00
|
|
|
"""Create a request object for the given parameters."""
|
|
|
|
return self._device._create_request(self._module, query, params)
|
2021-11-07 01:41:12 +00:00
|
|
|
|
2023-09-14 18:51:40 +00:00
|
|
|
@property
|
2024-11-10 18:55:13 +00:00
|
|
|
def estimated_query_response_size(self) -> int:
|
2023-09-14 18:51:40 +00:00
|
|
|
"""Estimated maximum size of query response.
|
|
|
|
|
|
|
|
The inheriting modules implement this to estimate how large a query response
|
|
|
|
will be so that queries can be split should an estimated response be too large
|
|
|
|
"""
|
|
|
|
return 256 # Estimate for modules that don't specify
|
|
|
|
|
2021-11-07 01:41:12 +00:00
|
|
|
@property
|
2024-11-10 18:55:13 +00:00
|
|
|
def data(self) -> dict[str, Any]:
|
2021-11-07 01:41:12 +00:00
|
|
|
"""Return the module specific raw data from the last update."""
|
2024-05-10 18:29:28 +00:00
|
|
|
dev = self._device
|
|
|
|
q = self.query()
|
|
|
|
|
|
|
|
if not q:
|
|
|
|
return dev.sys_info
|
|
|
|
|
|
|
|
if self._module not in dev._last_update:
|
2024-02-21 15:52:55 +00:00
|
|
|
raise KasaException(
|
2023-10-29 22:15:42 +00:00
|
|
|
f"You need to call update() prior accessing module data"
|
|
|
|
f" for '{self._module}'"
|
2022-01-29 19:33:35 +00:00
|
|
|
)
|
|
|
|
|
2024-05-10 18:29:28 +00:00
|
|
|
return dev._last_update[self._module]
|
2021-11-07 01:41:12 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
def is_supported(self) -> bool:
|
|
|
|
"""Return whether the module is supported by the device."""
|
2022-01-29 17:15:59 +00:00
|
|
|
if self._module not in self._device._last_update:
|
|
|
|
_LOGGER.debug("Initial update, so consider supported: %s", self._module)
|
|
|
|
return True
|
|
|
|
|
2021-11-07 01:41:12 +00:00
|
|
|
return "err_code" not in self.data
|