python-kasa/kasa/smartcam/smartcamchild.py
Steven B. 4e7e18cef1
Some checks are pending
CI / Perform linting checks (3.13) (push) Waiting to run
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.11) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.12) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, macos-latest, 3.13) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.11) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.12) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, ubuntu-latest, 3.13) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.11) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.12) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (false, windows-latest, 3.13) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.11) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.12) (push) Blocked by required conditions
CI / Python ${{ matrix.python-version}} on ${{ matrix.os }}${{ fromJSON('[" (extras)", ""]')[matrix.extras == ''] }} (true, ubuntu-latest, 3.13) (push) Blocked by required conditions
CodeQL checks / Analyze (python) (push) Waiting to run
Add battery module to smartcam devices (#1452)
2025-01-14 21:57:35 +00:00

112 lines
3.7 KiB
Python

"""Child device implementation."""
from __future__ import annotations
import logging
from typing import Any
from ..device import DeviceInfo
from ..device_type import DeviceType
from ..deviceconfig import DeviceConfig
from ..protocols.smartcamprotocol import _ChildCameraProtocolWrapper
from ..protocols.smartprotocol import SmartProtocol
from ..smart.smartchilddevice import SmartChildDevice
from ..smart.smartdevice import ComponentsRaw, SmartDevice
from .smartcamdevice import SmartCamDevice
_LOGGER = logging.getLogger(__name__)
# SmartCamChild devices have a different info format from getChildDeviceInfo
# than when querying getDeviceInfo directly on the child.
# As _get_device_info is also called by dump_devtools and generate_supported
# this key will be expected by _get_device_info
CHILD_INFO_FROM_PARENT = "child_info_from_parent"
class SmartCamChild(SmartChildDevice, SmartCamDevice):
"""Presentation of a child device.
This wraps the protocol communications and sets internal data for the child.
"""
CHILD_DEVICE_TYPE_MAP = {
"camera": DeviceType.Camera,
}
def __init__(
self,
parent: SmartDevice,
info: dict,
component_info_raw: ComponentsRaw,
*,
config: DeviceConfig | None = None,
protocol: SmartProtocol | None = None,
) -> None:
_protocol = protocol or _ChildCameraProtocolWrapper(
info["device_id"], parent.protocol
)
super().__init__(parent, info, component_info_raw, protocol=_protocol)
self._child_info_from_parent: dict = {}
@property
def device_info(self) -> DeviceInfo:
"""Return device info.
Child device does not have it info and components in _last_update so
this overrides the base implementation to call _get_device_info with
info and components combined as they would be in _last_update.
"""
return self._get_device_info(
{
CHILD_INFO_FROM_PARENT: self._child_info_from_parent,
},
None,
)
@staticmethod
def _map_child_info_from_parent(device_info: dict) -> dict:
mappings = {
"device_model": "model",
"sw_ver": "fw_ver",
"hw_id": "hwId",
}
return {mappings.get(k, k): v for k, v in device_info.items()}
def _update_internal_state(self, info: dict[str, Any]) -> None:
"""Update the internal info state.
This is used by the parent to push updates to its children.
"""
# smartcam children have info with different keys to their own
# getDeviceInfo queries
self._child_info_from_parent = info
# self._info will have the values normalized across smart and smartcam
# devices
self._info = self._map_child_info_from_parent(info)
@staticmethod
def _get_device_info(
info: dict[str, Any], discovery_info: dict[str, Any] | None
) -> DeviceInfo:
"""Get model information for a device."""
if not (cifp := info.get(CHILD_INFO_FROM_PARENT)):
return SmartCamDevice._get_device_info(info, discovery_info)
model = cifp["device_model"]
device_type = SmartCamDevice._get_device_type_from_sysinfo(cifp)
fw_version_full = cifp["sw_ver"]
firmware_version, firmware_build = fw_version_full.split(" ", maxsplit=1)
return DeviceInfo(
short_name=model,
long_name=model,
brand="tapo",
device_family=cifp["device_type"],
device_type=device_type,
hardware_version=cifp["hw_ver"],
firmware_version=firmware_version,
firmware_build=firmware_build,
requires_auth=True,
region=cifp.get("region"),
)