1use bacnet_types::enums::{ObjectType, PropertyIdentifier};
8use bacnet_types::error::Error;
9use bacnet_types::primitives::{ObjectIdentifier, PropertyValue, StatusFlags};
10use std::borrow::Cow;
11
12use crate::common::{self, read_common_properties};
13use crate::traits::BACnetObject;
14
15pub struct ElevatorGroupObject {
21 oid: ObjectIdentifier,
22 name: String,
23 description: String,
24 group_id: u64,
26 group_members: Vec<ObjectIdentifier>,
28 group_mode: u32,
30 landing_calls: u64,
32 landing_call_control: u32,
34 status_flags: StatusFlags,
35 out_of_service: bool,
36 reliability: u32,
37}
38
39impl ElevatorGroupObject {
40 pub fn new(instance: u32, name: impl Into<String>) -> Result<Self, Error> {
42 let oid = ObjectIdentifier::new(ObjectType::ELEVATOR_GROUP, instance)?;
43 Ok(Self {
44 oid,
45 name: name.into(),
46 description: String::new(),
47 group_id: 0,
48 group_members: Vec::new(),
49 group_mode: 0, landing_calls: 0,
51 landing_call_control: 0,
52 status_flags: StatusFlags::empty(),
53 out_of_service: false,
54 reliability: 0,
55 })
56 }
57
58 pub fn add_member(&mut self, oid: ObjectIdentifier) {
60 self.group_members.push(oid);
61 }
62}
63
64impl BACnetObject for ElevatorGroupObject {
65 fn object_identifier(&self) -> ObjectIdentifier {
66 self.oid
67 }
68
69 fn object_name(&self) -> &str {
70 &self.name
71 }
72
73 fn read_property(
74 &self,
75 property: PropertyIdentifier,
76 array_index: Option<u32>,
77 ) -> Result<PropertyValue, Error> {
78 if let Some(result) = read_common_properties!(self, property, array_index) {
79 return result;
80 }
81 match property {
82 p if p == PropertyIdentifier::OBJECT_TYPE => Ok(PropertyValue::Enumerated(
83 ObjectType::ELEVATOR_GROUP.to_raw(),
84 )),
85 p if p == PropertyIdentifier::GROUP_ID => Ok(PropertyValue::Unsigned(self.group_id)),
86 p if p == PropertyIdentifier::GROUP_MEMBERS => {
87 let items: Vec<PropertyValue> = self
88 .group_members
89 .iter()
90 .map(|oid| PropertyValue::ObjectIdentifier(*oid))
91 .collect();
92 Ok(PropertyValue::List(items))
93 }
94 p if p == PropertyIdentifier::GROUP_MODE => {
95 Ok(PropertyValue::Enumerated(self.group_mode))
96 }
97 p if p == PropertyIdentifier::LANDING_CALLS => {
98 Ok(PropertyValue::Unsigned(self.landing_calls))
99 }
100 p if p == PropertyIdentifier::LANDING_CALL_CONTROL => {
101 Ok(PropertyValue::Enumerated(self.landing_call_control))
102 }
103 _ => Err(common::unknown_property_error()),
104 }
105 }
106
107 fn write_property(
108 &mut self,
109 property: PropertyIdentifier,
110 _array_index: Option<u32>,
111 value: PropertyValue,
112 _priority: Option<u8>,
113 ) -> Result<(), Error> {
114 if let Some(result) =
115 common::write_out_of_service(&mut self.out_of_service, property, &value)
116 {
117 return result;
118 }
119 if let Some(result) = common::write_description(&mut self.description, property, &value) {
120 return result;
121 }
122 match property {
123 p if p == PropertyIdentifier::GROUP_ID => {
124 if let PropertyValue::Unsigned(v) = value {
125 self.group_id = v;
126 Ok(())
127 } else {
128 Err(common::invalid_data_type_error())
129 }
130 }
131 p if p == PropertyIdentifier::GROUP_MODE => {
132 if let PropertyValue::Enumerated(v) = value {
133 self.group_mode = v;
134 Ok(())
135 } else {
136 Err(common::invalid_data_type_error())
137 }
138 }
139 p if p == PropertyIdentifier::LANDING_CALL_CONTROL => {
140 if let PropertyValue::Enumerated(v) = value {
141 self.landing_call_control = v;
142 Ok(())
143 } else {
144 Err(common::invalid_data_type_error())
145 }
146 }
147 _ => Err(common::write_access_denied_error()),
148 }
149 }
150
151 fn property_list(&self) -> Cow<'static, [PropertyIdentifier]> {
152 static PROPS: &[PropertyIdentifier] = &[
153 PropertyIdentifier::OBJECT_IDENTIFIER,
154 PropertyIdentifier::OBJECT_NAME,
155 PropertyIdentifier::DESCRIPTION,
156 PropertyIdentifier::OBJECT_TYPE,
157 PropertyIdentifier::GROUP_ID,
158 PropertyIdentifier::GROUP_MEMBERS,
159 PropertyIdentifier::GROUP_MODE,
160 PropertyIdentifier::LANDING_CALLS,
161 PropertyIdentifier::LANDING_CALL_CONTROL,
162 PropertyIdentifier::STATUS_FLAGS,
163 PropertyIdentifier::OUT_OF_SERVICE,
164 PropertyIdentifier::RELIABILITY,
165 ];
166 Cow::Borrowed(PROPS)
167 }
168}
169
170pub struct EscalatorObject {
176 oid: ObjectIdentifier,
177 name: String,
178 description: String,
179 escalator_mode: u32,
181 fault_signals: Vec<u64>,
183 energy_meter: f32,
185 energy_meter_ref: Vec<u8>,
187 power_mode: bool,
189 operation_direction: u32,
191 status_flags: StatusFlags,
192 out_of_service: bool,
193 reliability: u32,
194}
195
196impl EscalatorObject {
197 pub fn new(instance: u32, name: impl Into<String>) -> Result<Self, Error> {
199 let oid = ObjectIdentifier::new(ObjectType::ESCALATOR, instance)?;
200 Ok(Self {
201 oid,
202 name: name.into(),
203 description: String::new(),
204 escalator_mode: 0, fault_signals: Vec::new(),
206 energy_meter: 0.0,
207 energy_meter_ref: Vec::new(),
208 power_mode: false,
209 operation_direction: 0, status_flags: StatusFlags::empty(),
211 out_of_service: false,
212 reliability: 0,
213 })
214 }
215}
216
217impl BACnetObject for EscalatorObject {
218 fn object_identifier(&self) -> ObjectIdentifier {
219 self.oid
220 }
221
222 fn object_name(&self) -> &str {
223 &self.name
224 }
225
226 fn read_property(
227 &self,
228 property: PropertyIdentifier,
229 array_index: Option<u32>,
230 ) -> Result<PropertyValue, Error> {
231 if let Some(result) = read_common_properties!(self, property, array_index) {
232 return result;
233 }
234 match property {
235 p if p == PropertyIdentifier::OBJECT_TYPE => {
236 Ok(PropertyValue::Enumerated(ObjectType::ESCALATOR.to_raw()))
237 }
238 p if p == PropertyIdentifier::ESCALATOR_MODE => {
239 Ok(PropertyValue::Enumerated(self.escalator_mode))
240 }
241 p if p == PropertyIdentifier::FAULT_SIGNALS => {
242 let items: Vec<PropertyValue> = self
243 .fault_signals
244 .iter()
245 .map(|v| PropertyValue::Unsigned(*v))
246 .collect();
247 Ok(PropertyValue::List(items))
248 }
249 p if p == PropertyIdentifier::ENERGY_METER => {
250 Ok(PropertyValue::Real(self.energy_meter))
251 }
252 p if p == PropertyIdentifier::ENERGY_METER_REF => {
253 Ok(PropertyValue::OctetString(self.energy_meter_ref.clone()))
254 }
255 p if p == PropertyIdentifier::POWER_MODE => Ok(PropertyValue::Boolean(self.power_mode)),
256 p if p == PropertyIdentifier::OPERATION_DIRECTION => {
257 Ok(PropertyValue::Enumerated(self.operation_direction))
258 }
259 _ => Err(common::unknown_property_error()),
260 }
261 }
262
263 fn write_property(
264 &mut self,
265 property: PropertyIdentifier,
266 _array_index: Option<u32>,
267 value: PropertyValue,
268 _priority: Option<u8>,
269 ) -> Result<(), Error> {
270 if let Some(result) =
271 common::write_out_of_service(&mut self.out_of_service, property, &value)
272 {
273 return result;
274 }
275 if let Some(result) = common::write_description(&mut self.description, property, &value) {
276 return result;
277 }
278 match property {
279 p if p == PropertyIdentifier::ESCALATOR_MODE => {
280 if let PropertyValue::Enumerated(v) = value {
281 if v > 4 {
282 return Err(common::value_out_of_range_error());
283 }
284 self.escalator_mode = v;
285 Ok(())
286 } else {
287 Err(common::invalid_data_type_error())
288 }
289 }
290 p if p == PropertyIdentifier::OPERATION_DIRECTION => {
291 if let PropertyValue::Enumerated(v) = value {
292 if v > 3 {
293 return Err(common::value_out_of_range_error());
294 }
295 self.operation_direction = v;
296 Ok(())
297 } else {
298 Err(common::invalid_data_type_error())
299 }
300 }
301 _ => Err(common::write_access_denied_error()),
302 }
303 }
304
305 fn property_list(&self) -> Cow<'static, [PropertyIdentifier]> {
306 static PROPS: &[PropertyIdentifier] = &[
307 PropertyIdentifier::OBJECT_IDENTIFIER,
308 PropertyIdentifier::OBJECT_NAME,
309 PropertyIdentifier::DESCRIPTION,
310 PropertyIdentifier::OBJECT_TYPE,
311 PropertyIdentifier::ESCALATOR_MODE,
312 PropertyIdentifier::FAULT_SIGNALS,
313 PropertyIdentifier::ENERGY_METER,
314 PropertyIdentifier::ENERGY_METER_REF,
315 PropertyIdentifier::POWER_MODE,
316 PropertyIdentifier::OPERATION_DIRECTION,
317 PropertyIdentifier::STATUS_FLAGS,
318 PropertyIdentifier::OUT_OF_SERVICE,
319 PropertyIdentifier::RELIABILITY,
320 ];
321 Cow::Borrowed(PROPS)
322 }
323}
324
325pub struct LiftObject {
331 oid: ObjectIdentifier,
332 name: String,
333 description: String,
334 tracking_value: u64,
336 car_position: u64,
338 car_moving_direction: u32,
340 car_door_status: Vec<u64>,
342 car_load: u64,
344 landing_doors: u64,
346 floor_text: Vec<String>,
348 energy_meter: f32,
350 status_flags: StatusFlags,
351 out_of_service: bool,
352 reliability: u32,
353}
354
355impl LiftObject {
356 pub fn new(instance: u32, name: impl Into<String>, num_floors: usize) -> Result<Self, Error> {
360 let oid = ObjectIdentifier::new(ObjectType::LIFT, instance)?;
361 let floor_text = (1..=num_floors).map(|i| format!("Floor {i}")).collect();
362 Ok(Self {
363 oid,
364 name: name.into(),
365 description: String::new(),
366 tracking_value: 1,
367 car_position: 1,
368 car_moving_direction: 1, car_door_status: Vec::new(),
370 car_load: 0,
371 landing_doors: num_floors as u64,
372 floor_text,
373 energy_meter: 0.0,
374 status_flags: StatusFlags::empty(),
375 out_of_service: false,
376 reliability: 0,
377 })
378 }
379}
380
381impl BACnetObject for LiftObject {
382 fn object_identifier(&self) -> ObjectIdentifier {
383 self.oid
384 }
385
386 fn object_name(&self) -> &str {
387 &self.name
388 }
389
390 fn read_property(
391 &self,
392 property: PropertyIdentifier,
393 array_index: Option<u32>,
394 ) -> Result<PropertyValue, Error> {
395 if let Some(result) = read_common_properties!(self, property, array_index) {
396 return result;
397 }
398 match property {
399 p if p == PropertyIdentifier::OBJECT_TYPE => {
400 Ok(PropertyValue::Enumerated(ObjectType::LIFT.to_raw()))
401 }
402 p if p == PropertyIdentifier::TRACKING_VALUE => {
403 Ok(PropertyValue::Unsigned(self.tracking_value))
404 }
405 p if p == PropertyIdentifier::CAR_POSITION => {
406 Ok(PropertyValue::Unsigned(self.car_position))
407 }
408 p if p == PropertyIdentifier::CAR_MOVING_DIRECTION => {
409 Ok(PropertyValue::Enumerated(self.car_moving_direction))
410 }
411 p if p == PropertyIdentifier::CAR_DOOR_STATUS => {
412 let items: Vec<PropertyValue> = self
413 .car_door_status
414 .iter()
415 .map(|v| PropertyValue::Unsigned(*v))
416 .collect();
417 Ok(PropertyValue::List(items))
418 }
419 p if p == PropertyIdentifier::CAR_LOAD => Ok(PropertyValue::Unsigned(self.car_load)),
420 p if p == PropertyIdentifier::LANDING_DOOR_STATUS => {
421 Ok(PropertyValue::Unsigned(self.landing_doors))
422 }
423 p if p == PropertyIdentifier::FLOOR_TEXT => {
424 let items: Vec<PropertyValue> = self
425 .floor_text
426 .iter()
427 .map(|s| PropertyValue::CharacterString(s.clone()))
428 .collect();
429 Ok(PropertyValue::List(items))
430 }
431 p if p == PropertyIdentifier::ENERGY_METER => {
432 Ok(PropertyValue::Real(self.energy_meter))
433 }
434 p if p == PropertyIdentifier::FLOOR_NUMBER => {
435 Ok(PropertyValue::Unsigned(self.tracking_value))
436 }
437 _ => Err(common::unknown_property_error()),
438 }
439 }
440
441 fn write_property(
442 &mut self,
443 property: PropertyIdentifier,
444 _array_index: Option<u32>,
445 value: PropertyValue,
446 _priority: Option<u8>,
447 ) -> Result<(), Error> {
448 if let Some(result) =
449 common::write_out_of_service(&mut self.out_of_service, property, &value)
450 {
451 return result;
452 }
453 if let Some(result) = common::write_description(&mut self.description, property, &value) {
454 return result;
455 }
456 match property {
457 p if p == PropertyIdentifier::TRACKING_VALUE => {
458 if let PropertyValue::Unsigned(v) = value {
459 self.tracking_value = v;
460 Ok(())
461 } else {
462 Err(common::invalid_data_type_error())
463 }
464 }
465 p if p == PropertyIdentifier::CAR_POSITION => {
466 if let PropertyValue::Unsigned(v) = value {
467 self.car_position = v;
468 Ok(())
469 } else {
470 Err(common::invalid_data_type_error())
471 }
472 }
473 p if p == PropertyIdentifier::CAR_MOVING_DIRECTION => {
474 if let PropertyValue::Enumerated(v) = value {
475 if v > 3 {
476 return Err(common::value_out_of_range_error());
477 }
478 self.car_moving_direction = v;
479 Ok(())
480 } else {
481 Err(common::invalid_data_type_error())
482 }
483 }
484 p if p == PropertyIdentifier::CAR_LOAD => {
485 if let PropertyValue::Unsigned(v) = value {
486 if v > 100 {
487 return Err(common::value_out_of_range_error());
488 }
489 self.car_load = v;
490 Ok(())
491 } else {
492 Err(common::invalid_data_type_error())
493 }
494 }
495 _ => Err(common::write_access_denied_error()),
496 }
497 }
498
499 fn property_list(&self) -> Cow<'static, [PropertyIdentifier]> {
500 static PROPS: &[PropertyIdentifier] = &[
501 PropertyIdentifier::OBJECT_IDENTIFIER,
502 PropertyIdentifier::OBJECT_NAME,
503 PropertyIdentifier::DESCRIPTION,
504 PropertyIdentifier::OBJECT_TYPE,
505 PropertyIdentifier::TRACKING_VALUE,
506 PropertyIdentifier::CAR_POSITION,
507 PropertyIdentifier::CAR_MOVING_DIRECTION,
508 PropertyIdentifier::CAR_DOOR_STATUS,
509 PropertyIdentifier::CAR_LOAD,
510 PropertyIdentifier::LANDING_DOOR_STATUS,
511 PropertyIdentifier::FLOOR_TEXT,
512 PropertyIdentifier::ENERGY_METER,
513 PropertyIdentifier::STATUS_FLAGS,
514 PropertyIdentifier::OUT_OF_SERVICE,
515 PropertyIdentifier::RELIABILITY,
516 ];
517 Cow::Borrowed(PROPS)
518 }
519}
520
521#[cfg(test)]
526mod tests {
527 use super::*;
528
529 #[test]
532 fn elevator_group_create_and_read_defaults() {
533 let eg = ElevatorGroupObject::new(1, "EG-1").unwrap();
534 assert_eq!(eg.object_name(), "EG-1");
535 assert_eq!(
536 eg.read_property(PropertyIdentifier::GROUP_ID, None)
537 .unwrap(),
538 PropertyValue::Unsigned(0)
539 );
540 assert_eq!(
541 eg.read_property(PropertyIdentifier::GROUP_MEMBERS, None)
542 .unwrap(),
543 PropertyValue::List(vec![])
544 );
545 assert_eq!(
546 eg.read_property(PropertyIdentifier::GROUP_MODE, None)
547 .unwrap(),
548 PropertyValue::Enumerated(0) );
550 }
551
552 #[test]
553 fn elevator_group_object_type() {
554 let eg = ElevatorGroupObject::new(1, "EG-1").unwrap();
555 assert_eq!(
556 eg.read_property(PropertyIdentifier::OBJECT_TYPE, None)
557 .unwrap(),
558 PropertyValue::Enumerated(ObjectType::ELEVATOR_GROUP.to_raw())
559 );
560 }
561
562 #[test]
563 fn elevator_group_add_members() {
564 let mut eg = ElevatorGroupObject::new(1, "EG-1").unwrap();
565 let lift1 = ObjectIdentifier::new(ObjectType::LIFT, 1).unwrap();
566 let lift2 = ObjectIdentifier::new(ObjectType::LIFT, 2).unwrap();
567 eg.add_member(lift1);
568 eg.add_member(lift2);
569 assert_eq!(
570 eg.read_property(PropertyIdentifier::GROUP_MEMBERS, None)
571 .unwrap(),
572 PropertyValue::List(vec![
573 PropertyValue::ObjectIdentifier(lift1),
574 PropertyValue::ObjectIdentifier(lift2),
575 ])
576 );
577 }
578
579 #[test]
580 fn elevator_group_read_landing_calls() {
581 let eg = ElevatorGroupObject::new(1, "EG-1").unwrap();
582 assert_eq!(
583 eg.read_property(PropertyIdentifier::LANDING_CALLS, None)
584 .unwrap(),
585 PropertyValue::Unsigned(0)
586 );
587 }
588
589 #[test]
590 fn elevator_group_property_list() {
591 let eg = ElevatorGroupObject::new(1, "EG-1").unwrap();
592 let list = eg.property_list();
593 assert!(list.contains(&PropertyIdentifier::GROUP_ID));
594 assert!(list.contains(&PropertyIdentifier::GROUP_MEMBERS));
595 assert!(list.contains(&PropertyIdentifier::GROUP_MODE));
596 assert!(list.contains(&PropertyIdentifier::LANDING_CALLS));
597 assert!(list.contains(&PropertyIdentifier::LANDING_CALL_CONTROL));
598 assert!(list.contains(&PropertyIdentifier::STATUS_FLAGS));
599 }
600
601 #[test]
604 fn escalator_create_and_read_defaults() {
605 let esc = EscalatorObject::new(1, "ESC-1").unwrap();
606 assert_eq!(esc.object_name(), "ESC-1");
607 assert_eq!(
608 esc.read_property(PropertyIdentifier::ESCALATOR_MODE, None)
609 .unwrap(),
610 PropertyValue::Enumerated(0) );
612 assert_eq!(
613 esc.read_property(PropertyIdentifier::ENERGY_METER, None)
614 .unwrap(),
615 PropertyValue::Real(0.0)
616 );
617 assert_eq!(
618 esc.read_property(PropertyIdentifier::POWER_MODE, None)
619 .unwrap(),
620 PropertyValue::Boolean(false)
621 );
622 }
623
624 #[test]
625 fn escalator_object_type() {
626 let esc = EscalatorObject::new(1, "ESC-1").unwrap();
627 assert_eq!(
628 esc.read_property(PropertyIdentifier::OBJECT_TYPE, None)
629 .unwrap(),
630 PropertyValue::Enumerated(ObjectType::ESCALATOR.to_raw())
631 );
632 }
633
634 #[test]
635 fn escalator_read_operation_direction() {
636 let esc = EscalatorObject::new(1, "ESC-1").unwrap();
637 assert_eq!(
638 esc.read_property(PropertyIdentifier::OPERATION_DIRECTION, None)
639 .unwrap(),
640 PropertyValue::Enumerated(0) );
642 }
643
644 #[test]
645 fn escalator_read_fault_signals() {
646 let esc = EscalatorObject::new(1, "ESC-1").unwrap();
647 assert_eq!(
648 esc.read_property(PropertyIdentifier::FAULT_SIGNALS, None)
649 .unwrap(),
650 PropertyValue::List(vec![])
651 );
652 }
653
654 #[test]
655 fn escalator_property_list() {
656 let esc = EscalatorObject::new(1, "ESC-1").unwrap();
657 let list = esc.property_list();
658 assert!(list.contains(&PropertyIdentifier::ESCALATOR_MODE));
659 assert!(list.contains(&PropertyIdentifier::FAULT_SIGNALS));
660 assert!(list.contains(&PropertyIdentifier::ENERGY_METER));
661 assert!(list.contains(&PropertyIdentifier::ENERGY_METER_REF));
662 assert!(list.contains(&PropertyIdentifier::POWER_MODE));
663 assert!(list.contains(&PropertyIdentifier::OPERATION_DIRECTION));
664 assert!(list.contains(&PropertyIdentifier::STATUS_FLAGS));
665 }
666
667 #[test]
670 fn lift_create_and_read_defaults() {
671 let lift = LiftObject::new(1, "LIFT-1", 10).unwrap();
672 assert_eq!(lift.object_name(), "LIFT-1");
673 assert_eq!(
674 lift.read_property(PropertyIdentifier::TRACKING_VALUE, None)
675 .unwrap(),
676 PropertyValue::Unsigned(1)
677 );
678 assert_eq!(
679 lift.read_property(PropertyIdentifier::CAR_POSITION, None)
680 .unwrap(),
681 PropertyValue::Unsigned(1)
682 );
683 assert_eq!(
684 lift.read_property(PropertyIdentifier::CAR_MOVING_DIRECTION, None)
685 .unwrap(),
686 PropertyValue::Enumerated(1) );
688 }
689
690 #[test]
691 fn lift_object_type() {
692 let lift = LiftObject::new(1, "LIFT-1", 5).unwrap();
693 assert_eq!(
694 lift.read_property(PropertyIdentifier::OBJECT_TYPE, None)
695 .unwrap(),
696 PropertyValue::Enumerated(ObjectType::LIFT.to_raw())
697 );
698 }
699
700 #[test]
701 fn lift_floor_text() {
702 let lift = LiftObject::new(1, "LIFT-1", 3).unwrap();
703 assert_eq!(
704 lift.read_property(PropertyIdentifier::FLOOR_TEXT, None)
705 .unwrap(),
706 PropertyValue::List(vec![
707 PropertyValue::CharacterString("Floor 1".into()),
708 PropertyValue::CharacterString("Floor 2".into()),
709 PropertyValue::CharacterString("Floor 3".into()),
710 ])
711 );
712 }
713
714 #[test]
715 fn lift_read_car_load() {
716 let lift = LiftObject::new(1, "LIFT-1", 5).unwrap();
717 assert_eq!(
718 lift.read_property(PropertyIdentifier::CAR_LOAD, None)
719 .unwrap(),
720 PropertyValue::Unsigned(0)
721 );
722 }
723
724 #[test]
725 fn lift_write_tracking_value() {
726 let mut lift = LiftObject::new(1, "LIFT-1", 10).unwrap();
727 lift.write_property(
728 PropertyIdentifier::TRACKING_VALUE,
729 None,
730 PropertyValue::Unsigned(5),
731 None,
732 )
733 .unwrap();
734 assert_eq!(
735 lift.read_property(PropertyIdentifier::TRACKING_VALUE, None)
736 .unwrap(),
737 PropertyValue::Unsigned(5)
738 );
739 }
740
741 #[test]
742 fn lift_write_car_load_out_of_range() {
743 let mut lift = LiftObject::new(1, "LIFT-1", 5).unwrap();
744 let result = lift.write_property(
745 PropertyIdentifier::CAR_LOAD,
746 None,
747 PropertyValue::Unsigned(101),
748 None,
749 );
750 assert!(result.is_err());
751 }
752
753 #[test]
754 fn lift_read_landing_doors() {
755 let lift = LiftObject::new(1, "LIFT-1", 8).unwrap();
756 assert_eq!(
757 lift.read_property(PropertyIdentifier::LANDING_DOOR_STATUS, None)
758 .unwrap(),
759 PropertyValue::Unsigned(8)
760 );
761 }
762
763 #[test]
764 fn lift_read_energy_meter() {
765 let lift = LiftObject::new(1, "LIFT-1", 5).unwrap();
766 assert_eq!(
767 lift.read_property(PropertyIdentifier::ENERGY_METER, None)
768 .unwrap(),
769 PropertyValue::Real(0.0)
770 );
771 }
772
773 #[test]
774 fn lift_property_list() {
775 let lift = LiftObject::new(1, "LIFT-1", 5).unwrap();
776 let list = lift.property_list();
777 assert!(list.contains(&PropertyIdentifier::TRACKING_VALUE));
778 assert!(list.contains(&PropertyIdentifier::CAR_POSITION));
779 assert!(list.contains(&PropertyIdentifier::CAR_MOVING_DIRECTION));
780 assert!(list.contains(&PropertyIdentifier::CAR_DOOR_STATUS));
781 assert!(list.contains(&PropertyIdentifier::CAR_LOAD));
782 assert!(list.contains(&PropertyIdentifier::LANDING_DOOR_STATUS));
783 assert!(list.contains(&PropertyIdentifier::FLOOR_TEXT));
784 assert!(list.contains(&PropertyIdentifier::ENERGY_METER));
785 assert!(list.contains(&PropertyIdentifier::STATUS_FLAGS));
786 }
787}