REQ-CAN-001 |
CAN bus transport |
The protocol shall use the CAN bus as the communication channel
between clients and servers. All protocol interactions follow a
client-server model where the client initiates requests and the server
processes them. |
REQ-CAN-002 |
Extended CAN identifiers |
The protocol shall use exclusively 29-bit extended CAN identifiers
for all transmitted and received frames. Both client and server shall
silently discard any frame using an 11-bit standard identifier. |
REQ-CAN-003 |
CAN identifier structure |
The 29-bit CAN identifier shall encode four fields: a 5-bit priority
field (bits 28-24), a 4-bit category field (bits 23-20), an 8-bit
message type field (bits 19-12), and a 12-bit node address field (bits
11-0). |
REQ-CAN-004 |
Client-server model |
The protocol shall follow a client-server architecture where the
client is the sole initiator of commands and queries, and the server
listens for incoming frames, processes them, and sends responses. The
server shall not initiate unsolicited commands to the client. |
REQ-CAN-005 |
Server node identity |
Each server shall be configured with a unique 12-bit node address
(1-4095) that identifies it on the CAN bus. The server shall process
only frames addressed to its own node address or to the broadcast
address (0x000). |
REQ-CAN-006 |
Multi-server client support |
The client shall support communication with multiple servers on the
same CAN bus by addressing frames to different server node addresses.
The client shall maintain independent sequence counters per server. |
REQ-CAN-006.1 |
Single-client server |
Each server shall serve exactly one client. The server shall
maintain a single sequence counter shared by all sequence-validated
categories, so concurrent command streams originating from more than one
client are not supported and shall be rejected with a sequence error.
The relationship is therefore one client to many servers, never many
clients to one server. |
REQ-CAN-007 |
Broadcast message support |
The protocol shall reserve node address 0x000 as the broadcast
address. All servers shall accept frames addressed to 0x000 regardless
of their configured node address, enabling simultaneous control of
multiple servers. |
REQ-CAN-008 |
Default system category |
The protocol shall define a built-in System category (0x0) that
provides heartbeat, command acknowledgement, status request, and
category discovery messages. This category shall be available without
any application-specific extensions. |
REQ-CAN-009 |
Server heartbeat mechanism |
The server shall automatically begin transmitting heartbeat frames
upon startup. A heartbeat frame shall contain a 1-byte protocol version
identifier and shall be sent at the lowest CAN priority level. The
server shall transmit a heartbeat at least 1 second after the last
message of any kind was sent, acting as a keep-alive during periods of
silence. The heartbeat shall not be sent while the server is actively
transmitting other messages within the 1-second window. |
REQ-CAN-009.1 |
Client online/offline detection |
The client shall use received heartbeat frames (and other messages)
to determine whether a server is online or offline. When a heartbeat is
received from a server, the client shall consider that server online and
notify the application layer. When no messages are received from a
server within a configurable timeout, the client shall consider that
server offline and notify the application layer. |
REQ-CAN-010 |
Protocol version identification |
The heartbeat frame shall carry a protocol version byte that allows
the client to verify wire-format compatibility with the server. |
REQ-CAN-011 |
Command acknowledgement |
The server shall transmit a 4-byte acknowledgement frame for every
processed command, containing the original command’s category, message
type, a status code indicating success or the specific error condition
(unknown command, invalid payload, invalid state, or sequence error),
and an expected-sequence byte (REQ-CAN-037). Messages rejected by rate
limiting are the exception: per REQ-CAN-022 they are silently discarded
and receive no acknowledgement, since sending one would itself add
traffic during the overload condition rate limiting exists to shed. |
REQ-CAN-012 |
Status request |
The client shall be able to send a status request message to a
server. Upon receiving this message, the server shall respond by
transmitting a heartbeat message, allowing the client to quickly confirm
the server is online without waiting for the next scheduled
heartbeat. |
REQ-CAN-013 |
Category-based message dispatch |
The protocol shall dispatch received frames to handlers based on the
category field in the CAN identifier. Each category handler shall be
independently registered and shall process only its own message
types. |
REQ-CAN-014 |
Application-defined categories |
The protocol shall allow applications to define additional message
categories beyond the built-in System and Firmware Upgrade categories by
registering custom category handlers on the server and client. Category
identifiers 0x2 to 0xF shall be available to applications.
RegisterCategory() shall reject, by returning false without registering,
an attempt to register a category whose ID is already registered, or
that would exceed canMaxRegisteredCategories (8) categories registered
at once on that server or client. This bound exists because the category
discovery response (REQ-CAN-008) reports every registered category ID in
a single 8-byte frame; it must never truncate. |
REQ-CAN-015 |
Fixed-point data encoding |
All floating-point values transmitted over CAN shall be encoded as
big-endian signed fixed-point integers with defined per-quantity scale
factors, with saturation clamping to prevent integer overflow. |
REQ-CAN-016 |
Short payload rejection |
The server shall reject any command frame whose payload is shorter
than the minimum required length for the given message type, and shall
respond with an invalid-payload error without applying any state
changes. |
REQ-CAN-017 |
Sequence number validation |
The server shall validate command frames using an 8-bit sequence
counter in the first payload byte. The first received command shall be
accepted regardless of its sequence value. Subsequent commands shall be
accepted only if their sequence number equals the previous sequence
number plus one, modulo 256. Out-of-sequence commands shall be rejected
with a sequence error response. |
REQ-CAN-018 |
Sequence number wrap-around |
The sequence counter shall wrap from 255 to 0 without error,
allowing continuous operation without sequence resets. |
REQ-CAN-019 |
Sequence bypass per category |
Individual category handlers shall be able to declare whether they
require sequence number validation. Categories or specific message types
that do not require sequencing shall bypass validation entirely. |
REQ-CAN-020 |
Unknown message category handling |
The server shall silently discard any received frame whose category
field does not correspond to a registered category handler, without
generating any response. |
REQ-CAN-021 |
Unknown message type handling |
The server shall respond with an unknown-command error when a frame
is received with a registered category but an unrecognized message
type. |
REQ-CAN-022 |
Message rate limiting |
The server shall enforce a configurable maximum number of received
messages per second. Messages exceeding this limit shall be silently
discarded. The rate counter shall be reset automatically every second by
an internal timer. |
REQ-CAN-023 |
Node address filtering |
The server shall process only CAN frames whose node address matches
its configured local address or the broadcast address (0x000), and shall
silently discard all other frames. |
REQ-CAN-024 |
No dynamic memory allocation |
The CAN protocol library shall not perform any dynamic memory
allocation and shall use only statically-sized data structures. |
REQ-CAN-025 |
Category discovery |
The client shall be able to send a category list request message to
a server. Upon receiving this message, the server shall respond with a
category list response containing the IDs of all registered category
handlers. The response payload shall list one category ID per byte,
limited to the maximum CAN frame payload size (8 bytes). If more than 8
categories are registered, the server shall include only the first 8 in
registration order and shall drop the remainder without an error
indication; a server needing to expose more than 8 categories is not
currently supported. |
REQ-CAN-026 |
Per-server sequence counter on client |
The client shall maintain independent 8-bit sequence counters for
each server node it communicates with. The sequence counter for a node
shall start at 0 on the first command and increment by 1 for each
subsequent command to that same node. Counters for different nodes shall
be independent. Up to 8 server nodes may be tracked simultaneously. |
REQ-CAN-027 |
Server liveness detection |
The client shall track server liveness independently for each server
node. When any frame is received from a source node ID (non-zero), the
client shall call OnServerOnline(nodeId) the first time and reset a
per-server timeout timer (default 3 s). If no frame is received from a
server within the timeout period, the client shall call
OnServerOffline(nodeId). Up to 8 server liveness slots may be tracked
simultaneously. |
REQ-CAN-028 |
Send queue overflow indication |
The CanFrameTransport::SendFrame() method shall return true if the
frame was successfully sent or enqueued, and false if the internal send
queue was full and the frame was dropped. The onDone callback shall not
be called when false is returned. |
REQ-CAN-029 |
ISO-TP segmentation support |
The library shall provide an optional ISO 15765-2 (ISO-TP) transport
layer that segments PDUs exceeding 8 bytes into multiple CAN frames and
reassembles them at the receiver. The transport layer shall be
attachable to CanProtocolServer and CanProtocolClient via
AttachIsoTpTransport(). |
REQ-CAN-030 |
ISO-TP frame types |
The ISO-TP implementation shall support all four ISO 15765-2 frame
types: Single Frame (SF, PCI nibble 0x0), First Frame (FF, PCI nibble
0x1), Consecutive Frame (CF, PCI nibble 0x2), and Flow Control (FC, PCI
nibble 0x3). |
REQ-CAN-031 |
ISO-TP flow control |
The sender shall wait for a Flow Control (ContinueToSend) frame from
the receiver before transmitting Consecutive Frames. The receiver shall
emit a Flow Control frame after receiving the First Frame. Block size
(BS=0) and separation time (STmin) fields shall be honoured. On Flow
Status = Wait, the sender shall restart the N_Bs timer and continue
waiting rather than aborting, up to N_WFTmax (16) consecutive Wait
frames, after which it shall abort. On Flow Status = Overflow, the
sender shall abort immediately. |
REQ-CAN-032 |
ISO-TP N_Bs timeout |
The sender shall abort an in-progress multi-frame transmission and
notify the abort callback with reason nBsTimeout if no Flow Control
frame is received within 1000 ms of sending the First Frame or the last
block of Consecutive Frames. |
REQ-CAN-033 |
ISO-TP N_Cr timeout |
The receiver shall abort reassembly and notify the abort callback
with reason nCrTimeout if no Consecutive Frame is received within 1000
ms of the previous frame. |
REQ-CAN-034 |
ISO-TP no dynamic memory allocation |
The ISO-TP transport layer shall not perform any dynamic memory
allocation. Channel state and PDU buffers shall use statically-sized
storage provided at construction time via
IsoTpTransportImpl::WithStorage. |
REQ-CAN-035 |
ISO-TP channel management |
IsoTpTransportImpl shall support registering multiple independent
receive channels identified by a (dataId, fcId) pair. The maximum number
of simultaneous channels shall be bounded at compile time via the
MaxChannels template parameter (default 4). Registering a channel with a
dataId already in use shall return false without modifying state. A
channel shall be reclaimable via ReleaseChannel(dataId), allowing its
slot to be reused once the application (or the transport itself, on
abort) is done with that dataId. |
REQ-CAN-036 |
Server-side client-liveness detection |
The client shall automatically begin transmitting heartbeat frames
upon construction, broadcast to node 0x000, following the same
quiet-period keep-alive rule as the server’s own heartbeat
(REQ-CAN-009). The server shall restart its client-liveness timeout
(default 3 s) on any frame correctly addressed to it, not only
heartbeats, since a client sending commands continuously may defer its
own heartbeat frame indefinitely; a received heartbeat shall
additionally notify the application via
CanProtocolServerObserver::Online(). If the timeout elapses without
further traffic from the client, the server shall notify
CanProtocolServerObserver::Offline(). A server tracks liveness for one
client only, consistent with REQ-CAN-006.1. |
REQ-CAN-037 |
Sequence resynchronization on sequence error |
The sequenceError acknowledgement (REQ-CAN-011) shall carry, in its
fourth byte, the sequence number the server expected. On receiving a
sequenceError acknowledgement, the client shall adopt that value as its
next sequence number for the acknowledging server, so that a single lost
frame, or the client’s own sequence state having reset independently of
the server, does not leave the two sides unable to recover. |
REQ-CAN-038 |
Command acknowledgement timeout |
When the client sends a sequence-validated command, it shall start a
timer (default 1 s, configurable). If no acknowledgement of any status
arrives for that command before the timer elapses, the client shall
notify the application via
CanProtocolClientObserver::OnCommandAckTimeout(nodeId, category,
messageType). Receiving a matching acknowledgement before the timer
elapses shall cancel it. The client shall not automatically retry the
timed-out command. |