hues/service/
thirdparty.rs

1use crate::{
2    api::HueAPIError,
3    command::{merge_commands, HomeKitCommand, MatterCommand},
4    service::{Bridge, ResourceIdentifier, ResourceType},
5};
6use serde::Deserialize;
7
8/// An Apple HomeKit device.
9#[derive(Debug)]
10pub struct HomeKit<'a> {
11    bridge: &'a Bridge,
12    data: HomeKitData,
13}
14
15impl<'a> HomeKit<'a> {
16    pub fn new(bridge: &'a Bridge, data: HomeKitData) -> Self {
17        HomeKit { bridge, data }
18    }
19
20    pub fn data(&self) -> &HomeKitData {
21        &self.data
22    }
23
24    pub fn id(&self) -> &str {
25        &self.data.id
26    }
27
28    pub fn rid(&self) -> ResourceIdentifier {
29        self.data.rid()
30    }
31
32    pub async fn send(
33        &self,
34        commands: &[HomeKitCommand],
35    ) -> Result<Vec<ResourceIdentifier>, HueAPIError> {
36        let payload = merge_commands(commands);
37        self.bridge.api.put_homekit(self.id(), &payload).await
38    }
39}
40
41/// Internal representation of a [HomeKit].
42#[derive(Clone, Debug, Deserialize)]
43pub struct HomeKitData {
44    /// Unique identifier representing a specific resource instance.
45    pub id: String,
46    /// Clip v1 resource identifier.
47    pub id_v1: Option<String>,
48    /// Read only field indicating whether homekit is already paired, currently open for pairing, or unpaired.
49
50    /// Transitions:
51    /// - [HomeKitStatus::Unpaired] to [HomeKitStatus::Pairing]: pushlink button press or power cycle.
52    /// - [HomeKitStatus::Pairing] to [HomeKitStatus::Paired]: through HAP.
53    /// - [HomeKitStatus::Pairing] to [HomeKitStatus::Unpaired]: >10 minutes spent attempting to pair.
54    /// - [HomeKitStatus::Paired] > [HomeKitStatus::Unpaired]: homekit reset.
55    pub status: HomeKitStatus,
56}
57
58impl HomeKitData {
59    pub fn rid(&self) -> ResourceIdentifier {
60        ResourceIdentifier {
61            rid: self.id.to_owned(),
62            rtype: ResourceType::HomeKit,
63        }
64    }
65}
66
67#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq)]
68#[serde(rename_all = "snake_case")]
69pub enum HomeKitStatus {
70    Paired,
71    Pairing,
72    Unpaired,
73}
74
75/// A virtual device representing interoperating
76/// [Matter](https://csa-iot.org/all-solutions/matter/) devices.
77#[derive(Debug)]
78pub struct Matter<'a> {
79    bridge: &'a Bridge,
80    data: MatterData,
81}
82
83impl<'a> Matter<'a> {
84    pub fn new(bridge: &'a Bridge, data: MatterData) -> Self {
85        Matter { bridge, data }
86    }
87
88    pub fn data(&self) -> &MatterData {
89        &self.data
90    }
91
92    pub fn id(&self) -> &str {
93        &self.data.id
94    }
95
96    pub fn rid(&self) -> ResourceIdentifier {
97        self.data.rid()
98    }
99
100    pub async fn send(
101        &self,
102        commands: &[MatterCommand],
103    ) -> Result<Vec<ResourceIdentifier>, HueAPIError> {
104        let payload = merge_commands(commands);
105        self.bridge.api.put_matter(self.id(), &payload).await
106    }
107}
108
109/// Internal representation of the [Matter] interop interface.
110#[derive(Clone, Debug, Deserialize)]
111pub struct MatterData {
112    /// Unique identifier representing a specific resource instance.
113    pub id: String,
114    /// Clip v1 resource identifier.
115    pub id_v1: Option<String>,
116    /// Maximum number of fabrics that can exist at a time.
117    pub max_fabrics: usize,
118    /// Indicates whether a physical QR code is present.
119    pub has_qr_code: bool,
120}
121
122impl MatterData {
123    pub fn rid(&self) -> ResourceIdentifier {
124        ResourceIdentifier {
125            rid: self.id.to_owned(),
126            rtype: ResourceType::Matter,
127        }
128    }
129}
130
131/// A virtual device representing the network of
132/// [Matter](https://csa-iot.org/all-solutions/matter/) devices.
133#[derive(Debug)]
134pub struct MatterFabric {
135    data: MatterFabricData,
136}
137
138impl MatterFabric {
139    pub fn new(data: MatterFabricData) -> Self {
140        MatterFabric { data }
141    }
142
143    pub fn data(&self) -> &MatterFabricData {
144        &self.data
145    }
146
147    pub fn id(&self) -> &str {
148        &self.data.id
149    }
150
151    pub fn rid(&self) -> ResourceIdentifier {
152        self.data.rid()
153    }
154}
155
156/// Internal representation of a [MatterFabric].
157#[derive(Clone, Debug, Deserialize)]
158pub struct MatterFabricData {
159    /// Unique identifier representing a specific resource instance.
160    pub id: String,
161    /// Clip v1 resource identifier.
162    pub id_v1: Option<String>,
163    /// Only a fabric with status [MatterFabricStatus::Paired] has some `fabric_data`.
164    pub status: MatterFabricStatus,
165    /// Human readable context to identify fabric.
166    pub fabric_data: Option<FabricData>,
167    /// UTC date and time when the fabric association was created.
168    pub creation_time: String,
169}
170
171impl MatterFabricData {
172    pub fn rid(&self) -> ResourceIdentifier {
173        ResourceIdentifier {
174            rid: self.id.to_owned(),
175            rtype: ResourceType::MatterFabric,
176        }
177    }
178}
179
180#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq)]
181#[serde(rename_all = "snake_case")]
182pub enum MatterFabricStatus {
183    Pending,
184    #[serde(rename = "timedout")]
185    TimedOut,
186    Paired,
187}
188
189#[derive(Clone, Debug, Deserialize)]
190pub struct FabricData {
191    pub label: String,
192    /// Matter vendor id of entity that created the fabric association.
193    pub vendor_id: usize,
194}