Skip to main content

Message

Enum Message 

Source
#[non_exhaustive]
pub enum Message {
Show 26 variants InitializationComplete { node_id: NodeId, simple: bool, }, VerifyNodeIdGlobal { node_id: Option<NodeId>, }, VerifyNodeIdAddressed { dest: u16, node_id: Option<NodeId>, }, VerifiedNodeId { node_id: NodeId, simple: bool, }, OptionalInteractionRejected { dest: u16, code: u16, mti: Mti, }, TerminateDueToError { dest: u16, code: u16, mti: Mti, }, ProtocolSupportInquiry { dest: u16, }, ProtocolSupportReply { dest: u16, flags: u32, }, IdentifyConsumer(EventId), ConsumerIdentified { event: EventId, state: EventState, }, ConsumerRangeIdentified(EventId), IdentifyProducer(EventId), ProducerIdentified { event: EventId, state: EventState, }, ProducerRangeIdentified(EventId), IdentifyEventsGlobal, IdentifyEventsAddressed { dest: u16, }, LearnEvent(EventId), Pcer(EventId), TractionCommand { dest: u16, payload: Vec<u8>, }, TractionReply { dest: u16, payload: Vec<u8>, }, SnipRequest { dest: u16, }, SnipReply { dest: u16, data: Vec<u8>, }, Datagram { dest: u16, data: Vec<u8>, }, DatagramReceivedOk { dest: u16, flags: u8, }, DatagramRejected { dest: u16, code: u16, }, Other { mti: Mti, dest: Option<u16>, payload: Vec<u8>, },
}
Expand description

A decoded OpenLCB message. Addressed messages carry the 12-bit dest alias of the node they are sent to.

The source of a message is not part of Message: when sending, it is the alias of the sending Node; when receiving, it is in the surrounding Received. Every variant maps to exactly one Mti (see Message::mti); MTIs without a dedicated variant are carried by Message::Other, so decoding never fails.

Traction payloads are kept as raw bytes; decode them with traction::Command::decode and traction::Reply::decode. SNIP data decodes with NodeInfo::from_snip.

use rolcb::{EventId, EventState, Message, Mti};

let m = Message::ProducerIdentified { event: EventId(1), state: EventState::Valid };
assert_eq!(m.mti(), Mti::PRODUCER_IDENTIFIED_VALID);
assert_eq!(m.dest(), None);
assert_eq!(m.payload(), vec![0, 0, 0, 0, 0, 0, 0, 1]);

let q = Message::SnipRequest { dest: 0x6A1 };
assert_eq!(q.dest(), Some(0x6A1));

The enum is #[non_exhaustive] so that new MTIs can get dedicated variants without a breaking release: match it with a _ arm (which also covers Message::Other).

Variants (Non-exhaustive)§

This enum is marked as non-exhaustive
Non-exhaustive enums could have additional variants added in future. Therefore, when matching against variants of non-exhaustive enums, an extra wildcard arm must be added to account for any future variants.
§

InitializationComplete

Initialization Complete (MTI 0x0100/0x0101). The last step of a node’s login; announces it is ready to communicate.

Fields

§node_id: NodeId

The node that just came online.

§simple: bool

True for the Simple Protocol variant (MTI 0x0101).

§

VerifyNodeIdGlobal

Verify Node ID Global (MTI 0x0490). Every node, or only the node whose ID is given, replies with Message::VerifiedNodeId. Tools use it to enumerate the network.

Fields

§node_id: Option<NodeId>

Restrict the query to one Node ID, or None for everyone.

§

VerifyNodeIdAddressed

Verify Node ID Addressed (MTI 0x0488): ask one node to identify itself, e.g. to confirm an alias is still mapped.

Fields

§dest: u16

Destination alias.

§node_id: Option<NodeId>

Optional Node ID payload.

§

VerifiedNodeId

Verified Node ID (MTI 0x0170/0x0171): reply to Verify Node ID.

Fields

§node_id: NodeId

The responding node.

§simple: bool

True for the Simple Protocol variant (MTI 0x0171).

§

OptionalInteractionRejected

Optional Interaction Rejected (MTI 0x0068): the destination sent us a request we do not support.

Fields

§dest: u16

Destination alias (the node whose request is being rejected).

§code: u16

Error code, see crate::mti::error_code.

§mti: Mti

The MTI of the rejected message.

§

TerminateDueToError

Terminate Due To Error (MTI 0x00A8): an ongoing interaction failed.

Fields

§dest: u16

Destination alias.

§code: u16

