oze_canopen/message_parsed.rs
1use crate::{
2 canopen::{NodeId, RxMessage},
3 proto::CobId,
4};
5
6/// Enumeration representing the type of a received CANopen message.
7///
8/// This enum is used to classify the different types of CANopen messages that can be received.
9/// Each variant corresponds to a specific type of CANopen message, as indicated by the COB-ID
10/// (Communication Object Identifier).
11#[derive(Clone, Debug, Copy, PartialEq, Eq)]
12pub enum RxMessageType {
13 /// Service Data Object Transmit (SDO Tx)
14 ///
15 /// Represents an SDO message sent from the server (node) to the client.
16 SdoTx,
17
18 /// Service Data Object Receive (SDO Rx)
19 ///
20 /// Represents an SDO message sent from the client to the server (node).
21 SdoRx,
22
23 /// Process Data Object (PDO)
24 ///
25 /// Represents any PDO message or Timestamp with COB-ID in the range 0x100 to 0x57F.
26 Pdo,
27
28 /// Synchronization (SYNC)
29 ///
30 /// Represents a SYNC message with COB-ID 0x80.
31 Sync,
32
33 /// Network Management (NMT)
34 ///
35 /// Represents an NMT message.
36 Nmt,
37
38 /// Layer Setting Services (LSS)
39 ///
40 /// Represents an LSS message.
41 Lss,
42
43 /// Node Guarding
44 ///
45 /// Represents a Node Guarding message.
46 Guarding,
47
48 /// Emergency (EMCY)
49 ///
50 /// Represents an EMCY message.
51 Emcy,
52
53 /// Unknown Message Type
54 ///
55 /// Represents a message type that could not be determined.
56 Unknown,
57}
58
59/// Struct representing a parsed received CANopen message, including its type and optional node ID.
60#[derive(Clone, Debug, Copy)]
61pub struct RxMessageParsed {
62 /// The parsed type of the received message.
63 pub parsed_type: RxMessageType,
64 /// The parsed node ID from the message, if applicable.
65 pub parsed_node_id: Option<NodeId>,
66 /// The original received message.
67 pub msg: RxMessage,
68}
69
70impl RxMessageParsed {
71 /// Creates a new `RxMessageParsed` instance by parsing the given received message.
72 ///
73 /// # Arguments
74 ///
75 /// * `msg` - The received CANopen message to be parsed.
76 ///
77 /// # Returns
78 ///
79 /// A new `RxMessageParsed` instance with the parsed type and node ID.
80 ///
81 /// # Examples
82 ///
83 /// ```
84 /// use oze_canopen::RxMessageParsed;
85 ///
86 /// let rx_message = RxMessage { /* fields */ };
87 /// let parsed_message = RxMessageParsed::new(rx_message);
88 /// ```
89 pub fn new(msg: RxMessage) -> Self {
90 Self {
91 parsed_type: Self::parse_type(msg.cob_id),
92 parsed_node_id: Self::parse_node_id(msg.cob_id),
93 msg,
94 }
95 }
96
97 /// Parses the type of a received message based on its COB ID.
98 ///
99 /// # Arguments
100 ///
101 /// * `cob_id` - The COB ID of the received message.
102 ///
103 /// # Returns
104 ///
105 /// The parsed type of the message as an `RxMessageType`.
106 ///
107 /// # Examples
108 ///
109 /// ```
110 /// use oze_canopen::RxMessageParsed;
111 ///
112 /// let message_type = RxMessageParsed::parse_type(0x580);
113 /// assert_eq!(message_type, RxMessageType::SdoTx);
114 /// ```
115 pub fn parse_type(cob_id: CobId) -> RxMessageType {
116 match cob_id {
117 0x0..=0x7F => RxMessageType::Nmt,
118 0x80 => RxMessageType::Sync,
119 0x100..=0x57F => RxMessageType::Pdo,
120 0x580..=0x5FF => RxMessageType::SdoTx,
121 0x600..=0x67F => RxMessageType::SdoRx,
122 0x81..=0xFF => RxMessageType::Emcy,
123 0x680..=0x6FF => RxMessageType::Unknown,
124 0x700..=0x77F => RxMessageType::Guarding,
125 0x780..=0x7FF => RxMessageType::Lss,
126 0x800.. => RxMessageType::Unknown,
127 }
128 }
129
130 /// Parses the node ID from a received message based on its COB ID.
131 ///
132 /// # Arguments
133 ///
134 /// * `cob_id` - The COB ID of the received message.
135 ///
136 /// # Returns
137 ///
138 /// The parsed node ID as an `Option<NodeId>`.
139 ///
140 /// # Examples
141 ///
142 /// ```
143 /// use oze_canopen::RxMessageParsed;
144 ///
145 /// let node_id = RxMessageParsed::parse_node_id(0x580);
146 /// assert_eq!(node_id, Some(0x0));
147 /// ```
148 pub fn parse_node_id(cob_id: CobId) -> Option<NodeId> {
149 match cob_id {
150 0x00..=0x80 => None, // NMT, SYNC
151 0x81..=0xFF => NodeId::try_from(cob_id - 0x80).ok(), // EMCY
152 0x100..=0x57F => {
153 let mut node_id = cob_id;
154 while node_id >= 0x80 {
155 node_id -= 0x80;
156 }
157 NodeId::try_from(node_id).ok()
158 } // PDO
159 0x580..=0x5FF => NodeId::try_from(cob_id - 0x580).ok(), // SDO Transmit
160 0x600..=0x67F => NodeId::try_from(cob_id - 0x600).ok(), // SDO Receive
161 0x680..=0x6FF => None, // ???
162 0x700..=0x77F => NodeId::try_from(cob_id - 0x700).ok(), // Node Guarding
163 0x780..=0x7FF => None, // Lss
164 0x800.. => None, // not possible ???
165 }
166 }
167}
168
169impl RxMessageType {
170 pub fn to_string(&self) -> &str {
171 match &self {
172 RxMessageType::SdoTx => "↓SDO S->C",
173 RxMessageType::SdoRx => "↑SDO C->S",
174 RxMessageType::Pdo => "PDO",
175 RxMessageType::Sync => "SYNC",
176 RxMessageType::Nmt => "NMT",
177 RxMessageType::Unknown => "?",
178 RxMessageType::Emcy => "EMCY",
179 RxMessageType::Guarding => "Guard",
180 RxMessageType::Lss => "LSS",
181 }
182 }
183}