1use crate::{
2 application_protocol::{
3 confirmed::ConfirmedServiceChoice,
4 primitives::data_value::{BitString, Date, Time},
5 },
6 common::{
7 error::{Error, Unimplemented},
8 helper::{
9 decode_context_object_id, decode_context_property_id, decode_signed, decode_unsigned,
10 encode_application_signed, encode_application_unsigned, encode_closing_tag,
11 encode_context_enumerated, encode_context_object_id, encode_context_unsigned,
12 encode_opening_tag, get_tagged_body_for_tag,
13 },
14 io::{Reader, Writer},
15 object_id::ObjectId,
16 property_id::PropertyId,
17 spec::BACNET_ARRAY_ALL,
18 tag::{ApplicationTagNumber, Tag, TagNumber},
19 },
20};
21
22#[cfg(feature = "alloc")]
23use {alloc::vec::Vec, bacnet_macros::remove_lifetimes_from_fn_args};
24
25#[derive(Debug, Clone)]
26#[cfg_attr(feature = "defmt", derive(defmt::Format))]
27pub struct ReadRange {
28 pub object_id: ObjectId, pub property_id: PropertyId, pub array_index: u32, pub request_type: ReadRangeRequestType,
32}
33
34#[derive(Debug, Clone)]
35#[cfg_attr(feature = "defmt", derive(defmt::Format))]
36pub enum ReadRangeRequestType {
37 ByPosition(ReadRangeByPosition),
38 BySequence(ReadRangeBySequence),
39 ByTime(ReadRangeByTime),
40 All,
41}
42
43#[derive(Debug, Clone)]
44#[cfg_attr(feature = "defmt", derive(defmt::Format))]
45pub struct ReadRangeByPosition {
46 pub index: u32,
47 pub count: u32,
48}
49
50#[derive(Debug, Clone)]
51#[cfg_attr(feature = "defmt", derive(defmt::Format))]
52pub struct ReadRangeBySequence {
53 pub sequence_num: u32,
54 pub count: u32,
55}
56
57#[derive(Debug, Clone)]
58#[cfg_attr(feature = "defmt", derive(defmt::Format))]
59pub struct ReadRangeByTime {
60 pub date: Date,
61 pub time: Time,
62 pub count: u32,
63}
64
65#[derive(Debug, Clone)]
66#[cfg_attr(feature = "defmt", derive(defmt::Format))]
67pub struct ReadRangeAck<'a> {
68 pub object_id: ObjectId,
69 pub property_id: PropertyId,
70 pub array_index: u32,
71 pub result_flags: BitString<'a>,
72 pub item_count: usize,
73 pub item_data: ReadRangeItems<'a>,
74}
75
76impl<'a> ReadRangeAck<'a> {
77 const OBJECT_ID_TAG: u8 = 0;
78 const PROPERTY_ID_TAG: u8 = 1;
79 const ARRAY_INDEX_TAG: u8 = 2;
80 const RESULT_FLAGS_TAG: u8 = 3;
81 const ITEM_COUNT_TAG: u8 = 4;
82 const ITEM_DATA_TAG: u8 = 5;
83
84 pub fn encode(&self, writer: &mut Writer) {
85 writer.push(ConfirmedServiceChoice::ReadRange as u8);
86 encode_context_object_id(writer, Self::OBJECT_ID_TAG, &self.object_id);
87 encode_context_enumerated(writer, Self::PROPERTY_ID_TAG, &self.property_id);
88 if self.array_index != BACNET_ARRAY_ALL {
89 encode_context_unsigned(writer, Self::ARRAY_INDEX_TAG, self.array_index)
90 }
91 self.result_flags
92 .encode_context(Self::RESULT_FLAGS_TAG, writer);
93 encode_context_unsigned(writer, Self::ITEM_COUNT_TAG, self.item_count as u32);
94
95 encode_opening_tag(writer, Self::ITEM_DATA_TAG);
97 self.item_data.encode(writer);
98 encode_closing_tag(writer, Self::ITEM_DATA_TAG);
99 }
100
101 #[cfg_attr(feature = "alloc", remove_lifetimes_from_fn_args)]
102 pub fn decode(reader: &mut Reader, buf: &'a [u8]) -> Result<Self, Error> {
103 let tag = Tag::decode_expected(
105 reader,
106 buf,
107 TagNumber::ContextSpecific(Self::OBJECT_ID_TAG),
108 "ReadRangeAck decode object_id",
109 )?;
110 let object_id = ObjectId::decode(tag.value, reader, buf)?;
111
112 let property_id = decode_context_property_id(
114 reader,
115 buf,
116 Self::PROPERTY_ID_TAG,
117 "ReadRangeAck decode property_id",
118 )?;
119
120 let mut tag = Tag::decode(reader, buf)?;
122 let mut array_index = BACNET_ARRAY_ALL;
123 if let TagNumber::ContextSpecific(Self::ARRAY_INDEX_TAG) = tag.number {
124 array_index = decode_unsigned(tag.value, reader, buf)? as u32;
125
126 tag = Tag::decode(reader, buf)?;
128 }
129
130 tag.expect_number(
132 "ReadRangeAck decode result_flag",
133 TagNumber::ContextSpecific(Self::RESULT_FLAGS_TAG),
134 )?;
135 let result_flags = BitString::decode(&property_id, tag.value, reader, buf)?;
136
137 let tag = Tag::decode_expected(
139 reader,
140 buf,
141 TagNumber::ContextSpecific(Self::ITEM_COUNT_TAG),
142 "ReadRangeAck decode item_count",
143 )?;
144 let item_count = decode_unsigned(tag.value, reader, buf)? as usize;
145
146 let buf = if reader.eof() {
148 &[]
149 } else {
150 get_tagged_body_for_tag(
151 reader,
152 buf,
153 Self::ITEM_DATA_TAG,
154 "ReadRangeAck decode item_data",
155 )?
156 };
157 let item_data = ReadRangeItems::decode(buf)?;
158
159 Ok(Self {
160 object_id,
161 property_id,
162 array_index,
163 result_flags,
164 item_count,
165 item_data,
166 })
167 }
168}
169
170#[cfg(not(feature = "alloc"))]
171#[derive(Debug, Clone)]
172#[cfg_attr(feature = "defmt", derive(defmt::Format))]
173pub struct ReadRangeItems<'a> {
174 items: &'a [ReadRangeItem<'a>],
175 buf: &'a [u8],
176}
177
178#[cfg(feature = "alloc")]
179#[derive(Debug, Clone)]
180#[cfg_attr(feature = "defmt", derive(defmt::Format))]
181pub struct ReadRangeItems<'a> {
182 pub items: Vec<ReadRangeItem<'a>>,
183}
184
185#[derive(Debug, Clone)]
186#[cfg_attr(feature = "defmt", derive(defmt::Format))]
187#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
188pub enum ReadRangeValue {
189 Status,
190 Bool(bool),
191 Real(f32),
192 Enum(u32),
193 Unsigned(u32),
194 Signed(i32),
195 Bits,
196 Null,
197 Error,
198 Delta,
199 Any,
200}
201
202#[derive(Debug, Clone)]
203#[cfg_attr(feature = "defmt", derive(defmt::Format))]
204#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
205#[repr(u8)]
206pub enum ReadRangeValueType {
207 Status = 0,
208 Bool = 1,
209 Real = 2,
210 Enum = 3,
211 Unsigned = 4,
212 Signed = 5,
213 Bits = 6,
214 Null = 7,
215 Error = 8,
216 Delta = 9,
217 Any = 10,
218}
219
220impl TryFrom<u8> for ReadRangeValueType {
221 type Error = u8;
222
223 fn try_from(value: u8) -> Result<Self, u8> {
224 match value {
225 0 => Ok(Self::Status),
226 1 => Ok(Self::Bool),
227 2 => Ok(Self::Real),
228 3 => Ok(Self::Enum),
229 4 => Ok(Self::Unsigned),
230 5 => Ok(Self::Signed),
231 6 => Ok(Self::Bits),
232 7 => Ok(Self::Null),
233 8 => Ok(Self::Error),
234 9 => Ok(Self::Delta),
235 10 => Ok(Self::Any),
236 unknown => Err(unknown),
237 }
238 }
239}
240
241impl<'a> ReadRangeItems<'a> {
242 #[cfg(not(feature = "alloc"))]
243 pub fn new_from_buf(buf: &'a [u8]) -> Self {
244 Self { items: &[], buf }
245 }
246
247 #[cfg(not(feature = "alloc"))]
248 pub fn new(items: &'a [ReadRangeItem<'a>]) -> Self {
249 Self { items, buf: &[] }
250 }
251
252 #[cfg(feature = "alloc")]
253 pub fn new(items: Vec<ReadRangeItem<'a>>) -> Self {
254 Self { items }
255 }
256
257 pub fn encode(&self, writer: &mut Writer) {
258 for item in self.items.iter() {
259 item.encode(writer)
260 }
261 }
262
263 #[cfg(not(feature = "alloc"))]
264 pub fn decode(buf: &'a [u8]) -> Result<Self, Error> {
265 Ok(Self::new_from_buf(buf))
266 }
267
268 #[cfg(feature = "alloc")]
269 pub fn decode(buf: &[u8]) -> Result<Self, Error> {
270 let mut reader = Reader::new_with_len(buf.len());
271 let mut items = Vec::new();
272
273 while !reader.eof() {
274 let item = ReadRangeItem::decode(&mut reader, buf)?;
275 items.push(item);
276 }
277
278 Ok(Self::new(items))
279 }
280}
281
282#[cfg(not(feature = "alloc"))]
283impl<'a> IntoIterator for &'_ ReadRangeItems<'a> {
284 type Item = Result<ReadRangeItem<'a>, Error>;
285
286 type IntoIter = ReadRangeItemsIter<'a>;
287
288 fn into_iter(self) -> Self::IntoIter {
289 ReadRangeItemsIter {
290 buf: self.buf,
291 reader: Reader::new_with_len(self.buf.len()),
292 }
293 }
294}
295
296pub struct ReadRangeItemsIter<'a> {
297 reader: Reader,
298 buf: &'a [u8],
299}
300
301impl<'a> Iterator for ReadRangeItemsIter<'a> {
302 type Item = Result<ReadRangeItem<'a>, Error>;
303
304 fn next(&mut self) -> Option<Self::Item> {
305 if self.reader.eof() {
306 return None;
307 }
308
309 let item = ReadRangeItem::decode(&mut self.reader, self.buf);
310 Some(item)
311 }
312}
313
314#[derive(Debug, Clone)]
315#[cfg_attr(feature = "defmt", derive(defmt::Format))]
316pub struct ReadRangeItem<'a> {
317 pub date: Date,
318 pub time: Time,
319 pub value: ReadRangeValue,
320 pub status_flags: BitString<'a>,
321}
322
323impl<'a> ReadRangeItem<'a> {
324 const DATE_TIME_TAG: u8 = 0;
325 const VALUE_TAG: u8 = 1;
326 const STATUS_FLAGS_TAG: u8 = 2;
327
328 pub fn encode(&self, writer: &mut Writer) {
329 Tag::new(TagNumber::ContextSpecificOpening(Self::DATE_TIME_TAG), 0).encode(writer);
331 Tag::new(
332 TagNumber::Application(ApplicationTagNumber::Date),
333 Date::LEN,
334 )
335 .encode(writer);
336 self.date.encode(writer);
337 Tag::new(
338 TagNumber::Application(ApplicationTagNumber::Time),
339 Time::LEN,
340 )
341 .encode(writer);
342 self.time.encode(writer);
343 Tag::new(TagNumber::ContextSpecificClosing(Self::DATE_TIME_TAG), 0).encode(writer);
344
345 Tag::new(TagNumber::ContextSpecificOpening(Self::VALUE_TAG), 0).encode(writer);
347 match self.value {
348 ReadRangeValue::Real(value) => {
349 Tag::new(
350 TagNumber::ContextSpecific(ReadRangeValueType::Real as u8),
351 4,
352 )
353 .encode(writer);
354 writer.extend_from_slice(&value.to_be_bytes());
355 }
356 _ => todo!("{:?}", self.value),
357 }
358 Tag::new(TagNumber::ContextSpecificClosing(Self::VALUE_TAG), 0).encode(writer);
359
360 self.status_flags
362 .encode_context(Self::STATUS_FLAGS_TAG, writer);
363 }
364
365 #[cfg_attr(feature = "alloc", bacnet_macros::remove_lifetimes_from_fn_args)]
366 pub fn decode(reader: &mut Reader, buf: &'a [u8]) -> Result<Self, Error> {
367 Tag::decode_expected(
369 reader,
370 buf,
371 TagNumber::ContextSpecificOpening(Self::DATE_TIME_TAG),
372 "ReadRangeItem decode",
373 )?;
374 Tag::decode_expected(
375 reader,
376 buf,
377 TagNumber::Application(ApplicationTagNumber::Date),
378 "ReadRangeItem decode",
379 )?;
380 let date = Date::decode(reader, buf)?;
381 Tag::decode_expected(
382 reader,
383 buf,
384 TagNumber::Application(ApplicationTagNumber::Time),
385 "ReadRangeItem decode",
386 )?;
387 let time = Time::decode(reader, buf)?;
388 Tag::decode_expected(
389 reader,
390 buf,
391 TagNumber::ContextSpecificClosing(Self::DATE_TIME_TAG),
392 "ReadRangeItem decode",
393 )?;
394
395 Tag::decode_expected(
397 reader,
398 buf,
399 TagNumber::ContextSpecificOpening(Self::VALUE_TAG),
400 "ReadRangeItem decode",
401 )?;
402 let tag = Tag::decode(reader, buf)?;
403 let value_type: ReadRangeValueType = match tag.number {
404 TagNumber::ContextSpecific(tag_number) => tag_number
405 .try_into()
406 .map_err(|x| Error::InvalidVariant(("ReadRangeValueType", x as u32)))?,
407 x => return Err(Error::TagNotSupported(("ReadRangeItems next value", x))),
408 };
409 let value = match value_type {
410 ReadRangeValueType::Real => {
411 let value = f32::from_be_bytes(reader.read_bytes(buf)?);
412 ReadRangeValue::Real(value)
413 }
414 x => return Err(Error::Unimplemented(Unimplemented::ReadRangeValueType(x))),
415 };
416 Tag::decode_expected(
417 reader,
418 buf,
419 TagNumber::ContextSpecificClosing(Self::VALUE_TAG),
420 "ReadRangeItem decode",
421 )?;
422
423 Tag::decode_expected(
425 reader,
426 buf,
427 TagNumber::ContextSpecific(Self::STATUS_FLAGS_TAG),
428 "ReadRangeItem decode",
429 )?;
430 let status_flags = BitString::decode(&PropertyId::PropStatusFlags, tag.value, reader, buf)?;
431
432 Ok(ReadRangeItem {
433 date,
434 time,
435 value,
436 status_flags,
437 })
438 }
439}
440
441impl ReadRange {
442 const OBJECT_ID_TAG: u8 = 0;
443 const PROPERTY_ID_TAG: u8 = 1;
444 const ARRAY_INDEX_TAG: u8 = 2;
445 const BY_POSITION_TAG: u8 = 3;
446 const BY_SEQUENCE_TAG: u8 = 6;
447 const BY_TIME_TAG: u8 = 7;
448
449 pub fn new(
450 object_id: ObjectId,
451 property_id: PropertyId,
452 request_type: ReadRangeRequestType,
453 ) -> Self {
454 Self {
455 object_id,
456 property_id,
457 array_index: BACNET_ARRAY_ALL,
458 request_type,
459 }
460 }
461
462 pub fn decode(reader: &mut Reader, buf: &[u8]) -> Result<Self, Error> {
463 let object_id = decode_context_object_id(
464 reader,
465 buf,
466 Self::OBJECT_ID_TAG,
467 "ReadRange decode object_id",
468 )?;
469 let property_id = decode_context_property_id(
470 reader,
471 buf,
472 Self::PROPERTY_ID_TAG,
473 "ReadRange decode property_id",
474 )?;
475
476 let mut tag = Tag::decode(reader, buf)?;
477 let array_index = if tag.number == TagNumber::ContextSpecific(Self::ARRAY_INDEX_TAG) {
478 let value = decode_unsigned(tag.value, reader, buf)? as u32;
479 tag = Tag::decode(reader, buf)?;
480 value
481 } else {
482 BACNET_ARRAY_ALL
483 };
484
485 let request_type = match tag.number {
486 TagNumber::ContextSpecificOpening(Self::BY_POSITION_TAG) => {
487 let index_tag = Tag::decode_expected(
489 reader,
490 buf,
491 TagNumber::Application(ApplicationTagNumber::UnsignedInt),
492 "ReadRange decode index",
493 )?;
494 let index = decode_unsigned(index_tag.value, reader, buf)? as u32;
495
496 let count_tag = Tag::decode(reader, buf)?;
498 let count = match count_tag.number {
499 TagNumber::Application(ApplicationTagNumber::UnsignedInt) => {
500 decode_unsigned(count_tag.value, reader, buf)? as u32
501 }
502 TagNumber::Application(ApplicationTagNumber::SignedInt) => {
503 let count = decode_signed(count_tag.value, reader, buf)?;
504 if count < 0 {
505 return Err(Error::InvalidValue("ReadRange count cannot be negative"));
506 }
507
508 count as u32
509 }
510 _ => {
511 return Err(Error::TagNotSupported((
512 "ReadRange count tag",
513 count_tag.number,
514 )))
515 }
516 };
517
518 Tag::decode_expected(
520 reader,
521 buf,
522 TagNumber::ContextSpecificClosing(Self::BY_POSITION_TAG),
523 "ReadRange decode closing position",
524 )?;
525
526 ReadRangeRequestType::ByPosition(ReadRangeByPosition {
527 count: count as u32,
528 index,
529 })
530 }
531 number => return Err(Error::TagNotSupported(("ReadRange opening tag", number))),
532 };
533
534 Ok(Self {
535 array_index,
536 object_id,
537 property_id,
538 request_type,
539 })
540 }
541
542 pub fn encode(&self, writer: &mut Writer) {
543 encode_context_object_id(writer, Self::OBJECT_ID_TAG, &self.object_id);
545
546 encode_context_enumerated(writer, Self::PROPERTY_ID_TAG, &self.property_id);
548
549 if self.array_index != BACNET_ARRAY_ALL {
551 encode_context_unsigned(writer, Self::ARRAY_INDEX_TAG, self.array_index);
552 }
553
554 match &self.request_type {
555 ReadRangeRequestType::ByPosition(x) => {
556 encode_opening_tag(writer, Self::BY_POSITION_TAG);
557 encode_application_unsigned(writer, x.index as u64);
558 encode_application_signed(writer, x.count as i32);
559 encode_closing_tag(writer, Self::BY_POSITION_TAG);
560 }
561 ReadRangeRequestType::BySequence(x) => {
562 encode_opening_tag(writer, Self::BY_SEQUENCE_TAG);
563 encode_application_unsigned(writer, x.sequence_num as u64);
564 encode_application_signed(writer, x.count as i32);
565 encode_closing_tag(writer, Self::BY_SEQUENCE_TAG);
566 }
567 ReadRangeRequestType::ByTime(x) => {
568 encode_opening_tag(writer, Self::BY_TIME_TAG);
569 x.date.encode(writer);
570 x.time.encode(writer);
571 encode_application_signed(writer, x.count as i32);
572 encode_closing_tag(writer, Self::BY_TIME_TAG);
573 }
574 ReadRangeRequestType::All => {
575 }
577 }
578 }
579}