From 9d632bb8ccbcdc8171a925ad9fa4e7616ea8ff27 Mon Sep 17 00:00:00 2001 From: Leo Shen Date: Thu, 4 Jul 2024 19:27:26 -0400 Subject: [PATCH 1/9] adv_parser: use separate parser for lock_pro - because of course they are different, why didn't I caught it earlier?! --- switchbot/adv_parser.py | 4 ++-- switchbot/adv_parsers/lock.py | 22 ++++++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/switchbot/adv_parser.py b/switchbot/adv_parser.py index 2dbbce03..24b2a551 100644 --- a/switchbot/adv_parser.py +++ b/switchbot/adv_parser.py @@ -19,7 +19,7 @@ from .adv_parsers.hub2 import process_wohub2 from .adv_parsers.humidifier import process_wohumidifier from .adv_parsers.light_strip import process_wostrip -from .adv_parsers.lock import process_wolock +from .adv_parsers.lock import process_wolock, process_wolock_pro from .adv_parsers.meter import process_wosensorth from .adv_parsers.motion import process_wopresence from .adv_parsers.plug import process_woplugmini @@ -153,7 +153,7 @@ class SwitchbotSupportedType(TypedDict): "$": { "modelName": SwitchbotModel.LOCK_PRO, "modelFriendlyName": "Lock Pro", - "func": process_wolock, + "func": process_wolock_pro, "manufacturer_id": 2409, }, "x": { diff --git a/switchbot/adv_parsers/lock.py b/switchbot/adv_parsers/lock.py index 8f7790e7..44df15eb 100644 --- a/switchbot/adv_parsers/lock.py +++ b/switchbot/adv_parsers/lock.py @@ -29,3 +29,25 @@ def process_wolock(data: bytes | None, mfr_data: bytes | None) -> dict[str, bool "auto_lock_paused": bool(mfr_data[8] & 0b00000010), "night_latch": bool(mfr_data[9] & 0b00000001) if len(mfr_data) > 9 else False, } + +def process_wolock_pro(data: bytes | None, mfr_data: bytes | None) -> dict[str, bool | int]: + _LOGGER.debug("mfr_data: %s", mfr_data.hex()) + if data: + _LOGGER.debug("data: %s", data.hex()) + + res = { + "battery": data[2] & 0b01111111 if data else None, + "calibration": bool(mfr_data[7] & 0b10000000), + "status": LockStatus(int(mfr_data[7] & 0b00111000) / 8), + "update_from_secondary_lock": bool(mfr_data[7] & 0b00001000), + # For some reason they used 2 bytes here, probably night latch? + "door_open": bool(mfr_data[8] & 0b110000), + "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), + "night_latch": bool(mfr_data[9] & 0b00000001) if len(mfr_data) > 9 else False, + "manual": not bool(mfr_data[7] & 0b00000010), + } + _LOGGER.debug(res) + return res From b8e8eadca7e939064eacf0b18d0a90e09b81fa1b Mon Sep 17 00:00:00 2001 From: Leo Shen Date: Thu, 4 Jul 2024 21:13:27 -0400 Subject: [PATCH 2/9] adv_parser/lock: add more fields --- switchbot/adv_parsers/lock.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/switchbot/adv_parsers/lock.py b/switchbot/adv_parsers/lock.py index 44df15eb..a34c6fbe 100644 --- a/switchbot/adv_parsers/lock.py +++ b/switchbot/adv_parsers/lock.py @@ -41,11 +41,11 @@ def process_wolock_pro(data: bytes | None, mfr_data: bytes | None) -> dict[str, "status": LockStatus(int(mfr_data[7] & 0b00111000) / 8), "update_from_secondary_lock": bool(mfr_data[7] & 0b00001000), # For some reason they used 2 bytes here, probably night latch? - "door_open": bool(mfr_data[8] & 0b110000), + "door_open": bool(mfr_data[8] & 0b01100000), "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), + "unclosed_alarm": bool(mfr_data[11] & 0b10000000), + "unlocked_alarm": bool(mfr_data[11] & 0b01000000), + "auto_lock_paused": bool(mfr_data[8] & 0b100000), "night_latch": bool(mfr_data[9] & 0b00000001) if len(mfr_data) > 9 else False, "manual": not bool(mfr_data[7] & 0b00000010), } From 083c3edbab8f15abcce9b6ff16e74268f66fd531 Mon Sep 17 00:00:00 2001 From: Leo Shen Date: Fri, 5 Jul 2024 13:56:23 -0400 Subject: [PATCH 3/9] adv_parser/lock: remove redundant check on lock pro data - also add notes on which fields are still pending --- switchbot/adv_parsers/lock.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/switchbot/adv_parsers/lock.py b/switchbot/adv_parsers/lock.py index a34c6fbe..c79032a3 100644 --- a/switchbot/adv_parsers/lock.py +++ b/switchbot/adv_parsers/lock.py @@ -39,14 +39,16 @@ def process_wolock_pro(data: bytes | None, mfr_data: bytes | None) -> dict[str, "battery": data[2] & 0b01111111 if data else None, "calibration": bool(mfr_data[7] & 0b10000000), "status": LockStatus(int(mfr_data[7] & 0b00111000) / 8), + # This field hasn't been tested on Lock Pro "update_from_secondary_lock": bool(mfr_data[7] & 0b00001000), - # For some reason they used 2 bytes here, probably night latch? "door_open": bool(mfr_data[8] & 0b01100000), + # This field hasn't been tested on Lock Pro "double_lock_mode": bool(mfr_data[8] & 0b10000000), "unclosed_alarm": bool(mfr_data[11] & 0b10000000), "unlocked_alarm": bool(mfr_data[11] & 0b01000000), "auto_lock_paused": bool(mfr_data[8] & 0b100000), - "night_latch": bool(mfr_data[9] & 0b00000001) if len(mfr_data) > 9 else False, + # This field hasn't been tested on Lock Pro + "night_latch": bool(mfr_data[9] & 0b00000001), "manual": not bool(mfr_data[7] & 0b00000010), } _LOGGER.debug(res) From 4e2e02ae49bbf6ef3e21d5b7ac59b22dd17f5bb9 Mon Sep 17 00:00:00 2001 From: Leo Shen Date: Sat, 6 Jul 2024 17:08:36 -0400 Subject: [PATCH 4/9] format code --- switchbot/adv_parsers/lock.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/switchbot/adv_parsers/lock.py b/switchbot/adv_parsers/lock.py index c79032a3..9ced990b 100644 --- a/switchbot/adv_parsers/lock.py +++ b/switchbot/adv_parsers/lock.py @@ -30,7 +30,10 @@ def process_wolock(data: bytes | None, mfr_data: bytes | None) -> dict[str, bool "night_latch": bool(mfr_data[9] & 0b00000001) if len(mfr_data) > 9 else False, } -def process_wolock_pro(data: bytes | None, mfr_data: bytes | None) -> dict[str, bool | int]: + +def process_wolock_pro( + data: bytes | None, mfr_data: bytes | None +) -> dict[str, bool | int]: _LOGGER.debug("mfr_data: %s", mfr_data.hex()) if data: _LOGGER.debug("data: %s", data.hex()) From f06d599b025c49b0474e05c60e395fb45c3ee87b Mon Sep 17 00:00:00 2001 From: Leo Shen Date: Sat, 6 Jul 2024 17:12:28 -0400 Subject: [PATCH 5/9] fix tests --- tests/test_adv_parser.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/test_adv_parser.py b/tests/test_adv_parser.py index 684aa43b..763cc67f 100644 --- a/tests/test_adv_parser.py +++ b/tests/test_adv_parser.py @@ -1413,6 +1413,7 @@ def test_parsing_lock_pro_active(): "unlocked_alarm": False, "auto_lock_paused": False, "night_latch": False, + "manual": False, }, "model": "$", "isEncrypted": False, @@ -1446,6 +1447,7 @@ def test_parsing_lock_pro_passive(): "unlocked_alarm": False, "auto_lock_paused": False, "night_latch": False, + "manual": False, }, "model": "$", "isEncrypted": False, From 5877a7717edd7198a91192d9260444627b8417ea Mon Sep 17 00:00:00 2001 From: Leo Shen Date: Sat, 6 Jul 2024 18:17:59 -0400 Subject: [PATCH 6/9] adv_parsers/lock: night_latch works without modification - thanks @jsprotky! --- switchbot/adv_parsers/lock.py | 1 - 1 file changed, 1 deletion(-) diff --git a/switchbot/adv_parsers/lock.py b/switchbot/adv_parsers/lock.py index 9ced990b..c7aa6ec0 100644 --- a/switchbot/adv_parsers/lock.py +++ b/switchbot/adv_parsers/lock.py @@ -50,7 +50,6 @@ def process_wolock_pro( "unclosed_alarm": bool(mfr_data[11] & 0b10000000), "unlocked_alarm": bool(mfr_data[11] & 0b01000000), "auto_lock_paused": bool(mfr_data[8] & 0b100000), - # This field hasn't been tested on Lock Pro "night_latch": bool(mfr_data[9] & 0b00000001), "manual": not bool(mfr_data[7] & 0b00000010), } From fc69ff957ed39e45b998b825482ce9920db4e8ab Mon Sep 17 00:00:00 2001 From: Leo Shen Date: Mon, 8 Jul 2024 12:14:30 -0400 Subject: [PATCH 7/9] adv_parsers/lock: double lock mode is not supported on Lock Pro - thus mark both field as False at all time --- switchbot/adv_parsers/lock.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/switchbot/adv_parsers/lock.py b/switchbot/adv_parsers/lock.py index c7aa6ec0..1a60f905 100644 --- a/switchbot/adv_parsers/lock.py +++ b/switchbot/adv_parsers/lock.py @@ -42,11 +42,10 @@ def process_wolock_pro( "battery": data[2] & 0b01111111 if data else None, "calibration": bool(mfr_data[7] & 0b10000000), "status": LockStatus(int(mfr_data[7] & 0b00111000) / 8), - # This field hasn't been tested on Lock Pro - "update_from_secondary_lock": bool(mfr_data[7] & 0b00001000), "door_open": bool(mfr_data[8] & 0b01100000), - # This field hasn't been tested on Lock Pro - "double_lock_mode": bool(mfr_data[8] & 0b10000000), + # Double lock mode is not supported on Lock Pro + "update_from_secondary_lock": False, + "double_lock_mode": False, "unclosed_alarm": bool(mfr_data[11] & 0b10000000), "unlocked_alarm": bool(mfr_data[11] & 0b01000000), "auto_lock_paused": bool(mfr_data[8] & 0b100000), From e60aaf2c6c27b669c3e75263fa39c8a8ce5a036e Mon Sep 17 00:00:00 2001 From: Leo Shen Date: Mon, 8 Jul 2024 19:53:54 -0400 Subject: [PATCH 8/9] adv_parsers/lock: remove inefficient debug code --- switchbot/adv_parsers/lock.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/switchbot/adv_parsers/lock.py b/switchbot/adv_parsers/lock.py index 1a60f905..29a6e3e7 100644 --- a/switchbot/adv_parsers/lock.py +++ b/switchbot/adv_parsers/lock.py @@ -41,7 +41,7 @@ def process_wolock_pro( res = { "battery": data[2] & 0b01111111 if data else None, "calibration": bool(mfr_data[7] & 0b10000000), - "status": LockStatus(int(mfr_data[7] & 0b00111000) / 8), + "status": LockStatus((mfr_data[7] & 0b00111000) >> 3), "door_open": bool(mfr_data[8] & 0b01100000), # Double lock mode is not supported on Lock Pro "update_from_secondary_lock": False, From 3f5a64241d0000e2a9ac0886acac06ac6a65c98b Mon Sep 17 00:00:00 2001 From: Leo Shen Date: Wed, 10 Jul 2024 23:37:08 -0400 Subject: [PATCH 9/9] adv_parsers/lock: remove manual field for now - as it's not needed by HA for now and is actually inaccurate --- switchbot/adv_parsers/lock.py | 1 - tests/test_adv_parser.py | 2 -- 2 files changed, 3 deletions(-) diff --git a/switchbot/adv_parsers/lock.py b/switchbot/adv_parsers/lock.py index 29a6e3e7..1ce35acd 100644 --- a/switchbot/adv_parsers/lock.py +++ b/switchbot/adv_parsers/lock.py @@ -50,7 +50,6 @@ def process_wolock_pro( "unlocked_alarm": bool(mfr_data[11] & 0b01000000), "auto_lock_paused": bool(mfr_data[8] & 0b100000), "night_latch": bool(mfr_data[9] & 0b00000001), - "manual": not bool(mfr_data[7] & 0b00000010), } _LOGGER.debug(res) return res diff --git a/tests/test_adv_parser.py b/tests/test_adv_parser.py index 763cc67f..684aa43b 100644 --- a/tests/test_adv_parser.py +++ b/tests/test_adv_parser.py @@ -1413,7 +1413,6 @@ def test_parsing_lock_pro_active(): "unlocked_alarm": False, "auto_lock_paused": False, "night_latch": False, - "manual": False, }, "model": "$", "isEncrypted": False, @@ -1447,7 +1446,6 @@ def test_parsing_lock_pro_passive(): "unlocked_alarm": False, "auto_lock_paused": False, "night_latch": False, - "manual": False, }, "model": "$", "isEncrypted": False,