Skip to content

Commit ea31b4f

Browse files
authored
Fix temp sensors with passive (#156)
1 parent fa3c1fd commit ea31b4f

File tree

3 files changed

+115
-17
lines changed

3 files changed

+115
-17
lines changed

switchbot/adv_parser.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -78,15 +78,15 @@ class SwitchbotSupportedType(TypedDict):
7878
},
7979
"manufacturer_id": 89,
8080
},
81-
"T": {
81+
"i": {
8282
"modelName": SwitchbotModel.METER,
83-
"modelFriendlyName": "Meter",
83+
"modelFriendlyName": "Meter Plus",
8484
"func": process_wosensorth,
8585
"manufacturer_id": 2409,
8686
},
87-
"i": {
87+
"T": {
8888
"modelName": SwitchbotModel.METER,
89-
"modelFriendlyName": "Meter Plus",
89+
"modelFriendlyName": "Meter",
9090
"func": process_wosensorth,
9191
"manufacturer_id": 2409,
9292
},
@@ -193,6 +193,9 @@ def _parse_data(
193193
"""Parse advertisement data."""
194194
_model = chr(_service_data[0] & 0b01111111) if _service_data else None
195195

196+
if _switchbot_model and _switchbot_model in _SWITCHBOT_MODEL_TO_CHAR:
197+
_model = _SWITCHBOT_MODEL_TO_CHAR[_switchbot_model]
198+
196199
if not _model and _mfr_id and _mfr_id in MODELS_BY_MANUFACTURER_DATA:
197200
_service_uuids = set(_service_uuids_str.split(","))
198201
for model_chr, model_data in MODELS_BY_MANUFACTURER_DATA[_mfr_id]:
@@ -204,9 +207,6 @@ def _parse_data(
204207
_model = model_chr
205208
break
206209

207-
if not _model and _switchbot_model and _switchbot_model in _SWITCHBOT_MODEL_TO_CHAR:
208-
_model = _SWITCHBOT_MODEL_TO_CHAR[_switchbot_model]
209-
210210
if not _model:
211211
return None
212212

switchbot/adv_parsers/meter.py

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,29 @@
66

77
def process_wosensorth(data: bytes | None, mfr_data: bytes | None) -> dict[str, Any]:
88
"""Process woSensorTH/Temp sensor services data."""
9-
if data is None:
9+
if mfr_data:
10+
temp_data = mfr_data[8:11]
11+
battery = None
12+
13+
if data:
14+
temp_data = data[3:6]
15+
battery = data[2] & 0b01111111
16+
17+
if not temp_data:
1018
return {}
1119

12-
_temp_sign = 1 if data[4] & 0b10000000 else -1
13-
_temp_c = _temp_sign * ((data[4] & 0b01111111) + ((data[3] & 0b00001111) / 10))
20+
_temp_sign = 1 if temp_data[1] & 0b10000000 else -1
21+
_temp_c = _temp_sign * (
22+
(temp_data[1] & 0b01111111) + ((temp_data[0] & 0b00001111) / 10)
23+
)
1424
_temp_f = (_temp_c * 9 / 5) + 32
1525
_temp_f = (_temp_f * 10) / 10
1626

1727
_wosensorth_data = {
1828
"temp": {"c": _temp_c, "f": _temp_f},
19-
"fahrenheit": bool(data[5] & 0b10000000),
20-
"humidity": data[5] & 0b01111111,
21-
"battery": data[2] & 0b01111111,
29+
"fahrenheit": bool(temp_data[2] & 0b10000000),
30+
"humidity": temp_data[2] & 0b01111111,
31+
"battery": battery,
2232
}
2333

2434
return _wosensorth_data

tests/test_adv_parser.py

Lines changed: 92 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -620,7 +620,7 @@ def test_bulb_active():
620620
tx_power=-127,
621621
rssi=-50,
622622
)
623-
result = parse_advertisement_data(ble_device, adv_data, SwitchbotModel.BOT)
623+
result = parse_advertisement_data(ble_device, adv_data)
624624
assert result == SwitchBotAdvertisement(
625625
address="aa:bb:cc:dd:ee:ff",
626626
data={
@@ -645,8 +645,6 @@ def test_bulb_active():
645645
)
646646

647647

648-
649-
650648
def test_lightstrip_passive():
651649
"""Test parsing lightstrip as passive."""
652650
ble_device = BLEDevice("aa:bb:cc:dd:ee:ff", "any")
@@ -658,7 +656,7 @@ def test_lightstrip_passive():
658656
tx_power=-127,
659657
rssi=-50,
660658
)
661-
result = parse_advertisement_data(ble_device, adv_data, SwitchbotModel.BOT)
659+
result = parse_advertisement_data(ble_device, adv_data)
662660
assert result == SwitchBotAdvertisement(
663661
address="aa:bb:cc:dd:ee:ff",
664662
data={
@@ -681,3 +679,93 @@ def test_lightstrip_passive():
681679
device=ble_device,
682680
rssi=-50,
683681
)
682+
683+
684+
def test_wosensor_passive_and_active():
685+
"""Test parsing wosensor as passive with active data as well."""
686+
ble_device = BLEDevice("aa:bb:cc:dd:ee:ff", "any")
687+
adv_data = generate_advertisement_data(
688+
manufacturer_data={2409: b"\xd7\xc1}]\xebC\xde\x03\x06\x985"},
689+
service_data={"0000fd3d-0000-1000-8000-00805f9b34fb": b"T\x00\xe4\x06\x985"},
690+
tx_power=-127,
691+
rssi=-50,
692+
)
693+
result = parse_advertisement_data(ble_device, adv_data)
694+
assert result == SwitchBotAdvertisement(
695+
address="aa:bb:cc:dd:ee:ff",
696+
data={
697+
"data": {
698+
"battery": 100,
699+
"fahrenheit": False,
700+
"humidity": 53,
701+
"temp": {"c": 24.6, "f": 76.28},
702+
},
703+
"isEncrypted": False,
704+
"model": "T",
705+
"modelFriendlyName": "Meter",
706+
"modelName": SwitchbotModel.METER,
707+
"rawAdvData": b"T\x00\xe4\x06\x985",
708+
},
709+
device=ble_device,
710+
rssi=-50,
711+
)
712+
713+
714+
def test_wosensor_active():
715+
"""Test parsing wosensor with active data as well."""
716+
ble_device = BLEDevice("aa:bb:cc:dd:ee:ff", "any")
717+
adv_data = generate_advertisement_data(
718+
manufacturer_data={},
719+
service_data={"0000fd3d-0000-1000-8000-00805f9b34fb": b"T\x00\xe4\x06\x985"},
720+
tx_power=-127,
721+
rssi=-50,
722+
)
723+
result = parse_advertisement_data(ble_device, adv_data)
724+
assert result == SwitchBotAdvertisement(
725+
address="aa:bb:cc:dd:ee:ff",
726+
data={
727+
"data": {
728+
"battery": 100,
729+
"fahrenheit": False,
730+
"humidity": 53,
731+
"temp": {"c": 24.6, "f": 76.28},
732+
},
733+
"isEncrypted": False,
734+
"model": "T",
735+
"modelFriendlyName": "Meter",
736+
"modelName": SwitchbotModel.METER,
737+
"rawAdvData": b"T\x00\xe4\x06\x985",
738+
},
739+
device=ble_device,
740+
rssi=-50,
741+
)
742+
743+
744+
def test_wosensor_passive_only():
745+
"""Test parsing wosensor with only passive data."""
746+
ble_device = BLEDevice("aa:bb:cc:dd:ee:ff", "any")
747+
adv_data = generate_advertisement_data(
748+
manufacturer_data={2409: b"\xd7\xc1}]\xebC\xde\x03\x06\x985"},
749+
service_data={},
750+
tx_power=-127,
751+
rssi=-50,
752+
)
753+
result = parse_advertisement_data(ble_device, adv_data, SwitchbotModel.METER)
754+
assert result == SwitchBotAdvertisement(
755+
address="aa:bb:cc:dd:ee:ff",
756+
data={
757+
"data": {
758+
"battery": None,
759+
"fahrenheit": False,
760+
"humidity": 53,
761+
"temp": {"c": 24.6, "f": 76.28},
762+
},
763+
"isEncrypted": False,
764+
"model": "T",
765+
"modelFriendlyName": "Meter",
766+
"modelName": SwitchbotModel.METER,
767+
"rawAdvData": None,
768+
},
769+
device=ble_device,
770+
rssi=-50,
771+
)

0 commit comments

Comments
 (0)