Run minimal LPC845/LPC804 bring-up validation via JSON-RPC echo. Verifies the three transport components the bring-up sketch (examples/AutoResearchLpc/) exposes: 1. Serial.println — the response body itself ("REMOTE: {...}\\r\\n"). 2. FastLED log pipeline — the FL_DBG line from
(ctx: RunContext)
| 1524 | |
| 1525 | |
| 1526 | async def _run_bring_up_tests(ctx: RunContext) -> int: |
| 1527 | """Run minimal LPC845/LPC804 bring-up validation via JSON-RPC echo. |
| 1528 | |
| 1529 | Verifies the three transport components the bring-up sketch |
| 1530 | (examples/AutoResearchLpc/) exposes: |
| 1531 | 1. Serial.println — the response body itself ("REMOTE: {...}\\r\\n"). |
| 1532 | 2. FastLED log pipeline — the FL_DBG line from fl::Remote |
| 1533 | ("src/fl/remote/remote.cpp.hpp(151): Stored request ID for echo") |
| 1534 | that emits before the response. |
| 1535 | 3. JSON-RPC echo round-trip — TX {method:echo, params:[N], id:I} |
| 1536 | must produce RX {id:I, result:N, jsonrpc:"2.0"}. |
| 1537 | |
| 1538 | Uses raw serial (not ``RpcClient``) because the bring-up sketch binds |
| 1539 | ``echo`` as ``[](int v) -> int`` which expects a flat ``params:[N]`` |
| 1540 | JSON array; ``RpcClient.send`` wraps args one level deeper to support |
| 1541 | the AutoResearch.ino style where bindings take a struct. |
| 1542 | """ |
| 1543 | upload_port = ctx.upload_port |
| 1544 | assert upload_port is not None |
| 1545 | |
| 1546 | print() |
| 1547 | print("=" * 60) |
| 1548 | print("BRING-UP MODE — Serial + FastLED log + JSON-RPC echo") |
| 1549 | print("=" * 60) |
| 1550 | print() |
| 1551 | |
| 1552 | import serial as _serial # local — avoid top-level import in this hot path |
| 1553 | |
| 1554 | sentinel = 4242 |
| 1555 | ser = None |
| 1556 | try: |
| 1557 | print(" Opening serial port...", end="", flush=True) |
| 1558 | ser = _serial.Serial(upload_port, 115200, timeout=2) |
| 1559 | ser.dtr = False # type: ignore[assignment] |
| 1560 | ser.rts = False # type: ignore[assignment] |
| 1561 | await asyncio.sleep(0.5) |
| 1562 | ser.reset_input_buffer() |
| 1563 | await asyncio.sleep(2.0) # let boot banner drain |
| 1564 | ser.reset_input_buffer() |
| 1565 | print(f" {Fore.GREEN}ok{Style.RESET_ALL}") |
| 1566 | |
| 1567 | req = ( |
| 1568 | '{"jsonrpc":"2.0","method":"echo","params":[' |
| 1569 | + str(sentinel) |
| 1570 | + '],"id":1}\n' |
| 1571 | ) |
| 1572 | print(f" TX: {req.strip()}", flush=True) |
| 1573 | ser.write(req.encode()) |
| 1574 | ser.flush() |
| 1575 | |
| 1576 | # Collect for up to 5 seconds or until we see a complete REMOTE: line |
| 1577 | deadline = time.monotonic() + 5.0 |
| 1578 | accumulated = b"" |
| 1579 | while time.monotonic() < deadline: |
| 1580 | await asyncio.sleep(0.2) |
| 1581 | if ser.in_waiting: |
| 1582 | accumulated += ser.read(ser.in_waiting) |
| 1583 | if ( |
no test coverage detected