Refactor devices into subpackages and deprecate old names (#716)

* Refactor devices into subpackages and deprecate old names

* Tweak and add tests

* Fix linting

* Remove duplicate implementations affecting project coverage

* Update post review

* Add device base class attributes and rename subclasses

* Rename Module to BaseModule

* Remove has_emeter_history

* Fix missing _time in init

* Update post review

* Fix test_readmeexamples

* Fix erroneously duped files

* Clean up iot and smart imports

* Update post latest review

* Tweak Device docstring
This commit is contained in:
Steven B
2024-02-04 15:20:08 +00:00
committed by GitHub
parent 6afd05be59
commit 0d119e63d0
49 changed files with 1046 additions and 606 deletions

View File

@@ -15,6 +15,7 @@ try:
except ImportError:
from pydantic import BaseModel, ValidationError # pragma: no cover
from kasa import Device
from kasa.credentials import Credentials
from kasa.device_factory import (
get_device_class_from_family,
@@ -22,17 +23,21 @@ from kasa.device_factory import (
get_protocol,
)
from kasa.deviceconfig import ConnectionType, DeviceConfig, EncryptType
from kasa.exceptions import TimeoutException, UnsupportedDeviceException
from kasa.exceptions import (
SmartDeviceException,
TimeoutException,
UnsupportedDeviceException,
)
from kasa.iot.iotdevice import IotDevice
from kasa.json import dumps as json_dumps
from kasa.json import loads as json_loads
from kasa.smartdevice import SmartDevice, SmartDeviceException
from kasa.xortransport import XorEncryption
_LOGGER = logging.getLogger(__name__)
OnDiscoveredCallable = Callable[[SmartDevice], Awaitable[None]]
DeviceDict = Dict[str, SmartDevice]
OnDiscoveredCallable = Callable[[Device], Awaitable[None]]
DeviceDict = Dict[str, Device]
class _DiscoverProtocol(asyncio.DatagramProtocol):
@@ -121,7 +126,7 @@ class _DiscoverProtocol(asyncio.DatagramProtocol):
return
self.seen_hosts.add(ip)
device = None
device: Optional[Device] = None
config = DeviceConfig(host=ip, port_override=self.port)
if self.credentials:
@@ -300,7 +305,7 @@ class Discover:
port: Optional[int] = None,
timeout: Optional[int] = None,
credentials: Optional[Credentials] = None,
) -> SmartDevice:
) -> Device:
"""Discover a single device by the given IP address.
It is generally preferred to avoid :func:`discover_single()` and
@@ -382,7 +387,7 @@ class Discover:
raise SmartDeviceException(f"Unable to get discovery response for {host}")
@staticmethod
def _get_device_class(info: dict) -> Type[SmartDevice]:
def _get_device_class(info: dict) -> Type[Device]:
"""Find SmartDevice subclass for device described by passed data."""
if "result" in info:
discovery_result = DiscoveryResult(**info["result"])
@@ -397,7 +402,7 @@ class Discover:
return get_device_class_from_sys_info(info)
@staticmethod
def _get_device_instance_legacy(data: bytes, config: DeviceConfig) -> SmartDevice:
def _get_device_instance_legacy(data: bytes, config: DeviceConfig) -> IotDevice:
"""Get SmartDevice from legacy 9999 response."""
try:
info = json_loads(XorEncryption.decrypt(data))
@@ -408,7 +413,7 @@ class Discover:
_LOGGER.debug("[DISCOVERY] %s << %s", config.host, info)
device_class = Discover._get_device_class(info)
device_class = cast(Type[IotDevice], Discover._get_device_class(info))
device = device_class(config.host, config=config)
sys_info = info["system"]["get_sysinfo"]
if device_type := sys_info.get("mic_type", sys_info.get("type")):
@@ -423,7 +428,7 @@ class Discover:
def _get_device_instance(
data: bytes,
config: DeviceConfig,
) -> SmartDevice:
) -> Device:
"""Get SmartDevice from the new 20002 response."""
try:
info = json_loads(data[16:])