跳转到内容

BMCLI Message Command: CAN, CAN FD and LIN I/O

Reference version: BMCLI 1.6.5. Command names, parameters and machine-readable fields retain their source spelling.

Send CAN/CAN FD or LIN messages. --type selects CAN data/remote or LIN master-write/master-read/sync-break. CAN supports raw data, repeated sends, and DBC signal encoding. LIN supports IDs 0x00..0x3F and payloads up to 8 bytes.

Terminal window
# Single standard CAN frame
bmcli message send --channel=0 --message=0x123 --data="AA BB CC"
# CAN FD with bitrate switching
bmcli message send --channel=0 --message=0x100 --data="11 22" --flags=fdf+brs
# Extended ID (29-bit)
bmcli message send --channel=0 --message=0x18FEDC01 --flags=ide --data="01 02"
# Explicit zero-length Classic CAN frame (omitted data does not restore DLC 8)
bmcli message send --channel=0 --message=0x123 --dlc=0 --format=json
# Batch: 100 asynchronous writes at 10ms intervals (waits for the loop, not bus completion)
bmcli message send --channel=0 --message=0x100 --count=100 --cycle=10
# DBC signal encoding (uses globally loaded DBC, see `database load`)
bmcli message send --channel=0 --message=EngineStatus --signal=EngineSpeed:1500
# Multiple signals
bmcli message send --channel=0 --message=EngineStatus --signal=EngineSpeed:1500 --signal=CoolantTemp:85
# LIN master publishes a data frame
bmcli message send --channel=10356/4 --id=0x20 --type=master-write --data="01 02 03 04" --bitrate=19200
# LIN master read: payload+checksum response is required
bmcli message send --channel=10356/4 --id=0x20 --type=master-read --dlc=8 --timeout=500 --format=json
# LIN sync break: a slave payload response is an error
bmcli message send --channel=10356/4 --id=0x21 --type=sync-break --timeout=500 --format=json

Structured LIN transaction output distinguishes command attempts from bus error flags. Top-level attempts is the number of attempted command records and host_retry_count is currently 0; each result has one-based attempt, result_error, and checksum_valid. The retained errors field inside a LIN result is a firmware/BMAPI bit mask, duplicated as lin_error_flags with errors_semantics="bitmask"; for example value 32 is a LIN timeout flag, not 32 retries. A header-only no-response result has checksum_valid=false and is not counted in top-level received. A physical response with the wrong DLC is counted in received but also in errors and has result_error=true.

--signal format — all of the following are accepted (separator interchangeable):

Syntax Example
--signal=Name=Value --signal=EngineSpeed=1500
--signal=Name:Value --signal=EngineSpeed:1500
--signal Name=Value --signal EngineSpeed=1500
--signal Name:Value --signal EngineSpeed:1500

Repeat --signal for multiple signals. No spaces inside signal values.

BMCLI validates every DBC assignment before opening a standalone channel or submitting a daemon send. An unknown message or signal, an out-of-range value, or an invalid multiplexor selection fails without sending a frame. Structured output uses the same typed DBC encode diagnostic described under dbc encode. When a daemon client supplies a relative --dbc path, or a path-like relative --database selector, it is resolved from that client’s current working directory carried in structured IPC. A plain registered resource name is never rewritten as a path. Resolution failures retain the requested selector, caller directory, and resolved path in the structured error.

Option Default Description
--channel (required) CAN or LIN channel; bus is inferred from capability
--message / --id (required) CAN ID/DBC message name, or LIN frame ID 0x00..0x3F
--data CAN: 8 zero bytes; LIN: empty Payload hex bytes; explicit empty --data= selects a zero-length CAN payload; LIN supports up to 8 and forbids data with header-only operations
--type CAN data; LIN master-write CAN: data, remote. LIN: master-write, master-read, sync-break
--dlc CAN: 8 when data is omitted; LIN master-read: 8 CAN DLC 0..15 explicitly selects the wire length before the omitted-data default; shorter payloads are zero padded and payloads longer than the selected DLC are rejected. LIN expected response length is 0..8; sync-break uses 0.
--flags DBC metadata or none CAN only: ide, fdf, brs, rtr (plus-separated)
--checksum auto LIN only: auto, classic, or enhanced
--count 1 Number of frames (software-timed loop)
--cycle 0 Interval between frames in ms
--timeout direct publish 0; LIN transaction 500 LIN master-read/sync-break total transaction deadline in ms, shared by all --count attempts. It is never passed to BMAPI as a write timeout.
--signal — CAN only: repeatable DBC signal assignment
--bitrate CAN 500/2000; LIN 19200 Standalone CAN timing: one rate means nominal=data and N/D is explicit. LIN keeps its bps meaning; daemon channels keep their open-time configuration.

Every BMCLI-owned BM_Write* call uses write-timeout 0 and BMCLI never sets ECHO. A direct send result reports accepted, meaning BMAPI accepted the write; it does not claim that the frame reached the bus. A later event_kind=tx_complete is emitted only when the device returns a real TEF through BM_Read. Immediate or partial rejection reports accepted, failed_index, bmapi_status, and bmapi_status_name; it never creates a raw event or log record.

Successful CAN JSON reports the stable physical channel, and daemon mode also reports its separate channel_slot. dlc is the final wire DLC; payload_length counts explicitly supplied/DBC-produced bytes; padding_bytes and padded describe zero fill. Omitting both --data and --dlc deterministically sends eight zero bytes. Explicit --dlc=0 sends no payload in both Classic CAN and CAN FD. DLC 9..15 use the standard CAN FD 12/16/20/24/32/48/64-byte mapping.

--count/--cycle vs txtask: message send --count --cycle is a software-timed loop that keeps the command alive until all asynchronous writes have been attempted. txtask add is a hardware-timed task running on the device firmware — more precise, non-blocking, and persistent. Use message send for one-off batch tests; use txtask for long-running periodic messages.

For LIN header operations, accepted counts submitted headers and completed counts outcomes that matched the selected intent. Each JSON results item has an outcome. Master-read succeeds only with the expected DLC, payload/checksum, and no LIN errors. Sync-break succeeds only for a header-only sync_break=true event; a payload is reported as unexpected-response and returns nonzero.

In daemon mode all selected channels must already be open. Run channel open first; receive does not implicitly open a channel or replace its configuration. Standalone receive retains its own open/receive/close lifecycle.

Receive CAN, CAN FD, or LIN frames. Blocks until --count is reached or --duration elapses (or Ctrl+C in standalone). Standalone capture accepts multiple channels only when they have the same bus type.

In daemon mode, omitting --channel receives from ALL open channels simultaneously. In standalone mode, --channel is required.

Terminal window
# Standalone: single channel, exit after 100 frames
bmcli message recv --channel=10356/1 --count=100
# Standalone: multi-channel, 5-second capture
bmcli message recv --channel=10356/0,10356/1 --duration=5
# Daemon: receive from all open channels for 10 seconds
bmcli message recv --duration=10
# Daemon: preserve each raw CAN frame and add decoded data from a registered DBC
bmcli message recv --channel=10356/1 --decode --database=vehicle --duration=5 --format=json
# Daemon: direct one-off DBC file, one decoded event per JSONL line
bmcli message recv --channel=10356/1 --decode --dbc=network.dbc --duration=5 --format=jsonl
# With CAN ID filter
bmcli message recv --channel=10356/1 --id=0x100 --mask=0x7FF --duration=5
# Passive LIN capture
bmcli message recv --channel=10357/4 --mode=listen-only --bitrate=19200 --duration=5 --format=jsonl
Option Default Description
--channel daemon: all open; standalone: required Channel(s): SN/port, comma-separated list, or omit for all open (daemon only)
--count 0 (infinite) Max messages to receive. If a positive count is explicitly combined with duration, zero matching messages do not satisfy the count and the command fails.
--duration 0 (infinite, Ctrl+C to stop) Wall-clock capture duration in seconds. Daemon mode defaults to 10s if neither count nor duration is given; when duration is the only explicit stop condition, expiry is successful even with zero matching messages.
--id none CAN or LIN ID filter (software-filtered)
--mask 0x7FF ID filter mask
--decode off Decode matching CAN/CAN FD frames in standalone or daemon mode while retaining the raw frame
--database sole loaded DBC Registered DBC name or direct file used for receive decoding
--dbc sole loaded DBC Direct-file convenience alias for --database
--format text text, json (array), jsonl (one JSON per line), csv
--bitrate CAN 500/2000; LIN 19200 Standalone CAN timing: one rate means nominal=data and N/D is explicit. LIN keeps its bps meaning.
--mode LIN listen-only Standalone LIN role

