Connection Status Screen
Section titled “Connection Status Screen”Introduction
Section titled “Introduction”The Connection Status Screen is a full-screen LVGL UI component that provides real-time, interactive visibility into the active CNC transport link — whether that is WiFi (STA), Bluetooth Classic (SPP), Bluetooth BLE (GATT), Serial/UART, USB Serial, TCP Socket, or WebSocket. It is the diagnostic hub the user navigates to when a connection fails, stalls, or needs to be manually managed.
Unlike the compact ConnectionStatusComponent widget embedded in operational screens, this is a dedicated modal screen that exposes the full connection lifecycle: a color-coded header, protocol details, device info, and contextual action buttons that adapt to the precise connection state character reported by the transport layer.
Source files:
main/display/screens/connection_status_screen.hmain/display/screens/connection_status_screen.cpp
Architecture Overview
Section titled “Architecture Overview”The screen follows the same lifecycle patterns as firmware_status_screen — static module-level state, timer-based transitions, prepareForDestruction() guard, and UIManager registration — so developers already familiar with that screen can navigate this one immediately. See screens_architecture.md for the general screen system description.
Status Character Protocol
Section titled “Status Character Protocol”The connection model uses a single char per logical layer, published through ESP3DValues. See connection_management.md for the full protocol definition.
| Char | Meaning | Title bar color token |
|---|---|---|
C | Connected (transport or server fully established) | ESP3D_ACCENT_SELECT_COLOR (green) |
R | Read-only / Passive (connected but CNC control limited) | ESP3D_ACCENT_ACTION_COLOR (orange) |
T | Connecting (in progress, spinner shown) | ESP3D_ACCENT_ACTIVE_COLOR (blue) |
A | Authentication failed (wrong PIN / password) | ESP3D_ACCENT_ACTION_COLOR (orange) |
. | Radio/transport off (not attempting to connect) | ESP3D_DISABLED_COLOR (grey) |
? | Disconnected / unknown | ESP3D_ACCENT_ALERT_COLOR (red) |
Two independent status indices are tracked simultaneously:
connection_status→transport_char_: state of the transport layer (WiFi association, BT link, Serial readiness).server_status→server_char_: state of the CNC server connection on top of that transport (TCP socket peer, WebSocket handshake). Only meaningful when the output client is a socket or WebSocket client.
The displayed status character is computed by computeDisplayChar(), which mirrors the same logic used by the embedded ConnectionStatusComponent::compute_display_state():
This ensures that when WiFi is connected but the TCP/WS peer has not yet responded, the display correctly shows “Connecting” (blue, spinner) rather than the misleading “Connected” of the transport layer alone.
Component Layout
Section titled “Component Layout”The content area uses LVGL LV_FLEX_FLOW_COLUMN with center alignment. The spinner is always created in the column but hidden via LV_OBJ_FLAG_HIDDEN when not in connecting state, avoiding object creation/deletion overhead inside callbacks.
Button Layout and State Machine
Section titled “Button Layout and State Machine”The three virtual buttons are positioned left / center / right and their icon and enabled state are recalculated on every subscription callback via updateButtonsForStatus().
Button 0 — Transport Action (Left)
Section titled “Button 0 — Transport Action (Left)”Controls the transport layer: WiFi association, BT link, Serial open/close.
Icon mapping by transport type:
| Transport | ? state | C state | T state | A state |
|---|---|---|---|---|
| WiFi STA | wifi_s (enabled) | no_wifi_s | wifi_s (disabled) | unlock_b |
| BT Classic | connect_bt_b | disconnect_bt_b | connect_bt_b (disabled) | unlock_b |
| BT BLE | connect_bt_b | disconnect_bt_b | connect_bt_b (disabled) | unlock_b |
| Serial / UART | serial_m | disconnect_serial_m | serial_m (disabled) | — |
| UART Ext | ext_module_m | disconnect_ext_module_m | ext_module_m (disabled) | — |
Button 1 — Server Action (Center)
Section titled “Button 1 — Server Action (Center)”Present only in specific build configurations. Behavior depends on the active feature flags:
- WiFi + Socket Client or WebSocket Client (
ESP3D_SOCKET_CLIENT_FEATUREorESP3D_WS_CLIENT_SERVICE_FEATURE): controls the TCP/WS connection to the CNC host. Hidden when the active output client is not an IP-based CNC client. - Serial / UART (no BT, no WiFi socket): shows a “refresh init commands” button, visible only when transport is connected.
- BT builds: always hidden (BT host = server, single connection layer, no separate server control).
a14 changes (IP CNC client builds):
- No server saved: pressing the server button (or WiFi connecting during the WiFi setup flow,
open_server_scan_when_connected) opens the server scan screen instead of trying to connect to nothing. - Client running vs stopped:
server_statusalone cannot tell “retrying” from “stopped by the user” (both report?until the TCP link is up), so the screen also checks whether the IP CNC client task is alive. Running covers connected, read-only and retrying; a client stopped by the user is shown as not connected, not as connecting. After a press the button state is refreshed from the client state, sinceserver_statusmay not change. - Fallback to the server scan: while the screen shows the client trying to reach its server, a one-shot timer (
SERVER_AUTO_CONNECT_TIMEOUT_MS= 20 s: one TCP attempt can take 10 s + 5 s retry delay) is armed; it is disarmed as soon as the server is connected or the client stopped. On expiry the server scan opens so the user can confirm or pick another server (the client keeps retrying in the background). - WiFi setup flow: when WiFi connects after an SSID change (which blocked the CNC auto-reconnect), the screen opens the server scan if no server is saved, otherwise connects to the saved one with the same fallback.
Button 2 — Back (Right)
Section titled “Button 2 — Back (Right)”Always present and always enabled. Triggers the standard cleanup_timer → transition_timer chain that safely destroys this screen and navigates to config.return_screen (typically ESP3DScreenType::main).
What the Screen Shows (a14)
Section titled “What the Screen Shows (a14)”The screen is about the CNC link only:
- The WiFi row is shown and driven only when WiFi carries the CNC link (socket / WebSocket client output), whatever the radio mode (in the
wifi_ap_configfallback the user still needs to see the WiFi state to fix it). With a serial / UART Ext output the WiFi (remote / debug telnet) stays invisible. - The socket (telnet) server status label is shown only in WiFi STA with a WiFi CNC client output.
- UART Ext uses the serial baud rate setting when
UART_EXT_SAME_AS_SERIALis set. - Opening the BT scan screen is wrapped in
try/catch; the screen registers withregisterScreen(type, screen, prepareForDestruction).
Subscription Data Flow
Section titled “Subscription Data Flow”Thread safety: All
lv_obj_*calls happen on the LVGL task (Core 1) becauseESP3DValues::handle()is called from the LVGL tick timer and subscription callbacks are invoked synchronously fromhandle(). Transport tasks on Core 0 only callset_value(), which enqueues the update into a thread-safe ring buffer without touching LVGL objects.
Screen Lifecycle
Section titled “Screen Lifecycle”The prepareForDestruction() guard (is_prepared_for_destruction_ + cleanup_executed_) prevents double-unsubscription if both a timer callback and onScreenDestroy fire in quick succession — a real risk in the LVGL event model during rapid transitions. This pattern is described in detail in screen_transitions_flow.md.
Authentication Flows
Section titled “Authentication Flows”WiFi Authentication Failure (transport_char_ == 'A')
Section titled “WiFi Authentication Failure (transport_char_ == 'A')”The user pressed Btn 0 while transport status is 'A'. The screen opens inputScreen in alphanumeric (password) mode and returns to wifi_scan on completion.
Bluetooth PIN / BLE Passkey Failure (transport_char_ == 'A')
Section titled “Bluetooth PIN / BLE Passkey Failure (transport_char_ == 'A')”The openBTPinInput() helper selects the correct PIN length (4 digits for BT Classic HC-06, 6 digits for BLE passkey) and NVS setting index based on the active output client. Passing allow_empty=true permits an empty PIN, which means no authentication (SEC_NONE).
See Input_system.md for details on the PIN and alphanumeric keyboard modes.
Relationship to ConnectionStatusComponent
Section titled “Relationship to ConnectionStatusComponent”The compact ConnectionStatusComponent (defined separately for each CNC firmware variant in main/display/cnc/fluidnc/components/, main/display/cnc/grbl/components/, and main/display/cnc/grblhal/components/) is a lightweight embeddable widget shown inside operational screens (status screen, jog screen, probe screen).
| Aspect | ConnectionStatusComponent | connectionStatusScreen |
|---|---|---|
| Type | Inline widget (icon + spinner) | Full-screen modal |
| Purpose | Passive status indicator | Interactive diagnostic and action hub |
| Buttons | None — tap opens this screen | 3 adaptive action buttons |
| Navigation | Tap → opens connection_status screen | Back button → returns to return_screen |
| Status tracked | transport_char_ + server_char_ | transport_char_ + server_char_ |
| Display logic | compute_display_state() | computeDisplayChar() (identical logic) |
| Auth retry | Not available | Full PIN / password re-entry flow |
When the user taps the ConnectionStatusComponent icon, a timer fires createScreen(ESP3DScreenType::connection_status) with the parent screen set as return_screen, bringing up this full-screen view.
Build-Time Feature Guards
Section titled “Build-Time Feature Guards”The screen compiles conditionally based on active transport features. Only enabled features contribute code:
| Preprocessor symbol | Effect on this screen |
|---|---|
ESP3D_WIFI_FEATURE | Enables WiFi transport button, network label (WiFi: SSID), esp_wifi_sta_get_ap_info() |
ESP3D_BT_SERIAL_FEATURE | Enables BT Classic connect / disconnect / PIN flow |
ESP3D_BT_BLE_FEATURE | Enables BLE connect / disconnect / passkey flow |
ESP3D_SOCKET_CLIENT_FEATURE | Enables center button for TCP socket CNC connection |
ESP3D_WS_CLIENT_SERVICE_FEATURE | Enables center button for WebSocket CNC connection |
ESP3D_UART_EXT_FEATURE | Enables external UART module connect / disconnect |
ESP3D_SOCKET_SERVER_FEATURE | Adds socket_label_ showing local socket server state (WiFi STA only) |
Mutual exclusion:
ESP3D_SOCKET_CLIENT_FEATUREandESP3D_BT_SERIAL_FEATURE/ESP3D_BT_BLE_FEATUREare mutually exclusive at the build level, enforced bycmake/sanity_check.cmake. The center button logic reflects this: BT builds always hide Btn 1; WiFi + Socket builds show it only when the active output client is an IP client. See feature_resource_matrix.md for the full compatibility matrix.
Key Design Decisions and Constraints
Section titled “Key Design Decisions and Constraints”No LVGL Object Access from Background Tasks
Section titled “No LVGL Object Access from Background Tasks”All lv_obj_* calls (label text, color, visibility, spinner) happen exclusively inside subscription callbacks and button release callbacks, which both execute on the LVGL task (Core 1). Transport tasks on Core 0 only call ESP3DValues::set_value(), which enqueues the update into a thread-safe ring buffer without touching LVGL objects. This is the mandatory pattern for all UI updates in this project — see the LVGL constraints section of CLAUDE.md.
prepareForDestruction() Before Navigation
Section titled “prepareForDestruction() Before Navigation”Any code path that creates a new screen (Back press, PIN input entry, WiFi scan redirect) must call prepareForDestruction() first, or supply it as the prepare_current_screen_destruction callback. This unsubscribes all value callbacks before the LVGL object tree starts being torn down, preventing callbacks from firing on a partially-destroyed widget tree during the transition delay.
std::nothrow Allocation
Section titled “std::nothrow Allocation”GenericScreen is allocated with new (std::nothrow) to prevent uncaught exceptions in the LVGL context. An uncaught exception in an LVGL callback would reset the board. A failed allocation is logged with heap diagnostics and the function returns early, leaving the existing screen intact.
I4 Icon Images — No Recolor
Section titled “I4 Icon Images — No Recolor”The status_s icon in the title bar uses LVGL 9.2’s I4 (4-bit indexed) image format. Applying image_recolor with LV_OPA_COVER on indexed images silently drops pixel alpha, making the icon invisible. The palette is pre-baked to near-white pixels that render correctly on all title-bar background colors without requiring runtime recolor.
Spinner Always in the Flex Column
Section titled “Spinner Always in the Flex Column”The spinner is created once at screen creation time and inserted into the content flex column. It is shown or hidden with LV_OBJ_FLAG_HIDDEN based on computeDisplayChar() == 'T'. This avoids the LVGL object creation and deletion cost inside a subscription callback that fires on every status change.
Color-Coded Labels (WiFi + Socket Mode)
Section titled “Color-Coded Labels (WiFi + Socket Mode)”In WiFi + socket/WebSocket builds, the network label and device info label use three-level color coding updated on every status callback:
- Grey (
ESP3D_DISABLED_COLOR): WiFi is not associated — CNC host is unreachable. - Orange (
ESP3D_INDICATOR_WARNING_COLOR): WiFi is up but CNC is not connected. - Normal text (
ESP3D_SCREEN_BACKGROUND_TEXT_COLOR): both layers are connected.
Related Documentation
Section titled “Related Documentation”- screens_architecture.md — Screen system overview,
GenericScreenbase class, UIManager screen registry - screen_transitions_flow.md — Timer-based transition patterns:
cleanup_timer,transition_timer,prepareForDestruction()guard - connection_management.md — Full connection status protocol (
U,T,C,?,A), shared initialization sequence across transports - Input_system.md —
inputScreenPIN / password entry modal used for authentication retry flows - ui_components.md —
VirtualButtonsComponent,GenericScreen, and other shared UI building blocks - values.md —
ESP3DValuesobservable store, subscription API, thread-safety model - feature_resource_matrix.md — WiFi / BT / socket-client mutual exclusion rules, resource budgets