bacnet_emb/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#[cfg(feature = "alloc")]
23use {
24 crate::common::spooky::Phantom, alloc::vec::Vec, bacnet_macros::remove_lifetimes_from_fn_args,
25};
26
27#[derive(Debug, Clone)]
28#[cfg_attr(feature = "defmt", derive(defmt::Format))]
29pub enum ReadPropertyValue<'a> {
30 ObjectIdList(ObjectIdList<'a>),
31 ApplicationDataValue(ApplicationDataValue<'a>),
32}
33
34#[cfg(not(feature = "alloc"))]
35#[derive(Debug, Clone)]
36#[cfg_attr(feature = "defmt", derive(defmt::Format))]
37pub struct ObjectIdList<'a> {
38 object_ids: &'a [ObjectId],
39 buf: &'a [u8],
40}
41
42#[cfg(feature = "alloc")]
43#[derive(Debug, Clone)]
44#[cfg_attr(feature = "defmt", derive(defmt::Format))]
45pub struct ObjectIdList<'a> {
46 pub object_ids: Vec<ObjectId>,
47 _phantom: &'a Phantom,
48}
49
50#[derive(Debug, Clone)]
51#[cfg_attr(feature = "defmt", derive(defmt::Format))]
52pub struct ObjectIdIter<'a> {
53 reader: Reader,
54 buf: &'a [u8],
55}
56
57impl<'a> ObjectIdList<'a> {
58 #[cfg(not(feature = "alloc"))]
59 pub fn new(object_ids: &'a [ObjectId]) -> Self {
60 Self {
61 object_ids,
62 buf: &[],
63 }
64 }
65
66 #[cfg(not(feature = "alloc"))]
67 pub fn new_from_buf(buf: &'a [u8]) -> Self {
68 Self {
69 object_ids: &[],
70 buf,
71 }
72 }
73
74 #[cfg(feature = "alloc")]
75 pub fn new(object_ids: Vec<ObjectId>) -> Self {
76 use crate::common::spooky::PHANTOM;
77
78 Self {
79 object_ids,
80 _phantom: &PHANTOM,
81 }
82 }
83
84 pub fn encode(&self, writer: &mut Writer) {
85 for object_id in self.object_ids.iter() {
86 Tag::new(
87 TagNumber::Application(ApplicationTagNumber::ObjectId),
88 ObjectId::LEN,
89 )
90 .encode(writer);
91 object_id.encode(writer);
92 }
93 }
94
95 #[cfg(not(feature = "alloc"))]
96 pub fn decode(_reader: &mut Reader, buf: &'a [u8]) -> Result<Self, Error> {
97 Ok(Self::new_from_buf(buf))
98 }
99
100 #[cfg(feature = "alloc")]
101 pub fn decode(_reader: &mut Reader, buf: &[u8]) -> Result<Self, Error> {
102 let decoder = ObjectIdIter::new(buf);
103 let object_ids: Result<Vec<ObjectId>, Error> = decoder.into_iter().collect();
104 Ok(Self::new(object_ids?))
105 }
106}
107
108impl<'a> ObjectIdIter<'a> {
109 pub fn new(buf: &'a [u8]) -> Self {
110 Self {
111 reader: Reader::new_with_len(buf.len()),
112 buf,
113 }
114 }
115
116 fn next_internal(&mut self) -> Result<ObjectId, Error> {
117 let tag = Tag::decode_expected(
118 &mut self.reader,
119 self.buf,
120 TagNumber::Application(ApplicationTagNumber::ObjectId),
121 "ObjectIdList nex",
122 )?;
123
124 ObjectId::decode(tag.value, &mut self.reader, self.buf)
125 }
126}
127
128#[cfg(not(feature = "alloc"))]
129impl<'a> IntoIterator for &'_ ObjectIdList<'a> {
130 type Item = Result<ObjectId, Error>;
131 type IntoIter = ObjectIdIter<'a>;
132
133 fn into_iter(self) -> Self::IntoIter {
134 ObjectIdIter::new(self.buf)
135 }
136}
137
138impl<'a> Iterator for ObjectIdIter<'a> {
139 type Item = Result<ObjectId, Error>;
140
141 fn next(&mut self) -> Option<Self::Item> {
142 if self.reader.eof() {
143 None
144 } else {
145 Some(self.next_internal())
146 }
147 }
148}
149
150#[derive(Debug, Clone)]
151#[cfg_attr(feature = "defmt", derive(defmt::Format))]
152pub struct ReadPropertyAck<'a> {
153 pub object_id: ObjectId,
154 pub property_id: PropertyId,
155 pub property_value: ReadPropertyValue<'a>,
156}
157
158impl<'a> TryFrom<DataLink<'a>> for ReadPropertyAck<'a> {
159 type Error = Error;
160
161 fn try_from(value: DataLink<'a>) -> Result<Self, Self::Error> {
162 let ack: ComplexAck = value.try_into()?;
163 match ack.service {
164 ComplexAckService::ReadProperty(ack) => Ok(ack),
165 _ => Err(Error::ConvertDataLink(
166 "apdu message is not a ComplexAckService ReadPropertyAck",
167 )),
168 }
169 }
170}
171
172impl<'a> ReadPropertyAck<'a> {
173 pub fn encode(&self, writer: &mut Writer) {
174 writer.push(ConfirmedServiceChoice::ReadProperty as u8);
175 encode_context_object_id(writer, 0, &self.object_id);
176 encode_context_enumerated(writer, 1, &self.property_id);
177 encode_opening_tag(writer, 3);
178 match &self.property_value {
179 ReadPropertyValue::ApplicationDataValue(value) => {
180 value.encode(writer);
181 }
182 ReadPropertyValue::ObjectIdList(value) => {
183 value.encode(writer);
184 }
185 }
186 encode_closing_tag(writer, 3);
187 }
188
189 #[cfg_attr(feature = "alloc", remove_lifetimes_from_fn_args)]
190 pub fn decode(reader: &mut Reader, buf: &'a [u8]) -> Result<Self, Error> {
191 let object_id =
192 decode_context_object_id(reader, buf, 0, "ReadPropertyAck decode object_id")?;
193 let property_id =
194 decode_context_property_id(reader, buf, 1, "ReadPropertyAck decode property_id")?;
195
196 let buf = get_tagged_body_for_tag(reader, buf, 3, "ReadPropertyAck decode data values")?;
197 let mut reader = Reader::new_with_len(buf.len());
198
199 match property_id {
200 PropertyId::PropObjectList => {
201 let object_ids = ObjectIdList::decode(&mut reader, buf)?;
202 let property_value = ReadPropertyValue::ObjectIdList(object_ids);
203
204 Ok(Self {
205 object_id,
206 property_id,
207 property_value,
208 })
209 }
210 property_id => {
211 let tag = Tag::decode(&mut reader, buf)?;
212 let value =
213 ApplicationDataValue::decode(&tag, &object_id, &property_id, &mut reader, buf)?;
214 let property_value = ReadPropertyValue::ApplicationDataValue(value);
215
216 Ok(Self {
217 object_id,
218 property_id,
219 property_value,
220 })
221 }
222 }
223 }
224}
225
226#[derive(Debug, Clone)]
227#[cfg_attr(feature = "defmt", derive(defmt::Format))]
228pub struct ReadProperty {
229 pub object_id: ObjectId, pub property_id: PropertyId, pub array_index: u32, }
233
234impl ReadProperty {
235
236 pub fn new(object_id: ObjectId, property_id: PropertyId) -> Self {
237 Self {
238 object_id,
239 property_id,
240 array_index: BACNET_ARRAY_ALL,
241 }
242 }
243
244 pub fn encode(&self, writer: &mut Writer) {
245 encode_context_object_id(writer, 0, &self.object_id);
247
248 encode_context_enumerated(writer, 1, &self.property_id);
250
251 if self.array_index != BACNET_ARRAY_ALL {
253 encode_context_unsigned(writer, 2, self.array_index);
254 }
255 }
256
257 pub fn decode(reader: &mut Reader, buf: &[u8]) -> Result<Self, Error> {
258 let object_id = decode_context_object_id(reader, buf, 0, "ReadProperty decode object_id")?;
260
261 let property_id =
263 decode_context_property_id(reader, buf, 1, "ReadProperty decode property_id")?;
264
265 Ok(Self {
266 object_id,
267 property_id,
268 array_index: BACNET_ARRAY_ALL,
269 })
270 }
271}