From 81243ed87f1c1eb1fafce8ace9473743be3d140d Mon Sep 17 00:00:00 2001 From: michael-bohr Date: Sat, 31 Oct 2026 19:48:36 -0400 Subject: [PATCH] Extend KL400 ct range to 2500-900 + add KL400L10(US) fixture (#1819) --- SUPPORTED.md | 1 + kasa/iot/iotbulb.py | 2 +- tests/device_fixtures.py | 7 +- .../fixtures/iot/KL400L10(US)_1.0_1.0.11.json | 168 ++++++++++++++++++ tests/iot/test_iotbulb.py | 11 ++ 5 files changed, 185 insertions(+), 4 deletions(-) create mode 100644 tests/fixtures/iot/KL400L10(US)_1.0_1.0.11.json diff --git a/SUPPORTED.md b/SUPPORTED.md index 34a5ceae..552b4e5c 100644 --- a/SUPPORTED.md +++ b/SUPPORTED.md @@ -171,6 +171,7 @@ Some newer Kasa devices require authentication. These are marked with [^1] in th - **KL400L10** - Hardware: 1.0 (US) / Firmware: 1.0.10 + - Hardware: 1.0 (US) / Firmware: 1.0.11 - **KL400L5** - Hardware: 1.0 (US) / Firmware: 1.0.11 - Hardware: 1.0 (US) / Firmware: 1.0.5 diff --git a/kasa/iot/iotbulb.py b/kasa/iot/iotbulb.py index b7f06f6a..8be72d26 100644 --- a/kasa/iot/iotbulb.py +++ b/kasa/iot/iotbulb.py @@ -90,7 +90,7 @@ TPLINK_KELVIN = { "KL135": ColorTempRange(2500, 9000), r"KL120\(EU\)": ColorTempRange(2700, 6500), r"KL120\(US\)": ColorTempRange(2700, 5000), - r"KL400L5": ColorTempRange(2500, 9000), + r"KL400": ColorTempRange(2500, 9000), r"KL420": ColorTempRange(2500, 9000), r"KL430": ColorTempRange(2500, 9000), } diff --git a/tests/device_fixtures.py b/tests/device_fixtures.py index 32f75049..ffda9639 100644 --- a/tests/device_fixtures.py +++ b/tests/device_fixtures.py @@ -55,11 +55,12 @@ BULBS_IOT_VARIABLE_TEMP = { "KL135", "KL430", } -# KL400L5 firmware 1.0.5/1.0.8 and KL420L5 firmware 1.0.2 fixtures report no -# variable color temperature support, so match the supporting fixtures rather -# than the entire model. +# KL400L5 firmware 1.0.5/1.0.8, KL400L10 firmware 1.0.10 and KL420L5 firmware +# 1.0.2 fixtures report no variable color temperature support, so match the +# supporting fixtures rather than the entire model. BULBS_IOT_VARIABLE_TEMP_FIXTURES = { "KL400L5(US)_1.0_1.0.11", + "KL400L10(US)_1.0_1.0.11", "KL420L5(US)_1.0_1.0.7", } BULBS_IOT_COLOR = {"LB130", "KL125", "KL130", "KL135", *BULBS_IOT_LIGHT_STRIP} diff --git a/tests/fixtures/iot/KL400L10(US)_1.0_1.0.11.json b/tests/fixtures/iot/KL400L10(US)_1.0_1.0.11.json new file mode 100644 index 00000000..fe9caee3 --- /dev/null +++ b/tests/fixtures/iot/KL400L10(US)_1.0_1.0.11.json @@ -0,0 +1,168 @@ +{ + "smartlife.iot.common.cloud": { + "get_info": { + "binded": 1, + "cld_connection": 0, + "err_code": 0, + "fwDlPage": "", + "fwNotifyType": -1, + "illegalType": 0, + "server": "n-devs.tplinkcloud.com", + "stopConnect": 0, + "tcspInfo": "", + "tcspStatus": 1, + "username": "user@example.com" + }, + "get_intl_fw_list": { + "err_code": -4001, + "err_msg": "no reply from server" + } + }, + "smartlife.iot.common.emeter": { + "get_realtime": { + "err_code": 0, + "power_mw": 2450, + "total_wh": 2 + } + }, + "smartlife.iot.common.schedule": { + "get_next_action": { + "err_code": 0, + "type": -1 + }, + "get_rules": { + "enable": 0, + "err_code": 0, + "rule_list": [], + "version": 2 + } + }, + "smartlife.iot.lightStrip": { + "get_default_behavior": { + "err_code": 0, + "hard_on": { + "mode": "last_status" + }, + "soft_on": { + "mode": "last_status" + } + }, + "get_light_details": { + "color_rendering_index": 90, + "err_code": 0, + "incandescent_equivalent": 60, + "lamp_beam_angle": 220, + "max_lumens": 800, + "max_voltage": 120, + "min_voltage": 100, + "wattage": 10 + }, + "get_light_state": { + "err_code": 0, + "groups": [ + [ + 0, + 0, + 12, + 100, + 15, + 0 + ] + ], + "length": 1, + "mode": "normal", + "on_off": 1, + "transition": 1000 + } + }, + "system": { + "get_sysinfo": { + "LEF": 0, + "active_mode": "none", + "alias": "#MASKED_NAME#", + "ctrl_protocols": { + "name": "Linkie", + "version": "1.0" + }, + "description": "Kasa Smart Light Strip, Multicolor", + "dev_state": "normal", + "deviceId": "0000000000000000000000000000000000000000", + "disco_ver": "1.0", + "err_code": 0, + "hwId": "00000000000000000000000000000000", + "hw_ver": "1.0", + "is_color": 1, + "is_dimmable": 1, + "is_factory": false, + "is_variable_color_temp": 1, + "latitude_i": 0, + "length": 1, + "light_state": { + "brightness": 15, + "color_temp": 0, + "hue": 12, + "mode": "normal", + "on_off": 1, + "saturation": 100 + }, + "lighting_effect_state": { + "brightness": 80, + "custom": 0, + "enable": 0, + "id": "ojqpUUxdGHoIugGPknrUcRoyJiItsjuE", + "name": "Lightning" + }, + "longitude_i": 0, + "mic_mac": "D8:44:89:00:00:00", + "mic_type": "IOT.SMARTBULB", + "model": "KL400L10(US)", + "obd_src": "tplink", + "oemId": "00000000000000000000000000000000", + "preferred_state": [ + { + "brightness": 100, + "color_temp": 0, + "hue": 1, + "index": 0, + "mode": 1, + "saturation": 100 + }, + { + "brightness": 15, + "color_temp": 0, + "hue": 251, + "index": 1, + "mode": 1, + "saturation": 0 + }, + { + "brightness": 50, + "color_temp": 0, + "hue": 0, + "index": 2, + "mode": 1, + "saturation": 100 + }, + { + "brightness": 50, + "color_temp": 0, + "hue": 120, + "index": 3, + "mode": 1, + "saturation": 100 + }, + { + "brightness": 50, + "color_temp": 0, + "hue": 277, + "index": 4, + "mode": 1, + "saturation": 86 + } + ], + "rssi": -46, + "status": "new", + "sw_ver": "1.0.11 Build 240809 Rel.173811" + } + } +} diff --git a/tests/iot/test_iotbulb.py b/tests/iot/test_iotbulb.py index 870efe20..828b2337 100644 --- a/tests/iot/test_iotbulb.py +++ b/tests/iot/test_iotbulb.py @@ -102,6 +102,17 @@ async def test_unknown_temp_range( assert "Unknown color temperature range, fallback to 2700-5000" in caplog.text +@variable_temp_iot +@pytest.mark.xdist_group(name="caplog") +async def test_known_temp_range(dev: IotBulb, caplog: pytest.LogCaptureFixture) -> None: + light = dev.modules.get(Module.Light) + assert light + color_temp_feat = light.get_feature("color_temp") + assert color_temp_feat + assert color_temp_feat.range + assert "Unknown color temperature range" not in caplog.text + + @dimmable_iot @turn_on async def test_dimmable_brightness(dev: IotBulb, turn_on: bool) -> None: