embedded_bacnet/application_protocol/services/
read_property.rs1use crate::{
2 application_protocol::{
3 confirmed::{ComplexAck, ComplexAckService, ConfirmedServiceChoice},
4 primitives::data_value::ApplicationDataValue,
5 },
6 common::{
7 error::Error,
8 helper::{
9 decode_context_object_id, decode_context_property_id, encode_closing_tag,
10 encode_context_enumerated, encode_context_object_id, encode_context_unsigned,
11 encode_opening_tag, get_tagged_body_for_tag,
12 },
13 io::{Reader, Writer},
14 object_id::ObjectId,
15 property_id::PropertyId,
16 spec::BACNET_ARRAY_ALL,
17 tag::{ApplicationTagNumber, Tag, TagNumber},
18 },
19 network_protocol::data_link::DataLink,
20};
21
22#[derive(Debug, Clone)]
23#[cfg_attr(feature = "defmt", derive(defmt::Format))]
24pub enum ReadPropertyValue<'a> {
25 ObjectIdList(ObjectIdList<'a>),
26 ApplicationDataValue(ApplicationDataValue<'a>),
27}
28
29#[derive(Debug, Clone)]
30#[cfg_attr(feature = "defmt", derive(defmt::Format))]
31pub struct ObjectIdList<'a> {
32 object_ids: &'a [ObjectId],
33 buf: &'a [u8],
34}
35
36#[derive(Debug, Clone)]
37#[cfg_attr(feature = "defmt", derive(defmt::Format))]
38pub struct ObjectIdIter<'a> {
39 reader: Reader,
40 buf: &'a [u8],
41}
42
43impl<'a> ObjectIdList<'a> {
44 pub fn new(object_ids: &'a [ObjectId]) -> Self {
45 Self {
46 object_ids,
47 buf: &[],
48 }
49 }
50
51 pub fn new_from_buf(buf: &'a [u8]) -> Self {
52 Self {
53 object_ids: &[],
54 buf,
55 }
56 }
57
58 pub fn encode(&self, writer: &mut Writer) {
59 for object_id in self.object_ids {
60 Tag::new(
61 TagNumber::Application(ApplicationTagNumber::ObjectId),
62 ObjectId::LEN,
63 )
64 .encode(writer);
65 object_id.encode(writer);
66 }
67 }
68}
69
70impl<'a> ObjectIdIter<'a> {
71 pub fn new(buf: &'a [u8]) -> Self {
72 Self {
73 reader: Reader::new_with_len(buf.len()),
74 buf,
75 }
76 }
77
78 fn next_internal(&mut self) -> Result<ObjectId, Error> {
79 let tag = Tag::decode_expected(
80 &mut self.reader,
81 self.buf,
82 TagNumber::Application(ApplicationTagNumber::ObjectId),
83 "ObjectIdList nex",
84 )?;
85
86 ObjectId::decode(tag.value, &mut self.reader, self.buf)
87 }
88}
89
90impl<'a> IntoIterator for &'_ ObjectIdList<'a> {
91 type Item = Result<ObjectId, Error>;
92 type IntoIter = ObjectIdIter<'a>;
93
94 fn into_iter(self) -> Self::IntoIter {
95 ObjectIdIter::new(self.buf)
96 }
97}
98
99impl<'a> Iterator for ObjectIdIter<'a> {
100 type Item = Result<ObjectId, Error>;
101
102 fn next(&mut self) -> Option<Self::Item> {
103 if self.reader.eof() {
104 None
105 } else {
106 Some(self.next_internal())
107 }
108 }
109}
110
111#[derive(Debug, Clone)]
112#[cfg_attr(feature = "defmt", derive(defmt::Format))]
113pub struct ReadPropertyAck<'a> {
114 pub object_id: ObjectId,
115 pub property_id: PropertyId,
116 pub property_value: ReadPropertyValue<'a>,
117}
118
119impl<'a> TryFrom<DataLink<'a>> for ReadPropertyAck<'a> {
120 type Error = Error;
121
122 fn try_from(value: DataLink<'a>) -> Result<Self, Self::Error> {
123 let ack: ComplexAck = value.try_into()?;
124 match ack.service {
125 ComplexAckService::ReadProperty(ack) => Ok(ack),
126 _ => Err(Error::ConvertDataLink(
127 "apdu message is not a ComplexAckService ReadPropertyAck",
128 )),
129 }
130 }
131}
132
133impl<'a> ReadPropertyAck<'a> {
134 pub fn encode(&self, writer: &mut Writer) {
135 writer.push(ConfirmedServiceChoice::ReadProperty as u8);
136 encode_context_object_id(writer, 0, &self.object_id);
137 encode_context_enumerated(writer, 1, &self.property_id);
138 encode_opening_tag(writer, 3);
139 match &self.property_value {
140 ReadPropertyValue::ApplicationDataValue(value) => {
141 value.encode(writer);
142 }
143 ReadPropertyValue::ObjectIdList(value) => {
144 value.encode(writer);
145 }
146 }
147 encode_closing_tag(writer, 3);
148 }
149
150 pub fn decode(reader: &mut Reader, buf: &'a [u8]) -> Result<Self, Error> {
151 let object_id =
152 decode_context_object_id(reader, buf, 0, "ReadPropertyAck decode object_id")?;
153 let property_id =
154 decode_context_property_id(reader, buf, 1, "ReadPropertyAck decode property_id")?;
155
156 let buf = get_tagged_body_for_tag(reader, buf, 3, "ReadPropertyAck decode data values")?;
157 let mut reader = Reader {
158 index: 0,
159 end: buf.len(),
160 };
161
162 match property_id {
163 PropertyId::PropObjectList => {
164 let property_value =
165 ReadPropertyValue::ObjectIdList(ObjectIdList::new_from_buf(buf));
166
167 Ok(Self {
168 object_id,
169 property_id,
170 property_value,
171 })
172 }
173 property_id => {
174 let tag = Tag::decode(&mut reader, buf)?;
175 let value =
176 ApplicationDataValue::decode(&tag, &object_id, &property_id, &mut reader, buf)?;
177 let property_value = ReadPropertyValue::ApplicationDataValue(value);
178
179 Ok(Self {
180 object_id,
181 property_id,
182 property_value,
183 })
184 }
185 }
186 }
187}
188
189#[derive(Debug, Clone)]
190#[cfg_attr(feature = "defmt", derive(defmt::Format))]
191pub struct ReadProperty {
192 pub object_id: ObjectId, pub property_id: PropertyId, pub array_index: u32, }
196
197impl ReadProperty {
198 pub fn new(object_id: ObjectId, property_id: PropertyId) -> Self {
199 Self {
200 object_id,
201 property_id,
202 array_index: BACNET_ARRAY_ALL,
203 }
204 }
205
206 pub fn encode(&self, writer: &mut Writer) {
207 encode_context_object_id(writer, 0, &self.object_id);
209
210 encode_context_enumerated(writer, 1, &self.property_id);
212
213 if self.array_index != BACNET_ARRAY_ALL {
215 encode_context_unsigned(writer, 2, self.array_index);
216 }
217 }
218
219 pub fn decode(reader: &mut Reader, buf: &[u8]) -> Result<Self, Error> {
220 let object_id = decode_context_object_id(reader, buf, 0, "ReadProperty decode object_id")?;
222
223 let property_id =
225 decode_context_property_id(reader, buf, 1, "ReadProperty decode property_id")?;
226
227 Ok(Self {
228 object_id,
229 property_id,
230 array_index: BACNET_ARRAY_ALL,
231 })
232 }
233}