Skip to main content

bacnet_objects/access_control/
zone.rs

1use super::*;
2
3// AccessZoneObject (type 36)
4// ---------------------------------------------------------------------------
5
6/// BACnet Access Zone object (type 36).
7///
8/// Represents a physical zone or area controlled by access points.
9/// Present value indicates the occupancy state (AccessZoneOccupancyState).
10pub struct AccessZoneObject {
11    oid: ObjectIdentifier,
12    name: String,
13    description: String,
14    present_value: u32, // AccessZoneOccupancyState enumeration
15    global_identifier: u64,
16    occupancy_count: u64,
17    access_doors: Vec<ObjectIdentifier>,
18    entry_points: Vec<ObjectIdentifier>,
19    exit_points: Vec<ObjectIdentifier>,
20    status_flags: StatusFlags,
21    out_of_service: bool,
22    reliability: u32,
23}
24
25impl AccessZoneObject {
26    /// Create a new Access Zone object.
27    pub fn new(instance: u32, name: impl Into<String>) -> Result<Self, Error> {
28        let oid = ObjectIdentifier::new(ObjectType::ACCESS_ZONE, instance)?;
29        Ok(Self {
30            oid,
31            name: name.into(),
32            description: String::new(),
33            present_value: 0,
34            global_identifier: 0,
35            occupancy_count: 0,
36            access_doors: Vec::new(),
37            entry_points: Vec::new(),
38            exit_points: Vec::new(),
39            status_flags: StatusFlags::empty(),
40            out_of_service: false,
41            reliability: 0,
42        })
43    }
44}
45
46impl BACnetObject for AccessZoneObject {
47    fn object_identifier(&self) -> ObjectIdentifier {
48        self.oid
49    }
50
51    fn object_name(&self) -> &str {
52        &self.name
53    }
54
55    fn read_property(
56        &self,
57        property: PropertyIdentifier,
58        array_index: Option<u32>,
59    ) -> Result<PropertyValue, Error> {
60        if let Some(result) = read_common_properties!(self, property, array_index) {
61            return result;
62        }
63        match property {
64            p if p == PropertyIdentifier::OBJECT_TYPE => {
65                Ok(PropertyValue::Enumerated(ObjectType::ACCESS_ZONE.to_raw()))
66            }
67            p if p == PropertyIdentifier::PRESENT_VALUE => {
68                Ok(PropertyValue::Enumerated(self.present_value))
69            }
70            p if p == PropertyIdentifier::GLOBAL_IDENTIFIER => {
71                Ok(PropertyValue::Unsigned(self.global_identifier))
72            }
73            p if p == PropertyIdentifier::OCCUPANCY_COUNT => {
74                Ok(PropertyValue::Unsigned(self.occupancy_count))
75            }
76            p if p == PropertyIdentifier::ACCESS_DOORS => Ok(PropertyValue::List(
77                self.access_doors
78                    .iter()
79                    .map(|oid| PropertyValue::ObjectIdentifier(*oid))
80                    .collect(),
81            )),
82            p if p == PropertyIdentifier::ENTRY_POINTS => Ok(PropertyValue::List(
83                self.entry_points
84                    .iter()
85                    .map(|oid| PropertyValue::ObjectIdentifier(*oid))
86                    .collect(),
87            )),
88            p if p == PropertyIdentifier::EXIT_POINTS => Ok(PropertyValue::List(
89                self.exit_points
90                    .iter()
91                    .map(|oid| PropertyValue::ObjectIdentifier(*oid))
92                    .collect(),
93            )),
94            _ => Err(common::unknown_property_error()),
95        }
96    }
97
98    fn write_property(
99        &mut self,
100        property: PropertyIdentifier,
101        _array_index: Option<u32>,
102        value: PropertyValue,
103        _priority: Option<u8>,
104    ) -> Result<(), Error> {
105        if let Some(result) =
106            common::write_out_of_service(&mut self.out_of_service, property, &value)
107        {
108            return result;
109        }
110        if let Some(result) = common::write_description(&mut self.description, property, &value) {
111            return result;
112        }
113        match property {
114            p if p == PropertyIdentifier::PRESENT_VALUE => {
115                if let PropertyValue::Enumerated(v) = value {
116                    self.present_value = v;
117                    Ok(())
118                } else {
119                    Err(common::invalid_data_type_error())
120                }
121            }
122            p if p == PropertyIdentifier::GLOBAL_IDENTIFIER => {
123                if let PropertyValue::Unsigned(v) = value {
124                    self.global_identifier = v;
125                    Ok(())
126                } else {
127                    Err(common::invalid_data_type_error())
128                }
129            }
130            _ => Err(common::write_access_denied_error()),
131        }
132    }
133
134    fn property_list(&self) -> Cow<'static, [PropertyIdentifier]> {
135        static PROPS: &[PropertyIdentifier] = &[
136            PropertyIdentifier::OBJECT_IDENTIFIER,
137            PropertyIdentifier::OBJECT_NAME,
138            PropertyIdentifier::DESCRIPTION,
139            PropertyIdentifier::OBJECT_TYPE,
140            PropertyIdentifier::PRESENT_VALUE,
141            PropertyIdentifier::GLOBAL_IDENTIFIER,
142            PropertyIdentifier::OCCUPANCY_COUNT,
143            PropertyIdentifier::ACCESS_DOORS,
144            PropertyIdentifier::ENTRY_POINTS,
145            PropertyIdentifier::EXIT_POINTS,
146            PropertyIdentifier::STATUS_FLAGS,
147            PropertyIdentifier::OUT_OF_SERVICE,
148            PropertyIdentifier::RELIABILITY,
149        ];
150        Cow::Borrowed(PROPS)
151    }
152}
153
154// ---------------------------------------------------------------------------