From cc883ae96a36dc3f6e688e6c01b134aa7753b7f5 Mon Sep 17 00:00:00 2001 From: Teemu Rytilahti Date: Wed, 20 Nov 2024 19:01:30 +0100 Subject: [PATCH 1/6] Make discovery on unsupported devices less noisy --- kasa/discover.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kasa/discover.py b/kasa/discover.py index 74b663e8d..7c153a19e 100755 --- a/kasa/discover.py +++ b/kasa/discover.py @@ -776,14 +776,14 @@ def _get_device_instance( type_, https=encrypt_schm.is_support_https ) ) is None: - _LOGGER.warning("Got unsupported device type: %s", type_) + _LOGGER.debug("Got unsupported device type: %s", type_) raise UnsupportedDeviceError( f"Unsupported device {config.host} of type {type_}: {info}", discovery_result=discovery_result.to_dict(), host=config.host, ) if (protocol := get_protocol(config)) is None: - _LOGGER.warning( + _LOGGER.debug( "Got unsupported connection type: %s", config.connection_type.to_dict() ) raise UnsupportedDeviceError( From 5e8eaa646a1e173a8124c0528315fe50071aeaac Mon Sep 17 00:00:00 2001 From: Teemu Rytilahti Date: Wed, 20 Nov 2024 19:21:02 +0100 Subject: [PATCH 2/6] Add some newlines to improve readability --- kasa/discover.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/kasa/discover.py b/kasa/discover.py index 7c153a19e..75651b7ff 100755 --- a/kasa/discover.py +++ b/kasa/discover.py @@ -715,6 +715,7 @@ def _get_device_instance( raise KasaException( f"Unable to read response from device: {config.host}: {ex}" ) from ex + try: discovery_result = DiscoveryResult.from_dict(info["result"]) except Exception as ex: @@ -733,6 +734,7 @@ def _get_device_instance( f"Unable to parse discovery from device: {config.host}: {ex}", host=config.host, ) from ex + # Decrypt the data if ( encrypt_info := discovery_result.encrypt_info @@ -746,11 +748,13 @@ def _get_device_instance( type_ = discovery_result.device_type encrypt_schm = discovery_result.mgt_encrypt_schm + try: if not (encrypt_type := encrypt_schm.encrypt_type) and ( encrypt_info := discovery_result.encrypt_info ): encrypt_type = encrypt_info.sym_schm + if not encrypt_type: raise UnsupportedDeviceError( f"Unsupported device {config.host} of type {type_} " @@ -771,6 +775,7 @@ def _get_device_instance( discovery_result=discovery_result.to_dict(), host=config.host, ) from ex + if ( device_class := get_device_class_from_family( type_, https=encrypt_schm.is_support_https @@ -782,6 +787,7 @@ def _get_device_instance( discovery_result=discovery_result.to_dict(), host=config.host, ) + if (protocol := get_protocol(config)) is None: _LOGGER.debug( "Got unsupported connection type: %s", config.connection_type.to_dict() @@ -800,6 +806,7 @@ def _get_device_instance( else info ) _LOGGER.debug("[DISCOVERY] %s << %s", config.host, pf(data)) + device = device_class(config.host, protocol=protocol) di = discovery_result.to_dict() From 3d742a738d3d3a021d058049ea07facbe27e0f45 Mon Sep 17 00:00:00 2001 From: Teemu Rytilahti Date: Wed, 20 Nov 2024 19:24:26 +0100 Subject: [PATCH 3/6] Noise-- for devicefactory with smart fallback --- kasa/device_factory.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kasa/device_factory.py b/kasa/device_factory.py index dab867997..f0b90b6ef 100755 --- a/kasa/device_factory.py +++ b/kasa/device_factory.py @@ -164,7 +164,7 @@ def get_device_class_from_family( and device_type.startswith("SMART.") and not require_exact ): - _LOGGER.warning("Unknown SMART device with %s, using SmartDevice", device_type) + _LOGGER.debug("Unknown SMART device with %s, using SmartDevice", device_type) cls = SmartDevice return cls From 7190ac336a0f6853e9123cb8c162603e3ba251aa Mon Sep 17 00:00:00 2001 From: Teemu Rytilahti Date: Wed, 20 Nov 2024 20:14:14 +0100 Subject: [PATCH 4/6] Fix tests --- tests/test_device_factory.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_device_factory.py b/tests/test_device_factory.py index 9102a5287..8f9f635ae 100644 --- a/tests/test_device_factory.py +++ b/tests/test_device_factory.py @@ -195,6 +195,6 @@ async def test_device_types(dev: Device): async def test_device_class_from_unknown_family(caplog): """Verify that unknown SMART devices yield a warning and fallback to SmartDevice.""" dummy_name = "SMART.foo" - with caplog.at_level(logging.WARNING): + with caplog.at_level(logging.DEBUG): assert get_device_class_from_family(dummy_name, https=False) == SmartDevice assert f"Unknown SMART device with {dummy_name}" in caplog.text From ac08b63208d67673019188f102d8eacc97e93533 Mon Sep 17 00:00:00 2001 From: Teemu Rytilahti Date: Wed, 20 Nov 2024 20:38:33 +0100 Subject: [PATCH 5/6] Add unknown_iot_device_family to unupported devices fixture --- tests/discovery_fixtures.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/discovery_fixtures.py b/tests/discovery_fixtures.py index e272cef81..97dd8439b 100644 --- a/tests/discovery_fixtures.py +++ b/tests/discovery_fixtures.py @@ -51,6 +51,7 @@ def _make_unsupported(device_family, encrypt_type, *, omit_keys=None): UNSUPPORTED_DEVICES = { "unknown_device_family": _make_unsupported("SMART.TAPOXMASTREE", "AES"), + "unknown_iot_device_family": _make_unsupported("IOT.IOTXMASTREE", "AES"), "wrong_encryption_iot": _make_unsupported("IOT.SMARTPLUGSWITCH", "AES"), "wrong_encryption_smart": _make_unsupported("SMART.TAPOBULB", "IOT"), "unknown_encryption": _make_unsupported("IOT.SMARTPLUGSWITCH", "FOO"), From 820bb4c9c9a3060e23c2b1162aa6c217376b037c Mon Sep 17 00:00:00 2001 From: Steven B <51370195+sdb9696@users.noreply.github.com> Date: Thu, 21 Nov 2024 16:44:34 +0000 Subject: [PATCH 6/6] Fix coverage --- tests/discovery_fixtures.py | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/tests/discovery_fixtures.py b/tests/discovery_fixtures.py index 97dd8439b..f8df43975 100644 --- a/tests/discovery_fixtures.py +++ b/tests/discovery_fixtures.py @@ -3,6 +3,7 @@ import copy from dataclasses import dataclass from json import dumps as json_dumps +from typing import Any, TypedDict import pytest @@ -16,10 +17,21 @@ DISCOVERY_MOCK_IP = "127.0.0.123" -def _make_unsupported(device_family, encrypt_type, *, omit_keys=None): +class DiscoveryResponse(TypedDict): + result: dict[str, Any] + error_code: int + + +def _make_unsupported( + device_family, + encrypt_type, + *, + https: bool = False, + omit_keys: dict[str, Any] | None = None, +) -> DiscoveryResponse: if omit_keys is None: omit_keys = {"encrypt_info": None} - result = { + result: DiscoveryResponse = { "result": { "device_id": "xx", "owner": "xx", @@ -31,7 +43,7 @@ def _make_unsupported(device_family, encrypt_type, *, omit_keys=None): "obd_src": "tplink", "factory_default": False, "mgt_encrypt_schm": { - "is_support_https": False, + "is_support_https": https, "encrypt_type": encrypt_type, "http_port": 80, "lv": 2, @@ -65,6 +77,11 @@ def _make_unsupported(device_family, encrypt_type, *, omit_keys=None): "FOO", omit_keys={"mgt_encrypt_schm": None}, ), + "invalidinstance": _make_unsupported( + "IOT.SMARTPLUGSWITCH", + "KLAP", + https=True, + ), }