Skip to content

Communication Transports Module

The Communication_Transports module (main/modules/) provides all CNC controller link implementations for the pendant firmware. It abstracts the physical and network medium through a common ESP3DClient base class, presenting a uniform priority-aware message queue interface to the GCode host and command dispatcher regardless of which transport is active.

Each transport is independent and mutually exclusive at build time: exactly one CNC-link transport is compiled in per firmware image. The module covers these transport options:

TransportSub-pathPhysical mediumBuild flag
Serial UARTserial/UART pinsalways available
Bluetooth SPPbt_serial/Classic BluetoothESP3D_BT_SERIAL_FEATURE
Bluetooth BLEbt_ble/BLE GATTESP3D_BT_BLE_FEATURE
USB Serial (OTG)usb_serial/USB Host (VCP)ESP3D_USB_SERIAL_FEATURE
USB CDC device (a14)usb_cdc_device/Native USB device (TinyUSB, CDC #0)ESP3D_USB_CDC_DEVICE_FEATURE
Socket Client (TCP)socket_client/WiFi TCPSOCKET_CLIENT_SERVICE
Socket Server (TCP)socket_server/WiFi TCPSOCKET_SERVER_SERVICE
WebSocket Clientwebsocket_client/WiFi WS/WSSESP3D_WS_CLIENT_SERVICE_FEATURE

A special internal rendering client (rendering/) acts as an in-process sink, routing commands directly to the active GCode handler without any physical medium.


Network / Hardware

CNC Integration

Communication Transports (this module)

Core Platform

popRx → process()

popRx → process()

popRx → process()

popRx → process()

popRx → process()

popRx → process()

popRx → process()

popRx → process()

route

process(msg)

process(msg)

process(msg)

process(msg)

process(msg)

process(msg)

process(msg)

set_value

NVS reads on begin()

NVS reads on begin()

NVS reads on begin()

NVS reads on begin()

NVS reads on begin()

NVS reads on begin()

NVS reads on begin()

esp3dCommands

(command dispatcher)

ESP3DValues

(observable state)

ESP3DSettings

(NVS)

ESP3DClient

(base class - queues + mutexes)

ESP3DSerialClient

serial/

ESP3DBTSerialClient

bt_serial/

ESP3DBTBleClient

bt_ble/

ESP3DUsbSerialClient

usb_serial/

ESP3DSocketClient

socket_client/

ESP3DSocketServer

socket_server/

ESP3DWebsocketClient

websocket_client/

ESP3DRenderingClient

rendering/

ESP3DGCodeHandlerService

(FluidNC / grbl / grblHAL)

ESP3DGCodeHostService

(streaming + flow control)

UART Driver

Bluedroid Stack

(GAP + SPP / GATTC)

USB Host + CDC-ACM

VCP drivers

lwIP BSD Sockets

esp_websocket_client

(RFC 6455)

All transports implement the same lifecycle interface inherited from ESP3DClient:

ESP3DClient

-_rx_queue deque

-_tx_queue deque

+begin() : bool

+handle()

+end()

+process(msg)

+flush()

+addRxData(msg) : bool

+addTxData(msg) : bool

+popRx() : ESP3DMessage

+popTx() : ESP3DMessage

+enqueueTxByPriority(msg) : bool

+clearRxQueue()

+clearTxQueue()

+getRxMsgsCount() : size_t

+getTxMsgsCount() : size_t

+setRxMutex(m)

+setTxMutex(m)

ESP3DSerialClient

+change_baud_rate() +swap_rx_tx()

ESP3DBTSerialClient

+scan(devices) +connect() +disconnect()

ESP3DBTBleClient

+scan(devices) +connect() +disconnect()

ESP3DUsbSerialClient

+connectDevice()

ESP3DSocketClient

+connect() +disconnect() +stopAutoConnect()

ESP3DSocketServer

+getClient() +readSockets() +clientsConnected()

ESP3DWebsocketClient

+connect() +disconnect() +stopAutoConnect()

ESP3DRenderingClient

TX Queue(ESP3DClient)esp3dCommandshandle()(main loop)RX Queue(ESP3DClient)Active Transport(RX task / callback)CNC ControllerTX Queue(ESP3DClient)esp3dCommandshandle()(main loop)RX Queue(ESP3DClient)Active Transport(RX task / callback)CNC Controllerraw bytes / frameLine assembly into bufferpushMsgToRxQueue(line)popRx()ESP3DMessage*process(msg)enqueueTxByPriority(gcode_line)popTx()ESP3DMessage*send bytes / frame

Connection Status State Machine (shared across all transports)

Section titled “Connection Status State Machine (shared across all transports)”

not started

begin() / connect() called

firmware identified\n(init command response received)

connection failed / timeout

link lost / inactivity timeout

authentication failure (BT/BLE)

auto-reconnect attempt

end() called

end() called

U

T

C

QM

A

connection_status = 'T'

connection_status = 'C'

connection_status = '?'

connection_status = 'A'

no PSRAM:

mutually exclusive

no PSRAM:

mutually exclusive

one BT radio

same CNC-over-WiFi role

same CNC-over-WiFi role

same WiFi CNC role

one OTG controller

(host vs device)

Serial UART

(default CNC link)

BT Serial SPP

BT BLE GATT

USB Serial

USB CDC device

Socket Client

(WiFi CNC)

Socket Server

(WiFi listen)

WebSocket Client

(WiFi WS CNC)

WiFi transports

(SOC / SOSERVER / WSC)

Exclusions are enforced at build time by cmake/sanity_check.cmake. See docs/features/feature_resource_matrix.md for the full compatibility matrix.


ESP3DSerialClient — main/modules/serial/

Section titled “ESP3DSerialClient — main/modules/serial/”

UART transport (the default CNC link). Runs a dedicated FreeRTOS RX task (esp3d_serial_rx_task). Supports runtime baud-rate change (change_baud_rate()) and RX/TX pin swap (swap_rx_tx()). Implements a 10 s ping / 30 s inactivity-timeout watchdog. Releases Bluetooth controller memory at begin() when no BT feature is active (~70 KB DRAM recovered).

Key files:

  • main/modules/serial/esp3d_serial_client.h — ESP3DSerialClient class
  • main/modules/serial/esp3d_serial_client.cpp — implementation + FreeRTOS task
  • main/modules/serial/esp3d_serial_config.h — esp3d_serial_config_t

ESP3DBTSerialClient — main/modules/bt_serial/

Section titled “ESP3DBTSerialClient — main/modules/bt_serial/”

Bluetooth Classic SPP transport. Manages Bluedroid stack lifecycle (controller → Bluedroid → GAP → SPP). Supports device scanning (scan()), legacy PIN authentication, bond clearing, and exponential back-off auto-reconnect (5 attempts, 5 s → 80 s). Releases BLE memory at begin().

Key files:

  • main/modules/bt_serial/esp3d_bt_serial_client.h — ESP3DBTSerialClient class
  • main/modules/bt_serial/esp3d_bt_serial_client.cpp — GAP/SPP callbacks + lifecycle
  • main/modules/bt_serial/esp3d_bt_device.h — BTDevice (scan result)
  • main/modules/bt_serial/esp3d_bt_serial_config.h — esp3d_bt_serial_config_t

BLE GATT Client transport targeting UART-over-BLE service UUID 0xFFF0 (BTT module protocol). Negotiates MTU (default 247 bytes), discovers service/characteristic handles, enables notifications via CCCD, and fragments TX frames by MTU−3. Implements Secure Connections pairing with MITM protection and passkey support.

Key files:

  • main/modules/bt_ble/esp3d_bt_ble_client.h — ESP3DBTBleClient class
  • main/modules/bt_ble/esp3d_bt_ble_client.cpp — GAP/GATTC callbacks + lifecycle
  • main/modules/bt_ble/esp3d_bt_ble_config.h — esp3d_bt_ble_config_t

ESP3DUsbSerialClient — main/modules/usb_serial/ + hardware/drivers_usb_otg/usb_serial/

Section titled “ESP3DUsbSerialClient — main/modules/usb_serial/ + hardware/drivers_usb_otg/usb_serial/”

Two-layer USB serial transport. The hardware driver layer (hardware/drivers_usb_otg/usb_serial/) manages the ESP32-S3 USB OTG PHY in host mode, installs the CDC-ACM host driver, and registers six VCP chipset drivers (FT23x, CP210x, CH34x built-in; PL2303, CH9102, STM32 custom). The application layer (main/modules/usb_serial/) handles connection polling, RX buffering, and GCode pipeline integration.

Key files:

  • hardware/drivers_usb_otg/usb_serial/usb_serial.cpp — PHY init, task, VCP registration
  • main/modules/usb_serial/esp3d_usb_serial_client.h — ESP3DUsbSerialClient class
  • main/modules/usb_serial/esp3d_usb_serial_client.cpp — connection task + callbacks

ESP3DUsbCdcDeviceClient — main/modules/usb_cdc_device/ + hardware/drivers_usb_device/usb_cdc_device/ (a14)

Section titled “ESP3DUsbCdcDeviceClient — main/modules/usb_cdc_device/ + hardware/drivers_usb_device/usb_cdc_device/ (a14)”

Client on CDC #0 of the TinyUSB dual CDC driver (CDC #1 carries the logs, see logging_backends.md). The board is the USB device here; with USB Serial it is the host. Two roles, depending on the selected output client:

RoleWhenBehaviour
Command channel (default)Output client is not usb_cdc_deviceA PC terminal sends ESP3D commands and G-code, gets the direct answers and a monitoring copy of the all_clients broadcasts while it holds the port open (DTR). Same model as the telnet socket_server client. Enabled with [ESP935] (ENABLE / DISABLE at next boot, CLOSE until boot or ENABLE)
CNC link[ESP950]USB-CDC (output client usb_cdc_device)The USB host is the machine side; same contract as the usb_serial client: init command ($I…) once per connection, ping / inactivity cycle, connection status, every G-code line queued (no observer drop). Started by ESP3DXStream whatever [ESP935] says. The host must assert DTR
  • isConnected(): enumerated, not suspended and DTR asserted; canSendData() = started and connected.
  • Own FreeRTOS task (readData(): session tracking, waits up to 10 ms for data); static line assembly buffer (ESP3D_USB_CDC_DEVICE_RX_BUFFER_SIZE, 512 on the 1.47” boards), no allocation in the RX path; driver overruns are reported.
  • Authentication (when serial authentication is not disabled): pwd= handling per line through esp3dCommands.checkCommandChannelLine(); logout() for [ESP500]LOGOUT.
  • Build rules (cmake/sanity_check.cmake): ESP32-S2 / S3 only; the board must opt in (BOARD_USB_CDC_DEVICE_SUPPORTED, USB connector on native GPIO19/20 with those pins free); exclusive with USB_SERIAL_SERVICE (host and device share one OTG controller). Today only the two 1.47” boards opt in (sdkconfig.usb_cdc_device).

Driver: see Hardware_Peripheral_Drivers.md, “Native USB Device”.

ESP3DSocketClient — main/modules/socket_client/

Section titled “ESP3DSocketClient — main/modules/socket_client/”

WiFi TCP client transport (Telnet-style). Implements a self-healing RX task that performs non-blocking connect() / recv() / send() loops without external orchestration. Guards against premature getaddrinfo() (fast inet_aton() path for plain IPs). Applies a 5 s EAGAIN retry budget on congested WiFi TX and a 30 s inactivity timeout.

Key files:

  • main/modules/socket_client/esp3d_socket_client.h — ESP3DSocketClient class
  • main/modules/socket_client/esp3d_socket_client.cpp — RX task + state machine

ESP3DSocketServer — main/modules/socket_server/

Section titled “ESP3DSocketServer — main/modules/socket_server/”

WiFi TCP server transport. Accepts up to two simultaneous inbound telnet-style clients. Performs per-session optional authentication (ESP3D_AUTHENTICATION_FEATURE). Routes unicast replies (by socket fd) and broadcast messages across connected clients.

Key files:

  • main/modules/socket_server/esp3d_socket_server.h — ESP3DSocketServer + ESP3DSocketInfos
  • main/modules/socket_server/esp3d_socket_server.cpp — accept loop + RX/TX dispatch

ESP3DWebsocketClient — main/modules/websocket_client/

Section titled “ESP3DWebsocketClient — main/modules/websocket_client/”

WiFi WebSocket (WS/WSS) client transport. Built on the vendored components/esp_websocket_client/ (RFC 6455). Supports a webui-v3 binary subprotocol for FluidNC compatibility. Decouples the IDF event-callback context from the RX task using a FreeRTOS chunk queue (WsChunk, 128 bytes per slot, depth 24).

Key files:

  • main/modules/websocket_client/esp3d_websocket_client.h — ESP3DWebsocketClient class
  • main/modules/websocket_client/esp3d_websocket_client.cpp — event handler + RX task
  • components/esp_websocket_client/esp_websocket_client.c — vendored WS transport

ESP3DRenderingClient — main/modules/rendering/

Section titled “ESP3DRenderingClient — main/modules/rendering/”

Internal in-process sink. Receives messages from esp3dCommands and delivers them directly to esp3dGcodeHandler.processCommand() via a FreeRTOS task polling at 10 ms intervals. No external endpoint — used to route locally-dispatched GCode commands on the pendant itself.

Key files:

  • main/modules/rendering/esp3d_rendering_client.h — ESP3DRenderingClient class
  • main/modules/rendering/esp3d_rendering_client.cpp — FreeRTOS task + dispatch

  • docs/architecture/connection_management.md — shared initialization sequence, "U"/"T"/"C"/"?"/"A" status codes, and cross-transport connection model
  • docs/architecture/gcode_host_architecture.md — GCode host integration and init-command sequence consumed by all transports
  • docs/architecture/gcode_host_streaming_flow.md — flow-control and in-flight cap mechanism relevant to TX from transports
  • docs/features/feature_resource_matrix.md — full transport compatibility matrix, WiFi/CNC SKU model, resource ticket accounting
  • docs/guides/esp32_memory_constraints.md — heap fragmentation, WiFi vs BT RAM budget, allocation rules
FileRole
main/core/includes/esp3d_client.hESP3DClient base class — dual-deque queues, message lifecycle
main/core/includes/esp3d_commands.hESP3DCommands — routes received messages to handlers
main/core/includes/esp3d_settings.hESP3DSettings — NVS reads on begin()
main/modules/values/esp3d_values.hESP3DValues — connection_status / server_status observables
cmake/sanity_check.cmakeBuild-time mutual exclusion enforcement