Jelajahi Sumber

feat: support the sync-datetime protocol on the plain Meter Pro (#538)

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Sven Kirmess 2 hari lalu
induk
melakukan
0d72eac251
3 mengubah file dengan 32 tambahan dan 6 penghapusan
  1. 2 1
      switchbot/__init__.py
  2. 6 2
      switchbot/devices/meter_pro.py
  3. 24 3
      tests/test_meter_pro.py

+ 2 - 1
switchbot/__init__.py

@@ -61,7 +61,7 @@ from .devices.light_strip import (
     SwitchbotStripLight3,
 )
 from .devices.lock import SwitchbotLock
-from .devices.meter_pro import SwitchbotMeterProCO2
+from .devices.meter_pro import SwitchbotMeterPro, SwitchbotMeterProCO2
 from .devices.plug import SwitchbotPlugMini
 from .devices.relay_switch import (
     SwitchbotGarageDoorOpener,
@@ -115,6 +115,7 @@ __all__ = [
     "SwitchbotKeypadVision",
     "SwitchbotLightStrip",
     "SwitchbotLock",
+    "SwitchbotMeterPro",
     "SwitchbotMeterProCO2",
     "SwitchbotModel",
     "SwitchbotOperationError",

+ 6 - 2
switchbot/devices/meter_pro.py

@@ -12,8 +12,8 @@ COMMAND_SET_DEVICE_DATETIME = "57000503"
 COMMAND_SET_DISPLAY_FORMAT = "570f680505"
 
 
-class SwitchbotMeterProCO2(SwitchbotDevice):
-    """API to control Switchbot Meter Pro CO2."""
+class SwitchbotMeterPro(SwitchbotDevice):
+    """API to control Switchbot Meter Pro (and Meter Pro CO2, which shares the same datetime protocol)."""
 
     async def get_time_offset(self) -> int:
         """
@@ -170,3 +170,7 @@ class SwitchbotMeterProCO2(SwitchbotDevice):
                 f"{self.name}: Unexpected response len for {op_name}, wanted at least {min_length} (result={result.hex() if result else 'None'} rssi={self.rssi})"
             )
         return result
+
+
+class SwitchbotMeterProCO2(SwitchbotMeterPro):
+    """API to control Switchbot Meter Pro CO2."""

+ 24 - 3
tests/test_meter_pro.py

@@ -4,14 +4,18 @@ import pytest
 from bleak.backends.device import BLEDevice
 
 from switchbot import SwitchbotOperationError
-from switchbot.devices.meter_pro import MAX_TIME_OFFSET, SwitchbotMeterProCO2
+from switchbot.devices.meter_pro import (
+    MAX_TIME_OFFSET,
+    SwitchbotMeterPro,
+    SwitchbotMeterProCO2,
+)
 
 
-def create_device():
+def create_device(cls=SwitchbotMeterProCO2):
     ble_device = BLEDevice(
         address="aa:bb:cc:dd:ee:ff", name="any", details={"rssi": -80}
     )
-    device = SwitchbotMeterProCO2(ble_device)
+    device = cls(ble_device)
     device._send_command = AsyncMock()
     return device
 
@@ -248,3 +252,20 @@ async def test_set_time_display_format_failure():
 
     with pytest.raises(SwitchbotOperationError):
         await device.set_time_display_format(is_12h_mode=True)
+
+
+@pytest.mark.asyncio
+async def test_meter_pro_shares_datetime_protocol_with_co2_variant():
+    """The plain Meter Pro (no CO2 sensor) uses the same BLE commands as the CO2 variant."""
+    device = create_device(SwitchbotMeterPro)
+    device._send_command.return_value = bytes.fromhex("01e40294230007e90c1e083701")
+
+    result = await device.get_datetime()
+    device._send_command.assert_called_with("570f6901")
+    assert result["year"] == 2025
+
+    device._send_command.return_value = bytes.fromhex("01")
+    await device.set_datetime(1709251200)
+    device._send_command.assert_called_with(
+        "57000503" + "0c" + "65e11a80".zfill(16) + "00"
+    )