Skip to content

RaftSerialConsoleSysMod

Rob Dobson edited this page Oct 25, 2026 · 5 revisions

SerialConsole SysMod

Built-in SysMod that exposes the REST API over the console port - a UART, or the USB-Serial-JTAG port when that is the console (CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG). Lets a developer type API requests directly into the serial console and receive JSON responses, while simultaneously carrying a binary protocol channel (RICSerial / RICJSON) for tool-driven access.

Source: RaftSysMods/components/SerialConsole/

What it provides

  • ASCII command entry: type subscription?topic=devjson&rateHz=10 + Enter.
  • Deferred responses: an endpoint that replies later (e.g. devman/cmdraw, devman/typefile/check, datalog?action=start) can defer its reply, which is written when it is ready - so other commands' replies can come first. Replies include the request, so they can be matched.
  • Binary channel multiplexed on the same UART using ProtocolOverAscii: RICSerial (HDLC) frames are re-encoded so every byte has its top bit set, so they share the port with log text and typed input (bytes below 0x80). See RICREST Protocol → RICSerial framing for the encoding. Requests in these frames can have deferred responses like those on any RICREST channel.
  • Registers a Comms Channel so the binary side participates fully in the channel system.
  • XON/XOFF flow control hint via getXonXoff().

SysType configuration

{
    "name": "SerialConsole",
    "enable": 1,
    "uartNum": 0,
    "baudRate": 115200,
    "rxBuf": 4096,
    "txBuf": 4096,
    "crlfOnTx": 1,
    "protocol": "RICSerial"
}
Key Default Meaning
enable false Master switch
uartNum 0 ESP32 UART number
baudRate 115200 Baud rate
rxBuf 1024 on a UART, 4096 on USB-Serial-JTAG Driver receive buffer size
txBuf 4096 Driver transmit buffer size
crlfOnTx true Send CRLF on tx line endings
protocol "RICSerial" Protocol codec attached to the binary side

Receiving

Each loop() reads whatever has arrived (up to 1024 bytes) in one go. The protocol frame bytes in it are decoded from OverAscii and passed to the comms channel as one message; text goes to the command line. Processing stops after a complete command line (to run it), and any bytes left are kept for the next loop.

Before RaftSysMods 1.26.0 SerialConsole read at most 100 bytes a loop, one at a time, and a host's protocol frame of more than about 1 KB on the wire was lost (it arrived as many small messages that filled the channel's queue, and the USB-Serial-JTAG driver dropped bytes while its 1024-byte buffer was full). With the bulk read and the 4096-byte USB-Serial-JTAG buffer, file uploads over serial in 800-byte blocks sent one or two at a time work; larger batches (several KB on the wire at once) can still overflow the receive buffer, and are recovered, slowly, by the upload's timer acks.

Sending protocol frames

Outbound frames are OverAscii-encoded (at most 2 bytes per byte). The encoded frame is built on the stack when it fits in 1000 bytes, and in a heap (PSRAM where available) buffer when it is larger, so a large reply (e.g. a big filesection) can't overflow the stack.

REST endpoints exposed

Endpoint Method Purpose
console GET Console control (e.g. show registered endpoints)

JSON commands (receiveCmdJSON)

Sent from another SysMod with getSysManager()->sendCmdJSON("SerialConsole", ...):

Command Effect
{"cmd":"releasePort"} Stop reading from and writing to the port (console input, replies, and the binary channel - sendMsg returns false) until reclaimed. The driver stays installed.
{"cmd":"reclaimPort"} Resume normal operation.
{"cmd":"set","baudRate":n,"txBuf":n,"rxBuf":n} UART consoles only: change baud rate or driver buffer sizes.

Releasing the port

releasePort is for an owner that needs the console's port as a clean byte pipe for a while - the RaftROS serial link uses it on USB-Serial-JTAG. It only stops SerialConsole itself; other console output (Raft and ESP-IDF logging, printf, ROM printf) is silenced by RaftConsolePort, which the owner claims at the same time.

Notes

  • This is the recommended way to test Raft REST endpoints during bring-up — no network required.
  • Logging output (LOG_I etc.) shares the same port; the binary protocol uses MSB-set bytes so it does not collide with log text.
  • On a USB-Serial-JTAG console SerialConsole installs the USB-Serial-JTAG driver (with rxBuf / txBuf as its ring sizes) and an ESP-IDF log hook that writes to it.
  • Large replies on USB-Serial-JTAG. The driver takes a write whole or not at all, so a reply larger than the transmit ring (txBuf) used to be lost. Replies are now written in pieces of up to 1 KB without waiting; what doesn't fit is kept (in PSRAM, up to 64 KB) and written from loop() as the host reads, and later console output queues behind it, so the main loop is never held up and replies arrive whole (e.g. a 9.5 KB devman/typefile/check reply). If more than 64 KB is waiting (nothing on the host is reading), further output is dropped and a warning logged. Log lines from other tasks write to the port directly, so one can appear between the pieces of a large reply. (On a UART console, replies are written by uart_write_bytes, which waits for room.)
  • When nothing on the host is reading the USB port (no terminal has it open), the driver's transmit ring fills and stays full. Each console write then waits up to 10 ms (RAFT_LOGGER_USB_JTAG_WRITE_TIMEOUT_MS) and the text is dropped. In RaftCore versions after 1.58.1, once a write has timed out, later writes don't wait (and are dropped) until one succeeds again. A burst of log lines therefore costs one wait rather than 10 ms per line on the logging task, which is often the main loop. When a host starts reading again, output resumes with no lines lost after that point.
    • In RaftSysMods versions after 1.23.1 the ESP-IDF log hook writes through the same code (LoggerCore::writeToConsole()), so this applies to ESP-IDF logging as well as Raft logging.
    • Main-loop timing measured with a terminal attached can differ from timing with nothing reading the port, so measure both.

Related

Clone this wiki locally