fix: select RXTX channel by firmware family
This commit is contained in:
1 parent
34dd6b4c52
commit
da02bd31c6
7 files changed
+182
-4
No files matched your search
@@ -19,6 +19,8 @@ class FakeTransport:
|
||||
# fail_next_write 触发时抛出的异常实例(默认 SDK 包装后的 TransportError;
|
||||
# 真实硬件路径常是 bleak 裸抛的 BleakError,测试可替换)
|
||||
self.fail_exc = TransportError("connection lost")
|
||||
self.firmware_revision = "HM42_AIO_V1.0.9"
|
||||
self.rxtx_uuid = "00001f1f-0000-1000-8000-00805f9b34fb"
|
||||
|
||||
async def __aenter__(self):
|
||||
self.enters += 1
|
||||
@@ -204,6 +206,8 @@ class TestStatus:
|
||||
assert s["connect_timeout"] == 90.0
|
||||
assert s["idle_timeout"] == 300.0
|
||||
assert s["idle_seconds"] is None # 无先前活动;status 自身不得把读数归零
|
||||
assert s["firmware_revision"] == "HM42_AIO_V1.0.9"
|
||||
assert s["rxtx_uuid"].startswith("00001f1f")
|
||||
await m.close()
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
||||
@@ -61,6 +61,12 @@ class TestSetTime:
|
||||
|
||||
|
||||
class TestCommandFrames:
|
||||
def test_rxtx_channel_by_firmware_family(self):
|
||||
assert P.select_rxtx_uuid("HM42_AIO_V1.0.9") == P.RXTX_CHAR_UUID_LEGACY
|
||||
assert P.select_rxtx_uuid("hm42_aio_v2") == P.RXTX_CHAR_UUID_LEGACY
|
||||
assert P.select_rxtx_uuid("PP_da14585_4.2") == P.RXTX_CHAR_UUID
|
||||
assert P.select_rxtx_uuid(None) == P.RXTX_CHAR_UUID
|
||||
|
||||
def test_parking(self):
|
||||
"""停车牌 "12" → EF1122(向量#4)"""
|
||||
assert P.parking_frame("12") == bytes([0xEF, 0x11, 0x22])
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
"""本机 BLE 传输层的固件通道选择测试。"""
|
||||
|
||||
import pytest
|
||||
|
||||
from ppclock import protocol as P
|
||||
from ppclock.transports import local
|
||||
|
||||
|
||||
class FakeCharacteristic:
|
||||
def __init__(self, uuid, properties):
|
||||
self.uuid = uuid
|
||||
self.properties = properties
|
||||
|
||||
|
||||
class FakeServices:
|
||||
def __init__(self):
|
||||
self.characters = {
|
||||
P.RXTX_CHAR_UUID_LEGACY: FakeCharacteristic(
|
||||
P.RXTX_CHAR_UUID_LEGACY, ["write"]),
|
||||
P.RXTX_CHAR_UUID: FakeCharacteristic(
|
||||
P.RXTX_CHAR_UUID, ["read", "write", "notify"]),
|
||||
}
|
||||
|
||||
def get_characteristic(self, uuid):
|
||||
return self.characters.get(str(uuid).lower())
|
||||
|
||||
|
||||
class FakeBleakClient:
|
||||
firmware_revision = "PP_da14585_4.2"
|
||||
fail_firmware_read = False
|
||||
|
||||
def __init__(self, address, timeout):
|
||||
self.address = address
|
||||
self.timeout = timeout
|
||||
self.services = FakeServices()
|
||||
self.is_connected = False
|
||||
self.notifications = []
|
||||
self.writes = []
|
||||
|
||||
async def connect(self):
|
||||
self.is_connected = True
|
||||
|
||||
async def disconnect(self):
|
||||
self.is_connected = False
|
||||
|
||||
async def read_gatt_char(self, uuid):
|
||||
if str(uuid).lower() == P.FIRMWARE_REVISION_UUID:
|
||||
if self.fail_firmware_read:
|
||||
raise RuntimeError("DIS unavailable")
|
||||
return self.firmware_revision.encode()
|
||||
return b""
|
||||
|
||||
async def write_gatt_char(self, uuid, data, response=True):
|
||||
target = uuid.uuid if hasattr(uuid, "uuid") else uuid
|
||||
self.writes.append((target, bytes(data), response))
|
||||
|
||||
async def start_notify(self, uuid, callback):
|
||||
target = uuid.uuid if hasattr(uuid, "uuid") else uuid
|
||||
self.notifications.append(target)
|
||||
|
||||
async def stop_notify(self, uuid):
|
||||
self.notifications.remove(uuid)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_hm42_selects_write_only_1f1f(monkeypatch):
|
||||
class HM42Client(FakeBleakClient):
|
||||
firmware_revision = "HM42_AIO_V1.0.9"
|
||||
|
||||
monkeypatch.setattr(local, "BleakClient", HM42Client)
|
||||
transport = local.BLETransport("18:BC:5A:7E:BB:1E")
|
||||
await transport.connect()
|
||||
|
||||
assert transport.firmware_revision == "HM42_AIO_V1.0.9"
|
||||
assert transport.rxtx_uuid == P.RXTX_CHAR_UUID_LEGACY
|
||||
assert not transport._notify_started
|
||||
await transport.write_rxtx(b"\xe1\x02\x02")
|
||||
assert transport._client.writes[-1][0] == P.RXTX_CHAR_UUID_LEGACY
|
||||
with pytest.raises(local.TransportError, match="不支持通知"):
|
||||
await transport.request_device_id()
|
||||
await transport.close()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_pp42_keeps_331f_with_notifications(monkeypatch):
|
||||
monkeypatch.setattr(local, "BleakClient", FakeBleakClient)
|
||||
transport = local.BLETransport("18:BC:5A:5D:BF:28")
|
||||
await transport.connect()
|
||||
|
||||
assert transport.rxtx_uuid == P.RXTX_CHAR_UUID
|
||||
assert transport._notify_started
|
||||
assert transport._client.notifications == [P.RXTX_CHAR_UUID]
|
||||
await transport.write_rxtx(b"\xe2")
|
||||
assert transport._client.writes[-1][0] == P.RXTX_CHAR_UUID
|
||||
await transport.close()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_unknown_firmware_preserves_331f_default(monkeypatch):
|
||||
class NoDISClient(FakeBleakClient):
|
||||
fail_firmware_read = True
|
||||
|
||||
monkeypatch.setattr(local, "BleakClient", NoDISClient)
|
||||
transport = local.BLETransport("AA:BB:CC:DD:EE:FF")
|
||||
await transport.connect()
|
||||
|
||||
assert transport.firmware_revision is None
|
||||
assert transport.rxtx_uuid == P.RXTX_CHAR_UUID
|
||||
await transport.close()
|
||||
Reference in new issue
Block a user