from __future__ import annotations import tempfile import time from pathlib import Path import pytest from cognitive_agent.application.calibration import protocol from cognitive_agent.application.calibration.service import CalibrationService def test_protocol_matches_android_golden_vectors() -> None: assert protocol.crc8(b"123456789") == 0x4B vectors = ( ( protocol.command(0x00, protocol.OP_HELLO, protocol.AXIS_ALL), "A1 00 01 FF 00 00 00 55", ), ( protocol.command(0x01, protocol.OP_ARM, protocol.AXIS_ALL, 0x4E37), "A1 01 02 FF 37 4E 00 0A", ), ( protocol.command(0x23, protocol.OP_CALIBRATE, protocol.AXIS_ALL), "A1 23 10 FF 00 00 00 33", ), ( protocol.command(0x24, protocol.OP_MOVE_PERMILLE, 0, 1000), "A1 24 11 00 E8 03 00 78", ), ( protocol.command(0x25, protocol.OP_STOP, protocol.AXIS_ALL), "A1 25 12 FF 00 00 00 6E", ), ) for actual, expected in vectors: assert actual == bytes.fromhex(expected) def test_protocol_parses_status_and_rejects_bad_crc() -> None: ack = protocol.parse(0x621, bytes.fromhex("B1 22 10 02 00 07 01 A9")) assert isinstance(ack, protocol.Ack) assert ack.accepted controller = protocol.parse(0x622, bytes.fromhex("C1 01 00 17 07 FF 02 4E")) assert isinstance(controller, protocol.ControllerStatus) assert controller.can_ready assert controller.motor_ready assert controller.armed frame = bytearray.fromhex("D1 00 F0 00 E0 01 17 40") frame[2] ^= 1 with pytest.raises(protocol.ProtocolError): protocol.parse(0x630, bytes(frame)) def test_simulation_uses_real_wire_boundary_and_generates_pose() -> None: with tempfile.TemporaryDirectory() as directory: service = CalibrationService(Path(directory)) service.start() try: initial = service.snapshot() assert initial["transport"] == { "mode": "hardware", "state": "disconnected", "detail": "尚未连接", } connected = service.connect_can({"mode": "simulation"}) assert connected["transport"]["state"] == "online" assert connected["controller"]["can_ready"] assert connected["controller"]["motor_ready"] assert [axis["range"] for axis in connected["axes"]] == [480, 647, 917, 373] service.move(0, 800) time.sleep(0.2) moving = service.snapshot() assert moving["controller"]["armed"] assert moving["axes"][0]["moving"] time.sleep(0.45) pose = service.snapshot()["mqtt"] assert pose["state"] == "simulated" assert pose["count"] >= 1 assert "Seat_cushion" in pose["areas"] stopped = service.stop() assert not stopped["controller"]["armed"] finally: service.close()