1use core::fmt::Display;
2
3use crate::{
4 application_protocol::{
5 confirmed::{ComplexAck, ComplexAckService, ConfirmedServiceChoice},
6 primitives::data_value::ApplicationDataValue,
7 },
8 common::{
9 daily_schedule::WeeklySchedule,
10 error::Error,
11 helper::{
12 decode_context_object_id, decode_context_property_id, decode_unsigned,
13 encode_closing_tag, encode_context_enumerated, encode_context_object_id,
14 encode_context_unsigned, encode_opening_tag, get_tagged_body, get_tagged_body_for_tag,
15 },
16 io::{Reader, Writer},
17 object_id::{ObjectId, ObjectType},
18 property_id::PropertyId,
19 spec::{ErrorClass, ErrorCode, BACNET_ARRAY_ALL},
20 tag::{ApplicationTagNumber, Tag, TagNumber},
21 },
22 network_protocol::data_link::DataLink,
23};
24
25#[derive(Debug, Clone)]
26#[cfg_attr(feature = "defmt", derive(defmt::Format))]
27pub struct ReadPropertyMultipleAck<'a> {
28 pub objects_with_results: &'a [ObjectWithResults<'a>],
29 buf: &'a [u8],
30}
31
32impl<'a> IntoIterator for &'_ ReadPropertyMultipleAck<'a> {
33 type Item = Result<ObjectWithResults<'a>, Error>;
34
35 type IntoIter = ObjectWithResultsIter<'a>;
36
37 fn into_iter(self) -> Self::IntoIter {
38 ObjectWithResultsIter {
39 buf: self.buf,
40 reader: Reader::new_with_len(self.buf.len()),
41 }
42 }
43}
44
45impl<'a> TryFrom<DataLink<'a>> for ReadPropertyMultipleAck<'a> {
46 type Error = Error;
47
48 fn try_from(value: DataLink<'a>) -> Result<Self, Self::Error> {
49 let ack: ComplexAck = value.try_into()?;
50 match ack.service {
51 ComplexAckService::ReadPropertyMultiple(ack) => Ok(ack),
52 _ => Err(Error::ConvertDataLink(
53 "apdu message is not a ComplexAckService ReadPropertyMultipleAck",
54 )),
55 }
56 }
57}
58
59#[derive(Debug, Clone)]
60#[cfg_attr(feature = "defmt", derive(defmt::Format))]
61pub struct ObjectWithResults<'a> {
62 pub object_id: ObjectId,
63 pub property_results: PropertyResultList<'a>,
64}
65
66impl<'a> ObjectWithResults<'a> {
67 pub fn encode(&self, writer: &mut Writer) {
68 encode_context_object_id(writer, 0, &self.object_id);
69 encode_opening_tag(writer, 1);
70 self.property_results.encode(writer);
71 encode_closing_tag(writer, 1);
72 }
73
74 pub fn decode(reader: &mut Reader, buf: &'a [u8]) -> Result<Self, Error> {
75 let object_id =
76 decode_context_object_id(reader, buf, 0, "ObjectWithResults decode object_id")?;
77 let buf =
78 get_tagged_body_for_tag(reader, buf, 1, "ObjectWithResults decode list of results")?;
79
80 let property_results = PropertyResultList {
81 object_id,
82 buf,
83 property_results: &[],
84 };
85
86 Ok(ObjectWithResults {
87 object_id,
88 property_results,
89 })
90 }
91}
92
93impl<'a> IntoIterator for &'_ PropertyResultList<'a> {
94 type Item = Result<PropertyResult<'a>, Error>;
95 type IntoIter = PropertyResultIter<'a>;
96
97 fn into_iter(self) -> Self::IntoIter {
98 PropertyResultIter {
99 buf: self.buf,
100 reader: Reader::new_with_len(self.buf.len()),
101 object_id: self.object_id,
102 }
103 }
104}
105
106impl<'a> Iterator for PropertyResultIter<'a> {
107 type Item = Result<PropertyResult<'a>, Error>;
108
109 fn next(&mut self) -> Option<Self::Item> {
110 if self.reader.eof() {
111 return None;
112 }
113
114 Some(PropertyResult::decode(
115 &mut self.reader,
116 self.buf,
117 &self.object_id,
118 ))
119 }
120}
121
122fn read_error(reader: &mut Reader, buf: &[u8]) -> Result<PropertyAccessError, Error> {
123 let tag = Tag::decode_expected(
125 reader,
126 buf,
127 TagNumber::Application(ApplicationTagNumber::Enumerated),
128 "read_error error_class",
129 )?;
130 let value = decode_unsigned(tag.value, reader, buf)? as u32;
131 let error_class = value
132 .try_into()
133 .map_err(|x| Error::InvalidVariant(("ErrorClass", x)))?;
134
135 let tag = Tag::decode_expected(
137 reader,
138 buf,
139 TagNumber::Application(ApplicationTagNumber::Enumerated),
140 "read_error error code",
141 )?;
142 let value = decode_unsigned(tag.value, reader, buf)? as u32;
143 let error_code = value
144 .try_into()
145 .map_err(|x| Error::InvalidVariant(("ErrorCode", x)))?;
146
147 Ok(PropertyAccessError {
148 error_class,
149 error_code,
150 })
151}
152
153#[derive(Debug, Clone)]
154#[cfg_attr(feature = "defmt", derive(defmt::Format))]
155pub struct PropertyResultList<'a> {
156 pub property_results: &'a [PropertyResult<'a>],
157 object_id: ObjectId,
158 buf: &'a [u8],
159}
160
161#[derive(Debug, Clone)]
162#[cfg_attr(feature = "defmt", derive(defmt::Format))]
163pub struct PropertyResultIter<'a> {
164 object_id: ObjectId,
165 reader: Reader,
166 buf: &'a [u8],
167}
168
169impl<'a> PropertyResultList<'a> {
170 pub fn new(property_results: &'a [PropertyResult<'a>]) -> Self {
171 Self {
172 property_results,
173 object_id: ObjectId::new(ObjectType::Invalid, 0),
174 buf: &[],
175 }
176 }
177
178 pub fn encode(&self, writer: &mut Writer) {
179 for item in self.property_results {
180 item.encode(writer);
181 }
182 }
183}
184
185#[derive(Debug, Clone)]
186#[cfg_attr(feature = "defmt", derive(defmt::Format))]
187pub struct PropertyResult<'a> {
188 pub id: PropertyId,
189 pub value: PropertyValue<'a>,
190}
191
192impl<'a> PropertyResult<'a> {
193 const PROPERTY_ID_TAG: u8 = 2;
194
195 pub fn encode(&self, writer: &mut Writer) {
196 encode_context_unsigned(writer, Self::PROPERTY_ID_TAG, self.id as u32);
197 self.value.encode(writer);
198 }
199
200 pub fn decode(reader: &mut Reader, buf: &'a [u8], object_id: &ObjectId) -> Result<Self, Error> {
201 let property_id = decode_context_property_id(
202 reader,
203 buf,
204 Self::PROPERTY_ID_TAG,
205 "PropertyResultList next property_id",
206 )?;
207
208 let value = PropertyValue::decode(reader, buf, object_id, &property_id)?;
209
210 Ok(PropertyResult {
211 id: property_id,
212 value,
213 })
214 }
215}
216
217#[derive(Debug, Clone)]
218#[cfg_attr(feature = "defmt", derive(defmt::Format))]
219pub enum PropertyValue<'a> {
220 PropValue(ApplicationDataValue<'a>),
221 PropError(PropertyAccessError),
222 PropDescription(&'a str),
224 PropObjectName(&'a str),
225}
226
227impl<'a> PropertyValue<'a> {
228 const PROPERTY_VALUE_TAG: u8 = 4;
229 const PROPERTY_ERROR_TAG: u8 = 5;
230
231 pub fn encode(&self, writer: &mut Writer) {
232 match self {
233 Self::PropValue(val) => {
234 encode_opening_tag(writer, Self::PROPERTY_VALUE_TAG);
235 val.encode(writer);
236 encode_closing_tag(writer, Self::PROPERTY_VALUE_TAG);
237 }
238 Self::PropError(_) => todo!(),
239 Self::PropObjectName(_) => todo!(),
240 Self::PropDescription(_) => todo!(),
241 }
242 }
243
244 pub fn decode(
245 reader: &mut Reader,
246 buf: &'a [u8],
247 object_id: &ObjectId,
248 property_id: &PropertyId,
249 ) -> Result<Self, Error> {
250 let (buf, tag_number) = get_tagged_body(reader, buf)?;
251 let mut reader = Reader {
252 index: 0,
253 end: buf.len(),
254 };
255
256 let property_value = match tag_number {
257 Self::PROPERTY_VALUE_TAG => {
258 match &property_id {
259 PropertyId::PropEventTimeStamps => {
260 PropertyValue::PropValue(ApplicationDataValue::Boolean(false))
262 }
263 PropertyId::PropWeeklySchedule => {
264 let weekly_schedule = WeeklySchedule::decode(&mut reader, buf)?;
265 PropertyValue::PropValue(ApplicationDataValue::WeeklySchedule(
266 weekly_schedule,
267 ))
268 }
269 property_id => {
270 let tag = Tag::decode(&mut reader, buf)?;
271 let value = ApplicationDataValue::decode(
272 &tag,
273 object_id,
274 property_id,
275 &mut reader,
276 buf,
277 )?;
278 PropertyValue::PropValue(value)
279 }
280 }
281 }
282 Self::PROPERTY_ERROR_TAG => {
283 let error = read_error(&mut reader, buf)?;
285 PropertyValue::PropError(error)
286 }
287 x => {
288 return Err(Error::TagNotSupported((
289 "PropertyResultList next",
290 TagNumber::ContextSpecificOpening(x),
291 )));
292 }
293 };
294
295 Ok(property_value)
296 }
297}
298
299#[derive(Debug, Clone)]
300#[cfg_attr(feature = "defmt", derive(defmt::Format))]
301pub struct PropertyAccessError {
302 pub error_class: ErrorClass,
303 pub error_code: ErrorCode,
304}
305
306impl<'a> Display for PropertyValue<'a> {
307 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
308 match &self {
309 Self::PropValue(x) => write!(f, "{}", x),
310 _ => write!(f, "property value unprintable",),
311 }
312 }
313}
314
315impl<'a> ReadPropertyMultipleAck<'a> {
316 pub fn new(objects_with_results: &'a [ObjectWithResults<'a>]) -> Self {
317 Self {
318 objects_with_results,
319 buf: &[],
320 }
321 }
322
323 pub fn new_from_buf(buf: &'a [u8]) -> Self {
324 Self {
325 buf,
326 objects_with_results: &[],
327 }
328 }
329
330 pub fn encode(&self, writer: &mut Writer) {
331 writer.push(ConfirmedServiceChoice::ReadPropMultiple as u8);
332 for item in self.objects_with_results {
333 item.encode(writer);
334 }
335 }
336}
337
338pub struct ObjectWithResultsIter<'a> {
339 buf: &'a [u8],
340 reader: Reader,
341}
342
343impl<'a> Iterator for ObjectWithResultsIter<'a> {
344 type Item = Result<ObjectWithResults<'a>, Error>;
345
346 fn next(&mut self) -> Option<Self::Item> {
347 if self.reader.eof() {
348 return None;
349 }
350
351 let object_with_results = ObjectWithResults::decode(&mut self.reader, self.buf);
352 Some(object_with_results)
353 }
354}
355
356#[derive(Debug, Clone)]
357#[cfg_attr(feature = "defmt", derive(defmt::Format))]
358pub struct ReadPropertyMultiple<'a> {
359 _array_index: u32, objects: &'a [ReadPropertyMultipleObject<'a>],
361 buf: &'a [u8],
362}
363
364#[derive(Debug, Clone)]
365#[cfg_attr(feature = "defmt", derive(defmt::Format))]
366pub struct PropertyIdList<'a> {
367 pub property_ids: &'a [PropertyId],
368 buf: &'a [u8],
369}
370
371impl<'a> IntoIterator for &'_ PropertyIdList<'a> {
372 type Item = Result<PropertyId, Error>;
373
374 type IntoIter = PropertyIdIter<'a>;
375
376 fn into_iter(self) -> Self::IntoIter {
377 PropertyIdIter {
378 buf: self.buf,
379 reader: Reader::new_with_len(self.buf.len()),
380 }
381 }
382}
383
384pub struct PropertyIdIter<'a> {
385 reader: Reader,
386 buf: &'a [u8],
387}
388
389impl<'a> Iterator for PropertyIdIter<'a> {
390 type Item = Result<PropertyId, Error>;
391
392 fn next(&mut self) -> Option<Self::Item> {
393 if self.reader.eof() {
394 None
395 } else {
396 match decode_context_property_id(
397 &mut self.reader,
398 self.buf,
399 0,
400 "PropertyIdList next property_id",
401 ) {
402 Ok(property_id) => Some(Ok(property_id)),
403 Err(e) => Some(Err(e)),
404 }
405 }
406 }
407}
408
409impl<'a> PropertyIdList<'a> {
410 pub fn new(property_ids: &'a [PropertyId]) -> Self {
411 Self {
412 property_ids,
413 buf: &[],
414 }
415 }
416
417 pub fn encode(&self, writer: &mut Writer) {
418 encode_opening_tag(writer, 1);
419
420 for property_id in self.property_ids {
421 encode_context_enumerated(writer, 0, property_id);
423
424 }
429
430 encode_closing_tag(writer, 1);
431 }
432}
433
434#[derive(Debug, Clone)]
435#[cfg_attr(feature = "defmt", derive(defmt::Format))]
436pub struct ReadPropertyMultipleObject<'a> {
437 pub object_id: ObjectId, pub property_ids: PropertyIdList<'a>,
439}
440
441impl<'a> ReadPropertyMultipleObject<'a> {
442 pub fn new(object_id: ObjectId, property_ids: &'a [PropertyId]) -> Self {
443 let property_ids = PropertyIdList::new(property_ids);
444 Self {
445 object_id,
446 property_ids,
447 }
448 }
449
450 pub fn encode(&self, writer: &mut Writer) {
451 encode_context_object_id(writer, 0, &self.object_id);
453
454 encode_opening_tag(writer, 1);
455
456 for property_id in self.property_ids.property_ids {
457 encode_context_enumerated(writer, 0, property_id);
459
460 }
465
466 encode_closing_tag(writer, 1);
467 }
468
469 pub fn decode(reader: &mut Reader, buf: &'a [u8]) -> Result<Self, Error> {
470 let object_id =
471 decode_context_object_id(reader, buf, 0, "ReadPropertyMultiple next object_id")?;
472
473 let buf =
474 get_tagged_body_for_tag(reader, buf, 1, "ReadPropertyMultiple next list of results")?;
475 let property_ids = PropertyIdList {
476 property_ids: &[],
477 buf,
478 };
479
480 Ok(ReadPropertyMultipleObject {
481 object_id,
482 property_ids,
483 })
484 }
485}
486
487impl<'a> ReadPropertyMultiple<'a> {
488 pub fn new(objects: &'a [ReadPropertyMultipleObject]) -> Self {
489 Self {
490 objects,
491 _array_index: BACNET_ARRAY_ALL,
492 buf: &[],
493 }
494 }
495
496 pub fn new_from_buf(buf: &'a [u8]) -> Self {
497 Self {
498 objects: &[],
499 _array_index: BACNET_ARRAY_ALL,
500 buf,
501 }
502 }
503
504 pub fn encode(&self, writer: &mut Writer) {
505 for object in self.objects {
506 object.encode(writer)
507 }
508 }
509
510 pub fn decode(reader: &mut Reader, buf: &'a [u8]) -> Self {
511 let buf = &buf[reader.index..reader.end];
512 Self {
513 buf,
514 _array_index: BACNET_ARRAY_ALL,
515 objects: &[],
516 }
517 }
518}
519
520impl<'a> IntoIterator for &'_ ReadPropertyMultiple<'a> {
521 type Item = Result<ReadPropertyMultipleObject<'a>, Error>;
522
523 type IntoIter = ReadPropertyMultipleIter<'a>;
524
525 fn into_iter(self) -> Self::IntoIter {
526 ReadPropertyMultipleIter {
527 buf: self.buf,
528 reader: Reader::new_with_len(self.buf.len()),
529 }
530 }
531}
532
533pub struct ReadPropertyMultipleIter<'a> {
534 buf: &'a [u8],
535 reader: Reader,
536}
537
538impl<'a> Iterator for ReadPropertyMultipleIter<'a> {
539 type Item = Result<ReadPropertyMultipleObject<'a>, Error>;
540
541 fn next(&mut self) -> Option<Self::Item> {
542 if self.reader.eof() {
543 return None;
544 }
545
546 let object_with_property_ids =
547 ReadPropertyMultipleObject::decode(&mut self.reader, self.buf);
548 Some(object_with_property_ids)
549 }
550}