wled_json_api_library/
wled.rs

1use std::time::Duration;
2
3use reqwest;
4use reqwest::blocking::{Client, ClientBuilder, Response};
5use reqwest::Url;
6
7use crate::errors::WledJsonApiError;
8use crate::structures::cfg::Cfg;
9use crate::structures::effects::Effects;
10use crate::structures::info::Info;
11use crate::structures::live::Live;
12use crate::structures::net::Net;
13use crate::structures::nodes::Nodes;
14use crate::structures::palettes::Palettes;
15use crate::structures::state::State;
16
17
18
19#[derive(Debug)]
20pub struct Wled {
21    pub effects: Option<Effects>,
22    pub palettes: Option<Palettes>,
23    pub state: Option<State>,
24    pub info: Option<Info>,
25    pub cfg: Option<Cfg>,
26    pub live: Option<Live>,
27    pub nodes: Option<Nodes>,
28    pub net: Option<Net>,
29    pub client: Client, // should probably be private in most cases, but fuck you
30    pub url: Url,
31}
32
33impl Wled{
34
35
36    pub fn try_from_url(url: &Url) -> Result<Wled, WledJsonApiError> {
37        let temp_client: Client = ClientBuilder::new()
38            .gzip(true)
39            .timeout(Duration::from_millis(5000u64))
40            .build()
41            .map_err(|e|{WledJsonApiError::ReqwestError(e)})?;
42        let mut temp_url: Url = url.clone();
43        temp_url.set_path("json/cfg");
44        match temp_client
45            .get(temp_url.clone())
46            .send() {
47            Ok(a) if a.status() == reqwest::StatusCode::OK => {
48                Ok(Wled{
49                    effects: None,
50                    palettes: None,
51                    state: None,
52                    info: None,
53                    cfg: None,
54                    live: None,
55                    nodes: None,
56                    net: None,
57                    client: temp_client,
58                    url: temp_url,
59                })
60            }
61            Ok(o) => {Err(WledJsonApiError::HttpError(o.status()))}
62            Err(e) => {Err(WledJsonApiError::ReqwestError(e))}
63        }
64
65    }
66
67
68    pub fn flush_state(&self) -> Result<Response, WledJsonApiError> {
69
70        match &self.state{
71            Some(s) => {
72                let packet: String = s.try_into()?;
73
74                let mut temp_url = self.url.clone();
75                temp_url.set_path("json/state");
76
77                Ok(self.client.post(temp_url).body(packet).send()?)
78            }
79            None => Err(WledJsonApiError::FlushNone)
80        }
81    }
82
83
84    /// be careful with this, this library does not stop you from sending invalid and crazy configs.
85    /// as long as the feilds make sense it should work, but
86    pub fn flush_config(&self) -> Result<Response, WledJsonApiError> {
87
88        match &self.cfg{
89            Some(s) => {
90                let packet: String = s.try_into()?;
91
92                let mut temp_url = self.url.clone();
93                temp_url.set_path("json/cfg");
94
95                Ok(self.client.post(temp_url).body(packet).send()?)
96            }
97            None => Err(WledJsonApiError::FlushNone)
98        }
99    }
100
101    pub fn get_effects_from_wled(&mut self) -> Result<(), WledJsonApiError> {
102        let mut temp_url = self.url.clone();
103        temp_url.set_path("json/eff");
104        self.effects = Some(Effects::try_from(
105            &*self.client
106                .get(temp_url)
107                .header(reqwest::header::ACCEPT, "application/json")
108                .send()?
109                .text()?
110        )?);
111        Ok(())
112    }
113
114    pub fn get_info_from_wled(&mut self) -> Result<(), WledJsonApiError> {
115        let mut temp_url = self.url.clone();
116        temp_url.set_path("json/info");
117        self.info = Some(Info::try_from(
118            &*self.client
119                .get(temp_url)
120                .header(reqwest::header::ACCEPT, "application/json")
121                .send()?
122                .text()?
123        )?);
124        Ok(())
125    }
126
127    pub fn get_state_from_wled(&mut self) -> Result<(), WledJsonApiError> {
128        let mut temp_url = self.url.clone();
129        temp_url.set_path("json/state");
130        self.state = Some(State::try_from(
131            &*self.client
132                .get(temp_url)
133                .header(reqwest::header::ACCEPT, "application/json")
134                .send()?
135                .text()?
136        )?);
137        Ok(())
138    }
139
140    pub fn get_cfg_from_wled(&mut self) -> Result<(), WledJsonApiError> {
141        let mut temp_url = self.url.clone();
142        temp_url.set_path("json/cfg");
143        self.cfg = Some(Cfg::try_from(
144            &*self.client
145                .get(temp_url)
146                .header(reqwest::header::ACCEPT, "application/json")
147                .send()?
148                .text()?
149        )?);
150        Ok(())
151    }
152
153    pub fn get_net_from_wled(&mut self) -> Result<(), WledJsonApiError> {
154        let mut temp_url = self.url.clone();
155        temp_url.set_path("json/net");
156        self.net = Some(Net::try_from(
157            &*self.client
158                .get(temp_url)
159                .header(reqwest::header::ACCEPT, "application/json")
160                .send()?
161                .text()?
162        )?);
163        Ok(())
164    }
165
166    pub fn get_nodes_from_wled(&mut self) -> Result<(), WledJsonApiError> {
167        let mut temp_url = self.url.clone();
168        temp_url.set_path("json/nodes");
169        self.nodes = Some(Nodes::try_from(
170            &*self.client
171                .get(temp_url)
172                .header(reqwest::header::ACCEPT, "application/json")
173                .send()?
174                .text()?
175        )?);
176        Ok(())
177    }
178
179    pub fn get_palettes_from_wled(&mut self) -> Result<(), WledJsonApiError> {
180        let mut temp_url = self.url.clone();
181        temp_url.set_path("json/pal");
182        self.palettes = Some(Palettes::try_from(
183            &*self.client
184                .get(temp_url)
185                .header(reqwest::header::ACCEPT, "application/json")
186                .send()?
187                .text()?
188        )?);
189        Ok(())
190    }
191
192    pub fn get_live_from_wled(&mut self) -> Result<(), WledJsonApiError> {
193        let mut temp_url = self.url.clone();
194        temp_url.set_path("json/live");
195        self.live = Some(Live::try_from(
196            &*self.client
197                .get(temp_url)
198                .header(reqwest::header::ACCEPT, "application/json")
199                .send()?
200                .text()?
201        )?);
202        Ok(())
203    }
204}
205
206
207#[cfg(test)]
208mod tests {
209    use crate::structures::cfg::cfg_def::Def;
210    use super::*;
211
212    #[test]
213    fn it_works() {
214        // create the URL
215        let url: Url = Url::try_from("http://192.168.1.40/").unwrap();
216
217        // create the WLED connection
218        let mut wled: Wled = Wled::try_from_url(&url).unwrap();
219        println!("new wled: {wled:?}");
220
221        // turn off the WLED
222        {
223            // put the desired change in the internal state data member
224            wled.state = Some(State {
225                on: Some(true),
226                bri: None,
227                transition: None,
228                tt: None,
229                ps: None,
230                psave: None,
231                pl: None,
232                nl: None,
233                udpn: None,
234                v: None,
235                rb: None,
236                live: None,
237                lor: None,
238                time: None,
239                mainseg: None,
240                playlist: None,
241                seg: None,
242            });
243
244            // flush and print the server response
245            let response = wled.flush_state().unwrap();
246            println!("turning the thing off {:?}", response.text());
247        }
248
249
250        // fill internal cfg with result from WLED
251        wled.get_cfg_from_wled().unwrap();
252        wled.get_effects_from_wled().unwrap();
253        wled.get_live_from_wled().unwrap();
254        wled.get_net_from_wled().unwrap();
255        wled.get_nodes_from_wled().unwrap();
256        wled.get_palettes_from_wled().unwrap();
257        wled.get_state_from_wled().unwrap();
258        wled.get_info_from_wled().unwrap();
259    }
260}