bacnet_emb/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 #[cfg_attr(feature = "alloc", bacnet_macros::remove_lifetimes_from_fn_args)]
53 pub fn decode(reader: &mut Reader, buf: &'a [u8]) -> Result<Self, Error> {
54 let object_id = decode_context_object_id(
55 reader,
56 buf,
57 Self::TAG_OBJECT_ID,
58 "WriteProperty decode object_id",
59 )?;
60 let property_id = decode_context_property_id(
61 reader,
62 buf,
63 Self::TAG_PROPERTY_ID,
64 "WriteProperty decode property_id",
65 )?;
66
67 let mut tag = Tag::decode(reader, buf)?;
69 let mut array_index = None;
70 if let TagNumber::ContextSpecific(Self::TAG_ARRAY_INDEX) = tag.number {
71 let array_index_tmp = decode_unsigned(tag.value, reader, buf)? as u32;
72 if array_index_tmp != BACNET_ARRAY_ALL {
73 array_index = Some(array_index_tmp)
74 }
75
76 tag = Tag::decode(reader, buf)?;
78 }
79
80 tag.expect_number(
82 "WriteProperty decode value",
83 TagNumber::ContextSpecificOpening(Self::TAG_VALUE),
84 )?;
85 let value = ApplicationDataValueWrite::decode(&object_id, &property_id, reader, buf)?;
86 Tag::decode_expected(
87 reader,
88 buf,
89 TagNumber::ContextSpecificClosing(Self::TAG_VALUE),
90 "WriteProperty decode value",
91 )?;
92
93 let tag = Tag::decode_expected(
95 reader,
96 buf,
97 TagNumber::ContextSpecific(Self::TAG_PRIORITY),
98 "WriteProperty decode priority",
99 )?;
100 let priority = tag.value as u8;
101 let priority = if priority == Self::LOWEST_PRIORITY {
102 None
103 } else {
104 Some(priority)
105 };
106
107 Ok(Self {
108 object_id,
109 property_id,
110 array_index,
111 value,
112 priority,
113 })
114 }
115
116 pub fn encode(&self, writer: &mut Writer) {
117 encode_context_object_id(writer, Self::TAG_OBJECT_ID, &self.object_id);
119
120 encode_context_enumerated(writer, Self::TAG_PROPERTY_ID, &self.property_id);
122
123 if let Some(array_index) = self.array_index {
125 encode_context_unsigned(writer, Self::TAG_ARRAY_INDEX, array_index);
126 }
127
128 encode_opening_tag(writer, Self::TAG_VALUE);
130 self.value.encode(writer);
131 encode_closing_tag(writer, Self::TAG_VALUE);
132
133 let priority = self
135 .priority
136 .unwrap_or(Self::LOWEST_PRIORITY)
137 .min(Self::LOWEST_PRIORITY) as u32;
138 encode_context_unsigned(writer, Self::TAG_PRIORITY, priority);
139 }
140}