bacnet_emb/application_protocol/
application_pdu.rs

1use crate::{
2    application_protocol::{
3        confirmed::{ComplexAck, ConfirmedBacnetError, ConfirmedRequest, SegmentAck, SimpleAck},
4        segment::Segment,
5        unconfirmed::UnconfirmedRequest,
6    },
7    common::{
8        error::{self, Error},
9        io::{Reader, Writer},
10    },
11};
12
13// Application Layer Protocol Data Unit
14#[derive(Debug, Clone)]
15#[cfg_attr(feature = "defmt", derive(defmt::Format))]
16pub enum ApplicationPdu<'a> {
17    ConfirmedRequest(ConfirmedRequest<'a>),
18    UnconfirmedRequest(UnconfirmedRequest<'a>),
19    ComplexAck(ComplexAck<'a>),
20    SimpleAck(SimpleAck),
21    Error(ConfirmedBacnetError),
22    Segment(Segment<'a>),
23    SegmentAck(SegmentAck),
24    // add more here (see ApduType)
25}
26
27#[derive(Debug, Clone, PartialEq)]
28#[cfg_attr(feature = "defmt", derive(defmt::Format))]
29#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
30#[repr(u8)]
31pub enum ApduType {
32    ConfirmedServiceRequest = 0,
33    UnconfirmedServiceRequest = 1,
34    SimpleAck = 2,
35    ComplexAck = 3,
36    SegmentAck = 4,
37    Error = 5,
38    Reject = 6,
39    Abort = 7,
40}
41
42impl TryFrom<u8> for ApduType {
43    type Error = error::Error;
44
45    fn try_from(value: u8) -> Result<Self, Error> {
46        match value {
47            0 => Ok(Self::ConfirmedServiceRequest),
48            1 => Ok(Self::UnconfirmedServiceRequest),
49            2 => Ok(Self::SimpleAck),
50            3 => Ok(Self::ComplexAck),
51            4 => Ok(Self::SegmentAck),
52            5 => Ok(Self::Error),
53            6 => Ok(Self::Reject),
54            7 => Ok(Self::Abort),
55            x => Err(Error::InvalidVariant(("ApduType", x as u32))),
56        }
57    }
58}
59
60// preshifted by 4 bits
61#[derive(Debug, Clone)]
62#[cfg_attr(feature = "defmt", derive(defmt::Format))]
63#[repr(u8)]
64pub enum MaxSegments {
65    _0 = 0x00,
66    _2 = 0x10,
67    _4 = 0x20,
68    _8 = 0x30,
69    _16 = 0x40,
70    _32 = 0x50,
71    _64 = 0x60,
72    _65 = 0x70, // default
73}
74
75impl From<u8> for MaxSegments {
76    fn from(value: u8) -> Self {
77        match value {
78            0x00 => Self::_0,
79            0x10 => Self::_2,
80            0x20 => Self::_4,
81            0x30 => Self::_8,
82            0x40 => Self::_16,
83            0x50 => Self::_32,
84            0x60 => Self::_64,
85            0x70 => Self::_65,
86            _ => Self::_65,
87        }
88    }
89}
90
91#[derive(Debug, Clone)]
92#[cfg_attr(feature = "defmt", derive(defmt::Format))]
93#[repr(u8)]
94pub enum MaxAdpu {
95    _0 = 0x00,
96    _128 = 0x01,
97    _206 = 0x02,
98    _480 = 0x03,
99    _1024 = 0x04,
100    _1476 = 0x05, // default
101}
102
103impl From<u8> for MaxAdpu {
104    fn from(value: u8) -> Self {
105        match value {
106            0x00 => Self::_0,
107            0x01 => Self::_128,
108            0x02 => Self::_206,
109            0x03 => Self::_480,
110            0x04 => Self::_1024,
111            0x05 => Self::_1476,
112            _ => Self::_1476,
113        }
114    }
115}
116
117#[derive(Debug, Clone)]
118pub enum PduFlags {
119    Server = 0b0001,
120    SegmentedResponseAccepted = 0b0010,
121    MoreFollows = 0b0100,
122    SegmentedMessage = 0b1000,
123}
124
125impl<'a> ApplicationPdu<'a> {
126    pub fn encode(&self, writer: &mut Writer) {
127        match self {
128            Self::ConfirmedRequest(req) => req.encode(writer),
129            Self::UnconfirmedRequest(req) => req.encode(writer),
130            Self::ComplexAck(req) => req.encode(writer),
131            Self::SimpleAck(ack) => ack.encode(writer),
132            Self::SegmentAck(ack) => ack.encode(writer),
133            Self::Segment(segment) => segment.encode(writer),
134            Self::Error(_) => todo!(),
135        };
136    }
137
138    #[cfg_attr(feature = "alloc", bacnet_macros::remove_lifetimes_from_fn_args)]
139    pub fn decode(reader: &mut Reader, buf: &'a [u8]) -> Result<Self, Error> {
140        let byte0 = reader.read_byte(buf)?;
141        let pdu_type: ApduType = (byte0 >> 4).try_into()?;
142        let pdu_flags = byte0 & 0x0F;
143        let segmented_message = (pdu_flags & PduFlags::SegmentedMessage as u8) > 0;
144        let more_follows = (pdu_flags & PduFlags::MoreFollows as u8) > 0;
145        let _segmented_response_accepted =
146            (pdu_flags & PduFlags::SegmentedResponseAccepted as u8) > 0;
147
148        if segmented_message {
149            let segment = Segment::decode(more_follows, pdu_type, reader, buf)?;
150            return Ok(Self::Segment(segment));
151        }
152
153        match pdu_type {
154            ApduType::ConfirmedServiceRequest => {
155                let apdu = ConfirmedRequest::decode(reader, buf)?;
156                Ok(Self::ConfirmedRequest(apdu))
157            }
158            ApduType::UnconfirmedServiceRequest => {
159                let apdu = UnconfirmedRequest::decode(reader, buf)?;
160                Ok(Self::UnconfirmedRequest(apdu))
161            }
162            ApduType::ComplexAck => {
163                let adpu = ComplexAck::decode(reader, buf)?;
164                Ok(Self::ComplexAck(adpu))
165            }
166            ApduType::SimpleAck => {
167                let adpu = SimpleAck::decode(reader, buf)?;
168                Ok(Self::SimpleAck(adpu))
169            }
170            ApduType::SegmentAck => {
171                let adpu = SegmentAck::decode(reader, buf)?;
172                Ok(Self::SegmentAck(adpu))
173            }
174            ApduType::Error => {
175                let apdu = ConfirmedBacnetError::decode(reader, buf)?;
176                Ok(Self::Error(apdu))
177            }
178            apdu_type => Err(Error::ApduTypeNotSupported(apdu_type)),
179        }
180    }
181}