1use bacnet_types::constructed::{BACnetDeviceObjectPropertyReference, FaultParameters};
4use bacnet_types::enums::{ObjectType, PropertyIdentifier};
5use bacnet_types::error::Error;
6use bacnet_types::primitives::{ObjectIdentifier, PropertyValue, StatusFlags};
7use std::borrow::Cow;
8
9use crate::common::{self, read_common_properties};
10use crate::traits::BACnetObject;
11
12pub struct EventEnrollmentObject {
18 oid: ObjectIdentifier,
19 name: String,
20 description: String,
21 event_type: u32,
22 notify_type: u32,
23 event_parameters: Vec<u8>,
24 object_property_reference: Option<BACnetDeviceObjectPropertyReference>,
25 event_state: u32,
26 event_enable: u8,
27 acked_transitions: u8,
28 notification_class: u32,
29 fault_parameters: Option<FaultParameters>,
30 status_flags: StatusFlags,
31 out_of_service: bool,
32 reliability: u32,
33}
34
35impl EventEnrollmentObject {
36 pub fn new(instance: u32, name: impl Into<String>, event_type: u32) -> Result<Self, Error> {
40 let oid = ObjectIdentifier::new(ObjectType::EVENT_ENROLLMENT, instance)?;
41 Ok(Self {
42 oid,
43 name: name.into(),
44 description: String::new(),
45 event_type,
46 notify_type: 0,
47 event_parameters: Vec::new(),
48 object_property_reference: None,
49 event_state: 0,
50 event_enable: 0b111,
51 acked_transitions: 0b111,
52 notification_class: 0,
53 fault_parameters: None,
54 status_flags: StatusFlags::empty(),
55 out_of_service: false,
56 reliability: 0,
57 })
58 }
59
60 pub fn set_description(&mut self, desc: impl Into<String>) {
62 self.description = desc.into();
63 }
64
65 pub fn set_object_property_reference(
67 &mut self,
68 reference: Option<BACnetDeviceObjectPropertyReference>,
69 ) {
70 self.object_property_reference = reference;
71 }
72
73 pub fn set_event_parameters(&mut self, params: Vec<u8>) {
75 self.event_parameters = params;
76 }
77
78 pub fn set_fault_parameters(&mut self, fp: Option<FaultParameters>) {
80 self.fault_parameters = fp;
81 }
82
83 pub fn set_event_state(&mut self, state: u32) {
85 self.event_state = state;
86 }
87
88 pub fn set_notification_class(&mut self, nc: u32) {
90 self.notification_class = nc;
91 }
92
93 pub fn set_event_enable(&mut self, enable: u8) {
95 self.event_enable = enable & 0x07;
96 }
97}
98
99impl BACnetObject for EventEnrollmentObject {
100 fn object_identifier(&self) -> ObjectIdentifier {
101 self.oid
102 }
103
104 fn object_name(&self) -> &str {
105 &self.name
106 }
107
108 fn read_property(
109 &self,
110 property: PropertyIdentifier,
111 array_index: Option<u32>,
112 ) -> Result<PropertyValue, Error> {
113 if let Some(result) = read_common_properties!(self, property, array_index) {
114 return result;
115 }
116 match property {
117 p if p == PropertyIdentifier::OBJECT_TYPE => Ok(PropertyValue::Enumerated(
118 ObjectType::EVENT_ENROLLMENT.to_raw(),
119 )),
120 p if p == PropertyIdentifier::EVENT_TYPE => {
121 Ok(PropertyValue::Enumerated(self.event_type))
122 }
123 p if p == PropertyIdentifier::NOTIFY_TYPE => {
124 Ok(PropertyValue::Enumerated(self.notify_type))
125 }
126 p if p == PropertyIdentifier::EVENT_PARAMETERS => {
127 Ok(PropertyValue::OctetString(self.event_parameters.clone()))
128 }
129 p if p == PropertyIdentifier::OBJECT_PROPERTY_REFERENCE => {
130 match &self.object_property_reference {
131 None => Ok(PropertyValue::Null),
132 Some(r) => Ok(PropertyValue::List(vec![
133 PropertyValue::ObjectIdentifier(r.object_identifier),
134 PropertyValue::Unsigned(r.property_identifier as u64),
135 match r.property_array_index {
136 Some(idx) => PropertyValue::Unsigned(idx as u64),
137 None => PropertyValue::Null,
138 },
139 match r.device_identifier {
140 Some(dev) => PropertyValue::ObjectIdentifier(dev),
141 None => PropertyValue::Null,
142 },
143 ])),
144 }
145 }
146 p if p == PropertyIdentifier::EVENT_STATE => {
147 Ok(PropertyValue::Enumerated(self.event_state))
148 }
149 p if p == PropertyIdentifier::EVENT_ENABLE => Ok(PropertyValue::BitString {
150 unused_bits: 5,
151 data: vec![self.event_enable << 5],
152 }),
153 p if p == PropertyIdentifier::ACKED_TRANSITIONS => Ok(PropertyValue::BitString {
154 unused_bits: 5,
155 data: vec![self.acked_transitions << 5],
156 }),
157 p if p == PropertyIdentifier::NOTIFICATION_CLASS => {
158 Ok(PropertyValue::Unsigned(self.notification_class as u64))
159 }
160 p if p == PropertyIdentifier::FAULT_PARAMETERS => match &self.fault_parameters {
161 None => Ok(PropertyValue::Null),
162 Some(fp) => {
163 let variant_tag = match fp {
164 FaultParameters::FaultNone => 0u64,
165 FaultParameters::FaultCharacterString { .. } => 1,
166 FaultParameters::FaultExtended { .. } => 2,
167 FaultParameters::FaultLifeSafety { .. } => 3,
168 FaultParameters::FaultState { .. } => 4,
169 FaultParameters::FaultStatusFlags { .. } => 5,
170 FaultParameters::FaultOutOfRange { .. } => 6,
171 FaultParameters::FaultListed { .. } => 7,
172 };
173 Ok(PropertyValue::Unsigned(variant_tag))
174 }
175 },
176 _ => Err(common::unknown_property_error()),
177 }
178 }
179
180 fn write_property(
181 &mut self,
182 property: PropertyIdentifier,
183 _array_index: Option<u32>,
184 value: PropertyValue,
185 _priority: Option<u8>,
186 ) -> Result<(), Error> {
187 if property == PropertyIdentifier::NOTIFY_TYPE {
188 if let PropertyValue::Enumerated(v) = value {
189 self.notify_type = v;
190 return Ok(());
191 }
192 return Err(common::invalid_data_type_error());
193 }
194 if property == PropertyIdentifier::NOTIFICATION_CLASS {
195 if let PropertyValue::Unsigned(v) = value {
196 self.notification_class = common::u64_to_u32(v)?;
197 return Ok(());
198 }
199 return Err(common::invalid_data_type_error());
200 }
201 if property == PropertyIdentifier::EVENT_ENABLE {
202 if let PropertyValue::BitString { data, .. } = &value {
203 if let Some(&byte) = data.first() {
204 self.event_enable = byte >> 5;
205 return Ok(());
206 }
207 return Err(common::invalid_data_type_error());
208 }
209 return Err(common::invalid_data_type_error());
210 }
211 if property == PropertyIdentifier::EVENT_STATE {
212 if let PropertyValue::Enumerated(v) = value {
213 self.event_state = v;
214 return Ok(());
215 }
216 return Err(common::invalid_data_type_error());
217 }
218 if property == PropertyIdentifier::EVENT_PARAMETERS {
219 if let PropertyValue::OctetString(bytes) = value {
220 self.event_parameters = bytes;
221 return Ok(());
222 }
223 return Err(common::invalid_data_type_error());
224 }
225 if let Some(result) =
226 common::write_out_of_service(&mut self.out_of_service, property, &value)
227 {
228 return result;
229 }
230 if let Some(result) = common::write_description(&mut self.description, property, &value) {
231 return result;
232 }
233 Err(common::write_access_denied_error())
234 }
235
236 fn property_list(&self) -> Cow<'static, [PropertyIdentifier]> {
237 static PROPS: &[PropertyIdentifier] = &[
238 PropertyIdentifier::OBJECT_IDENTIFIER,
239 PropertyIdentifier::OBJECT_NAME,
240 PropertyIdentifier::DESCRIPTION,
241 PropertyIdentifier::OBJECT_TYPE,
242 PropertyIdentifier::EVENT_TYPE,
243 PropertyIdentifier::NOTIFY_TYPE,
244 PropertyIdentifier::EVENT_PARAMETERS,
245 PropertyIdentifier::OBJECT_PROPERTY_REFERENCE,
246 PropertyIdentifier::EVENT_STATE,
247 PropertyIdentifier::EVENT_ENABLE,
248 PropertyIdentifier::ACKED_TRANSITIONS,
249 PropertyIdentifier::NOTIFICATION_CLASS,
250 PropertyIdentifier::FAULT_PARAMETERS,
251 PropertyIdentifier::STATUS_FLAGS,
252 PropertyIdentifier::OUT_OF_SERVICE,
253 PropertyIdentifier::RELIABILITY,
254 ];
255 Cow::Borrowed(PROPS)
256 }
257}
258
259pub struct AlertEnrollmentObject {
269 oid: ObjectIdentifier,
270 name: String,
271 description: String,
272 status_flags: StatusFlags,
273 event_state: u32,
275 out_of_service: bool,
276 reliability: u32,
277 pub present_value: u32,
279 pub event_detection_enable: bool,
281 pub event_enable: u8,
283 pub notification_class: u32,
285}
286
287impl AlertEnrollmentObject {
288 pub fn new(instance: u32, name: impl Into<String>) -> Result<Self, Error> {
290 let oid = ObjectIdentifier::new(ObjectType::ALERT_ENROLLMENT, instance)?;
291 Ok(Self {
292 oid,
293 name: name.into(),
294 description: String::new(),
295 status_flags: StatusFlags::empty(),
296 event_state: 0, out_of_service: false,
298 reliability: 0,
299 present_value: 0,
300 event_detection_enable: true,
301 event_enable: 0b111,
302 notification_class: 0,
303 })
304 }
305}
306
307impl BACnetObject for AlertEnrollmentObject {
308 fn object_identifier(&self) -> ObjectIdentifier {
309 self.oid
310 }
311
312 fn object_name(&self) -> &str {
313 &self.name
314 }
315
316 fn read_property(
317 &self,
318 property: PropertyIdentifier,
319 array_index: Option<u32>,
320 ) -> Result<PropertyValue, Error> {
321 if let Some(result) = read_common_properties!(self, property, array_index) {
322 return result;
323 }
324 match property {
325 p if p == PropertyIdentifier::OBJECT_TYPE => Ok(PropertyValue::Enumerated(
326 ObjectType::ALERT_ENROLLMENT.to_raw(),
327 )),
328 p if p == PropertyIdentifier::PRESENT_VALUE => {
329 Ok(PropertyValue::Enumerated(self.present_value))
330 }
331 p if p == PropertyIdentifier::EVENT_DETECTION_ENABLE => {
332 Ok(PropertyValue::Boolean(self.event_detection_enable))
333 }
334 p if p == PropertyIdentifier::EVENT_ENABLE => Ok(PropertyValue::BitString {
335 unused_bits: 5,
336 data: vec![self.event_enable << 5],
337 }),
338 p if p == PropertyIdentifier::NOTIFICATION_CLASS => {
339 Ok(PropertyValue::Unsigned(self.notification_class as u64))
340 }
341 p if p == PropertyIdentifier::EVENT_STATE => {
342 Ok(PropertyValue::Enumerated(self.event_state))
343 }
344 _ => Err(common::unknown_property_error()),
345 }
346 }
347
348 fn write_property(
349 &mut self,
350 property: PropertyIdentifier,
351 _array_index: Option<u32>,
352 value: PropertyValue,
353 _priority: Option<u8>,
354 ) -> Result<(), Error> {
355 if property == PropertyIdentifier::EVENT_DETECTION_ENABLE {
356 if let PropertyValue::Boolean(v) = value {
357 self.event_detection_enable = v;
358 return Ok(());
359 }
360 return Err(common::invalid_data_type_error());
361 }
362 if property == PropertyIdentifier::EVENT_ENABLE {
363 if let PropertyValue::BitString { data, .. } = &value {
364 if let Some(&byte) = data.first() {
365 self.event_enable = byte >> 5;
366 return Ok(());
367 }
368 return Err(common::invalid_data_type_error());
369 }
370 return Err(common::invalid_data_type_error());
371 }
372 if property == PropertyIdentifier::NOTIFICATION_CLASS {
373 if let PropertyValue::Unsigned(v) = value {
374 self.notification_class = common::u64_to_u32(v)?;
375 return Ok(());
376 }
377 return Err(common::invalid_data_type_error());
378 }
379 if let Some(result) =
380 common::write_out_of_service(&mut self.out_of_service, property, &value)
381 {
382 return result;
383 }
384 if let Some(result) = common::write_description(&mut self.description, property, &value) {
385 return result;
386 }
387 Err(common::write_access_denied_error())
388 }
389
390 fn property_list(&self) -> Cow<'static, [PropertyIdentifier]> {
391 static PROPS: &[PropertyIdentifier] = &[
392 PropertyIdentifier::OBJECT_IDENTIFIER,
393 PropertyIdentifier::OBJECT_NAME,
394 PropertyIdentifier::DESCRIPTION,
395 PropertyIdentifier::OBJECT_TYPE,
396 PropertyIdentifier::PRESENT_VALUE,
397 PropertyIdentifier::EVENT_DETECTION_ENABLE,
398 PropertyIdentifier::EVENT_ENABLE,
399 PropertyIdentifier::NOTIFICATION_CLASS,
400 PropertyIdentifier::STATUS_FLAGS,
401 PropertyIdentifier::OUT_OF_SERVICE,
402 PropertyIdentifier::RELIABILITY,
403 ];
404 Cow::Borrowed(PROPS)
405 }
406}
407
408#[cfg(test)]
409mod tests;