Przeglądaj źródła

Add support for S20 Vacuum (#411)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: J. Nick Koston <nick@koston.org>
Retha Runolfsson 21 godzin temu
rodzic
commit
8a98883397

+ 6 - 0
switchbot/adv_parser.py

@@ -384,6 +384,12 @@ SUPPORTED_TYPES: dict[str | bytes, SwitchbotSupportedType] = {
         "func": process_smart_thermostat_radiator,
         "manufacturer_id": 2409,
     },
+    b"\x00\x10\xe0P": {
+        "modelName": SwitchbotModel.S20_VACUUM,
+        "modelFriendlyName": "S20 Vacuum",
+        "func": process_vacuum,
+        "manufacturer_id": 2409,
+    },
 }
 
 _SWITCHBOT_MODEL_TO_CHAR = {

+ 13 - 2
switchbot/adv_parsers/vacuum.py

@@ -2,8 +2,11 @@
 
 from __future__ import annotations
 
+import logging
 import struct
 
+_LOGGER = logging.getLogger(__name__)
+
 
 def process_vacuum(
     data: bytes | None, mfr_data: bytes | None
@@ -20,7 +23,7 @@ def process_vacuum(
     _battery = mfr_data[12]
     _work_status = mfr_data[13] & 0b00111111
 
-    return {
+    result = {
         "sequence_number": _seq_num,
         "soc_version": _soc_version,
         "step": _step,
@@ -29,6 +32,10 @@ def process_vacuum(
         "work_status": _work_status,
     }
 
+    _LOGGER.debug("Processed Vacuum data: %s, result: %s", data, result)
+
+    return result
+
 
 def get_device_fw_version(version_bytes: bytes) -> str | None:
     version1 = version_bytes[0] & 0x0F
@@ -51,7 +58,7 @@ def process_vacuum_k(
     _work_status = (mfr_data[7] & 0b00010000) >> 4
     _battery = mfr_data[8] & 0b01111111
 
-    return {
+    result = {
         "sequence_number": _seq_num,
         "dustbin_bound": _dustbin_bound,
         "dusbin_connected": _dusbin_connected,
@@ -59,3 +66,7 @@ def process_vacuum_k(
         "work_status": _work_status,
         "battery": _battery,
     }
+
+    _LOGGER.debug("Processed Vacuum K data: %s, result: %s", data, result)
+
+    return result

+ 1 - 0
switchbot/const/__init__.py

@@ -100,6 +100,7 @@ class SwitchbotModel(StrEnum):
     K11_VACUUM = "K11+ Vacuum"
     CLIMATE_PANEL = "Climate Panel"
     SMART_THERMOSTAT_RADIATOR = "Smart Thermostat Radiator"
+    S20_VACUUM = "S20 Vacuum"
 
 
 __all__ = [

+ 1 - 0
switchbot/devices/device.py

@@ -73,6 +73,7 @@ API_MODEL_TO_ENUM: dict[str, SwitchbotModel] = {
     "W1083002": SwitchbotModel.RELAY_SWITCH_1,  # Relay Switch 1
     "W1079000": SwitchbotModel.METER_PRO,  # Meter Pro (another variant)
     "W1102001": SwitchbotModel.STRIP_LIGHT_3,  # RGBWW Strip Light 3
+    "W1106000": SwitchbotModel.S20_VACUUM,
 }
 
 REQ_HEADER = "570f"

+ 38 - 0
tests/test_adv_parser.py

@@ -3486,6 +3486,21 @@ def test_humidifer_with_empty_data() -> None:
             "Smart Thermostat Radiator",
             SwitchbotModel.SMART_THERMOSTAT_RADIATOR,
         ),
+        AdvTestCase(
+            b"\xb0\xe9\xfe\xc3\x1a!:\x01\x11\x1e\x00\x00d\x03",
+            b"\x00\x00d\x00\x10\xe0P",
+            {
+                "battery": 100,
+                "mqtt_connected": False,
+                "sequence_number": 58,
+                "soc_version": "1.1.030",
+                "step": 0,
+                "work_status": 3,
+            },
+            b"\x00\x10\xe0P",
+            "S20 Vacuum",
+            SwitchbotModel.S20_VACUUM,
+        ),
     ],
 )
 def test_adv_active(test_case: AdvTestCase) -> None:
@@ -3738,6 +3753,21 @@ def test_adv_active(test_case: AdvTestCase) -> None:
             "Smart Thermostat Radiator",
             SwitchbotModel.SMART_THERMOSTAT_RADIATOR,
         ),
+        AdvTestCase(
+            b"\xb0\xe9\xfe\xc3\x1a!:\x01\x11\x1e\x00\x00d\x03",
+            None,
+            {
+                "battery": 100,
+                "mqtt_connected": False,
+                "sequence_number": 58,
+                "soc_version": "1.1.030",
+                "step": 0,
+                "work_status": 3,
+            },
+            b"\x00\x10\xe0P",
+            "S20 Vacuum",
+            SwitchbotModel.S20_VACUUM,
+        ),
     ],
 )
 def test_adv_passive(test_case: AdvTestCase) -> None:
@@ -3919,6 +3949,14 @@ def test_adv_passive(test_case: AdvTestCase) -> None:
             "Smart Thermostat Radiator",
             SwitchbotModel.SMART_THERMOSTAT_RADIATOR,
         ),
+        AdvTestCase(
+            None,
+            b"\x00\x00d\x00\x10\xe0P",
+            {},
+            b"\x00\x10\xe0P",
+            "S20 Vacuum",
+            SwitchbotModel.S20_VACUUM,
+        ),
     ],
 )
 def test_adv_with_empty_data(test_case: AdvTestCase) -> None:

+ 2 - 0
tests/test_vacuum.py

@@ -16,6 +16,7 @@ common_params = [
     (b"(\x00", "(", 1),
     (b"}\x00", "(", 1),
     (b"\x00\x00M\x00\x10\xfb\xa8", b"\x00\x10\xfb\xa8", 2),
+    (b"\x00\x00d\x00\x10\xe0P", b"\x00\x10\xe0P", 2),
 ]
 
 
@@ -88,6 +89,7 @@ def make_advertisement_data(
         (b"z\x00\x00", "z"),
         (b"3\x00\x00", "3"),
         (b"\x00\x00M\x00\x10\xfb\xa8", b"\x00\x10\xfb\xa8"),
+        (b"\x00\x00d\x00\x10\xe0P", b"\x00\x10\xe0P"),
     ],
 )
 async def test_status_from_proceess_adv(rawAdvData: bytes, model: str) -> None: