bacnet_objects/device/
audit_recipient.rs1use super::*;
3use bacnet_types::constructed::{BACnetAddress, BACnetRecipient};
4use std::sync::Weak;
5
6#[doc(hidden)]
8#[derive(Clone)]
9pub struct AuditWriteSource {
10 pub device: BACnetRecipient,
11 pub invoke_id: u8,
12}
13
14#[doc(hidden)]
17pub trait AuditRecipientChangeSink: Send + Sync {
18 fn change(
19 &self,
20 current: &mut BACnetRecipient,
21 new: BACnetRecipient,
22 source: Option<&AuditWriteSource>,
23 clock: Option<ClockFrame>,
24 ) -> Result<(), Error>;
25 fn is_active(&self) -> bool;
26}
27
28#[derive(Default)]
29pub(super) struct RecipientState {
30 value: Option<BACnetRecipient>,
31 sink: Option<Weak<dyn AuditRecipientChangeSink>>,
32}
33
34fn property_error(code: ErrorCode) -> Error {
35 Error::Protocol {
36 class: ErrorClass::PROPERTY,
37 code,
38 }
39}
40
41#[doc(hidden)]
44pub struct DeviceAuthority<'a>(pub(super) &'a mut DeviceObject);
45
46impl DeviceAuthority<'_> {
47 pub fn object_identifier(&self) -> ObjectIdentifier {
48 self.0.oid
49 }
50 pub fn set_services_supported(&mut self, services: &[ServiceSupported]) {
51 self.0.set_services_supported(services);
52 }
53 pub fn set_object_list(&mut self, oids: Vec<ObjectIdentifier>) {
54 self.0.set_object_list(oids);
55 }
56 pub fn set_system_status(&mut self, status: DeviceStatus) {
57 self.0.set_system_status(status);
58 }
59 pub fn set_database_revision(&mut self, revision: u32) {
60 self.0.set_database_revision(revision);
61 }
62 pub fn set_backup_and_restore_state(&mut self, state: BackupAndRestoreState) {
63 self.0.set_backup_and_restore_state(state);
64 }
65 pub fn set_last_restore_time(&mut self, time: BACnetTimeStamp) {
66 self.0.set_last_restore_time(time);
67 }
68 pub fn set_configuration_files(&mut self, files: Vec<ObjectIdentifier>) {
69 self.0.set_configuration_files(files);
70 }
71 pub fn write_property(
72 &mut self,
73 property: PropertyIdentifier,
74 index: Option<u32>,
75 value: PropertyValue,
76 priority: Option<u8>,
77 ) -> Result<(), Error> {
78 self.0.write_property(property, index, value, priority)
79 }
80 pub fn provision_audit_recipient(&mut self, recipient: BACnetRecipient) -> Result<(), Error> {
81 self.0.provision_audit_recipient(recipient)
82 }
83 pub fn provisioned_audit_recipient(&self) -> Option<&BACnetRecipient> {
84 self.0.recipient.value.as_ref()
85 }
86 pub fn validate_audit_recipient_installation(&self) -> Result<(), Error> {
87 if self.0.recipient.value.is_none()
88 || self
89 .0
90 .recipient
91 .sink
92 .as_ref()
93 .and_then(Weak::upgrade)
94 .is_some()
95 {
96 return Err(property_error(ErrorCode::WRITE_ACCESS_DENIED));
97 }
98 Ok(())
99 }
100 pub fn install_audit_recipient(
101 &mut self,
102 sink: &Arc<dyn AuditRecipientChangeSink>,
103 ) -> Result<(), Error> {
104 self.validate_audit_recipient_installation()?;
105 self.0.recipient.sink = Some(Arc::downgrade(sink));
106 Ok(())
107 }
108 pub fn uninstall_audit_recipient(&mut self, sink: &Arc<dyn AuditRecipientChangeSink>) {
109 if !sink.is_active()
110 && self
111 .0
112 .recipient
113 .sink
114 .as_ref()
115 .and_then(Weak::upgrade)
116 .is_some_and(|current| Arc::ptr_eq(¤t, sink))
117 {
118 self.0.recipient.sink = None;
119 }
120 }
121 pub fn write_audit_recipient(
122 &mut self,
123 index: Option<u32>,
124 value: PropertyValue,
125 priority: Option<u8>,
126 source: Option<&AuditWriteSource>,
127 ) -> Result<(), Error> {
128 self.0.write_audit_recipient(index, value, priority, source)
129 }
130}
131
132impl DeviceObject {
133 pub fn provision_audit_recipient(&mut self, recipient: BACnetRecipient) -> Result<(), Error> {
137 validate_recipient(&recipient)?;
138 if self
139 .recipient
140 .sink
141 .as_ref()
142 .and_then(Weak::upgrade)
143 .is_some()
144 {
145 return Err(property_error(ErrorCode::WRITE_ACCESS_DENIED));
146 }
147 self.recipient.value = Some(recipient);
148 Ok(())
149 }
150
151 pub(super) fn audit_recipient_present(&self) -> bool {
152 self.recipient.value.is_some()
153 && self
154 .recipient
155 .sink
156 .as_ref()
157 .and_then(Weak::upgrade)
158 .is_some()
159 }
160
161 pub(super) fn read_audit_recipient(&self, index: Option<u32>) -> Result<PropertyValue, Error> {
162 if !self.audit_recipient_present() {
163 return Err(property_error(ErrorCode::UNKNOWN_PROPERTY));
164 }
165 if index.is_some() {
166 return Err(property_error(ErrorCode::PROPERTY_IS_NOT_AN_ARRAY));
167 }
168 let mut bytes = bytes::BytesMut::new();
169 bacnet_encoding::constructed::encode_recipient(
170 &mut bytes,
171 self.recipient.value.as_ref().expect("present"),
172 )?;
173 Ok(PropertyValue::ApplicationData(bytes.to_vec()))
174 }
175
176 pub(super) fn write_audit_recipient(
177 &mut self,
178 index: Option<u32>,
179 value: PropertyValue,
180 priority: Option<u8>,
181 source: Option<&AuditWriteSource>,
182 ) -> Result<(), Error> {
183 let sink = self
184 .recipient
185 .sink
186 .as_ref()
187 .and_then(Weak::upgrade)
188 .ok_or_else(|| property_error(ErrorCode::UNKNOWN_PROPERTY))?;
189 if !sink.is_active() {
190 return Err(property_error(ErrorCode::WRITE_ACCESS_DENIED));
191 }
192 if index.is_some() {
193 return Err(property_error(ErrorCode::PROPERTY_IS_NOT_AN_ARRAY));
194 }
195 if priority.is_some_and(|p| !(1..=16).contains(&p)) {
196 return Err(Error::Protocol {
197 class: ErrorClass::SERVICES,
198 code: ErrorCode::PARAMETER_OUT_OF_RANGE,
199 });
200 }
201 if value == PropertyValue::Null {
202 return Ok(());
203 }
204 let PropertyValue::ApplicationData(bytes) = value else {
205 return Err(property_error(ErrorCode::INVALID_DATA_TYPE));
206 };
207 let (new, end) = bacnet_encoding::constructed::decode_recipient(&bytes, 0)
208 .map_err(|_| property_error(ErrorCode::INVALID_DATA_ENCODING))?;
209 if end != bytes.len() {
210 return Err(property_error(ErrorCode::INVALID_DATA_ENCODING));
211 }
212 validate_recipient(&new)?;
213 let clock = self.clock_frame();
214 let current = self.recipient.value.as_mut().expect("installed recipient");
215 if *current == new {
216 return Ok(());
217 }
218 sink.change(current, new, source, clock)
219 }
220}
221
222fn validate_recipient(recipient: &BACnetRecipient) -> Result<(), Error> {
226 match recipient {
227 BACnetRecipient::Device(oid)
228 if oid.object_type() != ObjectType::DEVICE
229 || oid.instance_number() == ObjectIdentifier::MAX_INSTANCE =>
230 {
231 Err(property_error(ErrorCode::INVALID_DATA_ENCODING))
232 }
233 BACnetRecipient::Address(address)
234 if address.mac_address.len() > BACnetAddress::MAX_MAC_LEN =>
235 {
236 Err(property_error(ErrorCode::INVALID_DATA_ENCODING))
237 }
238 _ => Ok(()),
239 }
240}