Skip to main content

m_bus_application_layer/
extended_link_layer.rs

1use crate::ApplicationLayerError;
2
3#[derive(Debug, PartialEq)]
4#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
5#[cfg_attr(feature = "defmt", derive(defmt::Format))]
6pub struct ExtendedLinkLayer {
7    pub communication_control: u8,
8    pub access_number: u8,
9    pub receiver_address: Option<ReceiverAddress>,
10    pub encryption: Option<EncryptionFields>,
11}
12
13#[derive(Debug, PartialEq)]
14#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
15#[cfg_attr(feature = "defmt", derive(defmt::Format))]
16pub struct ReceiverAddress {
17    pub manufacturer: u16,
18    pub address: [u8; 6],
19}
20
21#[derive(Debug, PartialEq)]
22#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
23#[cfg_attr(feature = "defmt", derive(defmt::Format))]
24pub struct EncryptionFields {
25    pub session_number: [u8; 4],
26    pub payload_crc: u16,
27}
28
29#[derive(Debug, Clone, Copy, PartialEq)]
30pub enum EllFormat {
31    /// Extended Link Layer I (2 bytes: CC, ACC)
32    FormatI,
33    /// Extended Link Layer II (8 bytes: CC, ACC, SN[4], CRC[2])
34    FormatII,
35    /// Extended Link Layer III (16 bytes: CC, ACC, MFR[2], ADDR[6], SN[4], CRC[2])
36    FormatIII,
37}
38
39impl ExtendedLinkLayer {
40    /// Parse Extended Link Layer from data, returns (ELL, bytes_consumed)
41    pub fn parse(data: &[u8], format: EllFormat) -> Result<(Self, usize), ApplicationLayerError> {
42        match format {
43            EllFormat::FormatI => Self::parse_format_i(data),
44            EllFormat::FormatII => Self::parse_format_ii(data),
45            EllFormat::FormatIII => Self::parse_format_iii(data),
46        }
47    }
48
49    fn parse_format_i(data: &[u8]) -> Result<(Self, usize), ApplicationLayerError> {
50        if data.len() < 2 {
51            return Err(ApplicationLayerError::InsufficientData);
52        }
53
54        Ok((
55            ExtendedLinkLayer {
56                communication_control: data[0],
57                access_number: data[1],
58                receiver_address: None,
59                encryption: None,
60            },
61            2,
62        ))
63    }
64
65    fn parse_format_ii(data: &[u8]) -> Result<(Self, usize), ApplicationLayerError> {
66        if data.len() < 8 {
67            return Err(ApplicationLayerError::InsufficientData);
68        }
69
70        Ok((
71            ExtendedLinkLayer {
72                communication_control: data[0],
73                access_number: data[1],
74                receiver_address: None,
75                encryption: Some(EncryptionFields {
76                    session_number: [data[2], data[3], data[4], data[5]],
77                    payload_crc: u16::from_le_bytes([data[6], data[7]]),
78                }),
79            },
80            8,
81        ))
82    }
83
84    fn parse_format_iii(data: &[u8]) -> Result<(Self, usize), ApplicationLayerError> {
85        if data.len() < 16 {
86            return Err(ApplicationLayerError::InsufficientData);
87        }
88
89        Ok((
90            ExtendedLinkLayer {
91                communication_control: data[0],
92                access_number: data[1],
93                receiver_address: Some(ReceiverAddress {
94                    manufacturer: u16::from_le_bytes([data[2], data[3]]),
95                    address: [data[4], data[5], data[6], data[7], data[8], data[9]],
96                }),
97                encryption: Some(EncryptionFields {
98                    session_number: [data[10], data[11], data[12], data[13]],
99                    payload_crc: u16::from_le_bytes([data[14], data[15]]),
100                }),
101            },
102            16,
103        ))
104    }
105}