embedded_bacnet/application_protocol/services/
write_property.rs1use crate::{
2 application_protocol::primitives::data_value::ApplicationDataValueWrite,
3 common::{
4 error::Error,
5 helper::{
6 decode_context_object_id, decode_context_property_id, decode_unsigned,
7 encode_closing_tag, encode_context_enumerated, encode_context_object_id,
8 encode_context_unsigned, encode_opening_tag,
9 },
10 io::{Reader, Writer},
11 object_id::ObjectId,
12 property_id::PropertyId,
13 spec::BACNET_ARRAY_ALL,
14 tag::{Tag, TagNumber},
15 },
16};
17
18#[derive(Debug, Clone)]
19#[cfg_attr(feature = "defmt", derive(defmt::Format))]
20pub struct WriteProperty<'a> {
21 pub object_id: ObjectId,
22 pub property_id: PropertyId,
23 pub priority: Option<u8>,
24 pub array_index: Option<u32>,
25 pub value: ApplicationDataValueWrite<'a>,
26}
27
28impl<'a> WriteProperty<'a> {
29 const TAG_OBJECT_ID: u8 = 0;
30 const TAG_PROPERTY_ID: u8 = 1;
31 const TAG_ARRAY_INDEX: u8 = 2;
32 const TAG_VALUE: u8 = 3;
33 const TAG_PRIORITY: u8 = 4;
34 const LOWEST_PRIORITY: u8 = 16;
35
36 pub fn new(
37 object_id: ObjectId,
38 property_id: PropertyId,
39 priority: Option<u8>,
40 array_index: Option<u32>,
41 value: ApplicationDataValueWrite<'a>,
42 ) -> Self {
43 Self {
44 object_id,
45 property_id,
46 priority,
47 array_index,
48 value,
49 }
50 }
51
52 pub fn decode(reader: &mut Reader, buf: &'a [u8]) -> Result<Self, Error> {
53 let object_id = decode_context_object_id(
54 reader,
55 buf,
56 Self::TAG_OBJECT_ID,
57 "WriteProperty decode object_id",
58 )?;
59 let property_id = decode_context_property_id(
60 reader,
61 buf,
62 Self::TAG_PROPERTY_ID,
63 "WriteProperty decode property_id",
64 )?;
65
66 let mut tag = Tag::decode(reader, buf)?;
68 let mut array_index = None;
69 if let TagNumber::ContextSpecific(Self::TAG_ARRAY_INDEX) = tag.number {
70 let array_index_tmp = decode_unsigned(tag.value, reader, buf)? as u32;
71 if array_index_tmp != BACNET_ARRAY_ALL {
72 array_index = Some(array_index_tmp)
73 }
74
75 tag = Tag::decode(reader, buf)?;
77 }
78
79 tag.expect_number(
81 "WriteProperty decode value",
82 TagNumber::ContextSpecificOpening(Self::TAG_VALUE),
83 )?;
84 let value = ApplicationDataValueWrite::decode(&object_id, &property_id, reader, buf)?;
85 Tag::decode_expected(
86 reader,
87 buf,
88 TagNumber::ContextSpecificClosing(Self::TAG_VALUE),
89 "WriteProperty decode value",
90 )?;
91
92 let tag = Tag::decode_expected(
94 reader,
95 buf,
96 TagNumber::ContextSpecific(Self::TAG_PRIORITY),
97 "WriteProperty decode priority",
98 )?;
99 let priority = tag.value as u8;
100 let priority = if priority == Self::LOWEST_PRIORITY {
101 None
102 } else {
103 Some(priority)
104 };
105
106 Ok(Self {
107 object_id,
108 property_id,
109 array_index,
110 value,
111 priority,
112 })
113 }
114
115 pub fn encode(&self, writer: &mut Writer) {
116 encode_context_object_id(writer, Self::TAG_OBJECT_ID, &self.object_id);
118
119 encode_context_enumerated(writer, Self::TAG_PROPERTY_ID, &self.property_id);
121
122 if let Some(array_index) = self.array_index {
124 encode_context_unsigned(writer, Self::TAG_ARRAY_INDEX, array_index);
125 }
126
127 encode_opening_tag(writer, Self::TAG_VALUE);
129 self.value.encode(writer);
130 encode_closing_tag(writer, Self::TAG_VALUE);
131
132 let priority = self
134 .priority
135 .unwrap_or(Self::LOWEST_PRIORITY)
136 .min(Self::LOWEST_PRIORITY) as u32;
137 encode_context_unsigned(writer, Self::TAG_PRIORITY, priority);
138 }
139}