bacnet_emb/common/
time_value.rs

1use crate::{
2    application_protocol::primitives::data_value::{Enumerated, Time},
3    common::{
4        error::{Error, Unimplemented},
5        helper::decode_unsigned,
6        io::{Reader, Writer},
7        spec::Binary,
8        tag::{ApplicationTagNumber, Tag, TagNumber},
9    },
10};
11
12// A simplified version of the ApplicationDataValue struct to avoid a recursive structure
13#[derive(Debug, Clone)]
14#[cfg_attr(feature = "defmt", derive(defmt::Format))]
15#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
16pub enum SimpleApplicationDataValue {
17    Boolean(bool),
18    SignedInt(i32),
19    UnsignedInt(u32),
20    Real(f32),
21    Double(f64),
22    Enumerated(Enumerated),
23}
24
25impl SimpleApplicationDataValue {
26    pub fn tag(&self) -> Tag {
27        match self {
28            Self::Boolean(_) => Tag::new(TagNumber::Application(ApplicationTagNumber::Boolean), 1),
29            Self::SignedInt(_) => {
30                Tag::new(TagNumber::Application(ApplicationTagNumber::SignedInt), 4)
31            }
32            Self::UnsignedInt(_) => {
33                Tag::new(TagNumber::Application(ApplicationTagNumber::UnsignedInt), 4)
34            }
35            Self::Real(_) => Tag::new(TagNumber::Application(ApplicationTagNumber::Real), 4),
36            Self::Double(_) => Tag::new(TagNumber::Application(ApplicationTagNumber::Double), 8),
37            Self::Enumerated(_) => {
38                Tag::new(TagNumber::Application(ApplicationTagNumber::Enumerated), 1)
39            }
40        }
41    }
42    pub fn decode(tag: &Tag, reader: &mut Reader, buf: &[u8]) -> Result<Self, Error> {
43        let tag_num = match &tag.number {
44            TagNumber::Application(x) => x,
45            unknown => {
46                return Err(Error::TagNotSupported((
47                    "SimpleApplicationDataValue decode",
48                    unknown.clone(),
49                )));
50            }
51        };
52
53        match tag_num {
54            ApplicationTagNumber::Boolean => {
55                let value = tag.value > 0;
56                Ok(SimpleApplicationDataValue::Boolean(value))
57            }
58            ApplicationTagNumber::UnsignedInt => {
59                let value = decode_unsigned(tag.value, reader, buf)? as u32;
60                Ok(SimpleApplicationDataValue::UnsignedInt(value))
61            }
62            ApplicationTagNumber::Real => {
63                if tag.value != 4 {
64                    return Err(Error::InvalidValue(
65                        "real value tag should have length of 4",
66                    ));
67                }
68                Ok(SimpleApplicationDataValue::Real(f32::from_be_bytes(
69                    reader.read_bytes(buf)?,
70                )))
71            }
72            ApplicationTagNumber::Enumerated => {
73                let value = decode_unsigned(tag.value, reader, buf)? as u32;
74                let value = if value > 0 { Binary::On } else { Binary::Off };
75                let value = Enumerated::Binary(value);
76                Ok(SimpleApplicationDataValue::Enumerated(value))
77            }
78
79            x => Err(Error::Unimplemented(Unimplemented::ApplicationTagNumber(
80                x.clone(),
81            ))),
82        }
83    }
84
85    pub fn encode(&self, writer: &mut Writer) {
86        match self {
87            Self::Boolean(x) => writer.push(*x as u8),
88            Self::SignedInt(x) => writer.extend_from_slice(&x.to_be_bytes()),
89            Self::UnsignedInt(x) => writer.extend_from_slice(&x.to_be_bytes()),
90            Self::Real(x) => writer.extend_from_slice(&x.to_be_bytes()),
91            Self::Double(x) => writer.extend_from_slice(&x.to_be_bytes()),
92            Self::Enumerated(Enumerated::Binary(x)) => writer.push(x.clone() as u32 as u8),
93            x => unimplemented!("{:?}", x),
94        }
95    }
96}
97
98#[derive(Debug, Clone)]
99#[cfg_attr(feature = "defmt", derive(defmt::Format))]
100#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
101pub struct TimeValue {
102    pub time: Time,
103    pub value: SimpleApplicationDataValue,
104}
105
106impl TimeValue {
107    pub const LEN: u32 = 4;
108
109    pub fn decode(reader: &mut Reader, buf: &[u8]) -> Result<TimeValue, Error> {
110        let tag = Tag::decode_expected(
111            reader,
112            buf,
113            TagNumber::Application(ApplicationTagNumber::Time),
114            "Decode weekly schedule TimeValue",
115        )?;
116
117        // 4 bytes
118        if tag.value != Self::LEN {
119            return Err(Error::Length((
120                "time tag should have length value 4",
121                tag.value,
122            )));
123        }
124        let time = match &tag.number {
125            TagNumber::Application(ApplicationTagNumber::Time) => Time::decode(reader, buf)?,
126            number => {
127                return Err(Error::TagNotSupported((
128                    "TimeValue decode time application tag expected",
129                    number.clone(),
130                )))
131            }
132        };
133        let tag = Tag::decode(reader, buf)?;
134        let value = SimpleApplicationDataValue::decode(&tag, reader, buf)?;
135        Ok(TimeValue { time, value })
136    }
137
138    pub fn encode(&self, writer: &mut Writer) {
139        let tag = Tag::new(
140            TagNumber::Application(ApplicationTagNumber::Time),
141            Self::LEN,
142        );
143        tag.encode(writer);
144        self.time.encode(writer);
145        let tag = self.value.tag();
146        tag.encode(writer);
147        self.value.encode(writer);
148    }
149}