Browse Source

Fixes for curtain firmware 6 (#139)

J. Nick Koston 1 year ago
parent
commit
7e388cb747
3 changed files with 89 additions and 2 deletions
  1. 1 1
      switchbot/__init__.py
  2. 14 1
      switchbot/adv_parser.py
  3. 74 0
      tests/test_adv_parser.py

+ 1 - 1
switchbot/__init__.py

@@ -1,7 +1,7 @@
 """Library to handle connection with Switchbot."""
 from __future__ import annotations
 
-from bleak_retry_connector import get_device, close_stale_connections
+from bleak_retry_connector import close_stale_connections, get_device
 
 from .adv_parser import SwitchbotSupportedType, parse_advertisement_data
 from .const import SwitchbotModel

+ 14 - 1
switchbot/adv_parser.py

@@ -24,6 +24,11 @@ from .models import SwitchBotAdvertisement
 
 _LOGGER = logging.getLogger(__name__)
 
+SERVICE_DATA_ORDER = (
+    "0000fd3d-0000-1000-8000-00805f9b34fb",
+    "00000d00-0000-1000-8000-00805f9b34fb",
+)
+
 
 class SwitchbotSupportedType(TypedDict):
     """Supported type of Switchbot."""
@@ -101,9 +106,17 @@ def parse_advertisement_data(
 
     if not _services:
         return None
-    _service_data = _services[0]
+
+    _service_data = None
+    for uuid in SERVICE_DATA_ORDER:
+        if uuid in _services:
+            _service_data = _services[uuid]
+            break
+    if not _service_data:
+        _service_data = _services[0]
     if not _service_data:
         return None
+
     _mfr_data = _mgr_datas[0] if _mgr_datas else None
 
     data = _parse_data(_service_data, _mfr_data)

+ 74 - 0
tests/test_adv_parser.py

@@ -180,6 +180,80 @@ def test_parse_advertisement_data_curtain_firmware_six_position_100_other_rssi()
     )
 
 
+def test_parse_advertisement_data_curtain_fully_closed():
+    """Test parse_advertisement_data with firmware six fully closed."""
+    ble_device = BLEDevice("aa:bb:cc:dd:ee:ff", "any")
+    adv_data = generate_advertisement_data(
+        local_name="WoCurtain",
+        manufacturer_data={2409: b"\xc1\xc7'}U\xab\"\x0fd\x11\x04"},
+        service_data={"0000fd3d-0000-1000-8000-00805f9b34fb": b"c\xc0Sd\x11\x04"},
+        service_uuids=[
+            "00001800-0000-1000-8000-00805f9b34fb",
+            "00001801-0000-1000-8000-00805f9b34fb",
+            "cba20d00-224d-11e6-9fb8-0002a5d5c51b",
+        ],
+        rssi=1,
+    )
+    result = parse_advertisement_data(ble_device, adv_data)
+    assert result == SwitchBotAdvertisement(
+        address="aa:bb:cc:dd:ee:ff",
+        data={
+            "rawAdvData": b"c\xc0Sd\x11\x04",
+            "data": {
+                "calibration": True,
+                "battery": 83,
+                "inMotion": False,
+                "position": 0,
+                "lightLevel": 1,
+                "deviceChain": 1,
+            },
+            "isEncrypted": False,
+            "model": "c",
+            "modelFriendlyName": "Curtain",
+            "modelName": SwitchbotModel.CURTAIN,
+        },
+        device=ble_device,
+        rssi=1,
+    )
+
+
+def test_parse_advertisement_data_curtain_fully_open():
+    """Test parse_advertisement_data with firmware six fully open."""
+    ble_device = BLEDevice("aa:bb:cc:dd:ee:ff", "any")
+    adv_data = generate_advertisement_data(
+        local_name="WoCurtain",
+        manufacturer_data={2409: b"\xc1\xc7'}U\xab%\x0f\x00\x11\x04"},
+        service_data={"0000fd3d-0000-1000-8000-00805f9b34fb": b"c\xc0S\x00\x11\x04"},
+        service_uuids=[
+            "00001800-0000-1000-8000-00805f9b34fb",
+            "00001801-0000-1000-8000-00805f9b34fb",
+            "cba20d00-224d-11e6-9fb8-0002a5d5c51b",
+        ],
+        rssi=1,
+    )
+    result = parse_advertisement_data(ble_device, adv_data)
+    assert result == SwitchBotAdvertisement(
+        address="aa:bb:cc:dd:ee:ff",
+        data={
+            "rawAdvData": b"c\xc0S\x00\x11\x04",
+            "data": {
+                "calibration": True,
+                "battery": 83,
+                "inMotion": False,
+                "position": 100,
+                "lightLevel": 1,
+                "deviceChain": 1,
+            },
+            "isEncrypted": False,
+            "model": "c",
+            "modelFriendlyName": "Curtain",
+            "modelName": SwitchbotModel.CURTAIN,
+        },
+        device=ble_device,
+        rssi=1,
+    )
+
+
 def test_parse_advertisement_data_contact():
     """Test parse_advertisement_data for the contact sensor."""
     ble_device = BLEDevice("aa:bb:cc:dd:ee:ff", "any")