Error code, see crate::mti::error_code.

§mti: Mti

The MTI of the message that caused the error.

§

ProtocolSupportInquiry

Protocol Support Inquiry (MTI 0x0828): “which protocols do you support?” Node answers automatically.

Fields

§dest: u16

Destination alias.

§

ProtocolSupportReply

Protocol Support Reply (MTI 0x0668).

Fields

§dest: u16

Destination alias (the node that asked).

§flags: u32

Supported protocols, a combination of protocol bits.

§

IdentifyConsumer(EventId)

Identify Consumer (MTI 0x08F4): nodes that consume this event reply with Message::ConsumerIdentified.

§

ConsumerIdentified

Consumer Identified (MTI 0x04C4/0x04C5/0x04C7): the sender consumes event, and reports its view of the event’s state.

Fields

§event: EventId

The event consumed.

§state: EventState

Current state; selects the MTI.

§

ConsumerRangeIdentified(EventId)

Consumer Range Identified (MTI 0x04A4): the sender consumes a range of events. The range is encoded in the ID itself: the low-order bits that are all equal (all 1s or all 0s) are “don’t care”.

§

IdentifyProducer(EventId)

Identify Producer (MTI 0x0914): nodes that produce this event reply with Message::ProducerIdentified. Also used for train search (see traction::search).

§

ProducerIdentified

Producer Identified (MTI 0x0544/0x0545/0x0547): the sender produces event, and reports whether it is currently valid.

Fields

§event: EventId

The event produced.

§state: EventState

Current state; selects the MTI.

§

ProducerRangeIdentified(EventId)

Producer Range Identified (MTI 0x0524): the sender produces a range of events, encoded like Message::ConsumerRangeIdentified.

§

IdentifyEventsGlobal

Identify Events Global (MTI 0x0970): every node replies with Producer/Consumer Identified for all its events.

§

IdentifyEventsAddressed

Identify Events Addressed (MTI 0x0968): one node lists all its events.

Fields

§dest: u16

Destination alias.

§

LearnEvent(EventId)

Learn Event (MTI 0x0594): teaching message. A node in “learn” mode adopts this Event ID for the selected input or output.

§

Pcer(EventId)

Producer/Consumer Event Report: “this event happened”.

MTI 0x05B4. The core message of the Event Transport Standard: a producer sends it, and every consumer of the Event ID acts on it.

§

TractionCommand

Traction Control Command (MTI 0x05EB), throttle → train. Build the payload with traction::Command::encode.

Fields

§dest: u16

Destination (train) alias.

§payload: Vec<u8>

Raw command bytes.

§

TractionReply

Traction Control Reply (MTI 0x01E9), train → throttle. Decode the payload with traction::Reply::decode.

Fields

§dest: u16

Destination (throttle) alias.

§payload: Vec<u8>

Raw reply bytes.

§

SnipRequest

Simple Node Information Request (MTI 0x0DE8).

Fields

§dest: u16

Destination alias.

§

SnipReply

Simple Node Information Reply (MTI 0x0A08), usually several frames.

Fields

§dest: u16

Destination alias (the node that asked).

§data: Vec<u8>

Encoded SNIP strings, see NodeInfo::snip_payload.

§

Datagram

Datagram (MTI 0x1C48): an addressed, acknowledged block of up to 72 bytes (Datagram Transport Standard). The first byte identifies the datagram protocol (e.g. 0x20 for Memory Configuration). The receiver must answer with Message::DatagramReceivedOk or Message::DatagramRejected.

Fields

§dest: u16

Destination alias.

§data: Vec<u8>

Datagram contents, at most 72 bytes (MAX_DATAGRAM). Enforced by Message::try_to_frames, not by Message::to_frames.

§

DatagramReceivedOk

Datagram Received OK (MTI 0x0A28).

Fields

§dest: u16

Destination alias (the datagram’s sender).

§flags: u8

Flags byte: bit 7 = “reply pending”, low nibble encodes the expected reply timeout as 2^N seconds.

§

DatagramRejected

Datagram Rejected (MTI 0x0A48).

Fields

§dest: u16

Destination alias (the datagram’s sender).

§code: u16

Error code, see crate::mti::error_code. Temporary errors (0x2xxx) invite a resend.

§

Other

Anything not specifically decoded.

Also produced for a known MTI whose payload is too short to decode (for example a PCER with fewer than 8 bytes).

Fields

§mti: Mti

The message type.

§dest: Option<u16>

Destination alias, for addressed MTIs.

§payload: Vec<u8>

