1use bacnet_types::enums::{ObjectType, PropertyIdentifier};
5use bacnet_types::error::Error;
6use bacnet_types::primitives::{BACnetTimeStamp, ObjectIdentifier, PropertyValue, StatusFlags};
7use std::borrow::Cow;
8
9use crate::common::{self, read_common_properties};
10use crate::event::{ChangeOfStateDetector, EventStateChange};
11use crate::traits::BACnetObject;
12
13pub struct BinaryInputObject {
22 oid: ObjectIdentifier,
23 name: String,
24 description: String,
25 present_value: u32,
26 out_of_service: bool,
27 status_flags: StatusFlags,
28 polarity: u32,
30 reliability: u32,
32 active_text: String,
33 inactive_text: String,
34 event_detector: ChangeOfStateDetector,
36}
37
38impl BinaryInputObject {
39 pub fn new(instance: u32, name: impl Into<String>) -> Result<Self, Error> {
40 let oid = ObjectIdentifier::new(ObjectType::BINARY_INPUT, instance)?;
41 Ok(Self {
42 oid,
43 name: name.into(),
44 description: String::new(),
45 present_value: 0,
46 out_of_service: false,
47 status_flags: StatusFlags::empty(),
48 polarity: 0,
49 reliability: 0,
50 active_text: "Active".into(),
51 inactive_text: "Inactive".into(),
52 event_detector: ChangeOfStateDetector::default(),
53 })
54 }
55
56 pub fn set_present_value(&mut self, value: u32) {
58 self.present_value = value;
59 }
60
61 pub fn set_description(&mut self, desc: impl Into<String>) {
63 self.description = desc.into();
64 }
65}
66
67impl BACnetObject for BinaryInputObject {
68 fn object_identifier(&self) -> ObjectIdentifier {
69 self.oid
70 }
71
72 fn object_name(&self) -> &str {
73 &self.name
74 }
75
76 fn supports_cov(&self) -> bool {
77 true
78 }
79
80 fn evaluate_intrinsic_reporting(&mut self) -> Option<EventStateChange> {
81 self.event_detector.evaluate(self.present_value)
82 }
83
84 fn read_property(
85 &self,
86 property: PropertyIdentifier,
87 array_index: Option<u32>,
88 ) -> Result<PropertyValue, Error> {
89 if property == PropertyIdentifier::STATUS_FLAGS {
90 return Ok(common::compute_status_flags(
91 self.status_flags,
92 self.reliability,
93 self.out_of_service,
94 self.event_detector.event_state.to_raw(),
95 ));
96 }
97 if let Some(result) = read_common_properties!(self, property, array_index) {
98 return result;
99 }
100 match property {
101 p if p == PropertyIdentifier::OBJECT_TYPE => {
102 Ok(PropertyValue::Enumerated(ObjectType::BINARY_INPUT.to_raw()))
103 }
104 p if p == PropertyIdentifier::PRESENT_VALUE => {
105 Ok(PropertyValue::Enumerated(self.present_value))
106 }
107 p if p == PropertyIdentifier::EVENT_STATE => Ok(PropertyValue::Enumerated(
108 self.event_detector.event_state.to_raw(),
109 )),
110 p if p == PropertyIdentifier::POLARITY => Ok(PropertyValue::Enumerated(self.polarity)),
111 p if p == PropertyIdentifier::ACTIVE_TEXT => {
112 Ok(PropertyValue::CharacterString(self.active_text.clone()))
113 }
114 p if p == PropertyIdentifier::INACTIVE_TEXT => {
115 Ok(PropertyValue::CharacterString(self.inactive_text.clone()))
116 }
117 p if p == PropertyIdentifier::ALARM_VALUES => Ok(PropertyValue::List(
118 self.event_detector
119 .alarm_values
120 .iter()
121 .map(|v| PropertyValue::Enumerated(*v))
122 .collect(),
123 )),
124 p if p == PropertyIdentifier::EVENT_ENABLE => Ok(PropertyValue::BitString {
125 unused_bits: 5,
126 data: vec![self.event_detector.event_enable << 5],
127 }),
128 p if p == PropertyIdentifier::ACKED_TRANSITIONS => Ok(PropertyValue::BitString {
129 unused_bits: 5,
130 data: vec![self.event_detector.acked_transitions << 5],
131 }),
132 p if p == PropertyIdentifier::NOTIFICATION_CLASS => Ok(PropertyValue::Unsigned(
133 self.event_detector.notification_class as u64,
134 )),
135 p if p == PropertyIdentifier::EVENT_TIME_STAMPS => Ok(PropertyValue::List(vec![
136 PropertyValue::Unsigned(0),
137 PropertyValue::Unsigned(0),
138 PropertyValue::Unsigned(0),
139 ])),
140 _ => Err(common::unknown_property_error()),
141 }
142 }
143
144 fn write_property(
145 &mut self,
146 property: PropertyIdentifier,
147 _array_index: Option<u32>,
148 value: PropertyValue,
149 _priority: Option<u8>,
150 ) -> Result<(), Error> {
151 if property == PropertyIdentifier::PRESENT_VALUE {
152 if !self.out_of_service {
153 return Err(common::write_access_denied_error());
154 }
155 if let PropertyValue::Enumerated(v) = value {
156 if v > 1 {
157 return Err(common::value_out_of_range_error());
158 }
159 self.present_value = v;
160 return Ok(());
161 }
162 return Err(common::invalid_data_type_error());
163 }
164 if property == PropertyIdentifier::ACTIVE_TEXT {
165 if let PropertyValue::CharacterString(s) = value {
166 self.active_text = s;
167 return Ok(());
168 }
169 return Err(common::invalid_data_type_error());
170 }
171 if property == PropertyIdentifier::INACTIVE_TEXT {
172 if let PropertyValue::CharacterString(s) = value {
173 self.inactive_text = s;
174 return Ok(());
175 }
176 return Err(common::invalid_data_type_error());
177 }
178 if let Some(result) =
179 common::write_out_of_service(&mut self.out_of_service, property, &value)
180 {
181 return result;
182 }
183 if let Some(result) = common::write_object_name(&mut self.name, property, &value) {
184 return result;
185 }
186 if let Some(result) = common::write_description(&mut self.description, property, &value) {
187 return result;
188 }
189 Err(common::write_access_denied_error())
190 }
191
192 fn property_list(&self) -> Cow<'static, [PropertyIdentifier]> {
193 static PROPS: &[PropertyIdentifier] = &[
194 PropertyIdentifier::OBJECT_IDENTIFIER,
195 PropertyIdentifier::OBJECT_NAME,
196 PropertyIdentifier::DESCRIPTION,
197 PropertyIdentifier::OBJECT_TYPE,
198 PropertyIdentifier::PRESENT_VALUE,
199 PropertyIdentifier::STATUS_FLAGS,
200 PropertyIdentifier::EVENT_STATE,
201 PropertyIdentifier::OUT_OF_SERVICE,
202 PropertyIdentifier::POLARITY,
203 PropertyIdentifier::RELIABILITY,
204 PropertyIdentifier::ACTIVE_TEXT,
205 PropertyIdentifier::INACTIVE_TEXT,
206 ];
207 Cow::Borrowed(PROPS)
208 }
209}
210
211pub struct BinaryOutputObject {
220 oid: ObjectIdentifier,
221 name: String,
222 description: String,
223 present_value: u32,
224 out_of_service: bool,
225 status_flags: StatusFlags,
226 priority_array: [Option<u32>; 16],
227 relinquish_default: u32,
228 polarity: u32,
230 reliability: u32,
232 active_text: String,
233 inactive_text: String,
234 event_detector: ChangeOfStateDetector,
236 value_source: common::ValueSourceTracking,
238}
239
240impl BinaryOutputObject {
241 pub fn new(instance: u32, name: impl Into<String>) -> Result<Self, Error> {
242 let oid = ObjectIdentifier::new(ObjectType::BINARY_OUTPUT, instance)?;
243 Ok(Self {
244 oid,
245 name: name.into(),
246 description: String::new(),
247 present_value: 0,
248 out_of_service: false,
249 status_flags: StatusFlags::empty(),
250 priority_array: [None; 16],
251 relinquish_default: 0,
252 polarity: 0,
253 reliability: 0,
254 active_text: "Active".into(),
255 inactive_text: "Inactive".into(),
256 event_detector: ChangeOfStateDetector::default(),
257 value_source: common::ValueSourceTracking::default(),
258 })
259 }
260
261 pub fn set_description(&mut self, desc: impl Into<String>) {
263 self.description = desc.into();
264 }
265
266 fn recalculate_present_value(&mut self) {
267 self.present_value =
268 common::recalculate_from_priority_array(&self.priority_array, self.relinquish_default);
269 }
270}
271
272impl BACnetObject for BinaryOutputObject {
273 fn object_identifier(&self) -> ObjectIdentifier {
274 self.oid
275 }
276
277 fn object_name(&self) -> &str {
278 &self.name
279 }
280
281 fn supports_cov(&self) -> bool {
282 true
283 }
284
285 fn evaluate_intrinsic_reporting(&mut self) -> Option<EventStateChange> {
286 self.event_detector.evaluate(self.present_value)
287 }
288
289 fn read_property(
290 &self,
291 property: PropertyIdentifier,
292 array_index: Option<u32>,
293 ) -> Result<PropertyValue, Error> {
294 if property == PropertyIdentifier::STATUS_FLAGS {
295 return Ok(common::compute_status_flags(
296 self.status_flags,
297 self.reliability,
298 self.out_of_service,
299 self.event_detector.event_state.to_raw(),
300 ));
301 }
302 if let Some(result) = read_common_properties!(self, property, array_index) {
303 return result;
304 }
305 match property {
306 p if p == PropertyIdentifier::OBJECT_TYPE => Ok(PropertyValue::Enumerated(
307 ObjectType::BINARY_OUTPUT.to_raw(),
308 )),
309 p if p == PropertyIdentifier::PRESENT_VALUE => {
310 Ok(PropertyValue::Enumerated(self.present_value))
311 }
312 p if p == PropertyIdentifier::EVENT_STATE => Ok(PropertyValue::Enumerated(
313 self.event_detector.event_state.to_raw(),
314 )),
315 p if p == PropertyIdentifier::PRIORITY_ARRAY => {
316 common::read_priority_array!(self, array_index, PropertyValue::Enumerated)
317 }
318 p if p == PropertyIdentifier::RELINQUISH_DEFAULT => {
319 Ok(PropertyValue::Enumerated(self.relinquish_default))
320 }
321 p if p == PropertyIdentifier::CURRENT_COMMAND_PRIORITY => {
322 Ok(common::current_command_priority(&self.priority_array))
323 }
324 p if p == PropertyIdentifier::VALUE_SOURCE => {
325 Ok(self.value_source.value_source.clone())
326 }
327 p if p == PropertyIdentifier::LAST_COMMAND_TIME => Ok(PropertyValue::Unsigned(
328 match self.value_source.last_command_time {
329 BACnetTimeStamp::SequenceNumber(n) => n,
330 _ => 0,
331 },
332 )),
333 p if p == PropertyIdentifier::POLARITY => Ok(PropertyValue::Enumerated(self.polarity)),
334 p if p == PropertyIdentifier::ACTIVE_TEXT => {
335 Ok(PropertyValue::CharacterString(self.active_text.clone()))
336 }
337 p if p == PropertyIdentifier::INACTIVE_TEXT => {
338 Ok(PropertyValue::CharacterString(self.inactive_text.clone()))
339 }
340 p if p == PropertyIdentifier::EVENT_ENABLE => Ok(PropertyValue::BitString {
341 unused_bits: 5,
342 data: vec![self.event_detector.event_enable << 5],
343 }),
344 p if p == PropertyIdentifier::ACKED_TRANSITIONS => Ok(PropertyValue::BitString {
345 unused_bits: 5,
346 data: vec![self.event_detector.acked_transitions << 5],
347 }),
348 p if p == PropertyIdentifier::NOTIFICATION_CLASS => Ok(PropertyValue::Unsigned(
349 self.event_detector.notification_class as u64,
350 )),
351 p if p == PropertyIdentifier::EVENT_TIME_STAMPS => Ok(PropertyValue::List(vec![
352 PropertyValue::Unsigned(0),
353 PropertyValue::Unsigned(0),
354 PropertyValue::Unsigned(0),
355 ])),
356 _ => Err(common::unknown_property_error()),
357 }
358 }
359
360 fn write_property(
361 &mut self,
362 property: PropertyIdentifier,
363 array_index: Option<u32>,
364 value: PropertyValue,
365 priority: Option<u8>,
366 ) -> Result<(), Error> {
367 common::write_priority_array_direct!(self, property, array_index, value, |v| {
368 if let PropertyValue::Enumerated(e) = v {
369 if e > 1 {
370 Err(common::value_out_of_range_error())
371 } else {
372 Ok(e)
373 }
374 } else {
375 Err(common::invalid_data_type_error())
376 }
377 });
378 if property == PropertyIdentifier::PRESENT_VALUE {
379 return common::write_priority_array!(self, value, priority, |v| {
380 if let PropertyValue::Enumerated(e) = v {
381 if e > 1 {
382 Err(common::value_out_of_range_error())
383 } else {
384 Ok(e)
385 }
386 } else {
387 Err(common::invalid_data_type_error())
388 }
389 });
390 }
391 if property == PropertyIdentifier::ACTIVE_TEXT {
392 if let PropertyValue::CharacterString(s) = value {
393 self.active_text = s;
394 return Ok(());
395 }
396 return Err(common::invalid_data_type_error());
397 }
398 if property == PropertyIdentifier::INACTIVE_TEXT {
399 if let PropertyValue::CharacterString(s) = value {
400 self.inactive_text = s;
401 return Ok(());
402 }
403 return Err(common::invalid_data_type_error());
404 }
405 if let Some(result) =
406 common::write_out_of_service(&mut self.out_of_service, property, &value)
407 {
408 return result;
409 }
410 if let Some(result) = common::write_object_name(&mut self.name, property, &value) {
411 return result;
412 }
413 if let Some(result) = common::write_description(&mut self.description, property, &value) {
414 return result;
415 }
416 Err(common::write_access_denied_error())
417 }
418
419 fn property_list(&self) -> Cow<'static, [PropertyIdentifier]> {
420 static PROPS: &[PropertyIdentifier] = &[
421 PropertyIdentifier::OBJECT_IDENTIFIER,
422 PropertyIdentifier::OBJECT_NAME,
423 PropertyIdentifier::DESCRIPTION,
424 PropertyIdentifier::OBJECT_TYPE,
425 PropertyIdentifier::PRESENT_VALUE,
426 PropertyIdentifier::STATUS_FLAGS,
427 PropertyIdentifier::EVENT_STATE,
428 PropertyIdentifier::OUT_OF_SERVICE,
429 PropertyIdentifier::PRIORITY_ARRAY,
430 PropertyIdentifier::RELINQUISH_DEFAULT,
431 PropertyIdentifier::CURRENT_COMMAND_PRIORITY,
432 PropertyIdentifier::POLARITY,
433 PropertyIdentifier::RELIABILITY,
434 PropertyIdentifier::ACTIVE_TEXT,
435 PropertyIdentifier::INACTIVE_TEXT,
436 ];
437 Cow::Borrowed(PROPS)
438 }
439}
440
441pub struct BinaryValueObject {
450 oid: ObjectIdentifier,
451 name: String,
452 description: String,
453 present_value: u32, out_of_service: bool,
455 status_flags: StatusFlags,
456 priority_array: [Option<u32>; 16],
457 relinquish_default: u32,
458 reliability: u32,
460 active_text: String,
461 inactive_text: String,
462 event_detector: ChangeOfStateDetector,
464 value_source: common::ValueSourceTracking,
466}
467
468impl BinaryValueObject {
469 pub fn new(instance: u32, name: impl Into<String>) -> Result<Self, Error> {
471 let oid = ObjectIdentifier::new(ObjectType::BINARY_VALUE, instance)?;
472 Ok(Self {
473 oid,
474 name: name.into(),
475 description: String::new(),
476 present_value: 0, out_of_service: false,
478 status_flags: StatusFlags::empty(),
479 priority_array: [None; 16],
480 relinquish_default: 0,
481 reliability: 0,
482 active_text: "Active".into(),
483 inactive_text: "Inactive".into(),
484 event_detector: ChangeOfStateDetector::default(),
485 value_source: common::ValueSourceTracking::default(),
486 })
487 }
488
489 pub fn set_description(&mut self, desc: impl Into<String>) {
491 self.description = desc.into();
492 }
493
494 fn recalculate_present_value(&mut self) {
495 self.present_value =
496 common::recalculate_from_priority_array(&self.priority_array, self.relinquish_default);
497 }
498}
499
500impl BACnetObject for BinaryValueObject {
501 fn object_identifier(&self) -> ObjectIdentifier {
502 self.oid
503 }
504
505 fn object_name(&self) -> &str {
506 &self.name
507 }
508
509 fn supports_cov(&self) -> bool {
510 true
511 }
512
513 fn evaluate_intrinsic_reporting(&mut self) -> Option<EventStateChange> {
514 self.event_detector.evaluate(self.present_value)
515 }
516
517 fn read_property(
518 &self,
519 property: PropertyIdentifier,
520 array_index: Option<u32>,
521 ) -> Result<PropertyValue, Error> {
522 if property == PropertyIdentifier::STATUS_FLAGS {
523 return Ok(common::compute_status_flags(
524 self.status_flags,
525 self.reliability,
526 self.out_of_service,
527 self.event_detector.event_state.to_raw(),
528 ));
529 }
530 if let Some(result) = read_common_properties!(self, property, array_index) {
531 return result;
532 }
533 match property {
534 p if p == PropertyIdentifier::OBJECT_TYPE => {
535 Ok(PropertyValue::Enumerated(ObjectType::BINARY_VALUE.to_raw()))
536 }
537 p if p == PropertyIdentifier::PRESENT_VALUE => {
538 Ok(PropertyValue::Enumerated(self.present_value))
539 }
540 p if p == PropertyIdentifier::EVENT_STATE => Ok(PropertyValue::Enumerated(
541 self.event_detector.event_state.to_raw(),
542 )),
543 p if p == PropertyIdentifier::PRIORITY_ARRAY => {
544 common::read_priority_array!(self, array_index, PropertyValue::Enumerated)
545 }
546 p if p == PropertyIdentifier::RELINQUISH_DEFAULT => {
547 Ok(PropertyValue::Enumerated(self.relinquish_default))
548 }
549 p if p == PropertyIdentifier::CURRENT_COMMAND_PRIORITY => {
550 Ok(common::current_command_priority(&self.priority_array))
551 }
552 p if p == PropertyIdentifier::VALUE_SOURCE => {
553 Ok(self.value_source.value_source.clone())
554 }
555 p if p == PropertyIdentifier::LAST_COMMAND_TIME => Ok(PropertyValue::Unsigned(
556 match self.value_source.last_command_time {
557 BACnetTimeStamp::SequenceNumber(n) => n,
558 _ => 0,
559 },
560 )),
561 p if p == PropertyIdentifier::ACTIVE_TEXT => {
562 Ok(PropertyValue::CharacterString(self.active_text.clone()))
563 }
564 p if p == PropertyIdentifier::INACTIVE_TEXT => {
565 Ok(PropertyValue::CharacterString(self.inactive_text.clone()))
566 }
567 p if p == PropertyIdentifier::EVENT_ENABLE => Ok(PropertyValue::BitString {
568 unused_bits: 5,
569 data: vec![self.event_detector.event_enable << 5],
570 }),
571 p if p == PropertyIdentifier::ACKED_TRANSITIONS => Ok(PropertyValue::BitString {
572 unused_bits: 5,
573 data: vec![self.event_detector.acked_transitions << 5],
574 }),
575 p if p == PropertyIdentifier::NOTIFICATION_CLASS => Ok(PropertyValue::Unsigned(
576 self.event_detector.notification_class as u64,
577 )),
578 p if p == PropertyIdentifier::EVENT_TIME_STAMPS => Ok(PropertyValue::List(vec![
579 PropertyValue::Unsigned(0),
580 PropertyValue::Unsigned(0),
581 PropertyValue::Unsigned(0),
582 ])),
583 _ => Err(common::unknown_property_error()),
584 }
585 }
586
587 fn write_property(
588 &mut self,
589 property: PropertyIdentifier,
590 array_index: Option<u32>,
591 value: PropertyValue,
592 priority: Option<u8>,
593 ) -> Result<(), Error> {
594 common::write_priority_array_direct!(self, property, array_index, value, |v| {
595 if let PropertyValue::Enumerated(e) = v {
596 if e > 1 {
597 Err(common::value_out_of_range_error())
598 } else {
599 Ok(e)
600 }
601 } else {
602 Err(common::invalid_data_type_error())
603 }
604 });
605 if property == PropertyIdentifier::PRESENT_VALUE {
606 return common::write_priority_array!(self, value, priority, |v| {
607 if let PropertyValue::Enumerated(e) = v {
608 if e > 1 {
609 Err(common::value_out_of_range_error())
610 } else {
611 Ok(e)
612 }
613 } else {
614 Err(common::invalid_data_type_error())
615 }
616 });
617 }
618 if property == PropertyIdentifier::ACTIVE_TEXT {
619 if let PropertyValue::CharacterString(s) = value {
620 self.active_text = s;
621 return Ok(());
622 }
623 return Err(common::invalid_data_type_error());
624 }
625 if property == PropertyIdentifier::INACTIVE_TEXT {
626 if let PropertyValue::CharacterString(s) = value {
627 self.inactive_text = s;
628 return Ok(());
629 }
630 return Err(common::invalid_data_type_error());
631 }
632 if let Some(result) =
633 common::write_out_of_service(&mut self.out_of_service, property, &value)
634 {
635 return result;
636 }
637 if let Some(result) = common::write_object_name(&mut self.name, property, &value) {
638 return result;
639 }
640 if let Some(result) = common::write_description(&mut self.description, property, &value) {
641 return result;
642 }
643 Err(common::write_access_denied_error())
644 }
645
646 fn property_list(&self) -> Cow<'static, [PropertyIdentifier]> {
647 static PROPS: &[PropertyIdentifier] = &[
648 PropertyIdentifier::OBJECT_IDENTIFIER,
649 PropertyIdentifier::OBJECT_NAME,
650 PropertyIdentifier::DESCRIPTION,
651 PropertyIdentifier::OBJECT_TYPE,
652 PropertyIdentifier::PRESENT_VALUE,
653 PropertyIdentifier::STATUS_FLAGS,
654 PropertyIdentifier::EVENT_STATE,
655 PropertyIdentifier::OUT_OF_SERVICE,
656 PropertyIdentifier::PRIORITY_ARRAY,
657 PropertyIdentifier::RELINQUISH_DEFAULT,
658 PropertyIdentifier::CURRENT_COMMAND_PRIORITY,
659 PropertyIdentifier::RELIABILITY,
660 PropertyIdentifier::ACTIVE_TEXT,
661 PropertyIdentifier::INACTIVE_TEXT,
662 ];
663 Cow::Borrowed(PROPS)
664 }
665}
666
667#[cfg(test)]
668mod tests {
669 use super::*;
670
671 #[test]
672 fn bv_read_present_value_default() {
673 let bv = BinaryValueObject::new(1, "BV-1").unwrap();
674 let val = bv
675 .read_property(PropertyIdentifier::PRESENT_VALUE, None)
676 .unwrap();
677 assert_eq!(val, PropertyValue::Enumerated(0)); }
679
680 #[test]
681 fn bv_write_present_value() {
682 let mut bv = BinaryValueObject::new(1, "BV-1").unwrap();
683 bv.write_property(
684 PropertyIdentifier::PRESENT_VALUE,
685 None,
686 PropertyValue::Enumerated(1), Some(8),
688 )
689 .unwrap();
690 let val = bv
691 .read_property(PropertyIdentifier::PRESENT_VALUE, None)
692 .unwrap();
693 assert_eq!(val, PropertyValue::Enumerated(1));
694 }
695
696 #[test]
697 fn bv_write_invalid_value_rejected() {
698 let mut bv = BinaryValueObject::new(1, "BV-1").unwrap();
699 let result = bv.write_property(
700 PropertyIdentifier::PRESENT_VALUE,
701 None,
702 PropertyValue::Enumerated(2), Some(8),
704 );
705 assert!(result.is_err());
706 }
707
708 #[test]
709 fn bv_write_wrong_type_rejected() {
710 let mut bv = BinaryValueObject::new(1, "BV-1").unwrap();
711 let result = bv.write_property(
712 PropertyIdentifier::PRESENT_VALUE,
713 None,
714 PropertyValue::Real(1.0), Some(8),
716 );
717 assert!(result.is_err());
718 }
719
720 #[test]
721 fn bv_read_object_type() {
722 let bv = BinaryValueObject::new(1, "BV-1").unwrap();
723 let val = bv
724 .read_property(PropertyIdentifier::OBJECT_TYPE, None)
725 .unwrap();
726 assert_eq!(
727 val,
728 PropertyValue::Enumerated(ObjectType::BINARY_VALUE.to_raw())
729 );
730 }
731
732 #[test]
733 fn bv_read_reliability_default() {
734 let bv = BinaryValueObject::new(1, "BV-1").unwrap();
735 let val = bv
736 .read_property(PropertyIdentifier::RELIABILITY, None)
737 .unwrap();
738 assert_eq!(val, PropertyValue::Enumerated(0)); }
740
741 #[test]
744 fn bi_read_present_value_default() {
745 let bi = BinaryInputObject::new(1, "BI-1").unwrap();
746 let val = bi
747 .read_property(PropertyIdentifier::PRESENT_VALUE, None)
748 .unwrap();
749 assert_eq!(val, PropertyValue::Enumerated(0));
750 }
751
752 #[test]
753 fn bi_write_denied_when_in_service() {
754 let mut bi = BinaryInputObject::new(1, "BI-1").unwrap();
755 let result = bi.write_property(
756 PropertyIdentifier::PRESENT_VALUE,
757 None,
758 PropertyValue::Enumerated(1),
759 None,
760 );
761 assert!(result.is_err());
762 }
763
764 #[test]
765 fn bi_write_allowed_when_out_of_service() {
766 let mut bi = BinaryInputObject::new(1, "BI-1").unwrap();
767 bi.write_property(
768 PropertyIdentifier::OUT_OF_SERVICE,
769 None,
770 PropertyValue::Boolean(true),
771 None,
772 )
773 .unwrap();
774 bi.write_property(
775 PropertyIdentifier::PRESENT_VALUE,
776 None,
777 PropertyValue::Enumerated(1),
778 None,
779 )
780 .unwrap();
781 let val = bi
782 .read_property(PropertyIdentifier::PRESENT_VALUE, None)
783 .unwrap();
784 assert_eq!(val, PropertyValue::Enumerated(1));
785 }
786
787 #[test]
788 fn bi_set_present_value() {
789 let mut bi = BinaryInputObject::new(1, "BI-1").unwrap();
790 bi.set_present_value(1);
791 let val = bi
792 .read_property(PropertyIdentifier::PRESENT_VALUE, None)
793 .unwrap();
794 assert_eq!(val, PropertyValue::Enumerated(1));
795 }
796
797 #[test]
798 fn bi_read_polarity_default() {
799 let bi = BinaryInputObject::new(1, "BI-1").unwrap();
800 let val = bi
801 .read_property(PropertyIdentifier::POLARITY, None)
802 .unwrap();
803 assert_eq!(val, PropertyValue::Enumerated(0)); }
805
806 #[test]
807 fn bi_read_reliability_default() {
808 let bi = BinaryInputObject::new(1, "BI-1").unwrap();
809 let val = bi
810 .read_property(PropertyIdentifier::RELIABILITY, None)
811 .unwrap();
812 assert_eq!(val, PropertyValue::Enumerated(0)); }
814
815 #[test]
818 fn bo_write_with_priority() {
819 let mut bo = BinaryOutputObject::new(1, "BO-1").unwrap();
820 bo.write_property(
821 PropertyIdentifier::PRESENT_VALUE,
822 None,
823 PropertyValue::Enumerated(1),
824 Some(8),
825 )
826 .unwrap();
827 let val = bo
828 .read_property(PropertyIdentifier::PRESENT_VALUE, None)
829 .unwrap();
830 assert_eq!(val, PropertyValue::Enumerated(1));
831 let slot = bo
832 .read_property(PropertyIdentifier::PRIORITY_ARRAY, Some(8))
833 .unwrap();
834 assert_eq!(slot, PropertyValue::Enumerated(1));
835 }
836
837 #[test]
838 fn bo_relinquish_falls_to_default() {
839 let mut bo = BinaryOutputObject::new(1, "BO-1").unwrap();
840 bo.write_property(
841 PropertyIdentifier::PRESENT_VALUE,
842 None,
843 PropertyValue::Enumerated(1),
844 Some(16),
845 )
846 .unwrap();
847 assert_eq!(
848 bo.read_property(PropertyIdentifier::PRESENT_VALUE, None)
849 .unwrap(),
850 PropertyValue::Enumerated(1)
851 );
852 bo.write_property(
853 PropertyIdentifier::PRESENT_VALUE,
854 None,
855 PropertyValue::Null,
856 Some(16),
857 )
858 .unwrap();
859 assert_eq!(
860 bo.read_property(PropertyIdentifier::PRESENT_VALUE, None)
861 .unwrap(),
862 PropertyValue::Enumerated(0)
863 );
864 }
865
866 #[test]
867 fn bo_invalid_value_rejected() {
868 let mut bo = BinaryOutputObject::new(1, "BO-1").unwrap();
869 let result = bo.write_property(
870 PropertyIdentifier::PRESENT_VALUE,
871 None,
872 PropertyValue::Enumerated(2),
873 None,
874 );
875 assert!(result.is_err());
876 }
877
878 #[test]
879 fn bo_read_polarity_default() {
880 let bo = BinaryOutputObject::new(1, "BO-1").unwrap();
881 let val = bo
882 .read_property(PropertyIdentifier::POLARITY, None)
883 .unwrap();
884 assert_eq!(val, PropertyValue::Enumerated(0)); }
886
887 #[test]
888 fn bo_read_reliability_default() {
889 let bo = BinaryOutputObject::new(1, "BO-1").unwrap();
890 let val = bo
891 .read_property(PropertyIdentifier::RELIABILITY, None)
892 .unwrap();
893 assert_eq!(val, PropertyValue::Enumerated(0)); }
895
896 #[test]
899 fn bo_priority_array_index_zero_returns_size() {
900 let bo = BinaryOutputObject::new(1, "BO-1").unwrap();
901 let val = bo
902 .read_property(PropertyIdentifier::PRIORITY_ARRAY, Some(0))
903 .unwrap();
904 assert_eq!(val, PropertyValue::Unsigned(16));
905 }
906
907 #[test]
908 fn bo_priority_array_index_out_of_bounds() {
909 let bo = BinaryOutputObject::new(1, "BO-1").unwrap();
910 let result = bo.read_property(PropertyIdentifier::PRIORITY_ARRAY, Some(17));
912 assert!(result.is_err());
913 }
914
915 #[test]
916 fn bo_priority_array_index_far_out_of_bounds() {
917 let bo = BinaryOutputObject::new(1, "BO-1").unwrap();
918 let result = bo.read_property(PropertyIdentifier::PRIORITY_ARRAY, Some(100));
919 assert!(result.is_err());
920 }
921
922 #[test]
925 fn bo_write_with_priority_zero_rejected() {
926 let mut bo = BinaryOutputObject::new(1, "BO-1").unwrap();
927 let result = bo.write_property(
929 PropertyIdentifier::PRESENT_VALUE,
930 None,
931 PropertyValue::Enumerated(1),
932 Some(0),
933 );
934 assert!(result.is_err());
935 }
936
937 #[test]
938 fn bo_write_with_priority_17_rejected() {
939 let mut bo = BinaryOutputObject::new(1, "BO-1").unwrap();
940 let result = bo.write_property(
942 PropertyIdentifier::PRESENT_VALUE,
943 None,
944 PropertyValue::Enumerated(1),
945 Some(17),
946 );
947 assert!(result.is_err());
948 }
949
950 #[test]
951 fn bo_write_with_priority_255_rejected() {
952 let mut bo = BinaryOutputObject::new(1, "BO-1").unwrap();
953 let result = bo.write_property(
955 PropertyIdentifier::PRESENT_VALUE,
956 None,
957 PropertyValue::Enumerated(1),
958 Some(255),
959 );
960 assert!(result.is_err());
961 }
962
963 #[test]
966 fn bi_polarity_is_readable_as_enumerated() {
967 let bi = BinaryInputObject::new(1, "BI-1").unwrap();
968 let val = bi
969 .read_property(PropertyIdentifier::POLARITY, None)
970 .unwrap();
971 match val {
973 PropertyValue::Enumerated(v) => assert_eq!(v, 0),
974 other => panic!("Expected Enumerated for POLARITY, got {:?}", other),
975 }
976 }
977
978 #[test]
979 fn bi_reliability_is_readable_as_enumerated() {
980 let bi = BinaryInputObject::new(1, "BI-1").unwrap();
981 let val = bi
982 .read_property(PropertyIdentifier::RELIABILITY, None)
983 .unwrap();
984 match val {
986 PropertyValue::Enumerated(v) => assert_eq!(v, 0),
987 other => panic!("Expected Enumerated for RELIABILITY, got {:?}", other),
988 }
989 }
990
991 #[test]
992 fn bo_polarity_is_readable_as_enumerated() {
993 let bo = BinaryOutputObject::new(1, "BO-1").unwrap();
994 let val = bo
995 .read_property(PropertyIdentifier::POLARITY, None)
996 .unwrap();
997 match val {
998 PropertyValue::Enumerated(v) => assert_eq!(v, 0),
999 other => panic!("Expected Enumerated for POLARITY, got {:?}", other),
1000 }
1001 }
1002
1003 #[test]
1004 fn bo_reliability_is_readable_as_enumerated() {
1005 let bo = BinaryOutputObject::new(1, "BO-1").unwrap();
1006 let val = bo
1007 .read_property(PropertyIdentifier::RELIABILITY, None)
1008 .unwrap();
1009 match val {
1010 PropertyValue::Enumerated(v) => assert_eq!(v, 0),
1011 other => panic!("Expected Enumerated for RELIABILITY, got {:?}", other),
1012 }
1013 }
1014
1015 #[test]
1016 fn bi_polarity_in_property_list() {
1017 let bi = BinaryInputObject::new(1, "BI-1").unwrap();
1018 let props = bi.property_list();
1019 assert!(props.contains(&PropertyIdentifier::POLARITY));
1020 assert!(props.contains(&PropertyIdentifier::RELIABILITY));
1021 }
1022
1023 #[test]
1024 fn bo_priority_array_read_all_slots_none_by_default() {
1025 let bo = BinaryOutputObject::new(1, "BO-1").unwrap();
1026 let val = bo
1027 .read_property(PropertyIdentifier::PRIORITY_ARRAY, None)
1028 .unwrap();
1029 if let PropertyValue::List(elements) = val {
1030 assert_eq!(elements.len(), 16);
1031 for elem in &elements {
1032 assert_eq!(elem, &PropertyValue::Null);
1033 }
1034 } else {
1035 panic!("Expected List for priority array without index");
1036 }
1037 }
1038
1039 #[test]
1042 fn bo_direct_priority_array_write_value() {
1043 let mut bo = BinaryOutputObject::new(1, "BO-1").unwrap();
1044 bo.write_property(
1045 PropertyIdentifier::PRIORITY_ARRAY,
1046 Some(5),
1047 PropertyValue::Enumerated(1), None,
1049 )
1050 .unwrap();
1051 assert_eq!(
1052 bo.read_property(PropertyIdentifier::PRESENT_VALUE, None)
1053 .unwrap(),
1054 PropertyValue::Enumerated(1)
1055 );
1056 assert_eq!(
1057 bo.read_property(PropertyIdentifier::PRIORITY_ARRAY, Some(5))
1058 .unwrap(),
1059 PropertyValue::Enumerated(1)
1060 );
1061 }
1062
1063 #[test]
1064 fn bo_direct_priority_array_relinquish() {
1065 let mut bo = BinaryOutputObject::new(1, "BO-1").unwrap();
1066 bo.write_property(
1067 PropertyIdentifier::PRIORITY_ARRAY,
1068 Some(5),
1069 PropertyValue::Enumerated(1),
1070 None,
1071 )
1072 .unwrap();
1073 bo.write_property(
1074 PropertyIdentifier::PRIORITY_ARRAY,
1075 Some(5),
1076 PropertyValue::Null,
1077 None,
1078 )
1079 .unwrap();
1080 assert_eq!(
1082 bo.read_property(PropertyIdentifier::PRESENT_VALUE, None)
1083 .unwrap(),
1084 PropertyValue::Enumerated(0)
1085 );
1086 }
1087
1088 #[test]
1089 fn bo_direct_priority_array_no_index_error() {
1090 let mut bo = BinaryOutputObject::new(1, "BO-1").unwrap();
1091 let result = bo.write_property(
1092 PropertyIdentifier::PRIORITY_ARRAY,
1093 None,
1094 PropertyValue::Enumerated(1),
1095 None,
1096 );
1097 assert!(result.is_err());
1098 }
1099
1100 #[test]
1101 fn bo_direct_priority_array_index_zero_error() {
1102 let mut bo = BinaryOutputObject::new(1, "BO-1").unwrap();
1103 let result = bo.write_property(
1104 PropertyIdentifier::PRIORITY_ARRAY,
1105 Some(0),
1106 PropertyValue::Enumerated(1),
1107 None,
1108 );
1109 assert!(result.is_err());
1110 }
1111
1112 #[test]
1113 fn bo_direct_priority_array_index_17_error() {
1114 let mut bo = BinaryOutputObject::new(1, "BO-1").unwrap();
1115 let result = bo.write_property(
1116 PropertyIdentifier::PRIORITY_ARRAY,
1117 Some(17),
1118 PropertyValue::Enumerated(1),
1119 None,
1120 );
1121 assert!(result.is_err());
1122 }
1123
1124 #[test]
1127 fn bv_write_with_priority() {
1128 let mut bv = BinaryValueObject::new(1, "BV-1").unwrap();
1129 bv.write_property(
1130 PropertyIdentifier::PRESENT_VALUE,
1131 None,
1132 PropertyValue::Enumerated(1),
1133 Some(8),
1134 )
1135 .unwrap();
1136 let val = bv
1137 .read_property(PropertyIdentifier::PRESENT_VALUE, None)
1138 .unwrap();
1139 assert_eq!(val, PropertyValue::Enumerated(1));
1140 let slot = bv
1141 .read_property(PropertyIdentifier::PRIORITY_ARRAY, Some(8))
1142 .unwrap();
1143 assert_eq!(slot, PropertyValue::Enumerated(1));
1144 }
1145
1146 #[test]
1147 fn bv_relinquish_falls_to_default() {
1148 let mut bv = BinaryValueObject::new(1, "BV-1").unwrap();
1149 bv.write_property(
1150 PropertyIdentifier::PRESENT_VALUE,
1151 None,
1152 PropertyValue::Enumerated(1),
1153 Some(16),
1154 )
1155 .unwrap();
1156 assert_eq!(
1157 bv.read_property(PropertyIdentifier::PRESENT_VALUE, None)
1158 .unwrap(),
1159 PropertyValue::Enumerated(1)
1160 );
1161 bv.write_property(
1162 PropertyIdentifier::PRESENT_VALUE,
1163 None,
1164 PropertyValue::Null,
1165 Some(16),
1166 )
1167 .unwrap();
1168 assert_eq!(
1169 bv.read_property(PropertyIdentifier::PRESENT_VALUE, None)
1170 .unwrap(),
1171 PropertyValue::Enumerated(0) );
1173 }
1174
1175 #[test]
1176 fn bv_read_priority_array_all_none() {
1177 let bv = BinaryValueObject::new(1, "BV-1").unwrap();
1178 let val = bv
1179 .read_property(PropertyIdentifier::PRIORITY_ARRAY, None)
1180 .unwrap();
1181 if let PropertyValue::List(elements) = val {
1182 assert_eq!(elements.len(), 16);
1183 for elem in &elements {
1184 assert_eq!(elem, &PropertyValue::Null);
1185 }
1186 } else {
1187 panic!("Expected List for priority array without index");
1188 }
1189 }
1190
1191 #[test]
1192 fn bv_read_relinquish_default() {
1193 let bv = BinaryValueObject::new(1, "BV-1").unwrap();
1194 let val = bv
1195 .read_property(PropertyIdentifier::RELINQUISH_DEFAULT, None)
1196 .unwrap();
1197 assert_eq!(val, PropertyValue::Enumerated(0));
1198 }
1199
1200 #[test]
1201 fn bv_priority_array_in_property_list() {
1202 let bv = BinaryValueObject::new(1, "BV-1").unwrap();
1203 let props = bv.property_list();
1204 assert!(props.contains(&PropertyIdentifier::PRIORITY_ARRAY));
1205 assert!(props.contains(&PropertyIdentifier::RELINQUISH_DEFAULT));
1206 }
1207
1208 #[test]
1209 fn bv_direct_priority_array_write() {
1210 let mut bv = BinaryValueObject::new(1, "BV-1").unwrap();
1211 bv.write_property(
1212 PropertyIdentifier::PRIORITY_ARRAY,
1213 Some(5),
1214 PropertyValue::Enumerated(1),
1215 None,
1216 )
1217 .unwrap();
1218 assert_eq!(
1219 bv.read_property(PropertyIdentifier::PRESENT_VALUE, None)
1220 .unwrap(),
1221 PropertyValue::Enumerated(1)
1222 );
1223 assert_eq!(
1224 bv.read_property(PropertyIdentifier::PRIORITY_ARRAY, Some(5))
1225 .unwrap(),
1226 PropertyValue::Enumerated(1)
1227 );
1228 }
1229
1230 #[test]
1231 fn bv_direct_priority_array_relinquish() {
1232 let mut bv = BinaryValueObject::new(1, "BV-1").unwrap();
1233 bv.write_property(
1234 PropertyIdentifier::PRIORITY_ARRAY,
1235 Some(5),
1236 PropertyValue::Enumerated(1),
1237 None,
1238 )
1239 .unwrap();
1240 bv.write_property(
1241 PropertyIdentifier::PRIORITY_ARRAY,
1242 Some(5),
1243 PropertyValue::Null,
1244 None,
1245 )
1246 .unwrap();
1247 assert_eq!(
1248 bv.read_property(PropertyIdentifier::PRESENT_VALUE, None)
1249 .unwrap(),
1250 PropertyValue::Enumerated(0) );
1252 }
1253
1254 #[test]
1257 fn bv_description_read_write() {
1258 let mut bv = BinaryValueObject::new(1, "BV-1").unwrap();
1259 assert_eq!(
1261 bv.read_property(PropertyIdentifier::DESCRIPTION, None)
1262 .unwrap(),
1263 PropertyValue::CharacterString(String::new())
1264 );
1265 bv.write_property(
1266 PropertyIdentifier::DESCRIPTION,
1267 None,
1268 PropertyValue::CharacterString("Occupied/Unoccupied".into()),
1269 None,
1270 )
1271 .unwrap();
1272 assert_eq!(
1273 bv.read_property(PropertyIdentifier::DESCRIPTION, None)
1274 .unwrap(),
1275 PropertyValue::CharacterString("Occupied/Unoccupied".into())
1276 );
1277 }
1278
1279 #[test]
1280 fn bv_description_in_property_list() {
1281 let bv = BinaryValueObject::new(1, "BV-1").unwrap();
1282 assert!(bv
1283 .property_list()
1284 .contains(&PropertyIdentifier::DESCRIPTION));
1285 }
1286
1287 #[test]
1288 fn bi_description_read_write() {
1289 let mut bi = BinaryInputObject::new(1, "BI-1").unwrap();
1290 bi.write_property(
1291 PropertyIdentifier::DESCRIPTION,
1292 None,
1293 PropertyValue::CharacterString("Door contact".into()),
1294 None,
1295 )
1296 .unwrap();
1297 assert_eq!(
1298 bi.read_property(PropertyIdentifier::DESCRIPTION, None)
1299 .unwrap(),
1300 PropertyValue::CharacterString("Door contact".into())
1301 );
1302 }
1303
1304 #[test]
1305 fn bo_description_read_write() {
1306 let mut bo = BinaryOutputObject::new(1, "BO-1").unwrap();
1307 bo.write_property(
1308 PropertyIdentifier::DESCRIPTION,
1309 None,
1310 PropertyValue::CharacterString("Fan enable".into()),
1311 None,
1312 )
1313 .unwrap();
1314 assert_eq!(
1315 bo.read_property(PropertyIdentifier::DESCRIPTION, None)
1316 .unwrap(),
1317 PropertyValue::CharacterString("Fan enable".into())
1318 );
1319 }
1320
1321 #[test]
1322 fn bv_higher_priority_wins() {
1323 let mut bv = BinaryValueObject::new(1, "BV-1").unwrap();
1324 bv.write_property(
1326 PropertyIdentifier::PRESENT_VALUE,
1327 None,
1328 PropertyValue::Enumerated(0),
1329 Some(10),
1330 )
1331 .unwrap();
1332 bv.write_property(
1334 PropertyIdentifier::PRESENT_VALUE,
1335 None,
1336 PropertyValue::Enumerated(1),
1337 Some(5),
1338 )
1339 .unwrap();
1340 assert_eq!(
1341 bv.read_property(PropertyIdentifier::PRESENT_VALUE, None)
1342 .unwrap(),
1343 PropertyValue::Enumerated(1) );
1345 bv.write_property(
1347 PropertyIdentifier::PRESENT_VALUE,
1348 None,
1349 PropertyValue::Null,
1350 Some(5),
1351 )
1352 .unwrap();
1353 assert_eq!(
1354 bv.read_property(PropertyIdentifier::PRESENT_VALUE, None)
1355 .unwrap(),
1356 PropertyValue::Enumerated(0) );
1358 }
1359
1360 #[test]
1363 fn bi_active_inactive_text_defaults() {
1364 let bi = BinaryInputObject::new(1, "BI-1").unwrap();
1365 assert_eq!(
1366 bi.read_property(PropertyIdentifier::ACTIVE_TEXT, None)
1367 .unwrap(),
1368 PropertyValue::CharacterString("Active".into())
1369 );
1370 assert_eq!(
1371 bi.read_property(PropertyIdentifier::INACTIVE_TEXT, None)
1372 .unwrap(),
1373 PropertyValue::CharacterString("Inactive".into())
1374 );
1375 }
1376
1377 #[test]
1378 fn bi_active_inactive_text_write_read() {
1379 let mut bi = BinaryInputObject::new(1, "BI-1").unwrap();
1380 bi.write_property(
1381 PropertyIdentifier::ACTIVE_TEXT,
1382 None,
1383 PropertyValue::CharacterString("On".into()),
1384 None,
1385 )
1386 .unwrap();
1387 bi.write_property(
1388 PropertyIdentifier::INACTIVE_TEXT,
1389 None,
1390 PropertyValue::CharacterString("Off".into()),
1391 None,
1392 )
1393 .unwrap();
1394 assert_eq!(
1395 bi.read_property(PropertyIdentifier::ACTIVE_TEXT, None)
1396 .unwrap(),
1397 PropertyValue::CharacterString("On".into())
1398 );
1399 assert_eq!(
1400 bi.read_property(PropertyIdentifier::INACTIVE_TEXT, None)
1401 .unwrap(),
1402 PropertyValue::CharacterString("Off".into())
1403 );
1404 }
1405
1406 #[test]
1407 fn bi_active_text_wrong_type_rejected() {
1408 let mut bi = BinaryInputObject::new(1, "BI-1").unwrap();
1409 assert!(bi
1410 .write_property(
1411 PropertyIdentifier::ACTIVE_TEXT,
1412 None,
1413 PropertyValue::Enumerated(1),
1414 None,
1415 )
1416 .is_err());
1417 }
1418
1419 #[test]
1420 fn bi_inactive_text_wrong_type_rejected() {
1421 let mut bi = BinaryInputObject::new(1, "BI-1").unwrap();
1422 assert!(bi
1423 .write_property(
1424 PropertyIdentifier::INACTIVE_TEXT,
1425 None,
1426 PropertyValue::Boolean(false),
1427 None,
1428 )
1429 .is_err());
1430 }
1431
1432 #[test]
1433 fn bi_active_inactive_text_in_property_list() {
1434 let bi = BinaryInputObject::new(1, "BI-1").unwrap();
1435 let props = bi.property_list();
1436 assert!(props.contains(&PropertyIdentifier::ACTIVE_TEXT));
1437 assert!(props.contains(&PropertyIdentifier::INACTIVE_TEXT));
1438 }
1439
1440 #[test]
1441 fn bo_active_inactive_text_defaults() {
1442 let bo = BinaryOutputObject::new(1, "BO-1").unwrap();
1443 assert_eq!(
1444 bo.read_property(PropertyIdentifier::ACTIVE_TEXT, None)
1445 .unwrap(),
1446 PropertyValue::CharacterString("Active".into())
1447 );
1448 assert_eq!(
1449 bo.read_property(PropertyIdentifier::INACTIVE_TEXT, None)
1450 .unwrap(),
1451 PropertyValue::CharacterString("Inactive".into())
1452 );
1453 }
1454
1455 #[test]
1456 fn bo_active_inactive_text_write_read() {
1457 let mut bo = BinaryOutputObject::new(1, "BO-1").unwrap();
1458 bo.write_property(
1459 PropertyIdentifier::ACTIVE_TEXT,
1460 None,
1461 PropertyValue::CharacterString("Running".into()),
1462 None,
1463 )
1464 .unwrap();
1465 bo.write_property(
1466 PropertyIdentifier::INACTIVE_TEXT,
1467 None,
1468 PropertyValue::CharacterString("Stopped".into()),
1469 None,
1470 )
1471 .unwrap();
1472 assert_eq!(
1473 bo.read_property(PropertyIdentifier::ACTIVE_TEXT, None)
1474 .unwrap(),
1475 PropertyValue::CharacterString("Running".into())
1476 );
1477 assert_eq!(
1478 bo.read_property(PropertyIdentifier::INACTIVE_TEXT, None)
1479 .unwrap(),
1480 PropertyValue::CharacterString("Stopped".into())
1481 );
1482 }
1483
1484 #[test]
1485 fn bo_active_inactive_text_in_property_list() {
1486 let bo = BinaryOutputObject::new(1, "BO-1").unwrap();
1487 let props = bo.property_list();
1488 assert!(props.contains(&PropertyIdentifier::ACTIVE_TEXT));
1489 assert!(props.contains(&PropertyIdentifier::INACTIVE_TEXT));
1490 }
1491
1492 #[test]
1493 fn bv_active_inactive_text_defaults() {
1494 let bv = BinaryValueObject::new(1, "BV-1").unwrap();
1495 assert_eq!(
1496 bv.read_property(PropertyIdentifier::ACTIVE_TEXT, None)
1497 .unwrap(),
1498 PropertyValue::CharacterString("Active".into())
1499 );
1500 assert_eq!(
1501 bv.read_property(PropertyIdentifier::INACTIVE_TEXT, None)
1502 .unwrap(),
1503 PropertyValue::CharacterString("Inactive".into())
1504 );
1505 }
1506
1507 #[test]
1508 fn bv_active_inactive_text_write_read() {
1509 let mut bv = BinaryValueObject::new(1, "BV-1").unwrap();
1510 bv.write_property(
1511 PropertyIdentifier::ACTIVE_TEXT,
1512 None,
1513 PropertyValue::CharacterString("Occupied".into()),
1514 None,
1515 )
1516 .unwrap();
1517 bv.write_property(
1518 PropertyIdentifier::INACTIVE_TEXT,
1519 None,
1520 PropertyValue::CharacterString("Unoccupied".into()),
1521 None,
1522 )
1523 .unwrap();
1524 assert_eq!(
1525 bv.read_property(PropertyIdentifier::ACTIVE_TEXT, None)
1526 .unwrap(),
1527 PropertyValue::CharacterString("Occupied".into())
1528 );
1529 assert_eq!(
1530 bv.read_property(PropertyIdentifier::INACTIVE_TEXT, None)
1531 .unwrap(),
1532 PropertyValue::CharacterString("Unoccupied".into())
1533 );
1534 }
1535
1536 #[test]
1537 fn bv_active_inactive_text_in_property_list() {
1538 let bv = BinaryValueObject::new(1, "BV-1").unwrap();
1539 let props = bv.property_list();
1540 assert!(props.contains(&PropertyIdentifier::ACTIVE_TEXT));
1541 assert!(props.contains(&PropertyIdentifier::INACTIVE_TEXT));
1542 }
1543
1544 #[test]
1545 fn bv_active_text_wrong_type_rejected() {
1546 let mut bv = BinaryValueObject::new(1, "BV-1").unwrap();
1547 assert!(bv
1548 .write_property(
1549 PropertyIdentifier::ACTIVE_TEXT,
1550 None,
1551 PropertyValue::Real(1.0),
1552 None,
1553 )
1554 .is_err());
1555 }
1556}