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.change_sink.as_ref().and_then(std::sync::Weak::upgrade) {
46 if !sink.is_active() {
47 return Err(crate::common::write_access_denied_error());
48 }
49 return sink.send_now(
50 self.oid,
51 &self.status,
52 value,
53 source,
54 self.clock.as_ref().and_then(|clock| clock.read_clock()),
55 );
56 }
57 if self.change_owner.upgrade().is_some() {
58 return Err(crate::common::write_access_denied_error());
59 }
60 self.status.commit_send_now(value, 0, false)?;
62 Ok(())
63 }
64}
65
66impl AuditReporterAuthority<'_> {
67 pub fn write_property(
69 &mut self,
70 property: PropertyIdentifier,
71 value: PropertyValue,
72 index: Option<u32>,
73 source: Option<&AuditWriteSource>,
74 ) -> Result<(), Error> {
75 if property == PropertyIdentifier::DESCRIPTION {
76 return self.write_description(value, index, source);
77 }
78 if !matches!(
79 property,
80 PropertyIdentifier::MAXIMUM_SEND_DELAY | PropertyIdentifier::SEND_NOW
81 ) {
82 return Err(crate::common::write_access_denied_error());
83 }
84 let mut next = self.0.configuration_internal();
85 if next.maximum_send_delay.is_none() {
86 return Err(crate::common::unknown_property_error());
87 }
88 if index.is_some() {
89 return Err(crate::common::property_is_not_an_array_error());
90 }
91 if matches!(value, PropertyValue::Null) {
92 return self.0.change_configuration(next, source);
94 }
95 match (property, value) {
96 (PropertyIdentifier::MAXIMUM_SEND_DELAY, PropertyValue::Unsigned(seconds)) => {
97 let seconds = u32::try_from(seconds)
98 .map_err(|_| crate::common::value_out_of_range_error())?;
99 next.maximum_send_delay = Some(AuditSendDelay::new(seconds)?);
100 self.0.change_configuration(next, source)
101 }
102 (PropertyIdentifier::SEND_NOW, PropertyValue::Boolean(value)) => {
103 self.0.command_send_now(value, source)
104 }
105 _ => Err(crate::common::invalid_data_type_error()),
106 }
107 }
108}
109
110impl AuditReporterStatus {
111 #[doc(hidden)]
113 pub fn capture_revision(&self) -> u64 {
114 self.0.lock().unwrap().capture_revision
115 }
116 #[doc(hidden)]
118 pub fn configuration_epoch(&self) -> u64 {
119 self.0.lock().unwrap().configuration_epoch
120 }
121 #[doc(hidden)]
123 pub fn send_now(&self) -> bool {
124 self.0.lock().unwrap().send_now
125 }
126 #[doc(hidden)]
128 pub fn validate_send_now(&self, captured: bool) -> Result<(), Error> {
129 let state = self.0.lock().unwrap();
130 if state.command_revision == u64::MAX || (captured && state.capture_revision == u64::MAX) {
131 return Err(Error::Encoding("audit command revision exhausted".into()));
132 }
133 Ok(())
134 }
135 #[doc(hidden)]
137 pub fn commit_send_now(&self, value: bool, fence: u64, captured: bool) -> Result<(), Error> {
138 let mut state = self.0.lock().unwrap();
139 let revision = state
140 .command_revision
141 .checked_add(1)
142 .ok_or_else(|| Error::Encoding("audit command revision exhausted".into()))?;
143 let capture = if captured {
144 state
145 .capture_revision
146 .checked_add(1)
147 .ok_or_else(|| Error::Encoding("audit capture revision exhausted".into()))?
148 } else {
149 state.capture_revision
150 };
151 state.command_revision = revision;
152 state.capture_revision = capture;
153 state.send_now = value && fence != 0;
154 if value {
155 state.command_fence = fence;
156 }
157 Ok(())
158 }
159 #[doc(hidden)]
161 pub fn settle_send_now(&self, first_unsent: Option<u64>) {
162 let mut state = self.0.lock().unwrap();
163 if first_unsent.is_none_or(|first| first > state.command_fence) {
164 state.send_now = false;
165 }
166 }
167}