calamp_rs/
message_header.rs

1//
2// Copyright (c) 2021 Murilo Ijanc' <mbsd@m0x.ru>
3//
4// Permission to use, copy, modify, and distribute this software for any
5// purpose with or without fee is hereby granted, provided that the above
6// copyright notice and this permission notice appear in all copies.
7//
8// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
11// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
12// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
13//
14
15use nom::error::ErrorKind;
16use nom::number::streaming::{be_u16, be_u8};
17use nom::IResult;
18#[cfg(feature = "serde")]
19use serde::{Deserialize, Serialize};
20use std::fmt;
21
22#[derive(PartialEq, Eq)]
23#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
24pub enum MessageType {
25    /// Null message
26    Null,
27    /// Ack/Nak message
28    AckNak,
29    /// Event Report message
30    EventReport,
31    /// ID Report message
32    IDReport,
33    /// User data message
34    UserData,
35    /// Application data message
36    ApplicationData,
37    /// Configuration parameter message
38    ConfigurationParameter,
39    /// Unit request message
40    UnitRequest,
41    /// Locate report message
42    LocateReport,
43    /// User data with accumulators message
44    UserDataWithAccumulators,
45    /// Mini event report message
46    MiniEventReport,
47    /// Mini user data message
48    MiniUserData,
49    /// Mini application message
50    MiniApplication,
51    /// Device version message
52    DeviceVersion,
53    /// Application message with accumulators
54    ApplicationMessageWithAccumulators,
55}
56
57impl MessageType {
58    pub fn parse(input: &[u8]) -> IResult<&[u8], MessageType> {
59        let (i, b): (&[u8], u8) = be_u8::<_, (_, ErrorKind)>(input).unwrap();
60
61        match b {
62            0 => Ok((i, MessageType::Null)),
63            1 => Ok((i, MessageType::AckNak)),
64            2 => Ok((i, MessageType::EventReport)),
65            3 => Ok((i, MessageType::IDReport)),
66            4 => Ok((i, MessageType::UserData)),
67            5 => Ok((i, MessageType::ApplicationData)),
68            6 => Ok((i, MessageType::ConfigurationParameter)),
69            7 => Ok((i, MessageType::UnitRequest)),
70            8 => Ok((i, MessageType::LocateReport)),
71            9 => Ok((i, MessageType::UserDataWithAccumulators)),
72            10 => Ok((i, MessageType::MiniEventReport)),
73            11 => Ok((i, MessageType::MiniUserData)),
74            12 => Ok((i, MessageType::MiniApplication)),
75            13 => Ok((i, MessageType::DeviceVersion)),
76            14 => Ok((i, MessageType::ApplicationMessageWithAccumulators)),
77            _ => panic!("not found"),
78        }
79    }
80}
81
82impl fmt::Display for MessageType {
83    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
84        match *self {
85            MessageType::Null => write!(f, "MessageType::Null"),
86            MessageType::AckNak => write!(f, "MessageType::AckNak"),
87            MessageType::EventReport => write!(f, "MessageType::EventReport"),
88            MessageType::IDReport => write!(f, "MessageType::IDReport"),
89            MessageType::UserData => write!(f, "MessageType::UserData"),
90            MessageType::ApplicationData => {
91                write!(f, "MessageType::ApplicationData")
92            }
93            MessageType::ConfigurationParameter => {
94                write!(f, "MessageType::ConfigurationParameter")
95            }
96            MessageType::UnitRequest => write!(f, "MessageType::UnitRequest"),
97            MessageType::LocateReport => write!(f, "MessageType::LocateReport"),
98            MessageType::UserDataWithAccumulators => {
99                write!(f, "MessageType::UserDataWithAccumulators")
100            }
101            MessageType::MiniEventReport => {
102                write!(f, "MessageType::MiniEventReport")
103            }
104            MessageType::MiniUserData => write!(f, "MessageType::MiniUserData"),
105            MessageType::MiniApplication => {
106                write!(f, "MessageType::MiniApplication")
107            }
108            MessageType::DeviceVersion => {
109                write!(f, "MessageType::DeviceVersion")
110            }
111            MessageType::ApplicationMessageWithAccumulators => {
112                write!(f, "MessageType::ApplicationMessageWithAccumulators")
113            }
114        }
115    }
116}
117
118impl fmt::Debug for MessageType {
119    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
120        match *self {
121            MessageType::Null => write!(f, "MessageType::Null"),
122            MessageType::AckNak => write!(f, "MessageType::AckNak"),
123            MessageType::EventReport => write!(f, "MessageType::EventReport"),
124            MessageType::IDReport => write!(f, "MessageType::IDReport"),
125            MessageType::UserData => write!(f, "MessageType::UserData"),
126            MessageType::ApplicationData => {
127                write!(f, "MessageType::ApplicationData")
128            }
129            MessageType::ConfigurationParameter => {
130                write!(f, "MessageType::ConfigurationParameter")
131            }
132            MessageType::UnitRequest => write!(f, "MessageType::UnitRequest"),
133            MessageType::LocateReport => write!(f, "MessageType::LocateReport"),
134            MessageType::UserDataWithAccumulators => {
135                write!(f, "MessageType::UserDataWithAccumulators")
136            }
137            MessageType::MiniEventReport => {
138                write!(f, "MessageType::MiniEventReport")
139            }
140            MessageType::MiniUserData => write!(f, "MessageType::MiniUserData"),
141            MessageType::MiniApplication => {
142                write!(f, "MessageType::MiniApplication")
143            }
144            MessageType::DeviceVersion => {
145                write!(f, "MessageType::DeviceVersion")
146            }
147            MessageType::ApplicationMessageWithAccumulators => {
148                write!(f, "MessageType::ApplicationMessageWithAccumulators")
149            }
150        }
151    }
152}
153
154#[derive(PartialEq, Eq)]
155#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
156pub enum ServiceType {
157    /// Unacknowledged Request
158    Unacknowledged,
159
160    /// Acknowledged Request
161    Acknowledged,
162
163    /// Response to an Acknowledged Request
164    ResponseToAnAcknowledged,
165}
166
167impl ServiceType {
168    pub fn parse(input: &[u8]) -> IResult<&[u8], ServiceType> {
169        let (i, b): (&[u8], u8) = be_u8::<_, (_, ErrorKind)>(input).unwrap();
170
171        match b {
172            0 => Ok((i, ServiceType::Unacknowledged)),
173            1 => Ok((i, ServiceType::Acknowledged)),
174            2 => Ok((i, ServiceType::ResponseToAnAcknowledged)),
175            _ => panic!("not found"),
176        }
177    }
178}
179
180impl fmt::Display for ServiceType {
181    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
182        match *self {
183            ServiceType::Unacknowledged => {
184                write!(f, "ServiceType::Unacknowledged")
185            }
186            ServiceType::Acknowledged => write!(f, "ServiceType::Acknowledged"),
187            ServiceType::ResponseToAnAcknowledged => {
188                write!(f, "ServiceType::ResponseToAnAcknowledged")
189            }
190        }
191    }
192}
193
194impl fmt::Debug for ServiceType {
195    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
196        match *self {
197            ServiceType::Unacknowledged => {
198                write!(f, "ServiceType::Unacknowledged")
199            }
200            ServiceType::Acknowledged => write!(f, "ServiceType::Acknowledged"),
201            ServiceType::ResponseToAnAcknowledged => {
202                write!(f, "ServiceType::ResponseToAnAcknowledged")
203            }
204        }
205    }
206}
207
208/// Sequence Number
209///
210/// A 16-bit number used to uniquely identify a message. This number shall be
211/// initialized to 1 by the LMU on a cold boot and will be incremented in the
212/// LMU each time an inbound message is originated by the LMU. The LMU remembers
213/// its current Sequence Number during sleep. Eventually the Sequence Number
214/// will rollover from 65535 to 1, skipping zero.
215///
216/// The Sequence Number is also used to identify acknowledgements and
217/// retransmissions. Responses to Acknowledged Requests shall contain the
218/// Sequence Number from the associated Acknowledged Request. A Server receiving
219/// from an LMU can also use the Sequence Number as a means to identify whether
220/// the received message is an original or a retransmitted copy, thus avoiding
221/// processing any duplicate reports from an LMU.
222///
223/// A Server can set the Sequence Number field to zero for all outbound messages
224/// sent to the LMU if it is not important that the LMU distinguish an original
225/// message from a retransmitted copy. However, if this distinction is
226/// necessary, the server can insert a changing non-zero value into the Sequence
227/// Number field of each new message sent to the LMU. The LMU will remember the
228/// last sequence number it received and will compare it to the non-zero
229/// sequence number for the new message. If different, it will process the
230/// message normally. If the same, it will not process the message and will
231/// return a NAK response with the 'ACK' field set to 7.
232#[derive(Clone, PartialEq, Eq)]
233#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
234pub struct SequenceNumber(u16);
235
236impl fmt::Display for SequenceNumber {
237    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
238        write!(f, "{}", self.0)
239    }
240}
241
242impl fmt::Debug for SequenceNumber {
243    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
244        write!(f, "SequenceNumber({})", self.0)
245    }
246}
247
248impl SequenceNumber {
249    pub fn parse(input: &[u8]) -> IResult<&[u8], SequenceNumber> {
250        let (i, b): (&[u8], u16) = be_u16::<_, (_, ErrorKind)>(input).unwrap();
251        Ok((i, SequenceNumber(b)))
252    }
253
254    pub fn data(&self) -> u16 {
255        self.0
256    }
257}
258
259#[derive(Debug)]
260#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
261pub struct MessageHeader {
262    pub service_type: ServiceType,
263    pub message_type: MessageType,
264    pub sequence_number: SequenceNumber,
265}
266
267impl MessageHeader {
268    pub fn parse(input: &[u8]) -> IResult<&[u8], MessageHeader> {
269        let (i, service_type) = ServiceType::parse(input).unwrap();
270        let (i, message_type) = MessageType::parse(i).unwrap();
271        let (i, sequence_number) = SequenceNumber::parse(i).unwrap();
272
273        Ok((
274            i,
275            MessageHeader {
276                service_type,
277                message_type,
278                sequence_number,
279            },
280        ))
281    }
282}
283
284#[cfg(test)]
285mod tests {
286    use super::{MessageHeader, MessageType, ServiceType};
287    use crate::options_header::OptionsHeader;
288
289    #[test]
290    fn test_parse_message_headers() {
291        let data: [u8; 117] = [
292            0x83, 0x05, 0x46, 0x34, 0x66, 0x32, 0x35, 0x01, 0x01, 0x01, 0x02,
293            0x3a, 0x86, 0x5f, 0xf1, 0x3a, 0x54, 0x5f, 0xf1, 0x3a, 0x57, 0xf1,
294            0xe2, 0x85, 0x78, 0xe4, 0x22, 0xd6, 0x40, 0x00, 0x01, 0x36, 0xf8,
295            0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x06, 0x20, 0x00, 0x00, 0xff,
296            0x8d, 0x02, 0x1e, 0x1e, 0x00, 0x7b, 0x21, 0x10, 0x00, 0x00, 0x00,
297            0x31, 0xe0, 0x00, 0x00, 0x10, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00,
298            0x22, 0x2a, 0x32, 0x00, 0x00, 0x03, 0xf1, 0x00, 0x00, 0x00, 0x00,
299            0x00, 0x00, 0x00, 0x00, 0x01, 0xc8, 0x2d, 0x3f, 0x01, 0xc8, 0x2d,
300            0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
301            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00,
302            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
303        ];
304
305        let (i, _) = OptionsHeader::parse(&data).unwrap();
306        let (_, message_header) = MessageHeader::parse(i).unwrap();
307        assert_eq!(message_header.service_type, ServiceType::Acknowledged);
308        assert_eq!(
309            format!("{}", message_header.service_type),
310            String::from("ServiceType::Acknowledged")
311        );
312
313        assert_eq!(message_header.message_type, MessageType::EventReport);
314        assert_eq!(
315            format!("{}", message_header.message_type),
316            String::from("MessageType::EventReport")
317        );
318
319        assert_eq!(message_header.sequence_number.data(), 14982);
320        assert_eq!(
321            format!("{}", message_header.sequence_number),
322            String::from("14982")
323        );
324        assert_eq!(
325            format!("{:?}", message_header.sequence_number),
326            String::from("SequenceNumber(14982)")
327        );
328    }
329}