diff --git a/README.md b/README.md
index 91235102f..c4dd918cb 100644
--- a/README.md
+++ b/README.md
@@ -231,6 +231,7 @@ The following devices have been tested and confirmed as working. If your device
- **Wall Switches**: ES20M, HS200, HS210, HS220, KP405, KS200M, KS205\*, KS220M, KS225\*, KS230
- **Bulbs**: KL110, KL120, KL125, KL130, KL135, KL50, KL60, LB110
- **Light Strips**: KL400L5, KL420L5, KL430
+- **Hubs**: KH100\*
### Supported Tapo\* devices
diff --git a/SUPPORTED.md b/SUPPORTED.md
index 16fdb0e1d..1587e9663 100644
--- a/SUPPORTED.md
+++ b/SUPPORTED.md
@@ -126,6 +126,11 @@ Some newer Kasa devices require authentication. These are marked with *\*
+
## Tapo devices
diff --git a/kasa/device_factory.py b/kasa/device_factory.py
index 3c0ae7164..29cc36ffd 100755
--- a/kasa/device_factory.py
+++ b/kasa/device_factory.py
@@ -166,6 +166,7 @@ def get_device_class_from_family(device_type: str) -> type[Device] | None:
"SMART.TAPOSWITCH": SmartBulb,
"SMART.KASAPLUG": SmartDevice,
"SMART.TAPOHUB": SmartDevice,
+ "SMART.KASAHUB": SmartDevice,
"SMART.KASASWITCH": SmartBulb,
"IOT.SMARTPLUGSWITCH": IotPlug,
"IOT.SMARTBULB": IotBulb,
diff --git a/kasa/deviceconfig.py b/kasa/deviceconfig.py
index 6ddff6ade..4144b784d 100644
--- a/kasa/deviceconfig.py
+++ b/kasa/deviceconfig.py
@@ -39,6 +39,7 @@ class DeviceFamilyType(Enum):
SmartTapoBulb = "SMART.TAPOBULB"
SmartTapoSwitch = "SMART.TAPOSWITCH"
SmartTapoHub = "SMART.TAPOHUB"
+ SmartKasaHub = "SMART.KASAHUB"
def _dataclass_from_dict(klass, in_val):
diff --git a/kasa/smart/modules/temperature.py b/kasa/smart/modules/temperature.py
index 2a5d73ba7..3cec427b5 100644
--- a/kasa/smart/modules/temperature.py
+++ b/kasa/smart/modules/temperature.py
@@ -28,16 +28,17 @@ def __init__(self, device: SmartDevice, module: str):
icon="mdi:thermometer",
)
)
- self._add_feature(
- Feature(
- device,
- "Temperature warning",
- container=self,
- attribute_getter="temperature_warning",
- type=FeatureType.BinarySensor,
- icon="mdi:alert",
+ if "current_temp_exception" in device.sys_info:
+ self._add_feature(
+ Feature(
+ device,
+ "Temperature warning",
+ container=self,
+ attribute_getter="temperature_warning",
+ type=FeatureType.BinarySensor,
+ icon="mdi:alert",
+ )
)
- )
self._add_feature(
Feature(
device,
@@ -57,7 +58,7 @@ def temperature(self):
@property
def temperature_warning(self) -> bool:
"""Return True if temperature is outside of the wanted range."""
- return self._device.sys_info["current_temp_exception"] != 0
+ return self._device.sys_info.get("current_temp_exception", 0) != 0
@property
def temperature_unit(self):
diff --git a/kasa/smart/modules/temperaturecontrol.py b/kasa/smart/modules/temperaturecontrol.py
index 8babf1164..9106a56fa 100644
--- a/kasa/smart/modules/temperaturecontrol.py
+++ b/kasa/smart/modules/temperaturecontrol.py
@@ -14,7 +14,7 @@
class TemperatureControl(SmartModule):
"""Implementation of temperature module."""
- REQUIRED_COMPONENT = "temperature_control"
+ REQUIRED_COMPONENT = "temp_control"
def __init__(self, device: SmartDevice, module: str):
super().__init__(device, module)
@@ -57,11 +57,11 @@ def maximum_target_temperature(self) -> int:
return self._device.sys_info["max_control_temp"]
@property
- def target_temperature(self) -> int:
+ def target_temperature(self) -> float:
"""Return target temperature."""
- return self._device.sys_info["target_temperature"]
+ return self._device.sys_info["target_temp"]
- async def set_target_temperature(self, target: int):
+ async def set_target_temperature(self, target: float):
"""Set target temperature."""
if (
target < self.minimum_target_temperature
diff --git a/kasa/tests/device_fixtures.py b/kasa/tests/device_fixtures.py
index 362015db9..3cad6357e 100644
--- a/kasa/tests/device_fixtures.py
+++ b/kasa/tests/device_fixtures.py
@@ -107,8 +107,9 @@
*DIMMERS_SMART,
}
-HUBS_SMART = {"H100"}
-SENSORS_SMART = {"T315"}
+HUBS_SMART = {"H100", "KH100"}
+SENSORS_SMART = {"T310", "T315"}
+THERMOSTATS_SMART = {"KE100"}
WITH_EMETER_IOT = {"HS110", "HS300", "KP115", "KP125", *BULBS_IOT}
WITH_EMETER_SMART = {"P110", "KP125M", "EP25"}
@@ -126,6 +127,7 @@
.union(HUBS_SMART)
.union(SENSORS_SMART)
.union(SWITCHES_SMART)
+ .union(THERMOSTATS_SMART)
)
ALL_DEVICES = ALL_DEVICES_IOT.union(ALL_DEVICES_SMART)
@@ -275,6 +277,9 @@ def parametrize(
sensors_smart = parametrize(
"sensors smart", model_filter=SENSORS_SMART, protocol_filter={"SMART.CHILD"}
)
+thermostats_smart = parametrize(
+ "thermostats smart", model_filter=THERMOSTATS_SMART, protocol_filter={"SMART.CHILD"}
+)
device_smart = parametrize(
"devices smart", model_filter=ALL_DEVICES_SMART, protocol_filter={"SMART"}
)
@@ -296,6 +301,7 @@ def check_categories():
+ dimmers_smart.args[1]
+ hubs_smart.args[1]
+ sensors_smart.args[1]
+ + thermostats_smart.args[1]
)
diffs: set[FixtureInfo] = set(FIXTURE_DATA) - set(categorized_fixtures)
if diffs:
@@ -313,7 +319,12 @@ def check_categories():
def device_for_fixture_name(model, protocol):
if "SMART" in protocol:
for d in chain(
- PLUGS_SMART, SWITCHES_SMART, STRIPS_SMART, HUBS_SMART, SENSORS_SMART
+ PLUGS_SMART,
+ SWITCHES_SMART,
+ STRIPS_SMART,
+ HUBS_SMART,
+ SENSORS_SMART,
+ THERMOSTATS_SMART,
):
if d in model:
return SmartDevice
diff --git a/kasa/tests/fixtures/smart/KH100(UK)_1.0_1.5.6.json b/kasa/tests/fixtures/smart/KH100(UK)_1.0_1.5.6.json
new file mode 100644
index 000000000..33e4cec68
--- /dev/null
+++ b/kasa/tests/fixtures/smart/KH100(UK)_1.0_1.5.6.json
@@ -0,0 +1,1557 @@
+ {
+ "component_nego": {
+ "component_list": [
+ {
+ "id": "device",
+ "ver_code": 2
+ },
+ {
+ "id": "firmware",
+ "ver_code": 2
+ },
+ {
+ "id": "quick_setup",
+ "ver_code": 3
+ },
+ {
+ "id": "inherit",
+ "ver_code": 1
+ },
+ {
+ "id": "time",
+ "ver_code": 1
+ },
+ {
+ "id": "wireless",
+ "ver_code": 1
+ },
+ {
+ "id": "account",
+ "ver_code": 1
+ },
+ {
+ "id": "synchronize",
+ "ver_code": 1
+ },
+ {
+ "id": "sunrise_sunset",
+ "ver_code": 1
+ },
+ {
+ "id": "led",
+ "ver_code": 1
+ },
+ {
+ "id": "cloud_connect",
+ "ver_code": 1
+ },
+ {
+ "id": "iot_cloud",
+ "ver_code": 1
+ },
+ {
+ "id": "child_device",
+ "ver_code": 1
+ },
+ {
+ "id": "child_quick_setup",
+ "ver_code": 1
+ },
+ {
+ "id": "child_inherit",
+ "ver_code": 1
+ },
+ {
+ "id": "control_child",
+ "ver_code": 1
+ },
+ {
+ "id": "alarm",
+ "ver_code": 1
+ },
+ {
+ "id": "device_load",
+ "ver_code": 1
+ },
+ {
+ "id": "device_local_time",
+ "ver_code": 1
+ },
+ {
+ "id": "alarm_logs",
+ "ver_code": 1
+ },
+ {
+ "id": "localSmart",
+ "ver_code": 1
+ }
+ ]
+ },
+ "discovery_result": {
+ "device_id": "00000000000000000000000000000000",
+ "device_model": "KH100(UK)",
+ "device_type": "SMART.KASAHUB",
+ "factory_default": false,
+ "ip": "127.0.0.123",
+ "is_support_iot_cloud": true,
+ "mac": "F0-A7-31-00-00-00",
+ "mgt_encrypt_schm": {
+ "encrypt_type": "AES",
+ "http_port": 80,
+ "is_support_https": false,
+ "lv": 2
+ },
+ "obd_src": "tplink",
+ "owner": "00000000000000000000000000000000"
+ },
+ "get_alarm_configure": {
+ "duration": 300,
+ "type": "Doorbell Ring 1",
+ "volume": "high"
+ },
+ "get_auto_update_info": {
+ "enable": true,
+ "random_range": 120,
+ "time": 900
+ },
+ "get_child_device_component_list": {
+ "child_component_list": [
+ {
+ "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
+ }
+ ],
+ "device_id": "SCRUBBED_CHILD_DEVICE_ID_1"
+ },
+ {
+ "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
+ }
+ ],
+ "device_id": "SCRUBBED_CHILD_DEVICE_ID_2"
+ },
+ {
+ "component_list": [
+ {
+ "id": "device",
+ "ver_code": 2
+ },
+ {
+ "id": "quick_setup",
+ "ver_code": 3
+ },
+ {
+ "id": "time",
+ "ver_code": 1
+ },
+ {
+ "id": "device_local_time",
+ "ver_code": 1
+ },
+ {
+ "id": "schedule",
+ "ver_code": 2
+ },
+ {
+ "id": "countdown",
+ "ver_code": 2
+ },
+ {
+ "id": "account",
+ "ver_code": 1
+ },
+ {
+ "id": "synchronize",
+ "ver_code": 1
+ },
+ {
+ "id": "sunrise_sunset",
+ "ver_code": 1
+ },
+ {
+ "id": "cloud_connect",
+ "ver_code": 1
+ },
+ {
+ "id": "iot_cloud",
+ "ver_code": 1
+ },
+ {
+ "id": "frost_protection",
+ "ver_code": 1
+ },
+ {
+ "id": "child_protection",
+ "ver_code": 1
+ },
+ {
+ "id": "temperature",
+ "ver_code": 1
+ },
+ {
+ "id": "temp_control",
+ "ver_code": 1
+ },
+ {
+ "id": "remove_scale",
+ "ver_code": 1
+ },
+ {
+ "id": "shutdown_mode",
+ "ver_code": 1
+ },
+ {
+ "id": "progress_calibration",
+ "ver_code": 1
+ },
+ {
+ "id": "early_start",
+ "ver_code": 1
+ },
+ {
+ "id": "temp_record",
+ "ver_code": 1
+ },
+ {
+ "id": "screen_setting",
+ "ver_code": 1
+ },
+ {
+ "id": "night_mode",
+ "ver_code": 1
+ },
+ {
+ "id": "smart_control_schedule",
+ "ver_code": 1
+ },
+ {
+ "id": "firmware",
+ "ver_code": 1
+ },
+ {
+ "id": "battery_detect",
+ "ver_code": 1
+ },
+ {
+ "id": "temperature_correction",
+ "ver_code": 1
+ },
+ {
+ "id": "window_open_detect",
+ "ver_code": 2
+ }
+ ],
+ "device_id": "SCRUBBED_CHILD_DEVICE_ID_3"
+ },
+ {
+ "component_list": [
+ {
+ "id": "device",
+ "ver_code": 2
+ },
+ {
+ "id": "quick_setup",
+ "ver_code": 3
+ },
+ {
+ "id": "time",
+ "ver_code": 1
+ },
+ {
+ "id": "device_local_time",
+ "ver_code": 1
+ },
+ {
+ "id": "schedule",
+ "ver_code": 2
+ },
+ {
+ "id": "countdown",
+ "ver_code": 2
+ },
+ {
+ "id": "account",
+ "ver_code": 1
+ },
+ {
+ "id": "synchronize",
+ "ver_code": 1
+ },
+ {
+ "id": "sunrise_sunset",
+ "ver_code": 1
+ },
+ {
+ "id": "cloud_connect",
+ "ver_code": 1
+ },
+ {
+ "id": "iot_cloud",
+ "ver_code": 1
+ },
+ {
+ "id": "frost_protection",
+ "ver_code": 1
+ },
+ {
+ "id": "child_protection",
+ "ver_code": 1
+ },
+ {
+ "id": "temperature",
+ "ver_code": 1
+ },
+ {
+ "id": "temp_control",
+ "ver_code": 1
+ },
+ {
+ "id": "remove_scale",
+ "ver_code": 1
+ },
+ {
+ "id": "shutdown_mode",
+ "ver_code": 1
+ },
+ {
+ "id": "progress_calibration",
+ "ver_code": 1
+ },
+ {
+ "id": "early_start",
+ "ver_code": 1
+ },
+ {
+ "id": "temp_record",
+ "ver_code": 1
+ },
+ {
+ "id": "screen_setting",
+ "ver_code": 1
+ },
+ {
+ "id": "night_mode",
+ "ver_code": 1
+ },
+ {
+ "id": "smart_control_schedule",
+ "ver_code": 1
+ },
+ {
+ "id": "firmware",
+ "ver_code": 1
+ },
+ {
+ "id": "battery_detect",
+ "ver_code": 1
+ },
+ {
+ "id": "temperature_correction",
+ "ver_code": 1
+ },
+ {
+ "id": "window_open_detect",
+ "ver_code": 2
+ }
+ ],
+ "device_id": "SCRUBBED_CHILD_DEVICE_ID_4"
+ },
+ {
+ "component_list": [
+ {
+ "id": "device",
+ "ver_code": 2
+ },
+ {
+ "id": "quick_setup",
+ "ver_code": 3
+ },
+ {
+ "id": "time",
+ "ver_code": 1
+ },
+ {
+ "id": "device_local_time",
+ "ver_code": 1
+ },
+ {
+ "id": "schedule",
+ "ver_code": 2
+ },
+ {
+ "id": "countdown",
+ "ver_code": 2
+ },
+ {
+ "id": "account",
+ "ver_code": 1
+ },
+ {
+ "id": "synchronize",
+ "ver_code": 1
+ },
+ {
+ "id": "sunrise_sunset",
+ "ver_code": 1
+ },
+ {
+ "id": "cloud_connect",
+ "ver_code": 1
+ },
+ {
+ "id": "iot_cloud",
+ "ver_code": 1
+ },
+ {
+ "id": "frost_protection",
+ "ver_code": 1
+ },
+ {
+ "id": "child_protection",
+ "ver_code": 1
+ },
+ {
+ "id": "temperature",
+ "ver_code": 1
+ },
+ {
+ "id": "temp_control",
+ "ver_code": 1
+ },
+ {
+ "id": "remove_scale",
+ "ver_code": 1
+ },
+ {
+ "id": "shutdown_mode",
+ "ver_code": 1
+ },
+ {
+ "id": "progress_calibration",
+ "ver_code": 1
+ },
+ {
+ "id": "early_start",
+ "ver_code": 1
+ },
+ {
+ "id": "temp_record",
+ "ver_code": 1
+ },
+ {
+ "id": "screen_setting",
+ "ver_code": 1
+ },
+ {
+ "id": "night_mode",
+ "ver_code": 1
+ },
+ {
+ "id": "smart_control_schedule",
+ "ver_code": 1
+ },
+ {
+ "id": "firmware",
+ "ver_code": 1
+ },
+ {
+ "id": "battery_detect",
+ "ver_code": 1
+ },
+ {
+ "id": "temperature_correction",
+ "ver_code": 1
+ },
+ {
+ "id": "window_open_detect",
+ "ver_code": 2
+ }
+ ],
+ "device_id": "SCRUBBED_CHILD_DEVICE_ID_5"
+ },
+ {
+ "component_list": [
+ {
+ "id": "device",
+ "ver_code": 2
+ },
+ {
+ "id": "quick_setup",
+ "ver_code": 3
+ },
+ {
+ "id": "time",
+ "ver_code": 1
+ },
+ {
+ "id": "device_local_time",
+ "ver_code": 1
+ },
+ {
+ "id": "schedule",
+ "ver_code": 2
+ },
+ {
+ "id": "countdown",
+ "ver_code": 2
+ },
+ {
+ "id": "account",
+ "ver_code": 1
+ },
+ {
+ "id": "synchronize",
+ "ver_code": 1
+ },
+ {
+ "id": "sunrise_sunset",
+ "ver_code": 1
+ },
+ {
+ "id": "cloud_connect",
+ "ver_code": 1
+ },
+ {
+ "id": "iot_cloud",
+ "ver_code": 1
+ },
+ {
+ "id": "frost_protection",
+ "ver_code": 1
+ },
+ {
+ "id": "child_protection",
+ "ver_code": 1
+ },
+ {
+ "id": "temperature",
+ "ver_code": 1
+ },
+ {
+ "id": "temp_control",
+ "ver_code": 1
+ },
+ {
+ "id": "remove_scale",
+ "ver_code": 1
+ },
+ {
+ "id": "shutdown_mode",
+ "ver_code": 1
+ },
+ {
+ "id": "progress_calibration",
+ "ver_code": 1
+ },
+ {
+ "id": "early_start",
+ "ver_code": 1
+ },
+ {
+ "id": "temp_record",
+ "ver_code": 1
+ },
+ {
+ "id": "screen_setting",
+ "ver_code": 1
+ },
+ {
+ "id": "night_mode",
+ "ver_code": 1
+ },
+ {
+ "id": "smart_control_schedule",
+ "ver_code": 1
+ },
+ {
+ "id": "firmware",
+ "ver_code": 1
+ },
+ {
+ "id": "battery_detect",
+ "ver_code": 1
+ },
+ {
+ "id": "temperature_correction",
+ "ver_code": 1
+ },
+ {
+ "id": "window_open_detect",
+ "ver_code": 2
+ }
+ ],
+ "device_id": "SCRUBBED_CHILD_DEVICE_ID_6"
+ },
+ {
+ "component_list": [
+ {
+ "id": "device",
+ "ver_code": 2
+ },
+ {
+ "id": "quick_setup",
+ "ver_code": 3
+ },
+ {
+ "id": "time",
+ "ver_code": 1
+ },
+ {
+ "id": "device_local_time",
+ "ver_code": 1
+ },
+ {
+ "id": "schedule",
+ "ver_code": 2
+ },
+ {
+ "id": "countdown",
+ "ver_code": 2
+ },
+ {
+ "id": "account",
+ "ver_code": 1
+ },
+ {
+ "id": "synchronize",
+ "ver_code": 1
+ },
+ {
+ "id": "sunrise_sunset",
+ "ver_code": 1
+ },
+ {
+ "id": "cloud_connect",
+ "ver_code": 1
+ },
+ {
+ "id": "iot_cloud",
+ "ver_code": 1
+ },
+ {
+ "id": "frost_protection",
+ "ver_code": 1
+ },
+ {
+ "id": "child_protection",
+ "ver_code": 1
+ },
+ {
+ "id": "temperature",
+ "ver_code": 1
+ },
+ {
+ "id": "temp_control",
+ "ver_code": 1
+ },
+ {
+ "id": "remove_scale",
+ "ver_code": 1
+ },
+ {
+ "id": "shutdown_mode",
+ "ver_code": 1
+ },
+ {
+ "id": "progress_calibration",
+ "ver_code": 1
+ },
+ {
+ "id": "early_start",
+ "ver_code": 1
+ },
+ {
+ "id": "temp_record",
+ "ver_code": 1
+ },
+ {
+ "id": "screen_setting",
+ "ver_code": 1
+ },
+ {
+ "id": "night_mode",
+ "ver_code": 1
+ },
+ {
+ "id": "smart_control_schedule",
+ "ver_code": 1
+ },
+ {
+ "id": "firmware",
+ "ver_code": 1
+ },
+ {
+ "id": "battery_detect",
+ "ver_code": 1
+ },
+ {
+ "id": "temperature_correction",
+ "ver_code": 1
+ },
+ {
+ "id": "window_open_detect",
+ "ver_code": 2
+ }
+ ],
+ "device_id": "SCRUBBED_CHILD_DEVICE_ID_7"
+ },
+ {
+ "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
+ }
+ ],
+ "device_id": "SCRUBBED_CHILD_DEVICE_ID_8"
+ },
+ {
+ "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
+ }
+ ],
+ "device_id": "SCRUBBED_CHILD_DEVICE_ID_9"
+ },
+ {
+ "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
+ }
+ ],
+ "device_id": "SCRUBBED_CHILD_DEVICE_ID_10"
+ }
+ ],
+ "start_index": 0,
+ "sum": 10
+ },
+ "get_child_device_list": {
+ "child_device_list": [
+ {
+ "at_low_battery": false,
+ "avatar": "kasa_trv",
+ "bind_count": 1,
+ "category": "subg.trv",
+ "child_protection": false,
+ "current_temp": 20.1,
+ "device_id": "SCRUBBED_CHILD_DEVICE_ID_3",
+ "frost_protection_on": false,
+ "fw_ver": "2.8.0 Build 240202 Rel.135229",
+ "hw_id": "00000000000000000000000000000000",
+ "hw_ver": "1.0",
+ "jamming_rssi": -117,
+ "jamming_signal_level": 1,
+ "location": "",
+ "mac": "F0A731000000",
+ "max_control_temp": 30,
+ "min_control_temp": 5,
+ "model": "KE100",
+ "nickname": "I01BU0tFRF9OQU1FIw==",
+ "oem_id": "00000000000000000000000000000000",
+ "parent_device_id": "0000000000000000000000000000000000000000",
+ "region": "Europe/London",
+ "rssi": -45,
+ "signal_level": 3,
+ "specs": "UK",
+ "status": "online",
+ "status_follow_edge": false,
+ "target_temp": 21.0,
+ "temp_offset": 0,
+ "temp_unit": "celsius",
+ "trv_states": [
+ "heating"
+ ],
+ "type": "SMART.KASAENERGY"
+ },
+ {
+ "at_low_battery": false,
+ "avatar": "kasa_trv",
+ "bind_count": 1,
+ "category": "subg.trv",
+ "child_protection": false,
+ "current_temp": 19.5,
+ "device_id": "SCRUBBED_CHILD_DEVICE_ID_4",
+ "frost_protection_on": false,
+ "fw_ver": "2.8.0 Build 240202 Rel.135229",
+ "hw_id": "00000000000000000000000000000000",
+ "hw_ver": "1.0",
+ "jamming_rssi": -117,
+ "jamming_signal_level": 1,
+ "location": "",
+ "mac": "F0A731000000",
+ "max_control_temp": 30,
+ "min_control_temp": 5,
+ "model": "KE100",
+ "nickname": "I01BU0tFRF9OQU1FIw==",
+ "oem_id": "00000000000000000000000000000000",
+ "parent_device_id": "0000000000000000000000000000000000000000",
+ "region": "Europe/London",
+ "rssi": -52,
+ "signal_level": 3,
+ "specs": "EU",
+ "status": "online",
+ "status_follow_edge": false,
+ "target_temp": 21.0,
+ "temp_offset": 0,
+ "temp_unit": "celsius",
+ "trv_states": [
+ "heating"
+ ],
+ "type": "SMART.KASAENERGY"
+ },
+ {
+ "at_low_battery": false,
+ "avatar": "kasa_trv",
+ "bind_count": 1,
+ "category": "subg.trv",
+ "child_protection": false,
+ "current_temp": 18.1,
+ "device_id": "SCRUBBED_CHILD_DEVICE_ID_5",
+ "frost_protection_on": false,
+ "fw_ver": "2.8.0 Build 240202 Rel.135229",
+ "hw_id": "00000000000000000000000000000000",
+ "hw_ver": "1.0",
+ "jamming_rssi": -120,
+ "jamming_signal_level": 1,
+ "location": "",
+ "mac": "F0A731000000",
+ "max_control_temp": 30,
+ "min_control_temp": 5,
+ "model": "KE100",
+ "nickname": "I01BU0tFRF9OQU1FIw==",
+ "oem_id": "00000000000000000000000000000000",
+ "parent_device_id": "0000000000000000000000000000000000000000",
+ "region": "Europe/London",
+ "rssi": -46,
+ "signal_level": 3,
+ "specs": "EU",
+ "status": "online",
+ "status_follow_edge": false,
+ "target_temp": 21.0,
+ "temp_offset": 0,
+ "temp_unit": "celsius",
+ "trv_states": [
+ "heating"
+ ],
+ "type": "SMART.KASAENERGY"
+ },
+ {
+ "at_low_battery": false,
+ "avatar": "kasa_trv",
+ "bind_count": 1,
+ "category": "subg.trv",
+ "child_protection": false,
+ "current_temp": 20.0,
+ "device_id": "SCRUBBED_CHILD_DEVICE_ID_6",
+ "frost_protection_on": false,
+ "fw_ver": "2.8.0 Build 240202 Rel.135229",
+ "hw_id": "00000000000000000000000000000000",
+ "hw_ver": "1.0",
+ "jamming_rssi": -114,
+ "jamming_signal_level": 1,
+ "location": "",
+ "mac": "A842A1000000",
+ "max_control_temp": 30,
+ "min_control_temp": 5,
+ "model": "KE100",
+ "nickname": "I01BU0tFRF9OQU1FIw==",
+ "oem_id": "00000000000000000000000000000000",
+ "parent_device_id": "0000000000000000000000000000000000000000",
+ "region": "Europe/London",
+ "rssi": -40,
+ "signal_level": 3,
+ "specs": "EU",
+ "status": "online",
+ "status_follow_edge": false,
+ "target_temp": 21.0,
+ "temp_offset": 0,
+ "temp_unit": "celsius",
+ "trv_states": [
+ "heating"
+ ],
+ "type": "SMART.KASAENERGY"
+ },
+ {
+ "at_low_battery": false,
+ "avatar": "kasa_trv",
+ "bind_count": 1,
+ "category": "subg.trv",
+ "child_protection": false,
+ "current_temp": 19.2,
+ "device_id": "SCRUBBED_CHILD_DEVICE_ID_7",
+ "frost_protection_on": false,
+ "fw_ver": "2.8.0 Build 240202 Rel.135229",
+ "hw_id": "00000000000000000000000000000000",
+ "hw_ver": "1.0",
+ "jamming_rssi": -121,
+ "jamming_signal_level": 1,
+ "location": "",
+ "mac": "F0A731000000",
+ "max_control_temp": 30,
+ "min_control_temp": 5,
+ "model": "KE100",
+ "nickname": "I01BU0tFRF9OQU1FIw==",
+ "oem_id": "00000000000000000000000000000000",
+ "parent_device_id": "0000000000000000000000000000000000000000",
+ "region": "Europe/London",
+ "rssi": -73,
+ "signal_level": 2,
+ "specs": "EU",
+ "status": "online",
+ "status_follow_edge": false,
+ "target_temp": 21.0,
+ "temp_offset": 0,
+ "temp_unit": "celsius",
+ "trv_states": [
+ "heating"
+ ],
+ "type": "SMART.KASAENERGY"
+ },
+ {
+ "at_low_battery": false,
+ "avatar": "balcony",
+ "bind_count": 1,
+ "category": "subg.trigger.temp-hmdt-sensor",
+ "current_humidity": 63,
+ "current_humidity_exception": 3,
+ "current_temp": 11.9,
+ "current_temp_exception": -8.1,
+ "device_id": "SCRUBBED_CHILD_DEVICE_ID_1",
+ "fw_ver": "1.5.0 Build 230105 Rel.150707",
+ "hw_id": "00000000000000000000000000000000",
+ "hw_ver": "1.0",
+ "jamming_rssi": -118,
+ "jamming_signal_level": 1,
+ "lastOnboardingTimestamp": 1713199738,
+ "mac": "40AE30000000",
+ "model": "T310",
+ "nickname": "I01BU0tFRF9OQU1FIw==",
+ "oem_id": "00000000000000000000000000000000",
+ "parent_device_id": "0000000000000000000000000000000000000000",
+ "region": "Europe/London",
+ "report_interval": 16,
+ "rssi": -63,
+ "signal_level": 3,
+ "specs": "EU",
+ "status": "online",
+ "status_follow_edge": false,
+ "temp_unit": "celsius",
+ "type": "SMART.TAPOSENSOR"
+ },
+ {
+ "at_low_battery": false,
+ "avatar": "sensor_t310",
+ "bind_count": 1,
+ "category": "subg.trigger.temp-hmdt-sensor",
+ "current_humidity": 54,
+ "current_humidity_exception": 0,
+ "current_temp": 19.1,
+ "current_temp_exception": -0.9,
+ "device_id": "SCRUBBED_CHILD_DEVICE_ID_2",
+ "fw_ver": "1.5.0 Build 230105 Rel.150707",
+ "hw_id": "00000000000000000000000000000000",
+ "hw_ver": "1.0",
+ "jamming_rssi": -123,
+ "jamming_signal_level": 1,
+ "lastOnboardingTimestamp": 1712755472,
+ "mac": "40AE30000000",
+ "model": "T310",
+ "nickname": "I01BU0tFRF9OQU1FIw==",
+ "oem_id": "00000000000000000000000000000000",
+ "parent_device_id": "0000000000000000000000000000000000000000",
+ "region": "Europe/London",
+ "report_interval": 16,
+ "rssi": -57,
+ "signal_level": 3,
+ "specs": "EU",
+ "status": "online",
+ "status_follow_edge": false,
+ "temp_unit": "celsius",
+ "type": "SMART.TAPOSENSOR"
+ },
+ {
+ "at_low_battery": false,
+ "avatar": "sensor_t310",
+ "bind_count": 1,
+ "category": "subg.trigger.temp-hmdt-sensor",
+ "current_humidity": 52,
+ "current_humidity_exception": 0,
+ "current_temp": 20.0,
+ "current_temp_exception": 0,
+ "device_id": "SCRUBBED_CHILD_DEVICE_ID_8",
+ "fw_ver": "1.5.0 Build 230105 Rel.150707",
+ "hw_id": "00000000000000000000000000000000",
+ "hw_ver": "1.0",
+ "jamming_rssi": -119,
+ "jamming_signal_level": 1,
+ "lastOnboardingTimestamp": 1706550338,
+ "mac": "E4FAC4000000",
+ "model": "T310",
+ "nickname": "I01BU0tFRF9OQU1FIw==",
+ "oem_id": "00000000000000000000000000000000",
+ "parent_device_id": "0000000000000000000000000000000000000000",
+ "region": "Europe/London",
+ "report_interval": 16,
+ "rssi": -68,
+ "signal_level": 3,
+ "specs": "EU",
+ "status": "online",
+ "status_follow_edge": false,
+ "temp_unit": "celsius",
+ "type": "SMART.TAPOSENSOR"
+ },
+ {
+ "at_low_battery": false,
+ "avatar": "sensor_t310",
+ "bind_count": 1,
+ "category": "subg.trigger.temp-hmdt-sensor",
+ "current_humidity": 60,
+ "current_humidity_exception": 0,
+ "current_temp": 20.1,
+ "current_temp_exception": 0.1,
+ "device_id": "SCRUBBED_CHILD_DEVICE_ID_9",
+ "fw_ver": "1.5.0 Build 230105 Rel.150707",
+ "hw_id": "00000000000000000000000000000000",
+ "hw_ver": "1.0",
+ "jamming_rssi": -116,
+ "jamming_signal_level": 1,
+ "lastOnboardingTimestamp": 1706551426,
+ "mac": "E4FAC4000000",
+ "model": "T310",
+ "nickname": "I01BU0tFRF9OQU1FIw==",
+ "oem_id": "00000000000000000000000000000000",
+ "parent_device_id": "0000000000000000000000000000000000000000",
+ "region": "Europe/London",
+ "report_interval": 16,
+ "rssi": -70,
+ "signal_level": 2,
+ "specs": "EU",
+ "status": "online",
+ "status_follow_edge": false,
+ "temp_unit": "celsius",
+ "type": "SMART.TAPOSENSOR"
+ },
+ {
+ "at_low_battery": false,
+ "avatar": "sensor_t310",
+ "bind_count": 1,
+ "category": "subg.trigger.temp-hmdt-sensor",
+ "current_humidity": 54,
+ "current_humidity_exception": 0,
+ "current_temp": 19.3,
+ "current_temp_exception": 0,
+ "device_id": "SCRUBBED_CHILD_DEVICE_ID_10",
+ "fw_ver": "1.5.0 Build 230105 Rel.150707",
+ "hw_id": "00000000000000000000000000000000",
+ "hw_ver": "1.0",
+ "jamming_rssi": -120,
+ "jamming_signal_level": 1,
+ "lastOnboardingTimestamp": 1706789728,
+ "mac": "E4FAC4000000",
+ "model": "T310",
+ "nickname": "I01BU0tFRF9OQU1FIw==",
+ "oem_id": "00000000000000000000000000000000",
+ "parent_device_id": "0000000000000000000000000000000000000000",
+ "region": "Europe/London",
+ "report_interval": 16,
+ "rssi": -81,
+ "signal_level": 1,
+ "specs": "EU",
+ "status": "online",
+ "status_follow_edge": false,
+ "temp_unit": "celsius",
+ "type": "SMART.TAPOSENSOR"
+ }
+ ],
+ "start_index": 0,
+ "sum": 10
+ },
+ "get_connect_cloud_state": {
+ "status": 0
+ },
+ "get_device_info": {
+ "avatar": "kasa_hub",
+ "device_id": "0000000000000000000000000000000000000000",
+ "fw_id": "00000000000000000000000000000000",
+ "fw_ver": "1.5.6 Build 240202 Rel.164142",
+ "has_set_location_info": true,
+ "hw_id": "00000000000000000000000000000000",
+ "hw_ver": "1.0",
+ "in_alarm": false,
+ "in_alarm_source": "",
+ "ip": "127.0.0.123",
+ "lang": "en_US",
+ "latitude": 0,
+ "longitude": 0,
+ "mac": "F0-A7-31-00-00-00",
+ "model": "KH100",
+ "nickname": "I01BU0tFRF9OQU1FIw==",
+ "oem_id": "00000000000000000000000000000000",
+ "overheated": false,
+ "region": "Europe/London",
+ "rssi": -37,
+ "signal_level": 3,
+ "specs": "UK",
+ "ssid": "I01BU0tFRF9TU0lEIw==",
+ "time_diff": 0,
+ "type": "SMART.KASAHUB"
+ },
+ "get_device_load_info": {
+ "cur_load_num": 24,
+ "load_level": "light",
+ "max_load_num": 64,
+ "total_memory": 4352,
+ "used_memory": 1581
+ },
+ "get_device_time": {
+ "region": "Europe/London",
+ "time_diff": 0,
+ "timestamp": 1713550228
+ },
+ "get_device_usage": {},
+ "get_fw_download_state": {
+ "auto_upgrade": false,
+ "download_progress": 0,
+ "reboot_time": 5,
+ "status": 0,
+ "upgrade_time": 5
+ },
+ "get_inherit_info": null,
+ "get_latest_fw": {
+ "fw_size": 0,
+ "fw_ver": "1.5.6 Build 240202 Rel.164142",
+ "hw_id": "",
+ "need_to_upgrade": false,
+ "oem_id": "",
+ "release_date": "",
+ "release_note": "",
+ "type": 0
+ },
+ "get_led_info": {
+ "led_rule": "always",
+ "led_status": true,
+ "night_mode": {
+ "end_time": 358,
+ "night_mode_type": "sunrise_sunset",
+ "start_time": 1210,
+ "sunrise_offset": 0,
+ "sunset_offset": 0
+ }
+ },
+ "get_support_alarm_type_list": {
+ "alarm_type_list": [
+ "Doorbell Ring 1",
+ "Doorbell Ring 2",
+ "Doorbell Ring 3",
+ "Doorbell Ring 4",
+ "Doorbell Ring 5",
+ "Doorbell Ring 6",
+ "Doorbell Ring 7",
+ "Doorbell Ring 8",
+ "Doorbell Ring 9",
+ "Doorbell Ring 10",
+ "Phone Ring",
+ "Alarm 1",
+ "Alarm 2",
+ "Alarm 3",
+ "Alarm 4",
+ "Dripping Tap",
+ "Alarm 5",
+ "Connection 1",
+ "Connection 2"
+ ]
+ },
+ "get_support_child_device_category": {
+ "device_category_list": [
+ {
+ "category": "subg.trv"
+ },
+ {
+ "category": "subg.trigger"
+ },
+ {
+ "category": "subg.plugswitch"
+ }
+ ]
+ },
+ "get_wireless_scan_info": {
+ "ap_list": [],
+ "start_index": 0,
+ "sum": 0,
+ "wep_supported": false
+ },
+ "qs_component_nego": {
+ "component_list": [
+ {
+ "id": "quick_setup",
+ "ver_code": 3
+ },
+ {
+ "id": "sunrise_sunset",
+ "ver_code": 1
+ },
+ {
+ "id": "iot_cloud",
+ "ver_code": 1
+ },
+ {
+ "id": "inherit",
+ "ver_code": 1
+ },
+ {
+ "id": "firmware",
+ "ver_code": 2
+ }
+ ],
+ "extra_info": {
+ "device_model": "KH100",
+ "device_type": "SMART.KASAHUB",
+ "is_klap": false
+ }
+ }
+}
diff --git a/kasa/tests/fixtures/smart/child/KE100(EU)_1.0_2.8.0.json b/kasa/tests/fixtures/smart/child/KE100(EU)_1.0_2.8.0.json
new file mode 100644
index 000000000..14bb10c97
--- /dev/null
+++ b/kasa/tests/fixtures/smart/child/KE100(EU)_1.0_2.8.0.json
@@ -0,0 +1,171 @@
+{
+ "component_nego": {
+ "component_list": [
+ {
+ "id": "device",
+ "ver_code": 2
+ },
+ {
+ "id": "quick_setup",
+ "ver_code": 3
+ },
+ {
+ "id": "time",
+ "ver_code": 1
+ },
+ {
+ "id": "device_local_time",
+ "ver_code": 1
+ },
+ {
+ "id": "schedule",
+ "ver_code": 2
+ },
+ {
+ "id": "countdown",
+ "ver_code": 2
+ },
+ {
+ "id": "account",
+ "ver_code": 1
+ },
+ {
+ "id": "synchronize",
+ "ver_code": 1
+ },
+ {
+ "id": "sunrise_sunset",
+ "ver_code": 1
+ },
+ {
+ "id": "cloud_connect",
+ "ver_code": 1
+ },
+ {
+ "id": "iot_cloud",
+ "ver_code": 1
+ },
+ {
+ "id": "frost_protection",
+ "ver_code": 1
+ },
+ {
+ "id": "child_protection",
+ "ver_code": 1
+ },
+ {
+ "id": "temperature",
+ "ver_code": 1
+ },
+ {
+ "id": "temp_control",
+ "ver_code": 1
+ },
+ {
+ "id": "remove_scale",
+ "ver_code": 1
+ },
+ {
+ "id": "shutdown_mode",
+ "ver_code": 1
+ },
+ {
+ "id": "progress_calibration",
+ "ver_code": 1
+ },
+ {
+ "id": "early_start",
+ "ver_code": 1
+ },
+ {
+ "id": "temp_record",
+ "ver_code": 1
+ },
+ {
+ "id": "screen_setting",
+ "ver_code": 1
+ },
+ {
+ "id": "night_mode",
+ "ver_code": 1
+ },
+ {
+ "id": "smart_control_schedule",
+ "ver_code": 1
+ },
+ {
+ "id": "firmware",
+ "ver_code": 1
+ },
+ {
+ "id": "battery_detect",
+ "ver_code": 1
+ },
+ {
+ "id": "temperature_correction",
+ "ver_code": 1
+ },
+ {
+ "id": "window_open_detect",
+ "ver_code": 2
+ }
+ ]
+ },
+ "get_connect_cloud_state": {
+ "status": 0
+ },
+ "get_device_info": {
+ "at_low_battery": false,
+ "avatar": "kasa_trv",
+ "battery_percentage": 100,
+ "bind_count": 1,
+ "category": "subg.trv",
+ "child_protection": false,
+ "current_temp": 19.2,
+ "device_id": "SCRUBBED_CHILD_DEVICE_ID_7",
+ "frost_protection_on": false,
+ "fw_ver": "2.8.0 Build 240202 Rel.135229",
+ "hw_id": "00000000000000000000000000000000",
+ "hw_ver": "1.0",
+ "jamming_rssi": -121,
+ "jamming_signal_level": 1,
+ "lastOnboardingTimestamp": 1705684116,
+ "location": "",
+ "mac": "F0A731000000",
+ "max_control_temp": 30,
+ "min_control_temp": 5,
+ "model": "KE100",
+ "nickname": "I01BU0tFRF9OQU1FIw==",
+ "oem_id": "00000000000000000000000000000000",
+ "parent_device_id": "0000000000000000000000000000000000000000",
+ "region": "Europe/London",
+ "rssi": -73,
+ "signal_level": 2,
+ "specs": "EU",
+ "status": "online",
+ "target_temp": 21.0,
+ "temp_offset": 0,
+ "temp_unit": "celsius",
+ "trv_states": [
+ "heating"
+ ],
+ "type": "SMART.KASAENERGY"
+ },
+ "get_fw_download_state": {
+ "cloud_cache_seconds": 1,
+ "download_progress": 0,
+ "reboot_time": 5,
+ "status": 0,
+ "upgrade_time": 5
+ },
+ "get_latest_fw": {
+ "fw_size": 0,
+ "fw_ver": "2.8.0 Build 240202 Rel.135229",
+ "hw_id": "",
+ "need_to_upgrade": false,
+ "oem_id": "",
+ "release_date": "",
+ "release_note": "",
+ "type": 0
+ }
+}
diff --git a/kasa/tests/fixtures/smart/child/KE100(UK)_1.0_2.8.0.json b/kasa/tests/fixtures/smart/child/KE100(UK)_1.0_2.8.0.json
new file mode 100644
index 000000000..199d572a6
--- /dev/null
+++ b/kasa/tests/fixtures/smart/child/KE100(UK)_1.0_2.8.0.json
@@ -0,0 +1,171 @@
+{
+ "component_nego": {
+ "component_list": [
+ {
+ "id": "device",
+ "ver_code": 2
+ },
+ {
+ "id": "quick_setup",
+ "ver_code": 3
+ },
+ {
+ "id": "time",
+ "ver_code": 1
+ },
+ {
+ "id": "device_local_time",
+ "ver_code": 1
+ },
+ {
+ "id": "schedule",
+ "ver_code": 2
+ },
+ {
+ "id": "countdown",
+ "ver_code": 2
+ },
+ {
+ "id": "account",
+ "ver_code": 1
+ },
+ {
+ "id": "synchronize",
+ "ver_code": 1
+ },
+ {
+ "id": "sunrise_sunset",
+ "ver_code": 1
+ },
+ {
+ "id": "cloud_connect",
+ "ver_code": 1
+ },
+ {
+ "id": "iot_cloud",
+ "ver_code": 1
+ },
+ {
+ "id": "frost_protection",
+ "ver_code": 1
+ },
+ {
+ "id": "child_protection",
+ "ver_code": 1
+ },
+ {
+ "id": "temperature",
+ "ver_code": 1
+ },
+ {
+ "id": "temp_control",
+ "ver_code": 1
+ },
+ {
+ "id": "remove_scale",
+ "ver_code": 1
+ },
+ {
+ "id": "shutdown_mode",
+ "ver_code": 1
+ },
+ {
+ "id": "progress_calibration",
+ "ver_code": 1
+ },
+ {
+ "id": "early_start",
+ "ver_code": 1
+ },
+ {
+ "id": "temp_record",
+ "ver_code": 1
+ },
+ {
+ "id": "screen_setting",
+ "ver_code": 1
+ },
+ {
+ "id": "night_mode",
+ "ver_code": 1
+ },
+ {
+ "id": "smart_control_schedule",
+ "ver_code": 1
+ },
+ {
+ "id": "firmware",
+ "ver_code": 1
+ },
+ {
+ "id": "battery_detect",
+ "ver_code": 1
+ },
+ {
+ "id": "temperature_correction",
+ "ver_code": 1
+ },
+ {
+ "id": "window_open_detect",
+ "ver_code": 2
+ }
+ ]
+ },
+ "get_connect_cloud_state": {
+ "status": 0
+ },
+ "get_device_info": {
+ "at_low_battery": false,
+ "avatar": "kasa_trv",
+ "battery_percentage": 100,
+ "bind_count": 1,
+ "category": "subg.trv",
+ "child_protection": false,
+ "current_temp": 20.1,
+ "device_id": "SCRUBBED_CHILD_DEVICE_ID_3",
+ "frost_protection_on": false,
+ "fw_ver": "2.8.0 Build 240202 Rel.135229",
+ "hw_id": "00000000000000000000000000000000",
+ "hw_ver": "1.0",
+ "jamming_rssi": -117,
+ "jamming_signal_level": 1,
+ "lastOnboardingTimestamp": 1705677078,
+ "location": "",
+ "mac": "F0A731000000",
+ "max_control_temp": 30,
+ "min_control_temp": 5,
+ "model": "KE100",
+ "nickname": "I01BU0tFRF9OQU1FIw==",
+ "oem_id": "00000000000000000000000000000000",
+ "parent_device_id": "0000000000000000000000000000000000000000",
+ "region": "Europe/London",
+ "rssi": -45,
+ "signal_level": 3,
+ "specs": "UK",
+ "status": "online",
+ "target_temp": 21.0,
+ "temp_offset": 0,
+ "temp_unit": "celsius",
+ "trv_states": [
+ "heating"
+ ],
+ "type": "SMART.KASAENERGY"
+ },
+ "get_fw_download_state": {
+ "cloud_cache_seconds": 1,
+ "download_progress": 0,
+ "reboot_time": 5,
+ "status": 0,
+ "upgrade_time": 5
+ },
+ "get_latest_fw": {
+ "fw_size": 0,
+ "fw_ver": "2.8.0 Build 240202 Rel.135229",
+ "hw_id": "",
+ "need_to_upgrade": false,
+ "oem_id": "",
+ "release_date": "",
+ "release_note": "",
+ "type": 0
+ }
+}
diff --git a/kasa/tests/fixtures/smart/child/T310(EU)_1.0_1.5.0.json b/kasa/tests/fixtures/smart/child/T310(EU)_1.0_1.5.0.json
new file mode 100644
index 000000000..d48875e5f
--- /dev/null
+++ b/kasa/tests/fixtures/smart/child/T310(EU)_1.0_1.5.0.json
@@ -0,0 +1,530 @@
+{
+ "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": "sensor_t310",
+ "bind_count": 1,
+ "category": "subg.trigger.temp-hmdt-sensor",
+ "current_humidity": 54,
+ "current_humidity_exception": 0,
+ "current_temp": 19.3,
+ "current_temp_exception": 0,
+ "device_id": "SCRUBBED_CHILD_DEVICE_ID_10",
+ "fw_ver": "1.5.0 Build 230105 Rel.150707",
+ "hw_id": "00000000000000000000000000000000",
+ "hw_ver": "1.0",
+ "jamming_rssi": -120,
+ "jamming_signal_level": 1,
+ "lastOnboardingTimestamp": 1706789728,
+ "mac": "E4FAC4000000",
+ "model": "T310",
+ "nickname": "I01BU0tFRF9OQU1FIw==",
+ "oem_id": "00000000000000000000000000000000",
+ "parent_device_id": "0000000000000000000000000000000000000000",
+ "region": "Europe/London",
+ "report_interval": 16,
+ "rssi": -81,
+ "signal_level": 1,
+ "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_size": 0,
+ "fw_ver": "1.5.0 Build 230105 Rel.150707",
+ "hw_id": "",
+ "need_to_upgrade": false,
+ "oem_id": "",
+ "release_date": "",
+ "release_note": "",
+ "type": 0
+ },
+ "get_temp_humidity_records": {
+ "local_time": 1713550233,
+ "past24h_humidity": [
+ 60,
+ 60,
+ 60,
+ 60,
+ 60,
+ 60,
+ 60,
+ 60,
+ 60,
+ 61,
+ 61,
+ 61,
+ 61,
+ 61,
+ 61,
+ 61,
+ 61,
+ 61,
+ 61,
+ 61,
+ 61,
+ 62,
+ 61,
+ 61,
+ 62,
+ 61,
+ 60,
+ 61,
+ 61,
+ 61,
+ 61,
+ 61,
+ 61,
+ 61,
+ 61,
+ 61,
+ 61,
+ 62,
+ 62,
+ 62,
+ 62,
+ 62,
+ 62,
+ 62,
+ 62,
+ 62,
+ 62,
+ 62,
+ 62,
+ 62,
+ 62,
+ 63,
+ 63,
+ 63,
+ 64,
+ 63,
+ 63,
+ 63,
+ 63,
+ 62,
+ 63,
+ 63,
+ 62,
+ 62,
+ 62,
+ 62,
+ 62,
+ 61,
+ 62,
+ 61,
+ 61,
+ 61,
+ 61,
+ 61,
+ 61,
+ 60,
+ 61,
+ 64,
+ 64,
+ 61,
+ 61,
+ 63,
+ 60,
+ 60,
+ 60,
+ 60,
+ 59,
+ 59,
+ 59,
+ 59,
+ 59,
+ 58,
+ 58,
+ 58,
+ 57,
+ 55
+ ],
+ "past24h_humidity_exception": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 2,
+ 1,
+ 1,
+ 2,
+ 1,
+ 0,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 2,
+ 2,
+ 2,
+ 2,
+ 2,
+ 2,
+ 2,
+ 2,
+ 2,
+ 2,
+ 2,
+ 2,
+ 2,
+ 2,
+ 3,
+ 3,
+ 3,
+ 4,
+ 3,
+ 3,
+ 3,
+ 3,
+ 2,
+ 3,
+ 3,
+ 2,
+ 2,
+ 2,
+ 2,
+ 2,
+ 1,
+ 2,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 0,
+ 1,
+ 4,
+ 4,
+ 1,
+ 1,
+ 3,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "past24h_temp": [
+ 175,
+ 175,
+ 174,
+ 174,
+ 173,
+ 172,
+ 172,
+ 171,
+ 170,
+ 169,
+ 169,
+ 167,
+ 167,
+ 166,
+ 165,
+ 164,
+ 163,
+ 163,
+ 162,
+ 162,
+ 162,
+ 162,
+ 163,
+ 163,
+ 162,
+ 162,
+ 161,
+ 160,
+ 159,
+ 159,
+ 159,
+ 159,
+ 158,
+ 158,
+ 159,
+ 159,
+ 158,
+ 159,
+ 159,
+ 159,
+ 159,
+ 159,
+ 159,
+ 159,
+ 159,
+ 159,
+ 158,
+ 158,
+ 158,
+ 158,
+ 158,
+ 158,
+ 159,
+ 159,
+ 160,
+ 161,
+ 161,
+ 162,
+ 162,
+ 162,
+ 162,
+ 162,
+ 163,
+ 163,
+ 166,
+ 168,
+ 170,
+ 172,
+ 174,
+ 175,
+ 176,
+ 177,
+ 179,
+ 181,
+ 183,
+ 184,
+ 185,
+ 187,
+ 189,
+ 190,
+ 190,
+ 193,
+ 194,
+ 194,
+ 194,
+ 194,
+ 194,
+ 194,
+ 195,
+ 195,
+ 195,
+ 196,
+ 196,
+ 196,
+ 195,
+ 193
+ ],
+ "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,
+ -1,
+ -1,
+ -1,
+ -1,
+ -2,
+ -2,
+ -1,
+ -1,
+ -2,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -1,
+ -2,
+ -2,
+ -2,
+ -2,
+ -2,
+ -2,
+ -1,
+ -1,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ],
+ "temp_unit": "celsius"
+ },
+ "get_trigger_logs": {
+ "logs": [],
+ "start_id": 0,
+ "sum": 0
+ }
+}
diff --git a/kasa/tests/smart/modules/test_temperature.py b/kasa/tests/smart/modules/test_temperature.py
index 3b9ab50e2..a7d20dac6 100644
--- a/kasa/tests/smart/modules/test_temperature.py
+++ b/kasa/tests/smart/modules/test_temperature.py
@@ -7,13 +7,18 @@
"has temperature", component_filter="temperature", protocol_filter={"SMART.CHILD"}
)
+temperature_warning = parametrize(
+ "has temperature warning",
+ component_filter="comfort_temperature",
+ protocol_filter={"SMART.CHILD"},
+)
+
@temperature
@pytest.mark.parametrize(
"feature, type",
[
("temperature", float),
- ("temperature_warning", bool),
("temperature_unit", str),
],
)
@@ -27,3 +32,16 @@ async def test_temperature_features(dev, feature, type):
feat = temp_module._module_features[feature]
assert feat.value == prop
assert isinstance(feat.value, type)
+
+
+@temperature_warning
+async def test_temperature_warning(dev):
+ """Test that features are registered and work as expected."""
+ temp_module: TemperatureSensor = dev.modules["TemperatureSensor"]
+
+ assert hasattr(temp_module, "temperature_warning")
+ assert isinstance(temp_module.temperature_warning, bool)
+
+ feat = temp_module._module_features["temperature_warning"]
+ assert feat.value == temp_module.temperature_warning
+ assert isinstance(feat.value, bool)
diff --git a/kasa/tests/smart/modules/test_temperaturecontrol.py b/kasa/tests/smart/modules/test_temperaturecontrol.py
index 5768a4820..5f6e3b56e 100644
--- a/kasa/tests/smart/modules/test_temperaturecontrol.py
+++ b/kasa/tests/smart/modules/test_temperaturecontrol.py
@@ -1,7 +1,7 @@
import pytest
from kasa.smart.modules import TemperatureSensor
-from kasa.tests.device_fixtures import parametrize
+from kasa.tests.device_fixtures import parametrize, thermostats_smart
temperature = parametrize(
"has temperature control",
@@ -10,11 +10,11 @@
)
-@temperature
+@thermostats_smart
@pytest.mark.parametrize(
"feature, type",
[
- ("target_temperature", int),
+ ("target_temperature", float),
("temperature_offset", int),
],
)