mirror of
https://github.com/python-kasa/python-kasa.git
synced 2025-08-06 10:44:04 +00:00
Use _get_device_info methods for smart and iot devs in devtools (#1265)
This commit is contained in:
@@ -162,7 +162,7 @@ class _DeviceInfo:
|
||||
device_family: str
|
||||
device_type: DeviceType
|
||||
hardware_version: str
|
||||
firmare_version: str
|
||||
firmware_version: str
|
||||
firmware_build: str
|
||||
requires_auth: bool
|
||||
region: str | None
|
||||
|
@@ -128,34 +128,6 @@ async def _connect(config: DeviceConfig, protocol: BaseProtocol) -> Device:
|
||||
)
|
||||
|
||||
|
||||
def _get_device_type_from_sys_info(info: dict[str, Any]) -> DeviceType:
|
||||
"""Find SmartDevice subclass for device described by passed data."""
|
||||
if "system" not in info or "get_sysinfo" not in info["system"]:
|
||||
raise KasaException("No 'system' or 'get_sysinfo' in response")
|
||||
|
||||
sysinfo: dict[str, Any] = info["system"]["get_sysinfo"]
|
||||
type_: str | None = sysinfo.get("type", sysinfo.get("mic_type"))
|
||||
if type_ is None:
|
||||
raise KasaException("Unable to find the device type field!")
|
||||
|
||||
if "dev_name" in sysinfo and "Dimmer" in sysinfo["dev_name"]:
|
||||
return DeviceType.Dimmer
|
||||
|
||||
if "smartplug" in type_.lower():
|
||||
if "children" in sysinfo:
|
||||
return DeviceType.Strip
|
||||
if (dev_name := sysinfo.get("dev_name")) and "light" in dev_name.lower():
|
||||
return DeviceType.WallSwitch
|
||||
return DeviceType.Plug
|
||||
|
||||
if "smartbulb" in type_.lower():
|
||||
if "length" in sysinfo: # strips have length
|
||||
return DeviceType.LightStrip
|
||||
|
||||
return DeviceType.Bulb
|
||||
raise UnsupportedDeviceError(f"Unknown device type: {type_}")
|
||||
|
||||
|
||||
def get_device_class_from_sys_info(sysinfo: dict[str, Any]) -> type[IotDevice]:
|
||||
"""Find SmartDevice subclass for device described by passed data."""
|
||||
TYPE_TO_CLASS = {
|
||||
@@ -166,7 +138,7 @@ def get_device_class_from_sys_info(sysinfo: dict[str, Any]) -> type[IotDevice]:
|
||||
DeviceType.WallSwitch: IotWallSwitch,
|
||||
DeviceType.LightStrip: IotLightStrip,
|
||||
}
|
||||
return TYPE_TO_CLASS[_get_device_type_from_sys_info(sysinfo)]
|
||||
return TYPE_TO_CLASS[IotDevice._get_device_type_from_sys_info(sysinfo)]
|
||||
|
||||
|
||||
def get_device_class_from_family(
|
||||
|
@@ -22,7 +22,8 @@ from datetime import datetime, timedelta, tzinfo
|
||||
from typing import TYPE_CHECKING, Any, Callable, cast
|
||||
from warnings import warn
|
||||
|
||||
from ..device import Device, WifiNetwork
|
||||
from ..device import Device, WifiNetwork, _DeviceInfo
|
||||
from ..device_type import DeviceType
|
||||
from ..deviceconfig import DeviceConfig
|
||||
from ..exceptions import KasaException
|
||||
from ..feature import Feature
|
||||
@@ -692,3 +693,66 @@ class IotDevice(Device):
|
||||
This should only be used for debugging purposes.
|
||||
"""
|
||||
return self._last_update or self._discovery_info
|
||||
|
||||
@staticmethod
|
||||
def _get_device_type_from_sys_info(info: dict[str, Any]) -> DeviceType:
|
||||
"""Find SmartDevice subclass for device described by passed data."""
|
||||
if "system" not in info or "get_sysinfo" not in info["system"]:
|
||||
raise KasaException("No 'system' or 'get_sysinfo' in response")
|
||||
|
||||
sysinfo: dict[str, Any] = info["system"]["get_sysinfo"]
|
||||
type_: str | None = sysinfo.get("type", sysinfo.get("mic_type"))
|
||||
if type_ is None:
|
||||
raise KasaException("Unable to find the device type field!")
|
||||
|
||||
if "dev_name" in sysinfo and "Dimmer" in sysinfo["dev_name"]:
|
||||
return DeviceType.Dimmer
|
||||
|
||||
if "smartplug" in type_.lower():
|
||||
if "children" in sysinfo:
|
||||
return DeviceType.Strip
|
||||
if (dev_name := sysinfo.get("dev_name")) and "light" in dev_name.lower():
|
||||
return DeviceType.WallSwitch
|
||||
return DeviceType.Plug
|
||||
|
||||
if "smartbulb" in type_.lower():
|
||||
if "length" in sysinfo: # strips have length
|
||||
return DeviceType.LightStrip
|
||||
|
||||
return DeviceType.Bulb
|
||||
_LOGGER.warning("Unknown device type %s, falling back to plug", type_)
|
||||
return DeviceType.Plug
|
||||
|
||||
@staticmethod
|
||||
def _get_device_info(
|
||||
info: dict[str, Any], discovery_info: dict[str, Any] | None
|
||||
) -> _DeviceInfo:
|
||||
"""Get model information for a device."""
|
||||
sys_info = info["system"]["get_sysinfo"]
|
||||
|
||||
# Get model and region info
|
||||
region = None
|
||||
device_model = sys_info["model"]
|
||||
long_name, _, region = device_model.partition("(")
|
||||
if region: # All iot devices have region but just in case
|
||||
region = region.replace(")", "")
|
||||
|
||||
# Get other info
|
||||
device_family = sys_info.get("type", sys_info.get("mic_type"))
|
||||
device_type = IotDevice._get_device_type_from_sys_info(info)
|
||||
fw_version_full = sys_info["sw_ver"]
|
||||
firmware_version, firmware_build = fw_version_full.split(" ", maxsplit=1)
|
||||
auth = bool(discovery_info and ("mgt_encrypt_schm" in discovery_info))
|
||||
|
||||
return _DeviceInfo(
|
||||
short_name=long_name,
|
||||
long_name=long_name,
|
||||
brand="kasa",
|
||||
device_family=device_family,
|
||||
device_type=device_type,
|
||||
hardware_version=sys_info["hw_ver"],
|
||||
firmware_version=firmware_version,
|
||||
firmware_build=firmware_build,
|
||||
requires_auth=auth,
|
||||
region=region,
|
||||
)
|
||||
|
@@ -9,7 +9,7 @@ from collections.abc import Mapping, Sequence
|
||||
from datetime import datetime, timedelta, timezone, tzinfo
|
||||
from typing import TYPE_CHECKING, Any, cast
|
||||
|
||||
from ..device import Device, WifiNetwork
|
||||
from ..device import Device, WifiNetwork, _DeviceInfo
|
||||
from ..device_type import DeviceType
|
||||
from ..deviceconfig import DeviceConfig
|
||||
from ..exceptions import AuthenticationError, DeviceError, KasaException, SmartErrorCode
|
||||
@@ -794,3 +794,48 @@ class SmartDevice(Device):
|
||||
return DeviceType.Thermostat
|
||||
_LOGGER.warning("Unknown device type, falling back to plug")
|
||||
return DeviceType.Plug
|
||||
|
||||
@staticmethod
|
||||
def _get_device_info(
|
||||
info: dict[str, Any], discovery_info: dict[str, Any] | None
|
||||
) -> _DeviceInfo:
|
||||
"""Get model information for a device."""
|
||||
di = info["get_device_info"]
|
||||
components = [comp["id"] for comp in info["component_nego"]["component_list"]]
|
||||
|
||||
# Get model/region info
|
||||
short_name = di["model"]
|
||||
region = None
|
||||
if discovery_info:
|
||||
device_model = discovery_info["device_model"]
|
||||
long_name, _, region = device_model.partition("(")
|
||||
if region: # P100 doesn't have region
|
||||
region = region.replace(")", "")
|
||||
else:
|
||||
long_name = short_name
|
||||
if not region: # some devices have region in specs
|
||||
region = di.get("specs")
|
||||
|
||||
# Get other info
|
||||
device_family = di["type"]
|
||||
device_type = SmartDevice._get_device_type_from_components(
|
||||
components, device_family
|
||||
)
|
||||
fw_version_full = di["fw_ver"]
|
||||
firmware_version, firmware_build = fw_version_full.split(" ", maxsplit=1)
|
||||
_protocol, devicetype = device_family.split(".")
|
||||
# Brand inferred from SMART.KASAPLUG/SMART.TAPOPLUG etc.
|
||||
brand = devicetype[:4].lower()
|
||||
|
||||
return _DeviceInfo(
|
||||
short_name=short_name,
|
||||
long_name=long_name,
|
||||
brand=brand,
|
||||
device_family=device_family,
|
||||
device_type=device_type,
|
||||
hardware_version=di["hw_ver"],
|
||||
firmware_version=firmware_version,
|
||||
firmware_build=firmware_build,
|
||||
requires_auth=True,
|
||||
region=region,
|
||||
)
|
||||
|
@@ -43,7 +43,7 @@ class SmartCamera(SmartDevice):
|
||||
long_name = discovery_info["device_model"] if discovery_info else short_name
|
||||
device_type = SmartCamera._get_device_type_from_sysinfo(basic_info)
|
||||
fw_version_full = basic_info["sw_version"]
|
||||
firmare_version, firmware_build = fw_version_full.split(" ", maxsplit=1)
|
||||
firmware_version, firmware_build = fw_version_full.split(" ", maxsplit=1)
|
||||
return _DeviceInfo(
|
||||
short_name=basic_info["device_model"],
|
||||
long_name=long_name,
|
||||
@@ -51,7 +51,7 @@ class SmartCamera(SmartDevice):
|
||||
device_family=basic_info["device_type"],
|
||||
device_type=device_type,
|
||||
hardware_version=basic_info["hw_version"],
|
||||
firmare_version=firmare_version,
|
||||
firmware_version=firmware_version,
|
||||
firmware_build=firmware_build,
|
||||
requires_auth=True,
|
||||
region=basic_info.get("region"),
|
||||
|
Reference in New Issue
Block a user