Repository navigation
ConsolePortSharing
Lets one owner take the console's port for itself — for example a binary protocol on the USB-Serial-JTAG port that the console normally uses — and give it back later. While the port is claimed nothing else writes text to it.
On most ESP32-S3/C3/C6 boards the console and the only USB connection are the same USB-Serial-JTAG port. Something that needs that port as a clean byte pipe — the RaftROS serial link is the first user — cannot tolerate a single stray log line. A Raft image writes to the console from several places:
| Writer / reader | Route | Silenced by |
|---|---|---|
Raft LOG_x
|
LoggerCore (direct USB-Serial-JTAG writes once the driver is installed, printf before) |
RaftConsolePort::claim() |
ESP-IDF ESP_LOGx (WiFi, MQTT, LogManager, WebServer, ...) |
the esp_log_set_vprintf hook (SerialConsole installs one) |
claim() |
printf / stdout / stderr
|
VFS to the console | claim() |
ROM printf (esp_rom_printf, ESP_EARLY_LOG, ESP_DRAM_LOG, often from ISRs) |
straight to the hardware | claim() |
| Console replies and the RICSerial channel |
SerialConsole::putStr / sendMsg
|
SerialConsole releasePort
|
| Console input | SerialConsole::getChar |
SerialConsole releasePort
|
Readers are SysMods, so the owner tells them separately (see SerialConsole); everything else is handled by RaftConsolePort.
#include "RaftConsolePort.h"
bool RaftConsolePort::claim(const char* owner, RaftConsoleTextSink sink = nullptr);
bool RaftConsolePort::release(const char* owner);
bool RaftConsolePort::isClaimed();
void RaftConsolePort::setSink(RaftConsoleTextSink sink);
bool RaftConsolePort::divert(const char* text, uint32_t len); // for console writers| Call | Effect |
|---|---|
claim(owner, sink) |
Stops LoggerCore's console write; replaces the ESP-IDF log hook (saving the previous one); fflushes stdout and freopens it to /dev/null (one FILE is shared by every task, so this covers all of them); points ROM printf channel 1 at a no-op. Text that would have gone to the console is given to sink if one is set. Returns false if another owner holds the port. |
release(owner) |
Restores each of the above: ROM output as ESP-IDF's startup sets it for the configured console, stdout back to /dev/console, the saved log hook. Only the claiming owner can release. |
isClaimed() |
Any task. |
divert(text, len) |
For code that writes to the console itself: returns true (and hands the text to the sink) if the port is claimed, in which case the caller must not write it. LoggerCore uses this. |
RaftConsoleTextSink is void (*)(const char* text, uint32_t len). It is called from whichever task logged, so it must be short and must not block or log.
claim() and release() are meant to be called from the main loop. On Linux builds they only track the flag.
Other loggers registered with LoggerCore (the LogManager network destinations, for example) still receive every line while the port is claimed — only the console write is diverted.
// Take the port
getSysManager()->sendCmdJSON("SerialConsole", R"({"cmd":"releasePort"})");
RaftConsolePort::claim("MyLink");
// ... the port is yours: use the usb_serial_jtag driver directly ...
// Give it back
RaftConsolePort::release("MyLink");
getSysManager()->sendCmdJSON("SerialConsole", R"({"cmd":"reclaimPort"})");Log a last line before claiming that says how to get the console back; after the claim nothing more reaches it.
- Panic output and the boot ROM's messages are written at reset, outside any claim.
- Code that writes to the USB-Serial-JTAG hardware or driver directly (rather than through the routes above) is not covered. None of the Raft libraries does, apart from
LoggerCoreand SerialConsole.
Getting Started
- Quick Start
- Architecture at a Glance
- Writing Your First SysMod
- Adding a Comms Channel
- Adding an I2C Device Type
- PlatformIO / Arduino
Scaffolding & Building
- Raft CLI
- SysTypes
- Top-Level SysType
- Build Process
- WebUI Build Pipeline
- File System
- Partitions & Flash
- Local Dev Libraries
- Library Developer Guide
Architecture
Built-in SysMods
- NetworkManager
- WiFi Troubleshooting
- BLEManager
- WebServer
- MQTTManager
- SerialConsole
- CommandSerial
- CommandSocket
- CommandFile
- FileManager
- LogManager
- ESPOTAUpdate
- StatePublisher
- Remote Logging
- Data Source Registration
Comms & Protocols
- Stack Overview
- Comms Channels
- ProtocolExchange
- RICREST Protocol
- Real-Time Streams
- Adding REST Endpoints
- Built-in REST Endpoints
- File Download (OKTO)
- OTA Update Flow
Devices & Buses
- DeviceManager
- Device Manager REST API
- Device Factory & Classes
- Device Type Records
- Adding an I2C Device Type
- Device Data Publishing
- Data Logger
- I2C Bus
- I2C Device Scanning
- I2C ID & Polling
- MotorControl Overview
- MotorControl Config
- MotorControl Commands
ROS 2
Helpers
Reference