From cba073ebde251d5f3e6eda342e31758f46981cb0 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Wed, 24 Jan 2024 21:54:56 -1000 Subject: [PATCH] Add support for tapo wall switches (S500D) (#704) * Add support for the S500D * tweak * Update README.md --- README.md | 4 + kasa/device_factory.py | 1 + kasa/deviceconfig.py | 1 + kasa/tests/conftest.py | 9 +- .../fixtures/smart/S500D(US)_1.0_1.0.5.json | 317 ++++++++++++++++++ 5 files changed, 331 insertions(+), 1 deletion(-) create mode 100644 kasa/tests/fixtures/smart/S500D(US)_1.0_1.0.5.json diff --git a/README.md b/README.md index d4cebe48..0300677f 100644 --- a/README.md +++ b/README.md @@ -298,6 +298,10 @@ At the moment, the following devices have been confirmed to work: * Tapo L920-5 * Tapo L930-5 +#### Wall switches + +* Tapo S500D + ### Newer Kasa branded devices Some newer hardware versions of Kasa branded devices are now using the same protocol as diff --git a/kasa/device_factory.py b/kasa/device_factory.py index 83db093f..d216e0ef 100755 --- a/kasa/device_factory.py +++ b/kasa/device_factory.py @@ -131,6 +131,7 @@ def get_device_class_from_family(device_type: str) -> Optional[Type[SmartDevice] supported_device_types: Dict[str, Type[SmartDevice]] = { "SMART.TAPOPLUG": TapoPlug, "SMART.TAPOBULB": TapoBulb, + "SMART.TAPOSWITCH": TapoBulb, "SMART.KASAPLUG": TapoPlug, "SMART.KASASWITCH": TapoBulb, "IOT.SMARTPLUGSWITCH": SmartPlug, diff --git a/kasa/deviceconfig.py b/kasa/deviceconfig.py index 58d33661..77ce6df4 100644 --- a/kasa/deviceconfig.py +++ b/kasa/deviceconfig.py @@ -30,6 +30,7 @@ class DeviceFamilyType(Enum): SmartKasaSwitch = "SMART.KASASWITCH" SmartTapoPlug = "SMART.TAPOPLUG" SmartTapoBulb = "SMART.TAPOBULB" + SmartTapoSwitch = "SMART.TAPOSWITCH" def _dataclass_from_dict(klass, in_val): diff --git a/kasa/tests/conftest.py b/kasa/tests/conftest.py index c043b18c..eb7b53f3 100644 --- a/kasa/tests/conftest.py +++ b/kasa/tests/conftest.py @@ -111,7 +111,7 @@ STRIPS_SMART: Set[str] = set() STRIPS = {*STRIPS_IOT, *STRIPS_SMART} DIMMERS_IOT = {"ES20M", "HS220", "KS220M", "KS230", "KP405"} -DIMMERS_SMART: Set[str] = set() +DIMMERS_SMART = {"S500D"} DIMMERS = { *DIMMERS_IOT, *DIMMERS_SMART, @@ -240,6 +240,9 @@ bulb_iot = parametrize("bulb devices iot", BULBS_IOT, protocol_filter={"IOT"}) plug_smart = parametrize("plug devices smart", PLUGS_SMART, protocol_filter={"SMART"}) bulb_smart = parametrize("bulb devices smart", BULBS_SMART, protocol_filter={"SMART"}) +dimmers_smart = parametrize( + "dimmer devices smart", DIMMERS_SMART, protocol_filter={"SMART"} +) device_smart = parametrize( "devices smart", ALL_DEVICES_SMART, protocol_filter={"SMART"} ) @@ -300,6 +303,7 @@ def check_categories(): + lightstrip.args[1] + plug_smart.args[1] + bulb_smart.args[1] + + dimmers_smart.args[1] ) diff = set(SUPPORTED_DEVICES) - set(categorized_fixtures) if diff: @@ -331,6 +335,9 @@ def device_for_file(model, protocol): for d in BULBS_SMART: if d in model: return TapoBulb + for d in DIMMERS_SMART: + if d in model: + return TapoBulb else: for d in STRIPS_IOT: if d in model: diff --git a/kasa/tests/fixtures/smart/S500D(US)_1.0_1.0.5.json b/kasa/tests/fixtures/smart/S500D(US)_1.0_1.0.5.json new file mode 100644 index 00000000..a141e700 --- /dev/null +++ b/kasa/tests/fixtures/smart/S500D(US)_1.0_1.0.5.json @@ -0,0 +1,317 @@ +{ + "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": "schedule", + "ver_code": 2 + }, + { + "id": "countdown", + "ver_code": 2 + }, + { + "id": "antitheft", + "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": "device_local_time", + "ver_code": 1 + }, + { + "id": "default_states", + "ver_code": 1 + }, + { + "id": "brightness", + "ver_code": 1 + }, + { + "id": "preset", + "ver_code": 1 + }, + { + "id": "on_off_gradually", + "ver_code": 2 + }, + { + "id": "dimmer_calibration", + "ver_code": 1 + }, + { + "id": "overheat_protection", + "ver_code": 1 + } + ] + }, + "discovery_result": { + "device_id": "00000000000000000000000000000000", + "device_model": "S500D(US)", + "device_type": "SMART.TAPOSWITCH", + "factory_default": false, + "ip": "127.0.0.123", + "is_support_iot_cloud": true, + "mac": "48-22-54-00-00-00", + "mgt_encrypt_schm": { + "encrypt_type": "AES", + "http_port": 80, + "is_support_https": false, + "lv": 2 + }, + "obd_src": "tplink", + "owner": "00000000000000000000000000000000" + }, + "get_antitheft_rules": { + "antitheft_rule_max_count": 1, + "enable": false, + "rule_list": [] + }, + "get_auto_update_info": { + "enable": false, + "random_range": 120, + "time": 180 + }, + "get_connect_cloud_state": { + "status": 0 + }, + "get_countdown_rules": { + "countdown_rule_max_count": 1, + "enable": false, + "rule_list": [] + }, + "get_device_info": { + "avatar": "switch_s500d", + "brightness": 46, + "default_states": { + "type": "last_states" + }, + "device_id": "0000000000000000000000000000000000000000", + "device_on": false, + "fw_id": "00000000000000000000000000000000", + "fw_ver": "1.0.5 Build 221014 Rel.112003", + "has_set_location_info": true, + "hw_id": "00000000000000000000000000000000", + "hw_ver": "1.0", + "ip": "127.0.0.123", + "lang": "en_US", + "latitude": 0, + "longitude": 0, + "mac": "48-22-54-00-00-00", + "model": "S500D", + "nickname": "I01BU0tFRF9OQU1FIw==", + "oem_id": "00000000000000000000000000000000", + "on_time": 0, + "overheat_status": "normal", + "region": "Pacific/Honolulu", + "rssi": -31, + "signal_level": 3, + "specs": "", + "ssid": "I01BU0tFRF9TU0lEIw==", + "time_diff": -600, + "type": "SMART.TAPOSWITCH" + }, + "get_device_time": { + "region": "Pacific/Honolulu", + "time_diff": -600, + "timestamp": 1706136515 + }, + "get_device_usage": { + "time_usage": { + "past30": 0, + "past7": 0, + "today": 0 + } + }, + "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": 786432, + "fw_ver": "1.1.0 Build 230906 Rel.141935", + "hw_id": "00000000000000000000000000000000", + "need_to_upgrade": true, + "oem_id": "00000000000000000000000000000000", + "release_date": "2023-10-07", + "release_note": "Modifications and Bug Fixes:\n1. Enhanced stability and performance.\n2. Enhanced local communication security.", + "type": 2 + }, + "get_led_info": { + "led_rule": "always", + "led_status": true, + "night_mode": { + "end_time": 426, + "night_mode_type": "sunrise_sunset", + "start_time": 1093, + "sunrise_offset": 0, + "sunset_offset": 0 + } + }, + "get_next_event": {}, + "get_on_off_gradually_info": { + "off_state": { + "duration": 2, + "enable": true + }, + "on_state": { + "duration": 3, + "enable": true + } + }, + "get_preset_rules": { + "brightness": [ + 100, + 75, + 50, + 25, + 1 + ] + }, + "get_schedule_rules": { + "enable": false, + "rule_list": [], + "schedule_rule_max_count": 32, + "start_index": 0, + "sum": 0 + }, + "get_wireless_scan_info": { + "ap_list": [ + { + "bssid": "000000000000", + "channel": 0, + "cipher_type": 2, + "key_type": "wpa_psk", + "signal_level": 3, + "ssid": "I01BU0tFRF9TU0lEIw==" + }, + { + "bssid": "000000000000", + "channel": 0, + "cipher_type": 2, + "key_type": "wpa_psk", + "signal_level": 2, + "ssid": "I01BU0tFRF9TU0lEIw==" + }, + { + "bssid": "000000000000", + "channel": 0, + "cipher_type": 2, + "key_type": "wpa_psk", + "signal_level": 2, + "ssid": "I01BU0tFRF9TU0lEIw==" + }, + { + "bssid": "000000000000", + "channel": 0, + "cipher_type": 2, + "key_type": "wpa_psk", + "signal_level": 1, + "ssid": "I01BU0tFRF9TU0lEIw==" + }, + { + "bssid": "000000000000", + "channel": 0, + "cipher_type": 2, + "key_type": "wpa_psk", + "signal_level": 1, + "ssid": "I01BU0tFRF9TU0lEIw==" + }, + { + "bssid": "000000000000", + "channel": 0, + "cipher_type": 2, + "key_type": "wpa_psk", + "signal_level": 1, + "ssid": "I01BU0tFRF9TU0lEIw==" + }, + { + "bssid": "000000000000", + "channel": 0, + "cipher_type": 2, + "key_type": "wpa_psk", + "signal_level": 1, + "ssid": "I01BU0tFRF9TU0lEIw==" + } + ], + "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": "S500D", + "device_type": "SMART.TAPOSWITCH" + } + } +}