With --decode, text keeps the existing raw line and prints the decoded object after it. JSON and JSONL keep every existing raw field and add a decoded object only when the selected DBC contains that CAN ID. Standard, extended, and CAN FD frames use the same codec and decoded schema as standalone receive. JSONL still emits one complete frame event per line.

Standalone JSONL makes the first complete event visible immediately. It then batches later stdio flushes with a maximum 100 ms cadence so a low-rate tail is visible without waiting for another frame or process exit, while high-rate capture does not force one synchronous flush per event. Normal buffer-capacity drain, the final summary, errors, and command completion remain flush boundaries. Daemon JSONL likewise streams each complete frame, gap, and summary record over the request socket as soon as it is formatted; it does not wait for the aggregate response buffer or command completion. The short-lived client flushes each received socket chunk to stdout. Client disconnect is checked at the receive poll cadence and releases that request’s Broker cursors. Bounded daemon --format=json deliberately keeps the existing one-document response.

An unmatched CAN ID remains a successful raw-only frame. A missing or unparseable DBC also follows the current standalone receive oracle: the frame remains raw-only rather than changing the receive command’s success result. Receive decoding reports observed signal values; if a decoded physical value is outside the DBC’s declared min/max, it is still returned exactly as standalone receive returns it. Supplying --database or --dbc without --decode does not load or decode the DBC and does not change raw output. These decode options are CAN-only and do not alter LIN receive behavior.

Structured raw events classify device input explicitly as event_kind=rx_frame or event_kind=tx_complete; direction is the derived rx/tx view. Daemon events also carry the RxBroker source_sequence, stream_epoch, extended timestamp_us, bus-specific flags/status and the hardware SEQ where applicable. Identical hardware events remain distinct and are never content-deduplicated. Every structured CAN frame reports stable channel=UID/port (or SN fallback); daemon frames additionally carry a separate numeric channel_slot, so a multi-channel consumer does not need enumeration or daemon open order to identify its source.

For LIN master-read, the slave response payload can appear in a tx_complete event for the master’s transaction. Consumers collecting LIN responses must inspect both event kinds rather than filtering for rx_frame only.

Daemon and standalone bounded JSON return one object with status, messages, received, channels, gaps, dropped, and completion_reason. JSONL emits one object per frame and always terminates with an event=summary object containing the same counters and completion reason. Text ends with the corresponding summary. For a duration-only capture with no matching traffic, the result is successful: received=0, gaps=0, dropped=0, and completion_reason=duration. A real RxBroker gap, channel/hardware error, or an explicitly requested positive count that expires at zero remains a nonzero failure; structured failures use the canonical error.code, error.message, error.details, and error.retryable envelope.

gaps and dropped measure only this command’s RxBroker observer link. gaps counts retention discontinuity events, while dropped counts retained events overwritten before this observer read them. They use the same source as stat integrity fields broker_gaps and broker_dropped_frames; they do not inspect DBC signals, E2E/application counters, or expected transmit cadence. For example, an ECU counter changing from 4 to 6 can still produce gaps=0,dropped=0 when every frame visible to RxBroker reached this observer. Conversely, an RxBroker retention overrun reports nonzero gaps/dropped even when the received payload counters themselves are consecutive. BMCLI does not infer application-level missing frames from generic payload data.

Note: message send --timeout is an upper-layer LIN transaction deadline; direct publish is always asynchronous. message recv --duration is a capture window in seconds. Neither option changes the BMAPI write-timeout, which is 0.



Source of truth: BMCLI 1.6.5 repository documentation. Run bmcli help <category> <action> --format=json for the exact contract of the installed version.