Skip to content

Commit e5bcffa

Browse files
boozer2bdraco
andauthored
Add Indoor/Outdoor Meter (#210)
Co-authored-by: J. Nick Koston <[email protected]>
1 parent d60b281 commit e5bcffa

File tree

7 files changed

+84
-6
lines changed

7 files changed

+84
-6
lines changed

switchbot/adv_parser.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,12 @@ class SwitchbotSupportedType(TypedDict):
7777
"func": process_wocurtain,
7878
"manufacturer_id": 2409,
7979
},
80+
"w": {
81+
"modelName": SwitchbotModel.IO_METER,
82+
"modelFriendlyName": "Indoor/Outdoor Meter",
83+
"func": process_wosensorth,
84+
"manufacturer_id": 2409,
85+
},
8086
"i": {
8187
"modelName": SwitchbotModel.METER,
8288
"modelFriendlyName": "Meter Plus",
@@ -93,7 +99,6 @@ class SwitchbotSupportedType(TypedDict):
9399
"modelName": SwitchbotModel.PLUG_MINI,
94100
"modelFriendlyName": "Plug Mini",
95101
"func": process_woplugmini,
96-
"manufacturer_data_length": 12,
97102
"manufacturer_id": 2409,
98103
},
99104
"j": {

switchbot/adv_parsers/blind_tilt.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,5 @@ def process_woblindtilt(
2323
"inMotion": _in_motion,
2424
"tilt": (100 - _tilt) if reverse else _tilt,
2525
"lightLevel": _light_level,
26-
"sequence_number": device_data[0]
26+
"sequence_number": device_data[0],
2727
}

switchbot/adv_parsers/meter.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,15 @@
66

77
def process_wosensorth(data: bytes | None, mfr_data: bytes | None) -> dict[str, Any]:
88
"""Process woSensorTH/Temp sensor services data."""
9+
temp_data = None
10+
battery = None
11+
912
if mfr_data:
1013
temp_data = mfr_data[8:11]
11-
battery = None
1214

1315
if data:
14-
temp_data = data[3:6]
16+
if not temp_data:
17+
temp_data = data[3:6]
1518
battery = data[2] & 0b01111111
1619

1720
if not temp_data:

switchbot/const.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class SwitchbotModel(StrEnum):
3434
CONTACT_SENSOR = "WoContact"
3535
LIGHT_STRIP = "WoStrip"
3636
METER = "WoSensorTH"
37+
IO_METER = "WoIOSensorTH"
3738
MOTION_SENSOR = "WoPresence"
3839
COLOR_BULB = "WoBulb"
3940
CEILING_LIGHT = "WoCeiling"

switchbot/devices/blind_tilt.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@
44
import logging
55
from typing import Any
66

7-
from switchbot.devices.device import REQ_HEADER, update_after_operation, SwitchbotSequenceDevice
7+
from switchbot.devices.device import (
8+
REQ_HEADER,
9+
SwitchbotSequenceDevice,
10+
update_after_operation,
11+
)
812

913
from .curtain import CURTAIN_EXT_SUM_KEY, SwitchbotCurtain
1014

switchbot/discovery.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,8 @@ async def get_tempsensors(self) -> dict[str, SwitchBotAdvertisement]:
103103
"""Return all WoSensorTH/Temp sensor devices with services data."""
104104
base_meters = await self._get_devices_by_model("T")
105105
plus_meters = await self._get_devices_by_model("i")
106-
return {**base_meters, **plus_meters}
106+
io_meters = await self._get_devices_by_model("w")
107+
return {**base_meters, **plus_meters, **io_meters}
107108

108109
async def get_contactsensors(self) -> dict[str, SwitchBotAdvertisement]:
109110
"""Return all WoContact/Contact sensor devices with services data."""

tests/test_adv_parser.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -857,6 +857,70 @@ def test_wosensor_passive_only():
857857
)
858858

859859

860+
def test_woiosensor_passive_and_active():
861+
"""Test parsing woiosensor as passive with active data as well."""
862+
ble_device = generate_ble_device("aa:bb:cc:dd:ee:ff", "any")
863+
adv_data = generate_advertisement_data(
864+
manufacturer_data={2409: b"\xaa\xbb\xcc\xdd\xee\xff\xe0\x0f\x06\x985\x00"},
865+
service_data={"0000fd3d-0000-1000-8000-00805f9b34fb": b"w\x00\xe4"},
866+
tx_power=-127,
867+
rssi=-50,
868+
)
869+
result = parse_advertisement_data(ble_device, adv_data)
870+
assert result == SwitchBotAdvertisement(
871+
address="aa:bb:cc:dd:ee:ff",
872+
data={
873+
"data": {
874+
"battery": 100,
875+
"fahrenheit": False,
876+
"humidity": 53,
877+
"temp": {"c": 24.6, "f": 76.28},
878+
"temperature": 24.6,
879+
},
880+
"isEncrypted": False,
881+
"model": "w",
882+
"modelFriendlyName": "Indoor/Outdoor Meter",
883+
"modelName": SwitchbotModel.IO_METER,
884+
"rawAdvData": b"w\x00\xe4",
885+
},
886+
device=ble_device,
887+
rssi=-50,
888+
active=True,
889+
)
890+
891+
892+
def test_woiosensor_passive_only():
893+
"""Test parsing woiosensor with only passive data."""
894+
ble_device = generate_ble_device("aa:bb:cc:dd:ee:ff", "any")
895+
adv_data = generate_advertisement_data(
896+
manufacturer_data={2409: b"\xaa\xbb\xcc\xdd\xee\xff\xe0\x0f\x06\x985\x00"},
897+
service_data={},
898+
tx_power=-127,
899+
rssi=-50,
900+
)
901+
result = parse_advertisement_data(ble_device, adv_data, SwitchbotModel.IO_METER)
902+
assert result == SwitchBotAdvertisement(
903+
address="aa:bb:cc:dd:ee:ff",
904+
data={
905+
"data": {
906+
"battery": None,
907+
"fahrenheit": False,
908+
"humidity": 53,
909+
"temp": {"c": 24.6, "f": 76.28},
910+
"temperature": 24.6,
911+
},
912+
"isEncrypted": False,
913+
"model": "w",
914+
"modelFriendlyName": "Indoor/Outdoor Meter",
915+
"modelName": SwitchbotModel.IO_METER,
916+
"rawAdvData": None,
917+
},
918+
device=ble_device,
919+
rssi=-50,
920+
active=False,
921+
)
922+
923+
860924
def test_motion_sensor_clear():
861925
"""Test parsing motion sensor with clear data."""
862926
ble_device = generate_ble_device("aa:bb:cc:dd:ee:ff", "any")

0 commit comments

Comments
 (0)