rustbac_core/services/
write_property.rs1use crate::apdu::ConfirmedRequestHeader;
2use crate::encoding::{
3 primitives::{
4 encode_closing_tag, encode_ctx_object_id, encode_ctx_unsigned, encode_opening_tag,
5 },
6 writer::Writer,
7};
8use crate::services::value_codec::encode_application_data_value;
9use crate::types::{DataValue, ObjectId, PropertyId};
10use crate::EncodeError;
11
12pub const SERVICE_WRITE_PROPERTY: u8 = 0x0F;
13
14#[derive(Debug, Clone, PartialEq)]
15pub struct WritePropertyRequest<'a> {
16 pub object_id: ObjectId,
17 pub property_id: PropertyId,
18 pub value: DataValue<'a>,
19 pub array_index: Option<u32>,
20 pub priority: Option<u8>,
21 pub invoke_id: u8,
22}
23
24impl<'a> Default for WritePropertyRequest<'a> {
25 fn default() -> Self {
26 Self {
27 object_id: ObjectId::new(crate::types::ObjectType::AnalogValue, 0),
28 property_id: PropertyId::PresentValue,
29 value: DataValue::Null,
30 array_index: None,
31 priority: None,
32 invoke_id: 1,
33 }
34 }
35}
36
37impl<'a> WritePropertyRequest<'a> {
38 pub fn encode(&self, w: &mut Writer<'_>) -> Result<(), EncodeError> {
39 ConfirmedRequestHeader {
40 segmented: false,
41 more_follows: false,
42 segmented_response_accepted: false,
43 max_segments: 0,
44 max_apdu: 5,
45 invoke_id: self.invoke_id,
46 sequence_number: None,
47 proposed_window_size: None,
48 service_choice: SERVICE_WRITE_PROPERTY,
49 }
50 .encode(w)?;
51
52 encode_ctx_object_id(w, 0, self.object_id.raw())?;
53 encode_ctx_unsigned(w, 1, self.property_id.to_u32())?;
54 if let Some(idx) = self.array_index {
55 encode_ctx_unsigned(w, 2, idx)?;
56 }
57
58 encode_opening_tag(w, 3)?;
59 encode_application_data_value(w, &self.value)?;
60 encode_closing_tag(w, 3)?;
61
62 if let Some(priority) = self.priority {
63 encode_ctx_unsigned(w, 4, priority as u32)?;
64 }
65 Ok(())
66 }
67}
68
69#[cfg(test)]
70mod tests {
71 use super::{WritePropertyRequest, SERVICE_WRITE_PROPERTY};
72 use crate::apdu::ConfirmedRequestHeader;
73 use crate::encoding::{reader::Reader, writer::Writer};
74 use crate::types::{DataValue, ObjectId, ObjectType, PropertyId};
75
76 #[test]
77 fn encode_write_property_with_character_string() {
78 let req = WritePropertyRequest {
79 object_id: ObjectId::new(ObjectType::AnalogValue, 3),
80 property_id: PropertyId::Description,
81 value: DataValue::CharacterString("loop tuning pending"),
82 priority: None,
83 ..Default::default()
84 };
85
86 let mut buf = [0u8; 256];
87 let mut w = Writer::new(&mut buf);
88 req.encode(&mut w).unwrap();
89
90 let mut r = Reader::new(w.as_written());
91 let hdr = ConfirmedRequestHeader::decode(&mut r).unwrap();
92 assert_eq!(hdr.service_choice, SERVICE_WRITE_PROPERTY);
93 }
94}