embedded_bacnet/application_protocol/
unconfirmed.rs

1use crate::common::{
2    error::{Error, Unimplemented},
3    io::{Reader, Writer},
4};
5
6use super::{
7    application_pdu::ApduType,
8    services::{
9        change_of_value::CovNotification, i_am::IAm, time_synchronization::TimeSynchronization,
10        who_is::WhoIs,
11    },
12};
13
14#[derive(Debug, Clone)]
15#[cfg_attr(feature = "defmt", derive(defmt::Format))]
16pub enum UnconfirmedRequest<'a> {
17    WhoIs(WhoIs),
18    IAm(IAm),
19    CovNotification(CovNotification<'a>),
20    TimeSynchronization(TimeSynchronization),
21}
22
23impl<'a> UnconfirmedRequest<'a> {
24    pub fn encode(&self, writer: &mut Writer) {
25        writer.push((ApduType::UnconfirmedServiceRequest as u8) << 4);
26
27        match &self {
28            Self::IAm(payload) => payload.encode(writer),
29            Self::WhoIs(payload) => payload.encode(writer),
30            Self::CovNotification(_) => todo!(),
31            Self::TimeSynchronization(payload) => payload.encode(writer),
32        }
33    }
34    pub fn decode(reader: &mut Reader, buf: &'a [u8]) -> Result<Self, Error> {
35        let choice: UnconfirmedServiceChoice = reader
36            .read_byte(buf)?
37            .try_into()
38            .map_err(|x| Error::InvalidVariant(("UnconfirmedRequest choice", x as u32)))?;
39        match choice {
40            UnconfirmedServiceChoice::IAm => {
41                let apdu = IAm::decode(reader, buf)?;
42                Ok(Self::IAm(apdu))
43            }
44            UnconfirmedServiceChoice::WhoIs => {
45                let apdu = WhoIs::decode(reader, buf);
46                Ok(Self::WhoIs(apdu))
47            }
48            UnconfirmedServiceChoice::CovNotification => {
49                let apdu = CovNotification::decode(reader, buf)?;
50                Ok(Self::CovNotification(apdu))
51            }
52            x => Err(Error::Unimplemented(
53                Unimplemented::UnconfirmedServiceChoice(x),
54            )),
55        }
56    }
57}
58
59#[derive(Debug, Clone)]
60#[cfg_attr(feature = "defmt", derive(defmt::Format))]
61#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
62pub enum UnconfirmedServiceChoice {
63    IAm = 0,
64    IHave = 1,
65    CovNotification = 2,
66    EventNotification = 3,
67    PrivateTransfer = 4,
68    TextMessage = 5,
69    TimeSynchronization = 6,
70    WhoHas = 7,
71    WhoIs = 8,
72    UtcTimeSynchronization = 9,
73
74    // addendum 2010-aa
75    WriteGroup = 10,
76
77    // addendum 2012-aq
78    CovNotificationMultiple = 11,
79
80    // addendum 2016-bi
81    AuditNotification = 12,
82
83    // addendum 2016-bz
84    WhoAmI = 13,
85    YouAre = 14,
86
87    // Other services to be added as they are defined.
88    // All choice values in this production are reserved
89    // for definition by ASHRAE.
90    // Proprietary extensions are made by using the
91    // UnconfirmedPrivateTransfer service. See Clause 23.
92    MaxBacnetUnconfirmedService = 15,
93}
94
95impl TryFrom<u8> for UnconfirmedServiceChoice {
96    type Error = u8;
97    fn try_from(value: u8) -> Result<Self, u8> {
98        match value {
99            0 => Ok(Self::IAm),
100            1 => Ok(Self::IHave),
101            2 => Ok(Self::CovNotification),
102            3 => Ok(Self::EventNotification),
103            4 => Ok(Self::PrivateTransfer),
104            5 => Ok(Self::TextMessage),
105            6 => Ok(Self::TimeSynchronization),
106            7 => Ok(Self::WhoHas),
107            8 => Ok(Self::WhoIs),
108            9 => Ok(Self::UtcTimeSynchronization),
109            10 => Ok(Self::WriteGroup),
110            11 => Ok(Self::CovNotificationMultiple),
111            12 => Ok(Self::AuditNotification),
112            13 => Ok(Self::WhoAmI),
113            14 => Ok(Self::YouAre),
114            15 => Ok(Self::MaxBacnetUnconfirmedService),
115            x => Err(x),
116        }
117    }
118}