Skip to content

Accessing the API over USB

The USB transport reuses the same route handlers via src/common/usb_comms.py. Requests are read from the serial console as route|headers|body lines and responded to with JSON.

Host-side scripts cannot import the MicroPython modules. Use the standalone client below based on dev/usb_coms_demo.py to talk to the board over serial.

Frame format

Each request line contains three pipe-delimited fields. Escape literal pipes in headers or body as \|. Headers are provided as raw HTTP-style text (e.g. Content-Type: application/json on separate lines) and the body is optional.

Host demo snippet

Save the following as usb_client.py (adapted from dev/usb_coms_demo.py) and run it locally:

#!/usr/bin/env python3
import json
import time

import serial


def send_and_receive(port: str, route: str, headers=None, body_text=""):
    ser = serial.Serial(port=port, baudrate=115200, timeout=10)
    time.sleep(2)  # allow the device to reset
    headers = headers or {"Content-Type": "application/json"}
    header_text = "\n".join(f"{k}: {v}" for k, v in headers.items())
    frame = f"{route}|{header_text}|{body_text}\n"
    ser.write(frame.encode())
    prefix = "USB API RESPONSE-->"
    while True:
        line = ser.readline().decode(errors="replace").strip()
        if not line.startswith(prefix):
            continue
        payload = json.loads(line[len(prefix) :])
        body_raw = payload.get("body")
        if isinstance(body_raw, str):
            try:
                payload["body"] = json.loads(body_raw)
            except json.JSONDecodeError:
                pass
        return payload


if __name__ == "__main__":
    port = "/dev/ttyACM0"  # adjust for your platform
    print(send_and_receive(port, "/api/version"))
    # Authenticated call: fetch challenge then include headers
    challenge_resp = send_and_receive(port, "/api/auth/challenge")
    print("challenge", challenge_resp.get("body"))

The helper opens the serial connection, writes a framed request, and parses the JSON response emitted by the firmware. Expand it with additional routes as needed.