embedded_bacnet/common/
time_value.rs

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