Просмотр исходного кода

fix: use supported firmware query for Circulator Fan Pro (#611)

* fix: use supported status query for Circulator Fan Pro

* fix: read Fan Pro firmware with supported basic-info command

---------

Co-authored-by: Fan Kai <fankai@onero.com>
Onero-testdev 19 часов назад
Родитель
Сommit
edb8139c92
2 измененных файлов с 31 добавлено и 13 удалено
  1. 4 10
      switchbot/devices/fan.py
  2. 27 3
      tests/test_fan.py

+ 4 - 10
switchbot/devices/fan.py

@@ -360,17 +360,11 @@ class SwitchbotCirculatorFanPro(SwitchbotEncryptedDevice, SwitchbotFan):
     _command_stop_vertical_oscillation: ClassVar[str] = "570f410229ff02"
 
     async def get_basic_info(self) -> dict[str, Any] | None:
-        """
-        Get device basic info.
-
-        The Pro carries all runtime state (fan + night light) in its
-        advertisement, so only the firmware is read here.
-        """
-        if not (_data1 := await self._get_basic_info(DEVICE_GET_BASIC_SETTINGS_KEY)):
-            return None
-        if len(_data1) <= 2:
+        """Read firmware using the Pro's basic-info query."""
+        response = await self._get_basic_info("57000300")
+        if not response or len(response) < 3 or response[0] != 1:
             return None
-        return {"firmware": _data1[2] / 10.0}
+        return {"firmware": response[2] / 10.0}
 
     @update_after_operation
     async def set_percentage(self, percentage: int) -> bool:

+ 27 - 3
tests/test_fan.py

@@ -586,16 +586,18 @@ async def test_circulator_fan_pro_get_basic_info():
         "ffffffffffffffffffffffffffffffff",
         model=SwitchbotModel.CIRCULATOR_FAN_PRO,
     )
-    fan_device._send_command = AsyncMock(return_value=b"\x01\x02\x37\x04")
+    fan_device._send_command = AsyncMock(return_value=b"\x01\x00\x37")
     info = await fan_device.get_basic_info()
     assert info == {"firmware": 5.5}
-    fan_device._send_command.assert_called_once()
+    fan_device._send_command.assert_awaited_once_with(
+        key="57000300", retry=fan_device._retry_count
+    )
 
 
 @pytest.mark.asyncio
 @pytest.mark.parametrize(
     "response",
-    [b"\x00", b"\x07", b"\x01\x02"],
+    [None, b"", b"\x00", b"\x07", b"\x05", b"\x01", b"\x01\x00", b"\x05\x00\x37"],
 )
 async def test_circulator_fan_pro_get_basic_info_returns_none(response):
     ble_device = generate_ble_device("aa:bb:cc:dd:ee:ff", "any")
@@ -958,3 +960,25 @@ def test_process_standing_fan_charging(battery_byte, charging, battery):
 def test_process_standing_fan_charging_short_payload():
     assert process_standing_fan(None, None) == {}
     assert process_standing_fan(None, b"\x00") == {}
+
+
+@pytest.mark.asyncio
+@pytest.mark.parametrize(
+    ("response", "expected"),
+    [(b"\x01\x00\x37", True), (b"\x05", False), (b"\x01\x00", False), (None, False)],
+)
+async def test_circulator_fan_pro_verify_encryption_key(
+    monkeypatch, response, expected
+):
+    send_command = AsyncMock(return_value=response)
+    monkeypatch.setattr(SwitchbotCirculatorFanPro, "_send_command", send_command)
+    device = generate_ble_device("aa:bb:cc:dd:ee:ff", "any")
+
+    assert (
+        await SwitchbotCirculatorFanPro.verify_encryption_key(
+            device, "ff", "ffffffffffffffffffffffffffffffff"
+        )
+        is expected
+    )
+    send_command.assert_awaited_once()
+    assert send_command.call_args.kwargs["key"] == "57000300"