Skip to main content

bacnet_objects/access_control/
credential.rs

1use super::*;
2
3// AccessCredentialObject (type 32)
4// ---------------------------------------------------------------------------
5
6/// BACnet Access Credential object (type 32).
7///
8/// Represents a credential (card, fob, biometric, etc.) used for access control.
9/// Present value indicates active/inactive status (BinaryPV).
10pub struct AccessCredentialObject {
11    oid: ObjectIdentifier,
12    name: String,
13    description: String,
14    present_value: u32, // BinaryPV: 0=inactive, 1=active
15    credential_status: u32,
16    assigned_access_rights_count: u32,
17    authentication_factors: Vec<Vec<u8>>,
18    status_flags: StatusFlags,
19    out_of_service: bool,
20    reliability: u32,
21}
22
23impl AccessCredentialObject {
24    /// Create a new Access Credential object.
25    pub fn new(instance: u32, name: impl Into<String>) -> Result<Self, Error> {
26        let oid = ObjectIdentifier::new(ObjectType::ACCESS_CREDENTIAL, instance)?;
27        Ok(Self {
28            oid,
29            name: name.into(),
30            description: String::new(),
31            present_value: 0, // inactive
32            credential_status: 0,
33            assigned_access_rights_count: 0,
34            authentication_factors: Vec::new(),
35            status_flags: StatusFlags::empty(),
36            out_of_service: false,
37            reliability: 0,
38        })
39    }
40}
41
42impl BACnetObject for AccessCredentialObject {
43    fn object_identifier(&self) -> ObjectIdentifier {
44        self.oid
45    }
46
47    fn object_name(&self) -> &str {
48        &self.name
49    }
50
51    fn read_property(
52        &self,
53        property: PropertyIdentifier,
54        array_index: Option<u32>,
55    ) -> Result<PropertyValue, Error> {
56        if let Some(result) = read_common_properties!(self, property, array_index) {
57            return result;
58        }
59        match property {
60            p if p == PropertyIdentifier::OBJECT_TYPE => Ok(PropertyValue::Enumerated(
61                ObjectType::ACCESS_CREDENTIAL.to_raw(),
62            )),
63            p if p == PropertyIdentifier::PRESENT_VALUE => {
64                Ok(PropertyValue::Enumerated(self.present_value))
65            }
66            p if p == PropertyIdentifier::CREDENTIAL_STATUS => {
67                Ok(PropertyValue::Enumerated(self.credential_status))
68            }
69            p if p == PropertyIdentifier::ASSIGNED_ACCESS_RIGHTS => Ok(PropertyValue::Unsigned(
70                self.assigned_access_rights_count as u64,
71            )),
72            p if p == PropertyIdentifier::AUTHENTICATION_FACTORS => Ok(PropertyValue::List(
73                self.authentication_factors
74                    .iter()
75                    .map(|f| PropertyValue::OctetString(f.clone()))
76                    .collect(),
77            )),
78            _ => Err(common::unknown_property_error()),
79        }
80    }
81
82    fn write_property(
83        &mut self,
84        property: PropertyIdentifier,
85        _array_index: Option<u32>,
86        value: PropertyValue,
87        _priority: Option<u8>,
88    ) -> Result<(), Error> {
89        if let Some(result) =
90            common::write_out_of_service(&mut self.out_of_service, property, &value)
91        {
92            return result;
93        }
94        if let Some(result) = common::write_description(&mut self.description, property, &value) {
95            return result;
96        }
97        match property {
98            p if p == PropertyIdentifier::PRESENT_VALUE => {
99                if let PropertyValue::Enumerated(v) = value {
100                    self.present_value = v;
101                    Ok(())
102                } else {
103                    Err(common::invalid_data_type_error())
104                }
105            }
106            p if p == PropertyIdentifier::CREDENTIAL_STATUS => {
107                if let PropertyValue::Enumerated(v) = value {
108                    self.credential_status = v;
109                    Ok(())
110                } else {
111                    Err(common::invalid_data_type_error())
112                }
113            }
114            _ => Err(common::write_access_denied_error()),
115        }
116    }
117
118    fn property_list(&self) -> Cow<'static, [PropertyIdentifier]> {
119        static PROPS: &[PropertyIdentifier] = &[
120            PropertyIdentifier::OBJECT_IDENTIFIER,
121            PropertyIdentifier::OBJECT_NAME,
122            PropertyIdentifier::DESCRIPTION,
123            PropertyIdentifier::OBJECT_TYPE,
124            PropertyIdentifier::PRESENT_VALUE,
125            PropertyIdentifier::CREDENTIAL_STATUS,
126            PropertyIdentifier::ASSIGNED_ACCESS_RIGHTS,
127            PropertyIdentifier::AUTHENTICATION_FACTORS,
128            PropertyIdentifier::STATUS_FLAGS,
129            PropertyIdentifier::OUT_OF_SERVICE,
130            PropertyIdentifier::RELIABILITY,
131        ];
132        Cow::Borrowed(PROPS)
133    }
134}
135
136// ---------------------------------------------------------------------------