Skip to content

Commit 2caa798

Browse files
authored
Fix lock discovery when first advertisement is missing service data (#171)
1 parent 6e745a0 commit 2caa798

File tree

4 files changed

+77
-5
lines changed

4 files changed

+77
-5
lines changed

switchbot/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from bleak_retry_connector import close_stale_connections, get_device
55

66
from .adv_parser import SwitchbotSupportedType, parse_advertisement_data
7-
from .const import SwitchbotModel
7+
from .const import LockStatus, SwitchbotModel
88
from .devices.base_light import SwitchbotBaseLight
99
from .devices.bot import Switchbot
1010
from .devices.bulb import SwitchbotBulb
@@ -25,6 +25,7 @@
2525
"GetSwitchbotDevices",
2626
"SwitchBotAdvertisement",
2727
"ColorMode",
28+
"LockStatus",
2829
"SwitchbotBaseLight",
2930
"SwitchbotBulb",
3031
"SwitchbotCeilingLight",

switchbot/adv_parser.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ class SwitchbotSupportedType(TypedDict):
6262
"modelFriendlyName": "Motion Sensor",
6363
"func": process_wopresence,
6464
"manufacturer_id": 2409,
65-
"manufacturer_data_length": 10,
6665
},
6766
"r": {
6867
"modelName": SwitchbotModel.LIGHT_STRIP,
@@ -125,6 +124,7 @@ class SwitchbotSupportedType(TypedDict):
125124
"modelName": SwitchbotModel.LOCK,
126125
"modelFriendlyName": "Lock",
127126
"func": process_wolock,
127+
"manufacturer_id": 2409,
128128
},
129129
}
130130

switchbot/adv_parsers/lock.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ def process_wolock(data: bytes | None, mfr_data: bytes | None) -> dict[str, bool
1414
return {}
1515

1616
_LOGGER.debug("mfr_data: %s", mfr_data.hex())
17-
_LOGGER.debug("data: %s", data.hex())
17+
if data:
18+
_LOGGER.debug("data: %s", data.hex())
1819

1920
return {
2021
"battery": data[2] & 0b01111111 if data else None,

tests/test_adv_parser.py

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from bleak.backends.device import BLEDevice
44
from bleak.backends.scanner import AdvertisementData
55

6-
from switchbot import SwitchbotModel
6+
from switchbot import LockStatus, SwitchbotModel
77
from switchbot.adv_parser import parse_advertisement_data
88
from switchbot.models import SwitchBotAdvertisement
99

@@ -1094,7 +1094,9 @@ def test_motion_sensor_motion_passive():
10941094
tx_power=-127,
10951095
rssi=-87,
10961096
)
1097-
result = parse_advertisement_data(ble_device, adv_data)
1097+
result = parse_advertisement_data(
1098+
ble_device, adv_data, SwitchbotModel.MOTION_SENSOR
1099+
)
10981100
assert result == SwitchBotAdvertisement(
10991101
address="aa:bb:cc:dd:ee:ff",
11001102
data={
@@ -1118,3 +1120,71 @@ def test_motion_sensor_motion_passive():
11181120
rssi=-87,
11191121
active=False,
11201122
)
1123+
1124+
1125+
def test_parsing_lock_active():
1126+
"""Test parsing lock with active data."""
1127+
ble_device = BLEDevice("aa:bb:cc:dd:ee:ff", "any")
1128+
adv_data = generate_advertisement_data(
1129+
manufacturer_data={2409: b"\xf1\t\x9fE\x1a]\x07\x83\x00 "},
1130+
service_data={"0000fd3d-0000-1000-8000-00805f9b34fb": b"o\x80d"},
1131+
rssi=-67,
1132+
)
1133+
result = parse_advertisement_data(ble_device, adv_data)
1134+
assert result == SwitchBotAdvertisement(
1135+
address="aa:bb:cc:dd:ee:ff",
1136+
data={
1137+
"data": {
1138+
"auto_lock_paused": False,
1139+
"battery": 100,
1140+
"calibration": True,
1141+
"door_open": False,
1142+
"double_lock_mode": False,
1143+
"status": LockStatus.LOCKED,
1144+
"unclosed_alarm": False,
1145+
"unlocked_alarm": False,
1146+
"update_from_secondary_lock": False,
1147+
},
1148+
"isEncrypted": False,
1149+
"model": "o",
1150+
"modelFriendlyName": "Lock",
1151+
"modelName": SwitchbotModel.LOCK,
1152+
"rawAdvData": b"o\x80d",
1153+
},
1154+
device=ble_device,
1155+
rssi=-67,
1156+
active=True,
1157+
)
1158+
1159+
1160+
def test_parsing_lock_passive():
1161+
"""Test parsing lock with active data."""
1162+
ble_device = BLEDevice("aa:bb:cc:dd:ee:ff", "any")
1163+
adv_data = generate_advertisement_data(
1164+
manufacturer_data={2409: b"\xf1\t\x9fE\x1a]\x07\x83\x00 "}, rssi=-67
1165+
)
1166+
result = parse_advertisement_data(ble_device, adv_data, SwitchbotModel.LOCK)
1167+
assert result == SwitchBotAdvertisement(
1168+
address="aa:bb:cc:dd:ee:ff",
1169+
data={
1170+
"data": {
1171+
"auto_lock_paused": False,
1172+
"battery": None,
1173+
"calibration": True,
1174+
"door_open": False,
1175+
"double_lock_mode": False,
1176+
"status": LockStatus.LOCKED,
1177+
"unclosed_alarm": False,
1178+
"unlocked_alarm": False,
1179+
"update_from_secondary_lock": False,
1180+
},
1181+
"isEncrypted": False,
1182+
"model": "o",
1183+
"modelFriendlyName": "Lock",
1184+
"modelName": SwitchbotModel.LOCK,
1185+
"rawAdvData": None,
1186+
},
1187+
device=ble_device,
1188+
rssi=-67,
1189+
active=False,
1190+
)

0 commit comments

Comments
 (0)