1use std::sync::Arc;
2
3use anyhow::Result;
4use serde::{de, Deserialize, Serialize};
5use serde_json::json;
6use serde_repr::{Deserialize_repr, Serialize_repr};
7
8use crate::gateway::Gateway;
9
10#[derive(Debug, Clone, Serialize, Deserialize)]
11pub enum BulbTemperature {
12 #[serde(rename = "f5faf6")]
13 White,
14 #[serde(rename = "f1e0b5")]
15 Warm,
16 #[serde(rename = "efd275")]
17 Glow,
18}
19
20#[derive(Clone, Debug, Serialize_repr, Deserialize_repr)]
21#[repr(u8)]
22pub enum DeviceState {
23 On = 1,
24 Off = 0,
25}
26
27#[derive(Clone, Debug, Serialize, Deserialize)]
28pub struct BulbData {
29 #[serde(rename = "5850")]
30 pub status: DeviceState,
31 #[serde(rename = "5706")]
32 pub temperature: BulbTemperature,
33}
34
35#[derive(Debug, Serialize, Deserialize)]
36pub struct Device<'a> {
37 #[serde(rename = "9003")]
38 pub id: u64,
39 #[serde(rename = "9001")]
40 pub name: String,
41 #[serde(deserialize_with = "flatten_bulb_data")]
42 #[serde(rename = "3311")]
43 pub data: BulbData,
44 #[serde(skip)]
45 gateway: Option<Arc<&'a Gateway>>,
46}
47
48impl<'a> Device<'a> {
49 pub(crate) fn set_gateway(&mut self, gateway: Arc<&'a Gateway>) {
50 self.gateway = Some(Arc::clone(&gateway))
51 }
52
53 pub fn turn_on(&self) -> Result<()> {
54 self.modify(BulbData {
55 status: DeviceState::On,
56 ..self.data.clone()
57 })
58 }
59
60 pub fn turn_off(&self) -> Result<()> {
61 self.modify(BulbData {
62 status: DeviceState::Off,
63 ..self.data.clone()
64 })
65 }
66
67 fn modify(&self, data: BulbData) -> Result<()> {
68 let gateway = self.gateway.clone().unwrap();
69 let gateway = gateway.as_ref();
70
71 let res = gateway.set_device_state(self.id, json!({ "3311": [data] }));
72
73 res
74 }
75}
76
77fn flatten_bulb_data<'de, D>(deserializer: D) -> Result<BulbData, D::Error>
78where
79 D: de::Deserializer<'de>,
80{
81 let vec: Vec<serde_json::Value> = de::Deserialize::deserialize(deserializer)?;
82 let value = vec.into_iter().nth(0).unwrap();
83 serde_json::from_value(value).map_err(de::Error::custom)
84}