govee_api/api/
api.rs

1use reqwest::Error as ReqwestError;
2use reqwest::{Client, Url};
3use serde_json::json;
4
5use crate::{
6    structs::govee::{
7        ApiResponseGoveeAppliances, ApiResponseGoveeDeviceState, ApiResponseGoveeDevices,
8        PayloadBody,
9    },
10    GoveeClient, GOVEE_ROOT_URL,
11};
12
13// ------------------------
14// Methods for the Govee API
15// ------------------------
16//
17
18/// Control a Govee device using the provided payload.
19///
20/// This method sends a PUT request to the Govee API's control endpoint in order to control a Govee device.
21///
22/// # Arguments
23///
24/// * `payload` - The payload containing control instructions for the device.
25///
26/// # Returns
27///
28/// Returns `Ok(())` if the request is successful. Otherwise, returns a `ReqwestError` indicating the failure
29impl GoveeClient {
30    pub async fn control_device(&self, payload: PayloadBody) -> Result<(), ReqwestError> {
31        let client = Client::new();
32        let payload_json = json!(payload);
33        let endpoint = format!("{}/v1/devices/control", &self.govee_root_url);
34        let result = client
35            .put(endpoint)
36            .header("Govee-API-Key", &self.govee_api_key.to_string())
37            .json(&payload_json)
38            .send()
39            .await;
40        match result {
41            Ok(res) => res,
42            Err(err) => return Err(err),
43        };
44        Ok(())
45    }
46}
47
48/// Asynchronously controls multiple devices by sending payloads to the Govee API.
49///
50/// This method takes a vector of `PayloadBody` objects and sends control requests to the Govee API
51/// for each payload asynchronously. It uses the provided `self.govee_api_key` and `self.govee_root_url`
52/// to construct the API endpoint for each request.
53///
54/// # Arguments
55///
56/// - `payloads`: A vector of `PayloadBody` objects representing the control payloads for the devices.
57///
58/// # Returns
59///
60/// Returns a `Result` indicating success or an error that occurred during the requests.
61///
62/// # Examples
63///
64/// let govee_client = GoveeClient::new("your_api_key", "https://api.govee.com");
65/// let payloads = vec![payload1, payload2];
66/// let result = govee_client.bulk_control_devices(payloads).await;
67/// match result {
68///     Ok(_) => println!("Devices controlled successfully"),
69///     Err(err) => eprintln!("Error controlling devices: {:?}", err),
70/// }
71///
72impl GoveeClient {
73    pub async fn bulk_control_devices(
74        &self,
75        payloads: Vec<PayloadBody>,
76    ) -> Result<(), ReqwestError> {
77        let client = Client::new();
78        let endpoint = format!("{}/v1/devices/control", &self.govee_root_url);
79        let requests = payloads
80            .iter()
81            .map(|payload| {
82                let payload_json = json!(payload);
83                let endpoint = endpoint.clone();
84                let govee_api_key = self.govee_api_key.to_string();
85                let client = client.clone();
86                async move {
87                    client
88                        .put(&endpoint)
89                        .header("Govee-API-Key", &govee_api_key)
90                        .json(&payload_json)
91                        .send()
92                        .await
93                }
94            })
95            .collect::<Vec<_>>();
96        let results = futures::future::join_all(requests).await;
97        for result in results {
98            match result {
99                Ok(_) => (),
100                Err(err) => return Err(err),
101            }
102        }
103        Ok(())
104    }
105}
106
107/// Controls a Govee appliance using the provided payload.
108///
109/// This method sends a PUT request to the Govee API to control an appliance
110/// with the specified payload. The payload should be in the form of a PayloadBody struct.
111///
112/// # Arguments
113///
114/// * `payload` - The payload containing the control instructions for the appliance.
115///
116/// # Returns
117///
118/// Returns `Ok(())` if the request is successful. Otherwise, returns a `ReqwestError` indicating the failure
119impl GoveeClient {
120    pub async fn control_appliance(&self, payload: PayloadBody) -> Result<(), ReqwestError> {
121        let client = Client::new();
122        let payload_json = json!(payload);
123        let endpoint = format!("{}/v1/appliance/devices/control", GOVEE_ROOT_URL);
124        let result = client
125            .put(endpoint)
126            .header("Govee-API-Key", &self.govee_api_key)
127            .json(&payload_json)
128            .send()
129            .await;
130        match result {
131            Ok(res) => res,
132            Err(err) => return Err(err),
133        };
134        Ok(())
135    }
136}
137
138/// Retrieves a list of Govee devices.
139///
140/// This method sends a GET request to the Govee API to retrieve a list of devices
141/// associated with the Govee account.
142///
143/// # Returns
144///
145/// An `ApiResponseGoveeDevices` containing information about the devices.
146///
147/// # Returns
148///
149/// Returns `Ok(())` if the request is successful. Otherwise, returns a `ReqwestError` indicating the failure
150impl GoveeClient {
151    pub async fn get_devices(&self) -> Result<ApiResponseGoveeDevices, ReqwestError> {
152        let client = Client::new();
153        let endpoint = format!("{}/v1/devices", GOVEE_ROOT_URL);
154        let response = client
155            .get(endpoint)
156            .header("Govee-API-Key", &self.govee_api_key)
157            .send()
158            .await?;
159        let response_json = response.json::<ApiResponseGoveeDevices>().await?;
160        Ok(response_json)
161    }
162}
163
164/// Retrieves a list of Govee appliances.
165///
166/// This method sends a GET request to the Govee API to retrieve a list of appliances
167/// associated with the Govee account.
168///
169/// # Returns
170///
171/// An `ApiResponseGoveeAppliances` containing information about the appliances.
172///
173/// # Returns
174///
175/// Returns `Ok(())` if the request is successful. Otherwise, returns a `ReqwestError` indicating the failure
176impl GoveeClient {
177    pub async fn get_appliances(&self) -> Result<ApiResponseGoveeAppliances, ReqwestError> {
178        let client = Client::new();
179        let endpoint = format!("{}/v1/appliance/devices", GOVEE_ROOT_URL);
180        let response = client
181            .get(endpoint)
182            .header("Govee-API-Key", &self.govee_api_key)
183            .send()
184            .await?;
185        let response_json = response.json::<ApiResponseGoveeAppliances>().await?;
186        Ok(response_json)
187    }
188}
189
190/// Retrieves the state of a Govee device.
191///
192/// This method sends a GET request to the Govee API to retrieve the state of a specific device.
193///
194/// # Arguments
195///
196/// * `device` - The device ID or name.
197/// * `model` - The model of the device.
198///
199/// # Returns
200///
201/// An `ApiResponseGoveeDeviceState` containing the current state of the device.
202///
203/// # Returns
204///
205/// Returns `Ok(())` if the request is successful. Otherwise, returns a `ReqwestError` indicating the failure
206impl GoveeClient {
207    pub async fn get_device_state(
208        &self,
209        device: &str,
210        model: &str,
211    ) -> Result<ApiResponseGoveeDeviceState, ReqwestError> {
212        let client = Client::new();
213        let params = [("device", device), ("model", model)];
214        let endpoint = format!("{}/v1/devices/state", GOVEE_ROOT_URL);
215        let url = Url::parse_with_params(&endpoint, &params).unwrap();
216        let response = client
217            .get(url)
218            .header("Govee-API-Key", &self.govee_api_key)
219            .send()
220            .await?;
221        let response_json = response
222            .json::<ApiResponseGoveeDeviceState>()
223            .await
224            .unwrap();
225        Ok(response_json)
226    }
227}