homecore_hap/accessory.rs
1//! HAP service type and characteristic enum catalogues.
2//!
3//! Mirrors the HAP-1.1 service/characteristic namespace used by Apple Home
4//! and the `hap` crate (https://crates.io/crates/hap). Keeping these as
5//! plain Rust enums in P1 avoids the heavy `hap` dep until P2.
6
7use serde::{Deserialize, Serialize};
8
9/// HAP service types exposed by the RuView bridge.
10///
11/// Derived from HomeKit Accessory Protocol Specification §8 (service
12/// definitions) and cross-checked against HA's `homekit` integration
13/// service catalog.
14#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
15pub enum HapAccessoryType {
16 /// HAP `Lightbulb` service — maps `light.*` entities.
17 Lightbulb,
18 /// HAP `Switch` service — maps generic boolean `switch.*` entities.
19 Switch,
20 /// HAP `OccupancySensor` — maps presence / occupancy binary sensors.
21 OccupancySensor,
22 /// HAP `MotionSensor` — maps motion binary sensors + RuView motion.
23 MotionSensor,
24 /// HAP `TemperatureSensor` — maps `sensor.*temperature*` entities.
25 TemperatureSensor,
26 /// HAP `HumiditySensor` — maps `sensor.*humidity*` entities.
27 HumiditySensor,
28 /// HAP `LeakSensor` — maps abnormal event sensors; used for fall detection
29 /// following HA's homekit_controller convention (HAP §11.42).
30 LeakSensor,
31 /// HAP `ContactSensor` — maps door / window binary sensors.
32 ContactSensor,
33 /// HAP `Door` service — maps `cover.*door*` entities.
34 Door,
35 /// HAP `LockMechanism` service — maps `lock.*` entities.
36 Lock,
37 /// HAP `SecuritySystem` service — maps alarm / security panel entities.
38 SecuritySystem,
39}
40
41impl HapAccessoryType {
42 /// All defined variants — used in tests and for UI enumeration.
43 pub const ALL: &'static [HapAccessoryType] = &[
44 HapAccessoryType::Lightbulb,
45 HapAccessoryType::Switch,
46 HapAccessoryType::OccupancySensor,
47 HapAccessoryType::MotionSensor,
48 HapAccessoryType::TemperatureSensor,
49 HapAccessoryType::HumiditySensor,
50 HapAccessoryType::LeakSensor,
51 HapAccessoryType::ContactSensor,
52 HapAccessoryType::Door,
53 HapAccessoryType::Lock,
54 HapAccessoryType::SecuritySystem,
55 ];
56}
57
58/// HAP characteristic identifiers that the bridge reads or writes.
59///
60/// Each variant corresponds to one HAP characteristic UUID as specified in
61/// HomeKit Accessory Protocol Specification §9.
62#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
63pub enum HapCharacteristic {
64 /// `On` (bool) — Lightbulb / Switch power state.
65 On,
66 /// `Brightness` (uint8, 0–100) — Lightbulb brightness percentage.
67 Brightness,
68 /// `CurrentTemperature` (float, °C) — TemperatureSensor reading.
69 CurrentTemperature,
70 /// `CurrentRelativeHumidity` (float, %) — HumiditySensor reading.
71 CurrentRelativeHumidity,
72 /// `OccupancyDetected` (uint8, 0=not detected, 1=detected).
73 OccupancyDetected,
74 /// `MotionDetected` (bool).
75 MotionDetected,
76 /// `LeakDetected` (uint8, 0=no leak, 1=leak detected). Re-used for falls.
77 LeakDetected,
78 /// `ContactSensorState` (uint8, 0=in contact, 1=not in contact).
79 ContactSensorState,
80 /// `CurrentDoorState` (uint8, HAP §9.30).
81 CurrentDoorState,
82 /// `LockCurrentState` (uint8, HAP §9.56).
83 LockCurrentState,
84 /// `SecuritySystemCurrentState` (uint8, HAP §9.97).
85 SecuritySystemCurrentState,
86}
87
88/// Typed value carried by a HAP characteristic update.
89#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
90pub enum HapCharacteristicValue {
91 Bool(bool),
92 UInt8(u8),
93 Float(f64),
94}
95
96#[cfg(test)]
97mod tests {
98 use super::*;
99
100 #[test]
101 fn all_11_accessory_types_defined() {
102 assert_eq!(HapAccessoryType::ALL.len(), 11);
103 // Spot-check each variant is present.
104 assert!(HapAccessoryType::ALL.contains(&HapAccessoryType::Lightbulb));
105 assert!(HapAccessoryType::ALL.contains(&HapAccessoryType::Switch));
106 assert!(HapAccessoryType::ALL.contains(&HapAccessoryType::OccupancySensor));
107 assert!(HapAccessoryType::ALL.contains(&HapAccessoryType::MotionSensor));
108 assert!(HapAccessoryType::ALL.contains(&HapAccessoryType::TemperatureSensor));
109 assert!(HapAccessoryType::ALL.contains(&HapAccessoryType::HumiditySensor));
110 assert!(HapAccessoryType::ALL.contains(&HapAccessoryType::LeakSensor));
111 assert!(HapAccessoryType::ALL.contains(&HapAccessoryType::ContactSensor));
112 assert!(HapAccessoryType::ALL.contains(&HapAccessoryType::Door));
113 assert!(HapAccessoryType::ALL.contains(&HapAccessoryType::Lock));
114 assert!(HapAccessoryType::ALL.contains(&HapAccessoryType::SecuritySystem));
115 }
116
117 #[test]
118 fn characteristic_value_roundtrip_serde() {
119 let v = HapCharacteristicValue::Float(22.5);
120 let json = serde_json::to_string(&v).unwrap();
121 let back: HapCharacteristicValue = serde_json::from_str(&json).unwrap();
122 assert_eq!(v, back);
123 }
124}