embedded_bacnet/common/
time_value.rs1use 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#[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 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}