Browse Source

fix: handle new switchbot firmwares (#124)

J. Nick Koston 1 year ago
parent
commit
f1be36bfb6

+ 9 - 7
switchbot/adv_parser.py

@@ -125,12 +125,14 @@ def _parse_data(
 
     type_data = SUPPORTED_TYPES.get(_model)
     if type_data:
-        data.update(
-            {
-                "modelFriendlyName": type_data["modelFriendlyName"],
-                "modelName": type_data["modelName"],
-                "data": type_data["func"](_service_data, _mfr_data),
-            }
-        )
+        model_data = type_data["func"](_service_data, _mfr_data)
+        if model_data:
+            data.update(
+                {
+                    "modelFriendlyName": type_data["modelFriendlyName"],
+                    "modelName": type_data["modelName"],
+                    "data": model_data,
+                }
+            )
 
     return data

+ 2 - 1
switchbot/adv_parsers/bulb.py

@@ -4,7 +4,8 @@ from __future__ import annotations
 
 def process_color_bulb(data: bytes, mfr_data: bytes | None) -> dict[str, bool | int]:
     """Process WoBulb services data."""
-    assert mfr_data is not None
+    if mfr_data is None:
+        return {}
     return {
         "sequence_number": mfr_data[6],
         "isOn": bool(mfr_data[7] & 0b10000000),

+ 2 - 1
switchbot/adv_parsers/ceiling_light.py

@@ -14,7 +14,8 @@ _LOGGER = logging.getLogger(__name__)
 
 def process_woceiling(data: bytes, mfr_data: bytes | None) -> dict[str, bool | int]:
     """Process WoCeiling services data."""
-    assert mfr_data is not None
+    if mfr_data is None:
+        return {}
     return {
         "sequence_number": mfr_data[6],
         "isOn": bool(mfr_data[10] & 0b10000000),

+ 2 - 1
switchbot/adv_parsers/light_strip.py

@@ -4,7 +4,8 @@ from __future__ import annotations
 
 def process_wostrip(data: bytes, mfr_data: bytes | None) -> dict[str, bool | int]:
     """Process WoStrip services data."""
-    assert mfr_data is not None
+    if mfr_data is None:
+        return {}
     return {
         "sequence_number": mfr_data[6],
         "isOn": bool(mfr_data[7] & 0b10000000),

+ 2 - 1
switchbot/adv_parsers/plug.py

@@ -4,7 +4,8 @@ from __future__ import annotations
 
 def process_woplugmini(data: bytes, mfr_data: bytes | None) -> dict[str, bool | int]:
     """Process plug mini."""
-    assert mfr_data is not None
+    if mfr_data is None:
+        return {}
     return {
         "switchMode": True,
         "isOn": mfr_data[7] == 0x80,

+ 26 - 4
tests/test_adv_parser.py

@@ -3,6 +3,7 @@ from bleak.backends.scanner import AdvertisementData
 from bleak.backends.device import BLEDevice
 
 from switchbot.models import SwitchBotAdvertisement
+from switchbot import SwitchbotModel
 
 
 def test_parse_advertisement_data_curtain():
@@ -16,7 +17,6 @@ def test_parse_advertisement_data_curtain():
     assert result == SwitchBotAdvertisement(
         address="aa:bb:cc:dd:ee:ff",
         data={
-            "address": "aa:bb:cc:dd:ee:ff",
             "rawAdvData": b"c\xc0X\x00\x11\x04",
             "data": {
                 "calibration": True,
@@ -25,12 +25,11 @@ def test_parse_advertisement_data_curtain():
                 "position": 100,
                 "lightLevel": 1,
                 "deviceChain": 1,
-                "rssi": 0,
             },
             "isEncrypted": False,
             "model": "c",
             "modelFriendlyName": "Curtain",
-            "modelName": "WoCurtain",
+            "modelName": SwitchbotModel.CURTAIN,
         },
         device=ble_device,
     )
@@ -44,4 +43,27 @@ def test_parse_advertisement_data_empty():
         service_data={"0000fd3d-0000-1000-8000-00805f9b34fb": b""},
     )
     result = parse_advertisement_data(ble_device, adv_data)
-    assert result is None
+    assert result is None
+
+
+def test_new_bot_firmware():
+    """Test parsing adv data from new bot firmware."""
+    ble_device = BLEDevice("aa:bb:cc:dd:ee:ff", "any")
+    adv_data = AdvertisementData(
+        manufacturer_data={89: b"\xd8.\xad\xcd\r\x85"},
+        service_data={"00000d00-0000-1000-8000-00805f9b34fb": b"H\x10\xe1"},
+        service_uuids=["CBA20D00-224D-11E6-9FB8-0002A5D5C51B"],
+    )
+    result = parse_advertisement_data(ble_device, adv_data)
+    assert result == SwitchBotAdvertisement(
+        address="aa:bb:cc:dd:ee:ff",
+        data={
+            "rawAdvData": b"H\x10\xe1",
+            "data": {"switchMode": False, "isOn": False, "battery": 97},
+            "model": "H",
+            "isEncrypted": False,
+            "modelFriendlyName": "Bot",
+            "modelName": SwitchbotModel.BOT,
+        },
+        device=ble_device,
+    )