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