From 29a77a28c4ac145d2229abb89e48af68d5ccf424 Mon Sep 17 00:00:00 2001 From: Teemu Rytilahti Date: Tue, 27 Feb 2024 20:21:19 +0100 Subject: [PATCH 1/8] Add T315 fixture --- .../fixtures/smart/T315(EU)_1.0_1.7.0.json | 461 ++++++++++++++++++ 1 file changed, 461 insertions(+) create mode 100644 kasa/tests/fixtures/smart/T315(EU)_1.0_1.7.0.json diff --git a/kasa/tests/fixtures/smart/T315(EU)_1.0_1.7.0.json b/kasa/tests/fixtures/smart/T315(EU)_1.0_1.7.0.json new file mode 100644 index 000000000..9467072ce --- /dev/null +++ b/kasa/tests/fixtures/smart/T315(EU)_1.0_1.7.0.json @@ -0,0 +1,461 @@ +{ + "get_connect_cloud_state": { + "status": 0 + }, + "get_device_info": { + "at_low_battery": false, + "avatar": "", + "battery_percentage": 100, + "bind_count": 1, + "category": "subg.trigger.temp-hmdt-sensor", + "current_humidity": 61, + "current_humidity_exception": 1, + "current_temp": 21.4, + "current_temp_exception": 0, + "device_id": "SCRUBBED_CHILD_DEVICE_ID_1", + "fw_ver": "1.7.0 Build 230424 Rel.170332", + "hw_id": "00000000000000000000000000000000", + "hw_ver": "1.0", + "jamming_rssi": -122, + "jamming_signal_level": 1, + "lastOnboardingTimestamp": 1706990901, + "mac": "F0A731000000", + "model": "T315", + "nickname": "I01BU0tFRF9OQU1FIw==", + "oem_id": "00000000000000000000000000000000", + "parent_device_id": "0000000000000000000000000000000000000000", + "region": "Europe/Berlin", + "report_interval": 16, + "rssi": -56, + "signal_level": 3, + "specs": "EU", + "status": "online", + "status_follow_edge": false, + "temp_unit": "celsius", + "type": "SMART.TAPOSENSOR" + }, + "get_fw_download_state": { + "cloud_cache_seconds": 1, + "download_progress": 0, + "reboot_time": 5, + "status": 0, + "upgrade_time": 5 + }, + "get_latest_fw": { + "fw_ver": "1.8.0 Build 230921 Rel.091446", + "hw_id": "00000000000000000000000000000000", + "need_to_upgrade": true, + "oem_id": "00000000000000000000000000000000", + "release_date": "2023-12-01", + "release_note": "Modifications and Bug Fixes:\nEnhance the stability of the sensor.", + "type": 2 + }, + "get_temp_humidity_records": { + "local_time": 1709061516, + "past24h_humidity": [ + 60, + 60, + 59, + 59, + 59, + 59, + 59, + 59, + 59, + 59, + 58, + 59, + 59, + 58, + 59, + 59, + 59, + 60, + 60, + 60, + 60, + 60, + 60, + 60, + 60, + 60, + 60, + 60, + 60, + 60, + 60, + 60, + 60, + 60, + 60, + 60, + 60, + 60, + 59, + 59, + 59, + 59, + 59, + 59, + 60, + 60, + 59, + 59, + 59, + 59, + 59, + 59, + 59, + 59, + 59, + 59, + 59, + 59, + 59, + 59, + 59, + 59, + 59, + 59, + 59, + 59, + 59, + 60, + 60, + 60, + 60, + 60, + 60, + 60, + 60, + 60, + 64, + 56, + 53, + 55, + 56, + 57, + 57, + 58, + 59, + 63, + 63, + 62, + 62, + 62, + 62, + 61, + 62, + 62, + 61, + 61 + ], + "past24h_humidity_exception": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 4, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 3, + 3, + 2, + 2, + 2, + 2, + 1, + 2, + 2, + 1, + 1 + ], + "past24h_temp": [ + 217, + 216, + 215, + 214, + 214, + 214, + 214, + 214, + 214, + 213, + 213, + 213, + 213, + 213, + 212, + 212, + 211, + 211, + 211, + 211, + 211, + 211, + 212, + 212, + 212, + 211, + 211, + 211, + 211, + 212, + 212, + 212, + 212, + 212, + 211, + 211, + 211, + 212, + 213, + 214, + 214, + 214, + 213, + 212, + 212, + 212, + 212, + 212, + 212, + 212, + 212, + 212, + 212, + 213, + 213, + 213, + 213, + 213, + 213, + 213, + 213, + 213, + 213, + 214, + 214, + 215, + 215, + 215, + 214, + 215, + 216, + 216, + 216, + 216, + 216, + 216, + 216, + 205, + 196, + 210, + 213, + 213, + 213, + 213, + 213, + 214, + 215, + 214, + 214, + 213, + 213, + 214, + 214, + 214, + 213, + 213 + ], + "past24h_temp_exception": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + -4, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "temp_unit": "celsius" + }, + "get_trigger_logs": { + "logs": [ + { + "event": "tooDry", + "eventId": "118040a8-5422-1100-0804-0a8542211000", + "id": 1, + "timestamp": 1706996915 + } + ], + "start_id": 1, + "sum": 1 + } +} From 09244c75a33d0901ec5feab44edb01a45dfcad0a Mon Sep 17 00:00:00 2001 From: Teemu Rytilahti Date: Mon, 4 Mar 2024 18:51:38 +0100 Subject: [PATCH 2/8] Add initial module tests --- kasa/module.py | 11 +- kasa/smart/modules/temperature.py | 4 +- kasa/tests/conftest.py | 2 +- kasa/tests/device_fixtures.py | 29 +- .../fixtures/smart/T315(EU)_1.0_1.7.0.json | 994 ++++++++++-------- kasa/tests/smart/__init__.py | 0 kasa/tests/smart/modules/__init__.py | 0 kasa/tests/smart/modules/test_humidity.py | 26 + kasa/tests/smart/modules/test_temperature.py | 27 + 9 files changed, 615 insertions(+), 478 deletions(-) create mode 100644 kasa/tests/smart/__init__.py create mode 100644 kasa/tests/smart/modules/__init__.py create mode 100644 kasa/tests/smart/modules/test_humidity.py create mode 100644 kasa/tests/smart/modules/test_temperature.py diff --git a/kasa/module.py b/kasa/module.py index 5066c9535..c879185a3 100644 --- a/kasa/module.py +++ b/kasa/module.py @@ -37,11 +37,20 @@ def data(self): def _add_feature(self, feature: Feature): """Add module feature.""" - feat_name = f"{self._module}_{feature.name}" + + def _slugified_name(name): + return name.lower().replace(" ", "_").replace("'", "_") + + feat_name = _slugified_name(feature.name) if feat_name in self._module_features: raise KasaException("Duplicate name detected %s" % feat_name) self._module_features[feat_name] = feature + @property + def features(self) -> Dict[str, Feature]: + """Return the list of supported features.""" + return self._module_features + def __repr__(self) -> str: return ( f" bool: - """Return True if humidity is outside of the wanted range.""" + """Return True if temperature is outside of the wanted range.""" return self._device.sys_info["current_temp_exception"] != 0 @property diff --git a/kasa/tests/conftest.py b/kasa/tests/conftest.py index 0917f081c..bec48bde2 100644 --- a/kasa/tests/conftest.py +++ b/kasa/tests/conftest.py @@ -2,7 +2,7 @@ from typing import Dict from unittest.mock import MagicMock -import pytest # type: ignore # see https://github.com/pytest-dev/pytest/issues/3342 +import pytest from kasa import ( DeviceConfig, diff --git a/kasa/tests/device_fixtures.py b/kasa/tests/device_fixtures.py index 085bab8e5..c81472224 100644 --- a/kasa/tests/device_fixtures.py +++ b/kasa/tests/device_fixtures.py @@ -1,3 +1,4 @@ +from itertools import chain from typing import Dict, List, Set import pytest @@ -106,6 +107,7 @@ } HUBS_SMART = {"H100"} +SENSORS_SMART = {"T315"} WITH_EMETER_IOT = {"HS110", "HS300", "KP115", "KP125", *BULBS_IOT} WITH_EMETER_SMART = {"P110", "KP125M", "EP25"} @@ -121,6 +123,7 @@ .union(STRIPS_SMART) .union(DIMMERS_SMART) .union(HUBS_SMART) + .union(SENSORS_SMART) .union(SWITCHES_SMART) ) ALL_DEVICES = ALL_DEVICES_IOT.union(ALL_DEVICES_SMART) @@ -263,6 +266,9 @@ def parametrize( hubs_smart = parametrize( "hubs smart", model_filter=HUBS_SMART, protocol_filter={"SMART"} ) +sensors_smart = parametrize( + "sensors smart", model_filter=SENSORS_SMART, protocol_filter={"SMART"} +) device_smart = parametrize( "devices smart", model_filter=ALL_DEVICES_SMART, protocol_filter={"SMART"} ) @@ -283,6 +289,7 @@ def check_categories(): + bulb_smart.args[1] + dimmers_smart.args[1] + hubs_smart.args[1] + + sensors_smart.args[1] ) diffs: Set[FixtureInfo] = set(FIXTURE_DATA) - set(categorized_fixtures) if diffs: @@ -299,24 +306,14 @@ def check_categories(): def device_for_fixture_name(model, protocol): if "SMART" in protocol: - for d in PLUGS_SMART: - if d in model: - return SmartDevice - for d in SWITCHES_SMART: + for d in chain( + PLUGS_SMART, SWITCHES_SMART, STRIPS_SMART, HUBS_SMART, SENSORS_SMART + ): if d in model: return SmartDevice - for d in BULBS_SMART: - if d in model: - return SmartBulb - for d in DIMMERS_SMART: + for d in chain(BULBS_SMART, DIMMERS_SMART): if d in model: return SmartBulb - for d in STRIPS_SMART: - if d in model: - return SmartDevice - for d in HUBS_SMART: - if d in model: - return SmartDevice else: for d in STRIPS_IOT: if d in model: @@ -378,7 +375,9 @@ async def get_device_for_fixture(fixture_data: FixtureInfo): discovery_data = { "system": {"get_sysinfo": fixture_data.data["system"]["get_sysinfo"]} } - if discovery_data: # Child devices do not have discovery info + + # Child devices have no discovery data. + if discovery_data is not None: d.update_from_discover_info(discovery_data) await _update_and_close(d) diff --git a/kasa/tests/fixtures/smart/T315(EU)_1.0_1.7.0.json b/kasa/tests/fixtures/smart/T315(EU)_1.0_1.7.0.json index 9467072ce..4fc49b0e8 100644 --- a/kasa/tests/fixtures/smart/T315(EU)_1.0_1.7.0.json +++ b/kasa/tests/fixtures/smart/T315(EU)_1.0_1.7.0.json @@ -1,461 +1,537 @@ { - "get_connect_cloud_state": { - "status": 0 - }, - "get_device_info": { - "at_low_battery": false, - "avatar": "", - "battery_percentage": 100, - "bind_count": 1, - "category": "subg.trigger.temp-hmdt-sensor", - "current_humidity": 61, - "current_humidity_exception": 1, - "current_temp": 21.4, - "current_temp_exception": 0, - "device_id": "SCRUBBED_CHILD_DEVICE_ID_1", - "fw_ver": "1.7.0 Build 230424 Rel.170332", - "hw_id": "00000000000000000000000000000000", - "hw_ver": "1.0", - "jamming_rssi": -122, - "jamming_signal_level": 1, - "lastOnboardingTimestamp": 1706990901, - "mac": "F0A731000000", - "model": "T315", - "nickname": "I01BU0tFRF9OQU1FIw==", - "oem_id": "00000000000000000000000000000000", - "parent_device_id": "0000000000000000000000000000000000000000", - "region": "Europe/Berlin", - "report_interval": 16, - "rssi": -56, - "signal_level": 3, - "specs": "EU", - "status": "online", - "status_follow_edge": false, - "temp_unit": "celsius", - "type": "SMART.TAPOSENSOR" - }, - "get_fw_download_state": { - "cloud_cache_seconds": 1, - "download_progress": 0, - "reboot_time": 5, - "status": 0, - "upgrade_time": 5 - }, - "get_latest_fw": { - "fw_ver": "1.8.0 Build 230921 Rel.091446", - "hw_id": "00000000000000000000000000000000", - "need_to_upgrade": true, - "oem_id": "00000000000000000000000000000000", - "release_date": "2023-12-01", - "release_note": "Modifications and Bug Fixes:\nEnhance the stability of the sensor.", - "type": 2 - }, - "get_temp_humidity_records": { - "local_time": 1709061516, - "past24h_humidity": [ - 60, - 60, - 59, - 59, - 59, - 59, - 59, - 59, - 59, - 59, - 58, - 59, - 59, - 58, - 59, - 59, - 59, - 60, - 60, - 60, - 60, - 60, - 60, - 60, - 60, - 60, - 60, - 60, - 60, - 60, - 60, - 60, - 60, - 60, - 60, - 60, - 60, - 60, - 59, - 59, - 59, - 59, - 59, - 59, - 60, - 60, - 59, - 59, - 59, - 59, - 59, - 59, - 59, - 59, - 59, - 59, - 59, - 59, - 59, - 59, - 59, - 59, - 59, - 59, - 59, - 59, - 59, - 60, - 60, - 60, - 60, - 60, - 60, - 60, - 60, - 60, - 64, - 56, - 53, - 55, - 56, - 57, - 57, - 58, - 59, - 63, - 63, - 62, - 62, - 62, - 62, - 61, - 62, - 62, - 61, - 61 - ], - "past24h_humidity_exception": [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 4, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 3, - 3, - 2, - 2, - 2, - 2, - 1, - 2, - 2, - 1, - 1 - ], - "past24h_temp": [ - 217, - 216, - 215, - 214, - 214, - 214, - 214, - 214, - 214, - 213, - 213, - 213, - 213, - 213, - 212, - 212, - 211, - 211, - 211, - 211, - 211, - 211, - 212, - 212, - 212, - 211, - 211, - 211, - 211, - 212, - 212, - 212, - 212, - 212, - 211, - 211, - 211, - 212, - 213, - 214, - 214, - 214, - 213, - 212, - 212, - 212, - 212, - 212, - 212, - 212, - 212, - 212, - 212, - 213, - 213, - 213, - 213, - 213, - 213, - 213, - 213, - 213, - 213, - 214, - 214, - 215, - 215, - 215, - 214, - 215, - 216, - 216, - 216, - 216, - 216, - 216, - 216, - 205, - 196, - 210, - 213, - 213, - 213, - 213, - 213, - 214, - 215, - 214, - 214, - 213, - 213, - 214, - 214, - 214, - 213, - 213 - ], - "past24h_temp_exception": [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - -4, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - ], - "temp_unit": "celsius" - }, - "get_trigger_logs": { - "logs": [ - { - "event": "tooDry", - "eventId": "118040a8-5422-1100-0804-0a8542211000", - "id": 1, - "timestamp": 1706996915 - } - ], - "start_id": 1, - "sum": 1 - } + "component_nego" : { + "component_list" : [ + { + "id" : "device", + "ver_code" : 2 + }, + { + "id" : "quick_setup", + "ver_code" : 3 + }, + { + "id" : "trigger_log", + "ver_code" : 1 + }, + { + "id" : "time", + "ver_code" : 1 + }, + { + "id" : "device_local_time", + "ver_code" : 1 + }, + { + "id" : "account", + "ver_code" : 1 + }, + { + "id" : "synchronize", + "ver_code" : 1 + }, + { + "id" : "cloud_connect", + "ver_code" : 1 + }, + { + "id" : "iot_cloud", + "ver_code" : 1 + }, + { + "id" : "firmware", + "ver_code" : 1 + }, + { + "id" : "localSmart", + "ver_code" : 1 + }, + { + "id" : "battery_detect", + "ver_code" : 1 + }, + { + "id" : "temperature", + "ver_code" : 1 + }, + { + "id" : "humidity", + "ver_code" : 1 + }, + { + "id" : "temp_humidity_record", + "ver_code" : 1 + }, + { + "id" : "comfort_temperature", + "ver_code" : 1 + }, + { + "id" : "comfort_humidity", + "ver_code" : 1 + }, + { + "id" : "report_mode", + "ver_code" : 1 + } + ] + }, + "get_connect_cloud_state" : { + "status" : 0 + }, + "get_device_info" : { + "at_low_battery" : false, + "avatar" : "", + "battery_percentage" : 100, + "bind_count" : 1, + "category" : "subg.trigger.temp-hmdt-sensor", + "current_humidity" : 61, + "current_humidity_exception" : 1, + "current_temp" : 21.4, + "current_temp_exception" : 0, + "device_id" : "SCRUBBED_CHILD_DEVICE_ID_1", + "fw_ver" : "1.7.0 Build 230424 Rel.170332", + "hw_id" : "00000000000000000000000000000000", + "hw_ver" : "1.0", + "jamming_rssi" : -122, + "jamming_signal_level" : 1, + "lastOnboardingTimestamp" : 1706990901, + "mac" : "F0A731000000", + "model" : "T315", + "nickname" : "I01BU0tFRF9OQU1FIw==", + "oem_id" : "00000000000000000000000000000000", + "parent_device_id" : "0000000000000000000000000000000000000000", + "region" : "Europe/Berlin", + "report_interval" : 16, + "rssi" : -56, + "signal_level" : 3, + "specs" : "EU", + "status" : "online", + "status_follow_edge" : false, + "temp_unit" : "celsius", + "type" : "SMART.TAPOSENSOR" + }, + "get_fw_download_state" : { + "cloud_cache_seconds" : 1, + "download_progress" : 0, + "reboot_time" : 5, + "status" : 0, + "upgrade_time" : 5 + }, + "get_latest_fw" : { + "fw_ver" : "1.8.0 Build 230921 Rel.091446", + "hw_id" : "00000000000000000000000000000000", + "need_to_upgrade" : true, + "oem_id" : "00000000000000000000000000000000", + "release_date" : "2023-12-01", + "release_note" : "Modifications and Bug Fixes:\nEnhance the stability of the sensor.", + "type" : 2 + }, + "get_temp_humidity_records" : { + "local_time" : 1709061516, + "past24h_humidity" : [ + 60, + 60, + 59, + 59, + 59, + 59, + 59, + 59, + 59, + 59, + 58, + 59, + 59, + 58, + 59, + 59, + 59, + 60, + 60, + 60, + 60, + 60, + 60, + 60, + 60, + 60, + 60, + 60, + 60, + 60, + 60, + 60, + 60, + 60, + 60, + 60, + 60, + 60, + 59, + 59, + 59, + 59, + 59, + 59, + 60, + 60, + 59, + 59, + 59, + 59, + 59, + 59, + 59, + 59, + 59, + 59, + 59, + 59, + 59, + 59, + 59, + 59, + 59, + 59, + 59, + 59, + 59, + 60, + 60, + 60, + 60, + 60, + 60, + 60, + 60, + 60, + 64, + 56, + 53, + 55, + 56, + 57, + 57, + 58, + 59, + 63, + 63, + 62, + 62, + 62, + 62, + 61, + 62, + 62, + 61, + 61 + ], + "past24h_humidity_exception" : [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 4, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 3, + 3, + 2, + 2, + 2, + 2, + 1, + 2, + 2, + 1, + 1 + ], + "past24h_temp" : [ + 217, + 216, + 215, + 214, + 214, + 214, + 214, + 214, + 214, + 213, + 213, + 213, + 213, + 213, + 212, + 212, + 211, + 211, + 211, + 211, + 211, + 211, + 212, + 212, + 212, + 211, + 211, + 211, + 211, + 212, + 212, + 212, + 212, + 212, + 211, + 211, + 211, + 212, + 213, + 214, + 214, + 214, + 213, + 212, + 212, + 212, + 212, + 212, + 212, + 212, + 212, + 212, + 212, + 213, + 213, + 213, + 213, + 213, + 213, + 213, + 213, + 213, + 213, + 214, + 214, + 215, + 215, + 215, + 214, + 215, + 216, + 216, + 216, + 216, + 216, + 216, + 216, + 205, + 196, + 210, + 213, + 213, + 213, + 213, + 213, + 214, + 215, + 214, + 214, + 213, + 213, + 214, + 214, + 214, + 213, + 213 + ], + "past24h_temp_exception" : [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + -4, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "temp_unit" : "celsius" + }, + "get_trigger_logs" : { + "logs" : [ + { + "event" : "tooDry", + "eventId" : "118040a8-5422-1100-0804-0a8542211000", + "id" : 1, + "timestamp" : 1706996915 + } + ], + "start_id" : 1, + "sum" : 1 + } } diff --git a/kasa/tests/smart/__init__.py b/kasa/tests/smart/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/kasa/tests/smart/modules/__init__.py b/kasa/tests/smart/modules/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/kasa/tests/smart/modules/test_humidity.py b/kasa/tests/smart/modules/test_humidity.py new file mode 100644 index 000000000..d61ca88b3 --- /dev/null +++ b/kasa/tests/smart/modules/test_humidity.py @@ -0,0 +1,26 @@ +import pytest + +from kasa.smart.modules import HumiditySensor +from kasa.tests.device_fixtures import parametrize + +humidity = parametrize("has humidity", component_filter="humidity") + + +@humidity +@pytest.mark.parametrize( + "feature, type", + [ + ("humidity", int), + ("humidity_warning", bool), + ], +) +async def test_humidity_features(dev, feature, type): + """Test that features are registered and work as expected.""" + humidity: HumiditySensor = dev.modules["HumiditySensor"] + + prop = getattr(humidity, feature) + assert isinstance(prop, type) + + feat = humidity.features[feature] + assert feat.value == prop + assert isinstance(feat.value, type) diff --git a/kasa/tests/smart/modules/test_temperature.py b/kasa/tests/smart/modules/test_temperature.py new file mode 100644 index 000000000..b2a0015d5 --- /dev/null +++ b/kasa/tests/smart/modules/test_temperature.py @@ -0,0 +1,27 @@ +import pytest + +from kasa.smart.modules import TemperatureSensor +from kasa.tests.device_fixtures import parametrize + +temperature = parametrize("has temperature", component_filter="temperature") + + +@temperature +@pytest.mark.parametrize( + "feature, type", + [ + ("temperature", float), + ("temperature_warning", bool), + ("temperature_unit", str), + ], +) +async def test_temperature_features(dev, feature, type): + """Test that features are registered and work as expected.""" + temp_module: TemperatureSensor = dev.modules["TemperatureSensor"] + + prop = getattr(temp_module, feature) + assert isinstance(prop, type) + + feat = temp_module.features[feature] + assert feat.value == prop + assert isinstance(feat.value, type) From 188fe35ead65b114f7ff964e164e5e12c9ae8c84 Mon Sep 17 00:00:00 2001 From: Teemu Rytilahti Date: Wed, 6 Mar 2024 15:57:51 +0100 Subject: [PATCH 3/8] Move child fixture to correct place and adjust the protocol --- kasa/tests/device_fixtures.py | 2 +- kasa/tests/fixtures/smart/child/.gitkeep | 1 - kasa/tests/fixtures/smart/{ => child}/T315(EU)_1.0_1.7.0.json | 0 3 files changed, 1 insertion(+), 2 deletions(-) delete mode 100644 kasa/tests/fixtures/smart/child/.gitkeep rename kasa/tests/fixtures/smart/{ => child}/T315(EU)_1.0_1.7.0.json (100%) diff --git a/kasa/tests/device_fixtures.py b/kasa/tests/device_fixtures.py index c81472224..5702f5944 100644 --- a/kasa/tests/device_fixtures.py +++ b/kasa/tests/device_fixtures.py @@ -267,7 +267,7 @@ def parametrize( "hubs smart", model_filter=HUBS_SMART, protocol_filter={"SMART"} ) sensors_smart = parametrize( - "sensors smart", model_filter=SENSORS_SMART, protocol_filter={"SMART"} + "sensors smart", model_filter=SENSORS_SMART, protocol_filter={"SMART.CHILD"} ) device_smart = parametrize( "devices smart", model_filter=ALL_DEVICES_SMART, protocol_filter={"SMART"} diff --git a/kasa/tests/fixtures/smart/child/.gitkeep b/kasa/tests/fixtures/smart/child/.gitkeep deleted file mode 100644 index 74bef8496..000000000 --- a/kasa/tests/fixtures/smart/child/.gitkeep +++ /dev/null @@ -1 +0,0 @@ -Can be deleted when first fixture is added diff --git a/kasa/tests/fixtures/smart/T315(EU)_1.0_1.7.0.json b/kasa/tests/fixtures/smart/child/T315(EU)_1.0_1.7.0.json similarity index 100% rename from kasa/tests/fixtures/smart/T315(EU)_1.0_1.7.0.json rename to kasa/tests/fixtures/smart/child/T315(EU)_1.0_1.7.0.json From 139306401cd6db3532e356a7f91b01de83aa88c7 Mon Sep 17 00:00:00 2001 From: Teemu Rytilahti Date: Wed, 6 Mar 2024 16:08:00 +0100 Subject: [PATCH 4/8] Fix protocol_filter for child modules --- kasa/tests/fixtureinfo.py | 2 +- kasa/tests/smart/modules/test_humidity.py | 2 +- kasa/tests/smart/modules/test_temperature.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/kasa/tests/fixtureinfo.py b/kasa/tests/fixtureinfo.py index 70d385f60..08414ad4d 100644 --- a/kasa/tests/fixtureinfo.py +++ b/kasa/tests/fixtureinfo.py @@ -93,7 +93,7 @@ def filter_fixtures( data_root_filter: return fixtures containing the supplied top level key, i.e. discovery_result - protocol_filter: set of protocols to match, IOT or SMART + protocol_filter: set of protocols to match, IOT, SMART, SMART.CHILD model_filter: set of device models to match component_filter: filter SMART fixtures that have the provided component in component_nego details. diff --git a/kasa/tests/smart/modules/test_humidity.py b/kasa/tests/smart/modules/test_humidity.py index d61ca88b3..712c3b88d 100644 --- a/kasa/tests/smart/modules/test_humidity.py +++ b/kasa/tests/smart/modules/test_humidity.py @@ -3,7 +3,7 @@ from kasa.smart.modules import HumiditySensor from kasa.tests.device_fixtures import parametrize -humidity = parametrize("has humidity", component_filter="humidity") +humidity = parametrize("has humidity", component_filter="humidity", protocol_filter={"SMART.CHILD"}) @humidity diff --git a/kasa/tests/smart/modules/test_temperature.py b/kasa/tests/smart/modules/test_temperature.py index b2a0015d5..c9d389776 100644 --- a/kasa/tests/smart/modules/test_temperature.py +++ b/kasa/tests/smart/modules/test_temperature.py @@ -3,7 +3,7 @@ from kasa.smart.modules import TemperatureSensor from kasa.tests.device_fixtures import parametrize -temperature = parametrize("has temperature", component_filter="temperature") +temperature = parametrize("has temperature", component_filter="temperature", protocol_filter={"SMART.CHILD"}) @temperature From bbceb7e56bad1ec7a44abc2ff73649de782aa879 Mon Sep 17 00:00:00 2001 From: Teemu Rytilahti Date: Wed, 6 Mar 2024 17:02:00 +0100 Subject: [PATCH 5/8] Filter out child devs for dev fixture, using a tip from @sdb9696 --- kasa/tests/device_fixtures.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kasa/tests/device_fixtures.py b/kasa/tests/device_fixtures.py index 5702f5944..c362da064 100644 --- a/kasa/tests/device_fixtures.py +++ b/kasa/tests/device_fixtures.py @@ -391,7 +391,7 @@ async def get_device_for_fixture_protocol(fixture, protocol): return await get_device_for_fixture(fixture_info) -@pytest.fixture(params=FIXTURE_DATA, ids=idgenerator) +@pytest.fixture(params=filter_fixtures("main devices"), ids=idgenerator) async def dev(request): """Device fixture. From a6c06a50318d0240b2b87bc26cb00df54d0520c5 Mon Sep 17 00:00:00 2001 From: Teemu Rytilahti Date: Wed, 6 Mar 2024 17:09:21 +0100 Subject: [PATCH 6/8] don't check for noneness on discovery_data --- kasa/tests/device_fixtures.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/kasa/tests/device_fixtures.py b/kasa/tests/device_fixtures.py index c362da064..71cc34bd7 100644 --- a/kasa/tests/device_fixtures.py +++ b/kasa/tests/device_fixtures.py @@ -376,8 +376,7 @@ async def get_device_for_fixture(fixture_data: FixtureInfo): "system": {"get_sysinfo": fixture_data.data["system"]["get_sysinfo"]} } - # Child devices have no discovery data. - if discovery_data is not None: + if discovery_data: # Child devices do not have discovery info d.update_from_discover_info(discovery_data) await _update_and_close(d) From 07ad0fcad22eb4b7917079f671a9c0aa7fb76407 Mon Sep 17 00:00:00 2001 From: Teemu Rytilahti Date: Wed, 6 Mar 2024 18:48:38 +0100 Subject: [PATCH 7/8] Remove Module.features getter --- kasa/module.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/kasa/module.py b/kasa/module.py index c879185a3..854ab960e 100644 --- a/kasa/module.py +++ b/kasa/module.py @@ -46,11 +46,6 @@ def _slugified_name(name): raise KasaException("Duplicate name detected %s" % feat_name) self._module_features[feat_name] = feature - @property - def features(self) -> Dict[str, Feature]: - """Return the list of supported features.""" - return self._module_features - def __repr__(self) -> str: return ( f" Date: Wed, 6 Mar 2024 18:57:07 +0100 Subject: [PATCH 8/8] Fix tests to use _module_features --- kasa/tests/smart/modules/test_humidity.py | 2 +- kasa/tests/smart/modules/test_temperature.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/kasa/tests/smart/modules/test_humidity.py b/kasa/tests/smart/modules/test_humidity.py index 712c3b88d..99e4702eb 100644 --- a/kasa/tests/smart/modules/test_humidity.py +++ b/kasa/tests/smart/modules/test_humidity.py @@ -21,6 +21,6 @@ async def test_humidity_features(dev, feature, type): prop = getattr(humidity, feature) assert isinstance(prop, type) - feat = humidity.features[feature] + feat = humidity._module_features[feature] assert feat.value == prop assert isinstance(feat.value, type) diff --git a/kasa/tests/smart/modules/test_temperature.py b/kasa/tests/smart/modules/test_temperature.py index c9d389776..649b5bc49 100644 --- a/kasa/tests/smart/modules/test_temperature.py +++ b/kasa/tests/smart/modules/test_temperature.py @@ -22,6 +22,6 @@ async def test_temperature_features(dev, feature, type): prop = getattr(temp_module, feature) assert isinstance(prop, type) - feat = temp_module.features[feature] + feat = temp_module._module_features[feature] assert feat.value == prop assert isinstance(feat.value, type)