BMCLI web
Reference version: BMCLI 1.6.3. Command names, parameters and machine-readable fields retain their source spelling.
Host the packaged engineering console and BUSMUST Automation API v1 inside the
BMCLI daemon. The service exposes typed bench and device snapshots, channel
lifecycle and statistics, CAN/CAN FD/LIN message send, cursor-based raw history,
SSE, binary WebSocket frames, DBC signal decode plans, logging/replay/gateway
lifecycle, bounded firmware-check jobs, and runtime command discovery. It does
not execute arbitrary command lines. /api/v1/operations reports every current
CLI operation, explicit permission/execution policy, parameter metadata, and
whether its typed HTTP handler has been migrated.
The packaged Console polls health and marks retained signal samples stale when the Web service is unavailable. Raw SSE, raw WebSocket, and signal SSE keep independent connection handles, cursors, status, gap diagnostics, and Stop controls; restarting one does not replace another. Refresh reloads devices, open channels, databases, DBC message catalogs, signal plans, runtime OpenAPI, operations, and metrics. If a server-local signal plan disappeared after a Web restart, the Console marks it expired and offers an in-page rebuild using the retained channel/database/message/history fields. Message Send validates its visible fields against the typed request contract before issuing a network request, while Advanced mode only relaxes the channel-selector source check.
web start
Section titled “web start”# Default: loopback only, packaged console, no token requiredbmcli web start --listen=127.0.0.1:8080 --format=json
# Explicit project Web rootbmcli web start --listen=127.0.0.1:8080 --web-root=<directory> --format=json
# Debug diagnostics appended to a filebmcli web start --log-level=debug --log-file=web-debug.log --format=json
# Non-loopback plain HTTP requires authentication and explicit risk acknowledgementbmcli web start --listen=0.0.0.0:8080 --token=<secret> --allow-insecure-http --format=jsonweb start starts the daemon when needed. Open hardware channels with daemon start --channel=... or channel open before using hardware endpoints. The
default history capacity is 8192 events and can be changed with
--history-capacity=<count>.
Web diagnostics default to --log-level=info and stderr. The accepted levels
are exactly lowercase off, error, info, and debug: off emits nothing;
error records startup/runtime errors and completed 4xx/5xx requests; info
also records lifecycle events and every completed request with method, path
without its query, status, and nonnegative duration; debug also reports route
hit/miss and sanitized error code/message detail. --log-file=<path> appends to
a file instead of stderr; a relative path is resolved from the daemon start
working directory. If the file cannot be opened, Web startup fails without
falling back to stderr. Successful start and running/stopped status output
report the effective log_level and log_destination; file destinations are
absolute and stderr is reported with that stable name. These options do not
introduce a project_root; existing Web-root and daemon working-directory
ownership remain unchanged.
| Endpoint | Purpose |
|---|---|
GET /api/v1/info |
Product, build, API, and service identity |
GET /api/v1/health |
Daemon, Web, and channel-broker health |
GET /api/v1/capabilities |
Transports, resources, limits, and security defaults |
GET /api/v1/openapi.json |
Packaged and regression-gated OpenAPI 3.1 contract |
GET /api/v1/operations[/{operation_id}] |
Runtime CommandRegistry and HTTP migration policy |
GET /api/v1/bench |
Selected project/global bench snapshot |
GET /api/v1/devices |
Local physical analyzers, deduplicated across channels |
POST /api/v1/devices/{selector}/firmware-check |
Queue a non-disruptive firmware release check |
GET /api/v1/jobs[/{job_id}] |
List or inspect bounded asynchronous jobs |
GET/POST /api/v1/channels |
List or open daemon channels |
GET/PATCH/DELETE /api/v1/channels/{selector} |
Inspect, configure, or close a daemon channel |
GET /api/v1/channels/{selector}/stats |
Hardware counters, rates, bus state, and broker retention |
GET/POST /api/v1/databases |
List or load typed database resources inside the project working root |
GET/DELETE /api/v1/databases/{name} |
Inspect or unload one database resource; DBC inspection includes bounded message metadata |
GET/POST /api/v1/tx-tasks |
List or add a channel TX task/LIN slave response |
DELETE /api/v1/tx-tasks/{task_id} |
Remove one channel TX task |
GET/POST /api/v1/routes |
List or add a hardware message route |
DELETE /api/v1/routes/{route_id} |
Remove one hardware message route |
POST /api/v1/messages |
Typed CAN/CAN FD/LIN send or LIN transaction |
GET /api/v1/messages/history |
Cursor-based raw history with explicit expiry |
GET /api/v1/messages/stream |
SSE raw-message stream with gap events |
GET /api/v1/messages/ws |
bmcli.frames.v2 BMF2 binary stream |
GET /api/v1/signals |
Active DBC decode plans |
POST /api/v1/signals/plans |
Create a bounded DBC signal plan |
DELETE /api/v1/signals/plans/{plan_id} |
Delete a signal plan |
GET /api/v1/signals/latest |
Latest decoded signal sample |
GET /api/v1/signals/history |
Cursor-based decoded signal history |
GET /api/v1/signals/stream |
SSE decoded-signal stream |
GET/POST/DELETE /api/v1/logging |
Inspect, start, or stop project-confined ASC logging |
GET/POST/DELETE /api/v1/replay |
Inspect, start, or stop project-confined ASC/BLF replay |
GET/POST/DELETE /api/v1/remote-bmapi |
Inspect, start, or stop the remote-BMAPI gateway |
The exact request fields, units, limits, errors, query parameters, and WebSocket
layout are authoritative in /api/v1/openapi.json. Read it at runtime instead
of copying this table into an application. Percent-encode / when a stable
SN/port selector is placed in a path segment, for example 10356%2F0; query
parameters and JSON fields keep the ordinary 10356/0 form. POST /api/v1/execute is not a
shell: v1 accepts only the migrated one-token version operation. Use dedicated
resource endpoints for hardware work.
Channel open and config intentionally use different request schemas:
ChannelOpenRequest requires channel, while ChannelConfigRequest obtains
the selector from the path and accepts one setter group. Message type is one
of data, remote, master-write, master-read, or sync-break; the runtime
rejects values outside that OpenAPI enum. The Console Typed API picker and body
template are generated from the runtime OpenAPI document rather than a copied
operation list.
Failed Web message sends preserve the submitted selector in
error.details.channel. Logical networks report selector_kind=network and
either network_unbound or the resolved physical selector; valid but unopened
physical/name selectors report channel_not_open; malformed SN/port or
UID/port forms report invalid_channel_selector. A failed lookup never
substitutes numeric daemon slot zero for the caller’s selector.
The raw WebSocket endpoint requires and selects bmcli.frames.v2 and emits only
BMF2. A v1-only, missing, or unknown frame subprotocol is rejected with HTTP 400
unsupported_websocket_subprotocol before the 101 upgrade. When v2 and v1 are
both offered, the server selects only v2. There is no BMF1 output, downgrade,
dual-stack mode, or compatibility switch. Each WebSocket binary message is one
BMF2 event: a 64-byte unsigned big-endian header followed by exactly
payload_length bytes, for a total length of 64 + payload_length. The fixed offsets
are magic[0:4], version@4, header_length@5, bus@6, event_kind@7,
channel@8:u16, payload_length@10, dlc@11, id@12:u32, flags@16:u32,
status@20:u32, event_id@24:u64, source_sequence@32:u64,
stream_epoch@40:u64, timestamp_us@48:u64, hardware_sequence@56:u16,
filter_hit@58, checksum@59, zero reserved@60:u32, and payload at 64.
event_kind is 1 for rx_frame and 2 for tx_complete.
One channel PATCH may contain only one hardware setter group. CAN nominal/data timing is one group and LIN version/checksum is one group; mode, termination, pull-up, bitrate, and power are separate groups. Valid same-value updates are idempotent. This prevents a later BMAPI setter failure from leaving an undisclosed partially applied multi-field request.
All ordinary daemon receive consumers share one RxBroker owner per channel.
message recv, software logging, gateway forwarding, Web history, SSE,
WebSocket, and DBC signal decoding therefore use independent cursors instead of
competing calls to BM_Read. History expiry returns 409 cursor_expired with
error.details.oldest_available and newest_available; SSE and WebSocket streams
emit an explicit gap event with the same recovery bounds. A resumable client
continues from oldest_available - 1, de-duplicates by sequence, and must not
silently replace an expired cursor with now.
For /api/v1/signals/latest and /api/v1/signals/history, both plan and
signal are required: missing/empty values return HTTP 400 invalid_argument;
a valid request with no sample returns 404. History uses after=<sequence>,
not cursor; omitted after means 0 and can therefore return 409 after ring
retention has advanced. Acknowledge the gap and continue with
after=oldest_available-1; after=newest_available deliberately drops retained
history and waits for later samples.
Relative web start --web-root paths are resolved from the invoking CLI’s
working directory before being handed to the daemon.
Security and limits
Section titled “Security and limits”- Default bind is
127.0.0.1; CORS is disabled. - Any non-loopback bind requires
--token; API callers useAuthorization: Bearer <token>. WebSocket clients may usebmcli.token.<token>as a second subprotocol. - Non-loopback bind also requires the presence-only
--allow-insecure-httpacknowledgement. This option does not weaken loopback defaults or add encryption; it prevents an accidental remote bind from looking secure merely because a token was supplied. - The current embedded server uses plain HTTP. A bearer token authenticates a caller but does not encrypt headers, payloads, bus traffic, or the token itself. Keep loopback as the normal deployment. Use a non-loopback listener only on a trusted isolated engineering network with host firewall rules, or place it behind an approved HTTPS reverse proxy; do not expose it directly to an untrusted LAN or the Internet.
- Linux packages include an audited Nginx profile at
share/bmcli/packaging/https/. It terminates TLS, preserves SSE/WebSocket streaming, and proxies only to the BMCLI loopback listener. Certificate validation must pass normally; do not use browser security bypasses. - Static files are read-only and reject path traversal.
- Diagnostic records never contain bearer tokens,
AuthorizationorCookievalues, raw query strings, request bodies, or the configured start token. Necessary dynamic error detail is logged as[redacted]. Control characters are escaped so each event remains exactly one physical log record. - CSP constrains executable script sources and reduces injected inline-script
execution. The current response policy is
script-src 'self'andstyle-src 'self' 'unsafe-inline': browser JavaScript must be served as an external file from the Web root, while inline style remains allowed. Prefer external JavaScript and CSS assets for generated dashboards. - Request body limit is 64 KiB; response limit is 2 MiB; simultaneous client,
SSE, and WebSocket limits are reported by
capabilities. - Treat Web message send and signal-plan creation as active bench operations. Apply the same authorization and cleanup rules as direct BMCLI commands.
web status / stop
Section titled “web status / stop”bmcli web status --format=jsonbmcli web stop --format=jsonweb stop releases the listener and stream clients but leaves a pre-existing
daemon and its open channels running. web status always reports
default_listen (127.0.0.1:8080). While running, listen_source=effective
and listen, configured_listen, and effective_listen identify the active
endpoint. While stopped, listen_source=default, listen matches the next
no-argument web start, effective_listen is null, and
configured_listen retains the last successful explicit configuration for
diagnostics. Stopped status also retains the last effective diagnostic level
and destination.
Source of truth: BMCLI 1.6.3 repository documentation. Run bmcli help <category> <action> --format=json for the exact contract of the installed version.