Skip to main content

rustbac_client/
point.rs

1//! Point type inference for BACnet objects.
2//!
3//! Maps BACnet [`ObjectType`](rustbac_core::types::ObjectType) to a simplified
4//! classification useful for building automation integrations.
5
6use rustbac_core::types::ObjectType;
7
8/// The data kind of a BACnet point.
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub enum PointKind {
11    Analog,
12    Binary,
13    MultiState,
14    Accumulator,
15    Unknown,
16}
17
18/// Whether a BACnet point is an input, output, or value.
19#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub enum PointDirection {
21    Input,
22    Output,
23    Value,
24    Unknown,
25}
26
27/// A simplified classification of a BACnet object.
28#[derive(Debug, Clone, PartialEq, Eq)]
29pub struct PointClassification {
30    pub kind: PointKind,
31    pub direction: PointDirection,
32    /// `true` when the object type supports writing to its present-value.
33    pub writable: bool,
34}
35
36/// Classify a BACnet object type into a simplified point description.
37pub fn classify_point(object_type: ObjectType) -> PointClassification {
38    match object_type {
39        ObjectType::AnalogInput => PointClassification {
40            kind: PointKind::Analog,
41            direction: PointDirection::Input,
42            writable: false,
43        },
44        ObjectType::AnalogOutput => PointClassification {
45            kind: PointKind::Analog,
46            direction: PointDirection::Output,
47            writable: true,
48        },
49        ObjectType::AnalogValue => PointClassification {
50            kind: PointKind::Analog,
51            direction: PointDirection::Value,
52            writable: true,
53        },
54        ObjectType::BinaryInput => PointClassification {
55            kind: PointKind::Binary,
56            direction: PointDirection::Input,
57            writable: false,
58        },
59        ObjectType::BinaryOutput => PointClassification {
60            kind: PointKind::Binary,
61            direction: PointDirection::Output,
62            writable: true,
63        },
64        ObjectType::BinaryValue => PointClassification {
65            kind: PointKind::Binary,
66            direction: PointDirection::Value,
67            writable: true,
68        },
69        ObjectType::MultiStateInput => PointClassification {
70            kind: PointKind::MultiState,
71            direction: PointDirection::Input,
72            writable: false,
73        },
74        ObjectType::MultiStateOutput => PointClassification {
75            kind: PointKind::MultiState,
76            direction: PointDirection::Output,
77            writable: true,
78        },
79        ObjectType::MultiStateValue => PointClassification {
80            kind: PointKind::MultiState,
81            direction: PointDirection::Value,
82            writable: true,
83        },
84        ObjectType::Accumulator => PointClassification {
85            kind: PointKind::Accumulator,
86            direction: PointDirection::Input,
87            writable: false,
88        },
89        ObjectType::PulseConverter => PointClassification {
90            kind: PointKind::Accumulator,
91            direction: PointDirection::Value,
92            writable: true,
93        },
94        _ => PointClassification {
95            kind: PointKind::Unknown,
96            direction: PointDirection::Unknown,
97            writable: false,
98        },
99    }
100}
101
102#[cfg(test)]
103mod tests {
104    use super::*;
105
106    #[test]
107    fn classify_analog_io() {
108        let c = classify_point(ObjectType::AnalogInput);
109        assert_eq!(c.kind, PointKind::Analog);
110        assert_eq!(c.direction, PointDirection::Input);
111        assert!(!c.writable);
112
113        let c = classify_point(ObjectType::AnalogOutput);
114        assert_eq!(c.kind, PointKind::Analog);
115        assert_eq!(c.direction, PointDirection::Output);
116        assert!(c.writable);
117
118        let c = classify_point(ObjectType::AnalogValue);
119        assert_eq!(c.kind, PointKind::Analog);
120        assert_eq!(c.direction, PointDirection::Value);
121        assert!(c.writable);
122    }
123
124    #[test]
125    fn classify_binary_io() {
126        let c = classify_point(ObjectType::BinaryInput);
127        assert_eq!(c.kind, PointKind::Binary);
128        assert!(!c.writable);
129
130        let c = classify_point(ObjectType::BinaryOutput);
131        assert_eq!(c.kind, PointKind::Binary);
132        assert!(c.writable);
133    }
134
135    #[test]
136    fn classify_multistate() {
137        let c = classify_point(ObjectType::MultiStateInput);
138        assert_eq!(c.kind, PointKind::MultiState);
139        assert_eq!(c.direction, PointDirection::Input);
140
141        let c = classify_point(ObjectType::MultiStateOutput);
142        assert_eq!(c.kind, PointKind::MultiState);
143        assert!(c.writable);
144    }
145
146    #[test]
147    fn classify_accumulator() {
148        let c = classify_point(ObjectType::Accumulator);
149        assert_eq!(c.kind, PointKind::Accumulator);
150        assert!(!c.writable);
151
152        let c = classify_point(ObjectType::PulseConverter);
153        assert_eq!(c.kind, PointKind::Accumulator);
154        assert!(c.writable);
155    }
156
157    #[test]
158    fn classify_unknown() {
159        let c = classify_point(ObjectType::Device);
160        assert_eq!(c.kind, PointKind::Unknown);
161        assert_eq!(c.direction, PointDirection::Unknown);
162        assert!(!c.writable);
163    }
164}