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 {
410 use super::*;
411
412 #[test]
413 fn create_event_enrollment() {
414 let ee = EventEnrollmentObject::new(1, "EE-1", 0).unwrap();
415 assert_eq!(
416 ee.object_identifier().object_type(),
417 ObjectType::EVENT_ENROLLMENT
418 );
419 assert_eq!(ee.object_identifier().instance_number(), 1);
420 assert_eq!(ee.object_name(), "EE-1");
421 }
422
423 #[test]
424 fn read_object_type() {
425 let ee = EventEnrollmentObject::new(1, "EE-1", 0).unwrap();
426 let val = ee
427 .read_property(PropertyIdentifier::OBJECT_TYPE, None)
428 .unwrap();
429 assert_eq!(
430 val,
431 PropertyValue::Enumerated(ObjectType::EVENT_ENROLLMENT.to_raw())
432 );
433 }
434
435 #[test]
436 fn read_event_type() {
437 let ee = EventEnrollmentObject::new(1, "EE-1", 3).unwrap();
438 let val = ee
439 .read_property(PropertyIdentifier::EVENT_TYPE, None)
440 .unwrap();
441 assert_eq!(val, PropertyValue::Enumerated(3));
442 }
443
444 #[test]
445 fn read_event_enable() {
446 let ee = EventEnrollmentObject::new(1, "EE-1", 0).unwrap();
447 let val = ee
448 .read_property(PropertyIdentifier::EVENT_ENABLE, None)
449 .unwrap();
450 assert_eq!(
452 val,
453 PropertyValue::BitString {
454 unused_bits: 5,
455 data: vec![0b1110_0000],
456 }
457 );
458 }
459
460 #[test]
461 fn read_notification_class() {
462 let ee = EventEnrollmentObject::new(1, "EE-1", 0).unwrap();
463 let val = ee
464 .read_property(PropertyIdentifier::NOTIFICATION_CLASS, None)
465 .unwrap();
466 assert_eq!(val, PropertyValue::Unsigned(0));
467 }
468
469 #[test]
470 fn write_notify_type() {
471 let mut ee = EventEnrollmentObject::new(1, "EE-1", 0).unwrap();
472 ee.write_property(
473 PropertyIdentifier::NOTIFY_TYPE,
474 None,
475 PropertyValue::Enumerated(1),
476 None,
477 )
478 .unwrap();
479 let val = ee
480 .read_property(PropertyIdentifier::NOTIFY_TYPE, None)
481 .unwrap();
482 assert_eq!(val, PropertyValue::Enumerated(1));
483 }
484
485 #[test]
486 fn write_notify_type_wrong_type() {
487 let mut ee = EventEnrollmentObject::new(1, "EE-1", 0).unwrap();
488 let result = ee.write_property(
489 PropertyIdentifier::NOTIFY_TYPE,
490 None,
491 PropertyValue::Real(1.0),
492 None,
493 );
494 assert!(result.is_err());
495 }
496
497 #[test]
498 fn read_acked_transitions() {
499 let ee = EventEnrollmentObject::new(1, "EE-1", 0).unwrap();
500 let val = ee
501 .read_property(PropertyIdentifier::ACKED_TRANSITIONS, None)
502 .unwrap();
503 assert_eq!(
505 val,
506 PropertyValue::BitString {
507 unused_bits: 5,
508 data: vec![0b1110_0000],
509 }
510 );
511 }
512
513 #[test]
514 fn read_object_property_reference_none() {
515 let ee = EventEnrollmentObject::new(1, "EE-1", 0).unwrap();
516 let val = ee
517 .read_property(PropertyIdentifier::OBJECT_PROPERTY_REFERENCE, None)
518 .unwrap();
519 assert_eq!(val, PropertyValue::Null);
520 }
521
522 #[test]
523 fn read_object_property_reference_some() {
524 let mut ee = EventEnrollmentObject::new(1, "EE-1", 0).unwrap();
525 let ai_oid = ObjectIdentifier::new(ObjectType::ANALOG_INPUT, 5).unwrap();
526 ee.set_object_property_reference(Some(BACnetDeviceObjectPropertyReference {
527 object_identifier: ai_oid,
528 property_identifier: PropertyIdentifier::PRESENT_VALUE.to_raw(),
529 property_array_index: None,
530 device_identifier: None,
531 }));
532 let val = ee
533 .read_property(PropertyIdentifier::OBJECT_PROPERTY_REFERENCE, None)
534 .unwrap();
535 if let PropertyValue::List(fields) = val {
536 assert_eq!(fields.len(), 4);
537 assert_eq!(fields[0], PropertyValue::ObjectIdentifier(ai_oid));
538 assert_eq!(
539 fields[1],
540 PropertyValue::Unsigned(PropertyIdentifier::PRESENT_VALUE.to_raw() as u64)
541 );
542 assert_eq!(fields[2], PropertyValue::Null); assert_eq!(fields[3], PropertyValue::Null); } else {
545 panic!("Expected List");
546 }
547 }
548
549 #[test]
550 fn write_notification_class() {
551 let mut ee = EventEnrollmentObject::new(1, "EE-1", 0).unwrap();
552 ee.write_property(
553 PropertyIdentifier::NOTIFICATION_CLASS,
554 None,
555 PropertyValue::Unsigned(42),
556 None,
557 )
558 .unwrap();
559 let val = ee
560 .read_property(PropertyIdentifier::NOTIFICATION_CLASS, None)
561 .unwrap();
562 assert_eq!(val, PropertyValue::Unsigned(42));
563 }
564
565 #[test]
566 fn write_event_enable() {
567 let mut ee = EventEnrollmentObject::new(1, "EE-1", 0).unwrap();
568 ee.write_property(
570 PropertyIdentifier::EVENT_ENABLE,
571 None,
572 PropertyValue::BitString {
573 unused_bits: 5,
574 data: vec![0b1000_0000],
575 },
576 None,
577 )
578 .unwrap();
579 let val = ee
580 .read_property(PropertyIdentifier::EVENT_ENABLE, None)
581 .unwrap();
582 assert_eq!(
583 val,
584 PropertyValue::BitString {
585 unused_bits: 5,
586 data: vec![0b1000_0000],
587 }
588 );
589 }
590
591 #[test]
592 fn property_list_complete() {
593 let ee = EventEnrollmentObject::new(1, "EE-1", 0).unwrap();
594 let props = ee.property_list();
595 assert!(props.contains(&PropertyIdentifier::EVENT_TYPE));
596 assert!(props.contains(&PropertyIdentifier::NOTIFY_TYPE));
597 assert!(props.contains(&PropertyIdentifier::EVENT_PARAMETERS));
598 assert!(props.contains(&PropertyIdentifier::OBJECT_PROPERTY_REFERENCE));
599 assert!(props.contains(&PropertyIdentifier::EVENT_STATE));
600 assert!(props.contains(&PropertyIdentifier::EVENT_ENABLE));
601 assert!(props.contains(&PropertyIdentifier::ACKED_TRANSITIONS));
602 assert!(props.contains(&PropertyIdentifier::NOTIFICATION_CLASS));
603 }
604
605 #[test]
606 fn write_event_parameters() {
607 let mut ee = EventEnrollmentObject::new(1, "EE-1", 0).unwrap();
608 let params = vec![0x01, 0x02, 0x03];
609 ee.write_property(
610 PropertyIdentifier::EVENT_PARAMETERS,
611 None,
612 PropertyValue::OctetString(params.clone()),
613 None,
614 )
615 .unwrap();
616 let val = ee
617 .read_property(PropertyIdentifier::EVENT_PARAMETERS, None)
618 .unwrap();
619 assert_eq!(val, PropertyValue::OctetString(params));
620 }
621
622 #[test]
623 fn read_event_state_default() {
624 let ee = EventEnrollmentObject::new(1, "EE-1", 0).unwrap();
625 let val = ee
626 .read_property(PropertyIdentifier::EVENT_STATE, None)
627 .unwrap();
628 assert_eq!(val, PropertyValue::Enumerated(0)); }
630
631 #[test]
632 fn write_unknown_property_denied() {
633 let mut ee = EventEnrollmentObject::new(1, "EE-1", 0).unwrap();
634 let result = ee.write_property(
635 PropertyIdentifier::PRESENT_VALUE,
636 None,
637 PropertyValue::Real(1.0),
638 None,
639 );
640 assert!(result.is_err());
641 }
642
643 #[test]
648 fn fault_parameters_default_none() {
649 let ee = EventEnrollmentObject::new(1, "EE-FP", 0).unwrap();
650 let val = ee
651 .read_property(PropertyIdentifier::FAULT_PARAMETERS, None)
652 .unwrap();
653 assert_eq!(val, PropertyValue::Null);
654 }
655
656 #[test]
657 fn fault_parameters_none_variant() {
658 let mut ee = EventEnrollmentObject::new(1, "EE-FP", 0).unwrap();
659 ee.set_fault_parameters(Some(FaultParameters::FaultNone));
660 let val = ee
661 .read_property(PropertyIdentifier::FAULT_PARAMETERS, None)
662 .unwrap();
663 assert_eq!(val, PropertyValue::Unsigned(0));
664 }
665
666 #[test]
667 fn fault_parameters_character_string() {
668 let mut ee = EventEnrollmentObject::new(1, "EE-FP", 0).unwrap();
669 ee.set_fault_parameters(Some(FaultParameters::FaultCharacterString {
670 fault_values: vec!["alarm".to_string(), "critical".to_string()],
671 }));
672 let val = ee
673 .read_property(PropertyIdentifier::FAULT_PARAMETERS, None)
674 .unwrap();
675 assert_eq!(val, PropertyValue::Unsigned(1));
676 }
677
678 #[test]
679 fn fault_parameters_extended() {
680 let mut ee = EventEnrollmentObject::new(1, "EE-FP", 0).unwrap();
681 ee.set_fault_parameters(Some(FaultParameters::FaultExtended {
682 vendor_id: 42,
683 extended_fault_type: 7,
684 parameters: vec![0x01, 0x02],
685 }));
686 let val = ee
687 .read_property(PropertyIdentifier::FAULT_PARAMETERS, None)
688 .unwrap();
689 assert_eq!(val, PropertyValue::Unsigned(2));
690 }
691
692 #[test]
693 fn fault_parameters_life_safety() {
694 let mut ee = EventEnrollmentObject::new(1, "EE-FP", 0).unwrap();
695 let ai_oid = ObjectIdentifier::new(ObjectType::ANALOG_INPUT, 1).unwrap();
696 ee.set_fault_parameters(Some(FaultParameters::FaultLifeSafety {
697 fault_values: vec![1, 2, 3],
698 mode_for_reference: BACnetDeviceObjectPropertyReference {
699 object_identifier: ai_oid,
700 property_identifier: PropertyIdentifier::PRESENT_VALUE.to_raw(),
701 property_array_index: None,
702 device_identifier: None,
703 },
704 }));
705 let val = ee
706 .read_property(PropertyIdentifier::FAULT_PARAMETERS, None)
707 .unwrap();
708 assert_eq!(val, PropertyValue::Unsigned(3));
709 }
710
711 #[test]
712 fn fault_parameters_state() {
713 use bacnet_types::constructed::BACnetPropertyStates;
714 let mut ee = EventEnrollmentObject::new(1, "EE-FP", 0).unwrap();
715 ee.set_fault_parameters(Some(FaultParameters::FaultState {
716 fault_values: vec![BACnetPropertyStates::BooleanValue(true)],
717 }));
718 let val = ee
719 .read_property(PropertyIdentifier::FAULT_PARAMETERS, None)
720 .unwrap();
721 assert_eq!(val, PropertyValue::Unsigned(4));
722 }
723
724 #[test]
725 fn fault_parameters_status_flags() {
726 let mut ee = EventEnrollmentObject::new(1, "EE-FP", 0).unwrap();
727 let ai_oid = ObjectIdentifier::new(ObjectType::ANALOG_INPUT, 1).unwrap();
728 ee.set_fault_parameters(Some(FaultParameters::FaultStatusFlags {
729 reference: BACnetDeviceObjectPropertyReference {
730 object_identifier: ai_oid,
731 property_identifier: PropertyIdentifier::STATUS_FLAGS.to_raw(),
732 property_array_index: None,
733 device_identifier: None,
734 },
735 }));
736 let val = ee
737 .read_property(PropertyIdentifier::FAULT_PARAMETERS, None)
738 .unwrap();
739 assert_eq!(val, PropertyValue::Unsigned(5));
740 }
741
742 #[test]
743 fn fault_parameters_out_of_range() {
744 let mut ee = EventEnrollmentObject::new(1, "EE-FP", 0).unwrap();
745 ee.set_fault_parameters(Some(FaultParameters::FaultOutOfRange {
746 min_normal: 0.0,
747 max_normal: 100.0,
748 }));
749 let val = ee
750 .read_property(PropertyIdentifier::FAULT_PARAMETERS, None)
751 .unwrap();
752 assert_eq!(val, PropertyValue::Unsigned(6));
753 }
754
755 #[test]
756 fn fault_parameters_listed() {
757 let mut ee = EventEnrollmentObject::new(1, "EE-FP", 0).unwrap();
758 let ai_oid = ObjectIdentifier::new(ObjectType::ANALOG_INPUT, 1).unwrap();
759 ee.set_fault_parameters(Some(FaultParameters::FaultListed {
760 reference: BACnetDeviceObjectPropertyReference {
761 object_identifier: ai_oid,
762 property_identifier: PropertyIdentifier::PRESENT_VALUE.to_raw(),
763 property_array_index: None,
764 device_identifier: None,
765 },
766 }));
767 let val = ee
768 .read_property(PropertyIdentifier::FAULT_PARAMETERS, None)
769 .unwrap();
770 assert_eq!(val, PropertyValue::Unsigned(7));
771 }
772
773 #[test]
774 fn fault_parameters_in_property_list() {
775 let ee = EventEnrollmentObject::new(1, "EE-FP", 0).unwrap();
776 let props = ee.property_list();
777 assert!(props.contains(&PropertyIdentifier::FAULT_PARAMETERS));
778 }
779
780 #[test]
781 fn fault_parameters_clear() {
782 let mut ee = EventEnrollmentObject::new(1, "EE-FP", 0).unwrap();
783 ee.set_fault_parameters(Some(FaultParameters::FaultNone));
784 let val = ee
785 .read_property(PropertyIdentifier::FAULT_PARAMETERS, None)
786 .unwrap();
787 assert_eq!(val, PropertyValue::Unsigned(0));
788
789 ee.set_fault_parameters(None);
791 let val = ee
792 .read_property(PropertyIdentifier::FAULT_PARAMETERS, None)
793 .unwrap();
794 assert_eq!(val, PropertyValue::Null);
795 }
796
797 #[test]
802 fn alert_enrollment_create() {
803 let ae = AlertEnrollmentObject::new(1, "AE-1").unwrap();
804 assert_eq!(
805 ae.object_identifier().object_type(),
806 ObjectType::ALERT_ENROLLMENT
807 );
808 assert_eq!(ae.object_identifier().instance_number(), 1);
809 assert_eq!(ae.object_name(), "AE-1");
810 }
811
812 #[test]
813 fn alert_enrollment_object_type() {
814 let ae = AlertEnrollmentObject::new(1, "AE").unwrap();
815 let val = ae
816 .read_property(PropertyIdentifier::OBJECT_TYPE, None)
817 .unwrap();
818 assert_eq!(
819 val,
820 PropertyValue::Enumerated(ObjectType::ALERT_ENROLLMENT.to_raw())
821 );
822 }
823
824 #[test]
825 fn alert_enrollment_present_value_default() {
826 let ae = AlertEnrollmentObject::new(1, "AE").unwrap();
827 let val = ae
828 .read_property(PropertyIdentifier::PRESENT_VALUE, None)
829 .unwrap();
830 assert_eq!(val, PropertyValue::Enumerated(0));
831 }
832
833 #[test]
834 fn alert_enrollment_event_detection_enable() {
835 let ae = AlertEnrollmentObject::new(1, "AE").unwrap();
836 let val = ae
837 .read_property(PropertyIdentifier::EVENT_DETECTION_ENABLE, None)
838 .unwrap();
839 assert_eq!(val, PropertyValue::Boolean(true));
840 }
841
842 #[test]
843 fn alert_enrollment_write_event_detection_enable() {
844 let mut ae = AlertEnrollmentObject::new(1, "AE").unwrap();
845 ae.write_property(
846 PropertyIdentifier::EVENT_DETECTION_ENABLE,
847 None,
848 PropertyValue::Boolean(false),
849 None,
850 )
851 .unwrap();
852 let val = ae
853 .read_property(PropertyIdentifier::EVENT_DETECTION_ENABLE, None)
854 .unwrap();
855 assert_eq!(val, PropertyValue::Boolean(false));
856 }
857
858 #[test]
859 fn alert_enrollment_event_enable() {
860 let ae = AlertEnrollmentObject::new(1, "AE").unwrap();
861 let val = ae
862 .read_property(PropertyIdentifier::EVENT_ENABLE, None)
863 .unwrap();
864 assert_eq!(
866 val,
867 PropertyValue::BitString {
868 unused_bits: 5,
869 data: vec![0b1110_0000],
870 }
871 );
872 }
873
874 #[test]
875 fn alert_enrollment_write_event_enable() {
876 let mut ae = AlertEnrollmentObject::new(1, "AE").unwrap();
877 ae.write_property(
878 PropertyIdentifier::EVENT_ENABLE,
879 None,
880 PropertyValue::BitString {
881 unused_bits: 5,
882 data: vec![0b1000_0000],
883 },
884 None,
885 )
886 .unwrap();
887 let val = ae
888 .read_property(PropertyIdentifier::EVENT_ENABLE, None)
889 .unwrap();
890 assert_eq!(
891 val,
892 PropertyValue::BitString {
893 unused_bits: 5,
894 data: vec![0b1000_0000],
895 }
896 );
897 }
898
899 #[test]
900 fn alert_enrollment_notification_class() {
901 let ae = AlertEnrollmentObject::new(1, "AE").unwrap();
902 let val = ae
903 .read_property(PropertyIdentifier::NOTIFICATION_CLASS, None)
904 .unwrap();
905 assert_eq!(val, PropertyValue::Unsigned(0));
906 }
907
908 #[test]
909 fn alert_enrollment_write_notification_class() {
910 let mut ae = AlertEnrollmentObject::new(1, "AE").unwrap();
911 ae.write_property(
912 PropertyIdentifier::NOTIFICATION_CLASS,
913 None,
914 PropertyValue::Unsigned(42),
915 None,
916 )
917 .unwrap();
918 let val = ae
919 .read_property(PropertyIdentifier::NOTIFICATION_CLASS, None)
920 .unwrap();
921 assert_eq!(val, PropertyValue::Unsigned(42));
922 }
923
924 #[test]
925 fn alert_enrollment_property_list() {
926 let ae = AlertEnrollmentObject::new(1, "AE").unwrap();
927 let props = ae.property_list();
928 assert!(props.contains(&PropertyIdentifier::PRESENT_VALUE));
929 assert!(props.contains(&PropertyIdentifier::EVENT_DETECTION_ENABLE));
930 assert!(props.contains(&PropertyIdentifier::EVENT_ENABLE));
931 assert!(props.contains(&PropertyIdentifier::NOTIFICATION_CLASS));
932 assert!(props.contains(&PropertyIdentifier::STATUS_FLAGS));
933 }
934}