195 lines
22 KiB
Markdown
195 lines
22 KiB
Markdown
# Command reference
|
||
|
||
UART0, authenticated `admin` SSH sessions, and the browser Admin shell use the same registered command implementations through one serialized dispatcher. The remote shells expose the operational registry, including interactive prompts, recovery-secret display, network diagnostics, reboot, and HTTPS/SSH material mutation. Initial administrator bootstrap and explicit recovery of an unavailable user database remain physically bound to UART0. A remote administrator cannot generate a replacement password for its own account, so the one-time value cannot be lost when the session is revoked. Run `help` for root commands and `<group> help` for a group summary. Configuration changes are RAM-only unless explicitly saved.
|
||
|
||
## System
|
||
|
||
| Command | Description |
|
||
|---|---|
|
||
| `memory` | Show free memory, minimum free memory, and largest blocks for internal RAM, DMA-capable RAM, and PSRAM. |
|
||
| `reboot` | Drain console output briefly and restart the ESP32. |
|
||
| `exit` | Close the current administrative SSH session after its acknowledgement drains; unavailable on UART0. Ctrl+D on an empty admin SSH command line does the same. |
|
||
|
||
## Role-based users
|
||
|
||
| Command | Description |
|
||
|---|---|
|
||
| `user status` / `user list` | Show database generation, capacity, administrator/bootstrap state, and all secret-free account summaries. |
|
||
| `user show <username>` | Show one account's role, ID, authentication generation, and SSH-key fingerprints. |
|
||
| `user bootstrap` | Set and confirm the `admin` password without echo, then promote the migrated account to `admin`. |
|
||
| `user bootstrap --generate` | Bootstrap `admin` with a generated 24-character password displayed once. |
|
||
| `user add <username> <user|admin>` | Create an account using a bounded no-echo password and confirmation prompt. |
|
||
| `user add <username> <user|admin> --generate` | Create an account with a generated password displayed once. |
|
||
| `user delete <username> --force` | Delete an account; the pre-bootstrap migrated `admin` and final administrator are protected. |
|
||
| `user role <username> <user|admin> --force` | Change a role; the final administrator cannot be demoted. |
|
||
| `user password <username>` | Set and confirm a new password without echo. |
|
||
| `user password <username> --generate` | Replace a password with a generated value displayed once. |
|
||
| `user key add <username>` | Prompt on UART0 or authenticated admin SSH for one bounded OpenSSH public-key line. |
|
||
| `user key add <username> <type> <base64>` | Import a key non-interactively; intended for authenticated admin SSH and also accepted on UART0. |
|
||
| `user key delete <username> <0..2> --force` | Delete one key by the index shown by `user show`. |
|
||
| `user key clear <username> --force` | Delete all public keys for an account. |
|
||
| `user recover --force` | When normal user-database initialization failed, explicitly replace its blob from the current legacy network credential. |
|
||
|
||
Usernames must match `[a-z][a-z0-9_-]{0,15}`. Passwords contain 12–64 printable ASCII characters. The fixed database supports eight users and three SSH keys per user; initial key types are `ssh-ed25519` and `ecdsa-sha2-nistp256`. A key may be assigned to multiple accounts but cannot be duplicated within one account. Password verifiers, salts, raw key blobs, and passwords are absent from ordinary status output. `Ctrl-C` cancels a password or key prompt, and generated passwords are shown once.
|
||
|
||
On the first Phase 8A boot, the old shared `admin` credential is imported as a role-`user` account, not silently granted administrator rights. Run `user bootstrap` from physical UART0 to establish the administrator. Phase 8B now authenticates HTTPS and SSH passwords through this database and enables stored SSH public keys. Before bootstrap, `web credentials rotate --force` and `web reset --force` synchronize the migrated verifier; after bootstrap, that legacy credential is recovery-only and does not authenticate or alter role-based users.
|
||
|
||
`user recover --force` is a destructive physical recovery operation and succeeds only while the database is unavailable. It replaces the user blob with one role-`user` account derived from the current legacy credential; run `user bootstrap` afterward. It does not erase unrelated NVS data. Successful password, role, key, bootstrap, and delete operations invalidate only that username's outstanding WebSocket tickets and active WebSocket/SSH sessions; unrelated users remain connected.
|
||
|
||
The administrator-only Settings dialog uses `/api/admin/users` for guided account create/list/edit/delete, role changes, entered or one-time generated passwords, and authorized Ed25519/P-256 key add/remove. Mutations include the displayed database generation and stable user ID, so a stale editor is rejected and reloaded instead of targeting a deleted/recreated account. CLI and browser mutations share `user_admin_service`; it serializes mutations with `admin_command_gate`, commits first, and then requests best-effort web and SSH revocation. Transport currentness checks remain authoritative if notification is incomplete. Entered keys/passwords and generated-password output are cleared from the dialog on close or failure.
|
||
|
||
## Local display
|
||
|
||
| Command | Description |
|
||
|---|---|
|
||
| `display status` | Show the runtime aging settings and OLED service state. |
|
||
| `display set dim-seconds <0..86400>` | Set the RAM inactivity delay before contrast drops to `1`; `0` disables dimming. |
|
||
| `display set off-seconds <0..86400>` | Set the RAM inactivity delay before the OLED switches off; `0` disables automatic off. |
|
||
| `display save` / `display load` | Save the working aging settings to NVS or load them. |
|
||
| `display defaults` / `display reset` | Apply 300/600-second defaults in RAM, or apply and persist them. |
|
||
|
||
When both transitions are enabled, `off-seconds` must be greater than `dim-seconds`. Applying settings counts as local UI activity. The administrator-only Settings dialog exposes the same typed Apply/Save/Load/Defaults/Reset behavior through `/api/admin/display`; all five operations are serialized with console display writers through `admin_command_gate`, and invalid aging combinations are rejected without applying them. At normal boot, an initialized OLED shows a bounded five-second identity animation before the status UI begins; it scrolls the device name in yellow and draws the compact upright-terminal logo in blue. A missing OLED remains nonfatal; after reconnecting it safely, one new button press requests a bounded reprobe and is consumed without navigating.
|
||
|
||
## Serial service
|
||
|
||
| Command | Description |
|
||
|---|---|
|
||
| `serial status` | Show UART1 state, configuration, modem signals, and ownership. |
|
||
| `serial start` / `serial stop` | Start or release the physical UART1 service. |
|
||
| `serial set <baud|data-bits|parity|stop-bits|flow|dtr|rts-threshold> <value>` | Change the working serial configuration and safely restart a running service. |
|
||
| `serial save` / `serial load` | Save the working configuration to NVS or load it. |
|
||
| `serial defaults` / `serial reset` | Apply defaults in RAM, or apply and persist them. |
|
||
| `serial counters` / `serial clear-counters` | Show or clear serial counters. |
|
||
|
||
Defaults are 115200 baud, 8 data bits, no parity, one stop bit, no flow control, and inactive DTR. Supported values: baud `110`–`1000000`; data bits `7` or `8`; parity `none`, `even`, or `odd`; stop bits `1` or `2`; flow `none` or `rts-cts`; DTR `inactive`, `active`, or `on-connect`; and RTS threshold `1`–`127` bytes. The broker exclusively owns serial data access.
|
||
|
||
## Session broker
|
||
|
||
| Command | Description |
|
||
|---|---|
|
||
| `broker status` / `broker clients` | Show broker state or connected clients. |
|
||
| `broker counters` / `broker clear-counters` | Show or clear broker counters. |
|
||
| `broker connect <name>` / `broker disconnect <client-id>` | Create or remove a console test client. |
|
||
| `broker request-writer <client-id>` / `broker release-writer <client-id>` | Request or relinquish the single writer lease. |
|
||
| `broker force-writer <client-id|none>` | Administratively assign or clear the writer lease. |
|
||
| `broker send-hex <client-id> <hex-bytes>` | Send hexadecimal bytes through a writer client. |
|
||
| `broker read <client-id> [maximum-bytes]` | Read queued serial output for a client. |
|
||
| `broker events <client-id>` | Show ownership and connection events for a client. |
|
||
|
||
Each client has a generation-safe ID. There can be one writer and multiple observers; a slow observer loses only its own queued output.
|
||
|
||
## Native USB CDC-ACM
|
||
|
||
| Command | Description |
|
||
|---|---|
|
||
| `usb` / `usb help` | Show USB command usage. |
|
||
| `usb status` | Show CDC connection, broker role, and runtime state. |
|
||
| `usb counters` / `usb clear-counters` | Show or clear USB counters. |
|
||
| `usb request-writer` / `usb release-writer` | Request or release USB writer ownership. |
|
||
|
||
Opening `/dev/ttyACM*` with DTR asserted creates the `usb-cdc` broker client, starts UART1 if needed, and requests writer ownership. It becomes an observer if another client is writer. USB data is binary-transparent. The host's CDC line coding is shown by `usb status` for diagnostics only; it does not alter UART1. Configure physical baud rate, framing, flow control, and DTR explicitly with `serial` commands and persist them with `serial save`.
|
||
|
||
## Wi-Fi
|
||
|
||
| Command | Description |
|
||
|---|---|
|
||
| `wifi status` / `wifi profiles` | Show Wi-Fi state or configured station profiles. |
|
||
| `wifi start` / `wifi stop` / `wifi reconnect` | Start, stop, or reconnect Wi-Fi. |
|
||
| `wifi next-profile` | Queue a switch to the enabled station profile after the currently active profile in priority order; wraps safely. |
|
||
| `wifi profile set <slot> <priority> <mixed|wpa3> <ssid>` | Set a station profile. |
|
||
| `wifi profile secret <slot>` | Set a profile password through a no-echo prompt. |
|
||
| `wifi profile enable|disable|delete <slot>` | Manage a station-profile slot. |
|
||
| `wifi ap policy <off|fallback|always>` | Configure fallback AP behavior. |
|
||
| `wifi ap ssid <ssid>` / `wifi ap channel <1..11>` | Set the AP name or channel. |
|
||
| `wifi ap secret` / `wifi ap show-secret` | Set or reveal the AP password. |
|
||
| `wifi save|load|defaults|reset` | Persist, restore, reset in RAM, or reset and persist configuration. |
|
||
| `wifi counters|clear-counters` | Show or clear Wi-Fi counters. |
|
||
| `wifi ping <host> [count]` | Send 1–20 IPv4 or IPv6 ICMP probes. |
|
||
| `wifi nslookup <host>` | Resolve and display unique IPv4/IPv6 addresses. |
|
||
| `wifi traceroute <host> [max-hops]` | Run IPv4 ICMP traceroute with up to 30 hops. |
|
||
|
||
`ping`, `nslookup`, and `traceroute` are root aliases. The four station-profile slots use lower priority values first. Edits to a disabled profile's SSID, priority, security mode, or secret are staged in RAM and do not interrupt the current Wi-Fi connection. Enabling or disabling a profile, changing an enabled profile, or changing AP policy/configuration applies the new radio policy and may reconnect Wi-Fi. Use `wifi save` to persist working changes.
|
||
|
||
The administrator-only Settings dialog uses `/api/admin/wifi-config` for typed station-profile, AP policy/SSID/channel, and write-only secret edits. Reads return only `secret_set` flags. Every mutation compares the exact working-configuration generation, and Save persists only that same generation; stale or exhausted generations fail closed without applying or saving another editor's state. On a conflict, the browser clears entered secrets and reloads current values without replaying the request.
|
||
|
||
## mDNS
|
||
|
||
| Command | Description |
|
||
|---|---|
|
||
| `mdns status` | Show the configured `sak-<suffix>.local` hostname and announcement state. |
|
||
| `mdns suffix <value>` | Set a 1–55-character lowercase hostname suffix in RAM. |
|
||
| `mdns save` / `mdns load` | Save the working suffix to its independent NVS record or load it. |
|
||
| `mdns defaults` / `mdns reset` | Restore the MAC-derived suffix in RAM, or restore and persist it. |
|
||
|
||
When the Wi-Fi station receives an IPv4 address, the Wi-Fi manager announces `sak-<suffix>.local`. The default suffix is the lower-case hexadecimal STA MAC address. Suffixes may contain lowercase ASCII letters, digits, and internal hyphens only. Changing a suffix while online causes a best-effort reannouncement; mDNS failures do not stop Wi-Fi, UART0, UART1, or native USB access.
|
||
|
||
## HTTPS web terminal
|
||
|
||
| Command | Description |
|
||
|---|---|
|
||
| `web` / `web help` | Show web-service command usage. |
|
||
| `web status` | Show HTTPS, browser-session, serial-WebSocket, and admin-WebSocket state. |
|
||
| `web start` / `web stop` | Start or stop HTTPS service. |
|
||
| `web counters` / `web clear-counters` | Show or clear web counters. |
|
||
| `web credentials show` | Display the legacy migration/recovery credential on UART0 or an authenticated remote admin shell; it is not a role-based network login. |
|
||
| `web credentials rotate --force` | Replace the legacy recovery credential and synchronize the migrated pre-bootstrap account only. |
|
||
| `web certificate info` | Display certificate identity and fingerprint. |
|
||
| `web certificate rotate --force` | Replace the HTTPS certificate and private key. |
|
||
| `web reset --force` | Explicitly replace missing, incompatible, or damaged legacy credentials and web material. |
|
||
|
||
HTTPS listens on port 443 only. Sign in with any current user-database username/password through the same-origin login page; explicit logout permits account switching without relying on a browser HTTP-authentication cache. The device stores at most eight opaque eight-hour browser sessions, with at most two retained per account, and sends the raw token only in a host-only secure cookie. State-changing requests require strict Origin and session-bound CSRF validation.
|
||
|
||
Both roles receive the offline browser serial terminal. Its one-time ticket and active WebSocket are bound to the exact browser session and obey the broker's one-writer rule. The combined **Connect serial**/**Disconnect serial** control closes only the serial WebSocket and pauses automatic reconnect when active. Account mutations revoke that account's browser sessions, serial/admin tickets, and WebSockets without disturbing unrelated accounts.
|
||
|
||
An administrator additionally receives a **Serial terminal**/**Admin shell** selector, typed Serial controls, guided user/password/role/authorized-key management, generation-safe Wi-Fi profile/AP/secret editing and saving, display-aging controls, and contextual Serial, Wi-Fi, broker-client, and writer-transfer popovers. The browser admin shell uses the same bounded editor, history, completion, prompts, serialized dispatcher, and registered command handlers as admin SSH and UART0; it never joins the serial broker. Switching terminal modes only changes visibility and focus: it does not close the serial WebSocket or release its writer lease. Writer transfer requires an explicit confirmation and atomically checks both the expected current writer and generation-safe target ID. Service/session controls beyond the guided serial/Wi-Fi actions, network diagnostics, security/danger operations, and unusual hardware/debug commands remain shell-only. Initial `user bootstrap` and `user recover --force` remain physical-UART0-only.
|
||
|
||
Typed mutation endpoints accept only body-backed URL-encoded forms bounded to 512 bytes and 10 unique fields; duplicate, oversized, malformed, stale-session, wrong-origin, and wrong-CSRF requests fail without a side effect. HTTPS start/stop and TLS refresh are serialized and carry a lifecycle generation. Certificate rotation and full material reset always trigger a post-material TLS refresh; a newer explicit lifecycle request takes precedence. Teardown disables transport-owned HTTPD calls, tracks any already in progress, retains an HTTPD handle after stop failure, and retries pending post-stop admin-transport finalization before a later start.
|
||
|
||
## SSH serial transport
|
||
|
||
| Command | Description |
|
||
|---|---|
|
||
| `ssh` / `ssh help` | Show SSH command usage. |
|
||
| `ssh status` | Show service state and resource information. |
|
||
| `ssh start` / `ssh stop` | Start or stop the SSH server. |
|
||
| `ssh sessions` | List active SSH sessions with account, user role, authentication method, route, broker role where applicable, and admin-worker state. |
|
||
| `ssh disconnect <session-id>` | Disconnect one SSH session. |
|
||
| `ssh counters` / `ssh clear-counters` | Show or clear SSH counters. |
|
||
| `ssh host-key info` | Display the OpenSSH host-key fingerprint. |
|
||
| `ssh host-key rotate --force` | Replace the persistent SSH host key. |
|
||
| `ssh reset --force` | Explicitly replace invalid or missing SSH material. |
|
||
|
||
SSH listens on port 22 and accepts user-database passwords plus stored `ssh-ed25519` and `ecdsa-sha2-nistp256` public keys. wolfSSH verifies key possession after the database authorizes the username/key pair; unsigned key probes do not complete authentication. A `user` receives the broker-backed UART1 serial stream. An `admin` receives the administration shell instead, does not become a broker client, and cannot acquire a UART1 writer lease.
|
||
|
||
UART0, admin SSH, and the browser admin shell submit to one bounded queue, and one dispatcher task is the sole caller of `esp_console_run()`. Consequently, remote commands execute the canonical UART0 handlers rather than using separate command implementations. Each remote frontend has generation-safe session identity, exact authorization checks, bounded editor/history/output state, and transport-owned network I/O; only the SSH transport task accesses wolfSSH and only HTTPD performs browser WebSocket sends/closes.
|
||
|
||
UART0 and admin SSH use shared whole-line Tab completion. A unique/common prefix expands inline; a Tab that cannot extend an ambiguous prefix prints the matching candidates and redraws the unchanged input line instead of cycling candidates. Admin SSH additionally supports four-entry per-session command history with Up/Down, inline cursor editing with Left/Right, Home/End (including Pos1/Ende terminal sequences), Backspace/Delete, Ctrl-C, and visible or no-echo interactive prompts. Its history is RAM-only, private to the session, and wiped on disconnect. Ping callbacks enqueue bounded typed results so all formatting remains on the dispatcher task.
|
||
|
||
`exit`, `reboot`, `ssh stop`, session disconnect, and SSH host-key reset/rotation use bounded deferred control. The firmware waits on a best-effort basis for the administration output ring and transport TX buffer to drain before acting; this is not confirmation that the peer received the acknowledgement. The shell stops accepting another command while such an action is pending. SSH host-key replacement or service stop closes all SSH sessions; reconnect and verify the new fingerprint where applicable. Web recovery credentials/certificates, Wi-Fi secrets, and interactive user passwords/keys are available to authenticated administrators and must therefore be treated as remotely accessible administrative material. `user bootstrap` and `user recover --force` remain UART0-only. A connected administrator also cannot generate its own replacement password remotely, preventing the one-time password from being lost during self-revocation. SSH does not provide `exec`, SFTP, SCP, forwarding, or subsystems.
|
||
|
||
## Hardware diagnostics
|
||
|
||
| Command | Description |
|
||
|---|---|
|
||
| `debug status` | Show MAX3243 driver, receiver, VLD, and shutdown states. It requires UART1 to be stopped. |
|
||
| `debug transceiver <enable|disable>` | Enable or shut down the MAX3243. |
|
||
| `debug drivers <tx 0|1> <dtr 0|1> <rts 0|1>` | Drive static TX, DTR, and RTS logic levels for measurement. |
|
||
| `debug loopback-a` / `debug loopback-b` | Test MAX3243 driver/receiver loopback configurations. |
|
||
| `debug valid-test` | Verify valid RS-232 voltage detection. |
|
||
| `debug uart-loopback <baud> [8N1|8E1|8O1|8N2|7E1|7O1] [bytes]` | Run a parameterized UART loopback test. |
|
||
| `debug uart-suite` | Test supported baud rates and frame formats. |
|
||
| `debug cts-flow-test` / `debug rts-flow-test` | Verify hardware transmit gating or receive backpressure. |
|
||
| `debug display status` | Show the current display diagnostic state. |
|
||
| `debug display probe` | Probe the expected OLED addresses 7-bit `0x3c` and `0x3d`, initially using 100 kHz I²C. The tested module responds at `0x3c`. |
|
||
| `debug display scan --force` | Scan usable 7-bit addresses `0x08`–`0x77` at 100 kHz; use only on this dedicated local-UI bus. |
|
||
| `debug display init [address]` | Initialize the OLED at 7-bit `0x3c`/`0x3d`, or their 8-bit write/read aliases: `0x78`/`0x79` and `0x7a`/`0x7b`. |
|
||
| `debug display off` | Turn off the initialized OLED. |
|
||
| `debug display pattern <clear|fill|checker|grid|corners|layout>` | Draw a full-screen electrical and geometry test pattern; `layout` renders separate status- and content-panel text. |
|
||
| `debug display row <0..63>` | Draw the selected one-pixel display row for addressing and color-boundary checks. |
|
||
| `debug display contrast <0..255>` | Set the OLED contrast to the specified bounded value. |
|
||
| `debug display invert <on|off>` | Enable or disable OLED pixel inversion. |
|
||
| `debug buttons status` | Show the current active-low state of previous/back GPIO10, select/confirm GPIO13, and next GPIO14. |
|
||
| `debug buttons test [seconds]` | Run the bounded button event test for 1–30 seconds; the default is 10 seconds. |
|
||
|
||
Follow the exact wiring in [Electrical tests](electrical_tests.md) before invoking diagnostics. The OLED must be powered from 3.3 V because module I²C pull-ups may connect to `VCC`; verify that all external pull-ups also terminate at 3.3 V. Display diagnostics probe the standard SSD1315-compatible 7-bit `0x3c`/`0x3d` addresses. The currently tested module acknowledges at `0x3c`, whose 8-bit write/read forms are `0x78`/`0x79`; an explicit `scan --force` is available only for the dedicated local-UI bus. Diagnostics initially run at 100 kHz and treat an absent display as nonfatal. RS-232 diagnostics that require UART1 refuse to use it until `serial stop` releases it. The RGB LED shows test state: blue idle, yellow/orange running, green passed, red failed.
|