Raw payload (excluding the destination bytes).

Implementations§

Source§

impl Message

Source

pub fn mti(&self) -> Mti

The MTI this message is sent with.

Source

pub fn dest(&self) -> Option<u16>

Destination alias for addressed messages; None for global ones.

Source

pub fn payload(&self) -> Vec<u8> ⓘ

The message payload (for addressed messages, excluding the destination).

This is the byte sequence defined by the relevant standard: a Node ID, an Event ID, error code + MTI, and so on. The Protocol Support Reply is padded to six bytes.

Source

pub fn from_parts(mti: Mti, dest: Option<u16>, p: Vec<u8>) -> Message

Decode from MTI, destination and payload.

This is the inverse of Message::mti + Message::dest + Message::payload. It never fails: unknown MTIs and payloads too short for their MTI become Message::Other. dest should be Some for addressed MTIs (a missing destination decodes as alias 0). Usually fed from a RawMessage produced by an Assembler; the From<RawMessage> impl does exactly that.

use rolcb::{EventId, Message, Mti};

let m = Message::from_parts(Mti::PCER, None, vec![5, 1, 1, 1, 0x22, 0, 0, 0x10]);
assert_eq!(m, Message::Pcer(EventId(0x0501_0101_2200_0010)));

// Too short to hold an Event ID: kept as Other.
let m = Message::from_parts(Mti::PCER, None, vec![1, 2]);
assert!(matches!(m, Message::Other { .. }));
Source

pub fn try_to_frames( &self, src_alias: u16, ) -> Result<Vec<CanFrame>, EncodeError>

Encode as one or more CAN frames sent from src_alias, rejecting messages that cannot be represented faithfully.

Framing is the same as Message::to_frames. The checks are:

ProblemError
global message with more than 8 payload bytesEncodeError::GlobalPayloadTooLong
addressed MTI with no dest (Message::Other only)EncodeError::MissingDestination
global MTI with a dest (Message::Other only)EncodeError::UnexpectedDestination
MTI with bit 12 or higher set, other than Mti::DATAGRAMEncodeError::MtiTooWide
datagram over 72 bytesEncodeError::DatagramTooLong
§Errors

Returns the first EncodeError from the table above.

use rolcb::{EncodeError, Message, Mti};

let ok = Message::Datagram { dest: 0x456, data: vec![0x20; 72] };
assert_eq!(ok.try_to_frames(0x123)?.len(), 9);

let wide = Message::Other { mti: Mti(0x1F88), dest: Some(0x456), payload: vec![] };
assert!(matches!(wide.try_to_frames(0x123), Err(EncodeError::MtiTooWide { .. })));
Source

pub fn to_frames(&self, src_alias: u16) -> Vec<CanFrame>

Encode as one or more CAN frames sent from src_alias.

  • Global messages produce one frame (payload truncated to 8 bytes).
  • Addressed messages produce one frame per 6 payload bytes (at least one), each starting with the framing flag and destination alias as described in the module docs.
  • Datagrams produce one frame per 8 bytes using the datagram frame types.

This encoder is lenient and never fails. For a message that Message::try_to_frames would reject it keeps its historical behaviour: global payloads are truncated to 8 bytes, an addressed MTI without a destination is sent as if it were global, a destination on a global MTI is sent as addressed framing, bits 12-15 of the MTI are dropped, and datagrams over 72 bytes are split into as many frames as needed. In debug builds such a message trips a debug_assert!; use try_to_frames when the message comes from untrusted input.

§Panics

In debug builds only, if try_to_frames would return an error.

use rolcb::{gridconnect, Message, NodeId};

let m = Message::VerifyNodeIdAddressed { dest: 0x456, node_id: None };
let f = m.to_frames(0x123);
assert_eq!(gridconnect::format(&f[0]), ":X19488123N0456;");

// A 20-byte datagram: frame types 3 (first), 4 (middle), 5 (final).
let d = Message::Datagram { dest: 0x456, data: (0..20).collect() };
let ids: Vec<u32> = d.to_frames(0x123).iter().map(|f| f.id).collect();
assert_eq!(ids, [0x1B45_6123, 0x1C45_6123, 0x1D45_6123]);

Trait Implementations§

Source§

impl Clone for Message

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Message

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Eq for Message

Source§

impl From<RawMessage> for Message

Source§

fn from(raw: RawMessage) -> Message

Decode with Message::from_parts. The source alias is dropped.

Source§

impl PartialEq for Message

Source§

fn eq(&self, other: &Self) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for Message

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.