Expand description
High-level OpenLCB messages and their encoding onto CAN frames.
A Message is one OpenLCB message as defined by the Message Network
Standard and the protocol standards built on it (Event Transport,
Traction Control, Simple Node Information, Datagram Transport).
This module converts between messages and CAN frames, following the
CAN Frame Transfer Standard:
Message::try_to_framesencodes a message sent from a given source alias into one or moreCanFrames, rejecting messages that cannot be represented on CAN;Message::to_framesis the lenient variant.Assemblercollects incoming frames, reassembles multi-frame messages, and yieldsRawMessages.Message::from_parts(orMessage::from(raw)) decodes aRawMessage(MTI, destination, payload) into aMessage.
Node wires these together (and resolves aliases into
Node IDs for Received), but they are usable on their own, for
example in a bus monitor.
§Global, addressed and datagram framing
Global messages (no destination, e.g. PCER) have at most 8 payload bytes and always fit in one frame, with the CAN-MTI in the header.
Addressed messages (MTI bit 3 set, e.g. Traction Control) start each frame’s data with two bytes holding a 4-bit framing flag and the 12-bit destination alias, leaving 6 payload bytes per frame:
data[0] = FFFF DDDD FFFF = framing flag, DDDD = dest alias bits 11-8
data[1] = DDDD DDDD dest alias bits 7-0
data[2..8] up to 6 payload bytes
flag 0x0_ : only frame flag 0x1_ : first frame
flag 0x3_ : middle frame flag 0x2_ : last frameSo a 9-byte Assign Controller command becomes two frames, the first
flagged 0x1_ with 6 bytes and the second flagged 0x2_ with 3.
Datagrams carry the destination in the header instead, so each frame
holds a full 8 bytes, and the framing is expressed by the frame type
(only / first / middle / final, see
MessageFrameType).
Multi-frame messages from different senders, or to different
destinations, may interleave on the bus; the Assembler keys partial
messages by (source, destination, MTI).
§Example
use rolcb::message::{Assembler, Message};
use rolcb::{gridconnect, EventId};
// A global message: one frame.
let pcer = Message::Pcer(EventId(0x0501_0101_2200_0010));
let frames = pcer.to_frames(0x123);
assert_eq!(gridconnect::format(&frames[0]), ":X195B4123N0501010122000010;");
// An addressed message with a 15-byte payload: three frames.
let reply = Message::TractionReply { dest: 0xABC, payload: (0..15).collect() };
let frames = reply.to_frames(0x123);
assert_eq!(frames.len(), 3);
assert_eq!(frames[0].data()[0], 0x1A); // first frame, dest bits 11-8 = 0xA
assert_eq!(frames[1].data()[0], 0x3A); // middle
assert_eq!(frames[2].data()[0], 0x2A); // last
// Reassemble and decode.
let mut asm = Assembler::new();
let raw = frames.iter().find_map(|f| asm.accept(f)).unwrap();
assert_eq!(raw.src_alias, 0x123);
assert_eq!(Message::from(raw), reply);Modules§
- protocol
- Protocol Support Inquiry flag bits (first three bytes of the reply, with byte 0 in bits 23-16).
Structs§
- Assembler
- Reassembles multi-frame addressed messages and datagrams.
- RawMessage
- A complete message reassembled from frames, before decoding.
- Received
- A message received from the bus, with its source.
Enums§
- Encode
Error - Why
Message::try_to_framesrefused to encode a message. - Message
- A decoded OpenLCB message. Addressed messages carry the 12-bit
destalias of the node they are sent to.
Constants§
- MAX_
DATAGRAM - The largest datagram the Datagram Transport Standard allows (72 bytes).
- PARTIAL_
TIMEOUT_ MS - How long
Assembler::accept_atkeeps a partial multi-frame message that receives no further frames (3 s).