Browse Source

Add read-only support for lock (#145)

Damian Sypniewski 1 year ago
parent
commit
001841bd38
5 changed files with 52 additions and 0 deletions
  1. 6 0
      switchbot/adv_parser.py
  2. 28 0
      switchbot/adv_parsers/lock.py
  3. 13 0
      switchbot/const.py
  4. 1 0
      switchbot/devices/lock.py
  5. 4 0
      switchbot/discovery.py

+ 6 - 0
switchbot/adv_parser.py

@@ -19,6 +19,7 @@ from .adv_parsers.light_strip import process_wostrip
 from .adv_parsers.meter import process_wosensorth
 from .adv_parsers.motion import process_wopresence
 from .adv_parsers.plug import process_woplugmini
+from .adv_parsers.lock import process_wolock
 from .const import SwitchbotModel
 from .models import SwitchBotAdvertisement
 
@@ -94,6 +95,11 @@ SUPPORTED_TYPES: dict[str, SwitchbotSupportedType] = {
         "modelFriendlyName": "Humidifier",
         "func": process_wohumidifier,
     },
+    "o": {
+        "modelName": SwitchbotModel.LOCK,
+        "modelFriendlyName": "Lock",
+        "func": process_wolock,
+    },
 }
 
 

+ 28 - 0
switchbot/adv_parsers/lock.py

@@ -0,0 +1,28 @@
+"""Lock parser."""
+from __future__ import annotations
+from ..const import LockStatus
+
+import logging
+
+_LOGGER = logging.getLogger(__name__)
+
+
+def process_wolock(data: bytes, mfr_data: bytes | None) -> dict[str, bool | int]:
+    """Process woLock services data."""
+    if mfr_data is None:
+        return {}
+
+    _LOGGER.debug("mfr_data: %s", mfr_data.hex())
+    _LOGGER.debug("data: %s", data.hex())
+
+    return {
+        "battery": data[2] & 0b01111111,
+        "calibration": bool(mfr_data[7] & 0b10000000),
+        "status": LockStatus(mfr_data[7] & 0b01110000),
+        "update_from_secondary_lock": bool(mfr_data[7] & 0b00001000),
+        "door_open": bool(mfr_data[7] & 0b00000100),
+        "double_lock_mode": bool(mfr_data[8] & 0b10000000),
+        "unclosed_alarm": bool(mfr_data[8] & 0b00100000),
+        "unlocked_alarm": bool(mfr_data[8] & 0b00010000),
+        "auto_lock_paused": bool(mfr_data[8] & 0b00000010),
+    }

+ 13 - 0
switchbot/const.py

@@ -1,6 +1,8 @@
 """Library to handle connection with Switchbot."""
 from __future__ import annotations
 
+from enum import Enum
+
 DEFAULT_RETRY_COUNT = 3
 DEFAULT_RETRY_TIMEOUT = 1
 DEFAULT_SCAN_TIMEOUT = 5
@@ -20,3 +22,14 @@ class SwitchbotModel(StrEnum):
     MOTION_SENSOR = "WoPresence"
     COLOR_BULB = "WoBulb"
     CEILING_LIGHT = "WoCeiling"
+    LOCK = "WoLock"
+
+
+class LockStatus(Enum):
+    LOCKED = 0b0000000
+    UNLOCKED = 0b0010000
+    LOCKING = 0b0100000
+    UNLOCKING = 0b0110000
+    LOCKING_STOP = 0b1000000
+    UNLOCKING_STOP = 0b1010000
+    NOT_FULLY_LOCKED = 0b1100000  # Only EU lock type

+ 1 - 0
switchbot/devices/lock.py

@@ -0,0 +1 @@
+from __future__ import annotations

+ 4 - 0
switchbot/discovery.py

@@ -101,6 +101,10 @@ class GetSwitchbotDevices:
         """Return all WoContact/Contact sensor devices with services data."""
         return await self._get_devices_by_model("d")
 
+    async def get_locks(self) -> dict[str, SwitchBotAdvertisement]:
+        """Return all WoLock/Locks devices with services data."""
+        return await self._get_devices_by_model("o")
+
     async def get_device_data(
         self, address: str
     ) -> dict[str, SwitchBotAdvertisement] | None: