bacnet_objects/audit/
reporter_delay.rs1use super::*;
3use crate::device::AuditWriteSource;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub struct AuditSendDelay(u16);
8impl AuditSendDelay {
9 pub fn new(seconds: u32) -> Result<Self, Error> {
11 if seconds > 3600 {
12 return Err(crate::common::value_out_of_range_error());
13 }
14 Ok(Self(seconds as u16))
15 }
16 pub fn seconds(self) -> u16 {
18 self.0
19 }
20}
21
22impl AuditReporterObject {
23 pub fn set_maximum_send_delay(&mut self, delay: Option<AuditSendDelay>) -> Result<(), Error> {
26 let mut next = self.configuration_internal();
27 next.maximum_send_delay = delay;
28 self.change_configuration(next, None)
29 }
30
31 pub fn set_send_now(&mut self, value: bool) -> Result<(), Error> {
34 self.command_send_now(value, None)
35 }
36
37 fn command_send_now(
38 &mut self,
39 value: bool,
40 source: Option<&AuditWriteSource>,
41 ) -> Result<(), Error> {
42 if self.configuration_internal().maximum_send_delay.is_none() {
43 return Err(crate::common::unknown_property_error());
44 }
45 if let Some(sink) = self
46 .change_sink
47 .as_ref()
48 .and_then(alloc::sync::Weak::upgrade)
49 {
50 if !sink.is_active() {
51 return Err(crate::common::write_access_denied_error());
52 }
53 return sink.send_now(
54 self.oid,
55 &self.status,
56 value,
57 source,
58 self.clock.as_ref().and_then(|clock| clock.read_clock()),
59 );
60 }
61 if self.change_owner.upgrade().is_some() {
62 return Err(crate::common::write_access_denied_error());
63 }
64 self.status.commit_send_now(value, 0, false)?;
66 Ok(())
67 }
68}
69
70impl AuditReporterAuthority<'_> {
71 pub fn write_property(
73 &mut self,
74 property: PropertyIdentifier,
75 value: PropertyValue,
76 index: Option<u32>,
77 source: Option<&AuditWriteSource>,
78 ) -> Result<(), Error> {
79 if property == PropertyIdentifier::DESCRIPTION {
80 return self.write_description(value, index, source);
81 }
82 if !matches!(
83 property,
84 PropertyIdentifier::MAXIMUM_SEND_DELAY | PropertyIdentifier::SEND_NOW
85 ) {
86 return Err(crate::common::write_access_denied_error());
87 }
88 let mut next = self.0.configuration_internal();
89 if next.maximum_send_delay.is_none() {
90 return Err(crate::common::unknown_property_error());
91 }
92 if index.is_some() {
93 return Err(crate::common::property_is_not_an_array_error());
94 }
95 if matches!(value, PropertyValue::Null) {
96 return self.0.change_configuration(next, source);
98 }
99 match (property, value) {
100 (PropertyIdentifier::MAXIMUM_SEND_DELAY, PropertyValue::Unsigned(seconds)) => {
101 let seconds = u32::try_from(seconds)
102 .map_err(|_| crate::common::value_out_of_range_error())?;
103 next.maximum_send_delay = Some(AuditSendDelay::new(seconds)?);
104 self.0.change_configuration(next, source)
105 }
106 (PropertyIdentifier::SEND_NOW, PropertyValue::Boolean(value)) => {
107 self.0.command_send_now(value, source)
108 }
109 _ => Err(crate::common::invalid_data_type_error()),
110 }
111 }
112}
113
114impl AuditReporterStatus {
115 #[doc(hidden)]
117 pub fn capture_revision(&self) -> u64 {
118 self.0.lock().capture_revision
119 }
120 #[doc(hidden)]
122 pub fn configuration_epoch(&self) -> u64 {
123 self.0.lock().configuration_epoch
124 }
125 #[doc(hidden)]
127 pub fn send_now(&self) -> bool {
128 self.0.lock().send_now
129 }
130 #[doc(hidden)]
132 pub fn validate_send_now(&self, captured: bool) -> Result<(), Error> {
133 let state = self.0.lock();
134 if state.command_revision == u64::MAX || (captured && state.capture_revision == u64::MAX) {
135 return Err(Error::Encoding("audit command revision exhausted".into()));
136 }
137 Ok(())
138 }
139 #[doc(hidden)]
141 pub fn commit_send_now(&self, value: bool, fence: u64, captured: bool) -> Result<(), Error> {
142 let mut state = self.0.lock();
143 let revision = state
144 .command_revision
145 .checked_add(1)
146 .ok_or_else(|| Error::Encoding("audit command revision exhausted".into()))?;
147 let capture = if captured {
148 state
149 .capture_revision
150 .checked_add(1)
151 .ok_or_else(|| Error::Encoding("audit capture revision exhausted".into()))?
152 } else {
153 state.capture_revision
154 };
155 state.command_revision = revision;
156 state.capture_revision = capture;
157 state.send_now = value && fence != 0;
158 if value {
159 state.command_fence = fence;
160 }
161 Ok(())
162 }
163 #[doc(hidden)]
165 pub fn settle_send_now(&self, first_unsent: Option<u64>) {
166 let mut state = self.0.lock();
167 if first_unsent.is_none_or(|first| first > state.command_fence) {
168 state.send_now = false;
169 }
170 }
171}