pub struct DeviceHandle {Show 19 fields
pub id: String,
pub mac: Option<String>,
pub port_path: String,
pub baud_rate: u32,
pub native_usb: bool,
pub serial_connected: AtomicBool,
pub collection_running: AtomicBool,
pub firmware_verified: AtomicBool,
pub cmd_tx: Sender<String>,
pub csi_tx: Sender<Vec<u8>>,
pub output_mode_tx: Sender<OutputMode>,
pub session_file_tx: Sender<Option<String>>,
pub info_request_tx: Sender<InfoResponder>,
pub config: Mutex<DeviceConfig>,
pub device_info: Mutex<Option<DeviceInfo>>,
pub fault: Mutex<Option<String>>,
pub recovery_cycles: AtomicU32,
pub shutdown: CancellationToken,
pub profile: Arc<dyn CsiProfile>,
}Expand description
All per-device runtime state for one attached ESP32.
Wrapped in an Arc and shared between the device’s serial task and every
route handler that resolves it from the registry. The inner atomics,
mutexes, and watch senders are plain (not individually Arc-wrapped): the
single Arc<DeviceHandle> provides the sharing.
Fields§
§id: StringStable identifier used in URL paths. Derived from the board’s MAC
(D0-CF-13-E2-90-E8) when known, so it survives a ttyACMx
renumbering; falls back to a CLI alias or the sanitized port basename.
mac: Option<String>Stable hardware identity: the board’s MAC as reported by its USB
iSerialNumber descriptor (AA:BB:CC:DD:EE:FF), read at scan time
without opening the port. None for adapters that expose no serial
number (most CP210x/CH340 UART bridges). This is what lets the
supervisor follow a board across a re-enumeration that changes its
/dev/ttyACMx number — see crate::supervisor::run_supervisor. The
firmware also echoes it in the info block (mac=) as confirmation.
port_path: StringUSB serial port path used to reach the ESP32 (e.g. /dev/ttyUSB0).
Pinned for the lifetime of the per-device task; if the board
re-enumerates under a different node the supervisor tears this task
down and respawns it (keyed by Self::mac) at the new path.
baud_rate: u32Baud rate negotiated at startup. The serial task and the RTS-reset handler both read this so a single source of truth governs the link.
native_usb: boolTrue when this port is an Espressif native USB-Serial-JTAG endpoint
(VID 0x303A). Such chips re-enumerate their USB device when reset, so
the serial task must NOT pulse RTS/DTR on connect — doing so drops the
/dev/ttyACMx node (often returning under a different number) and the
pinned-path reconnect loop can then never re-verify the device.
serial_connected: AtomicBoolWhether the serial task currently has an open and healthy ESP32 link.
collection_running: AtomicBoolBest-effort flag: true after successful start, false after reset/disconnect.
firmware_verified: AtomicBooltrue once the serial task (or an explicit /api/.../info call) has
observed a valid ESP-CSI-CLI/<version> magic block from the device.
Cleared on disconnect, on reset (until the post-reset re-verification
completes), and on a failed verification. Command endpoints refuse to
send while this is false.
cmd_tx: Sender<String>Send CLI command strings to the serial background task.
csi_tx: Sender<Vec<u8>>Broadcast raw CSI frame bytes (COBS-framed postcard) to this device’s WebSocket clients.
output_mode_tx: Sender<OutputMode>Notify the serial task of output-mode changes (stream / dump / both).
session_file_tx: Sender<Option<String>>Signal the serial task of the current session’s dump file path.
Some(path) → open/reuse that file; None → session ended, close file.
info_request_tx: Sender<InfoResponder>Issue an info command on the device and capture the magic block.
The serial task synchronously consumes the responder.
config: Mutex<DeviceConfig>Cached view of this device’s configuration.
device_info: Mutex<Option<DeviceInfo>>Last successfully parsed firmware identification block. None until
the first verification succeeds; cleared alongside firmware_verified.
fault: Mutex<Option<String>>Detected chip fault (e.g. the ESP32-C5/C6 USB-JTAG reset-loop wedge or
a ROM boot loop), with the recovery action, set by the serial task when
firmware verification keeps failing with a recognizable boot signature.
Cleared on successful verification. Surfaced via GET /api/devices.
recovery_cycles: AtomicU32Completed recovery attempts (the firmware restart rung, whose reboot
re-enumerates native USB and thus restarts the per-connection
escalation ladder). Carried across handle respawns (re-enumeration
replaces the handle!) via RecoveryCarryOver so an unrecoverable
device is restarted at most once and then declared faulted, instead
of being bounced through reboots forever. Cleared on successful
verification.
shutdown: CancellationTokenCancelled by the supervisor when the device is unplugged, signalling the serial task to tear down cleanly.
profile: Arc<dyn CsiProfile>Optional capability extensions (extra protocols/presets/format labels).
Inherited from the owning DeviceRegistry; the per-device serial task
consults it when labelling Parquet data_format.
Implementations§
Source§impl DeviceHandle
impl DeviceHandle
Sourcepub fn require_firmware(&self) -> Option<(StatusCode, Json<ApiResponse>)>
pub fn require_firmware(&self) -> Option<(StatusCode, Json<ApiResponse>)>
Returns an early-return tuple suitable for handlers when the firmware
has not yet been verified as esp-csi-cli-rs. Use this to short-circuit
any endpoint that issues a CLI command — sending commands to an
unverified device may interact with whatever bootloader/firmware is
listening in unintended ways.