wled_json_api_library/structures/
state.rs

1use serde;
2use serde::{Serialize, Deserialize};
3use crate::errors::WledJsonApiError;
4use crate::structures::none_function;
5
6
7#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
8#[serde(rename_all = "camelCase")]
9pub struct State {
10    /// On/Off state of the light
11    #[serde(skip_serializing_if = "Option::is_none")]
12    #[serde(default = "none_function")]
13    pub on: Option<bool>,
14
15    /// Brightness of the light. If on is false, contains last brightness when light was on (aka brightness when on is set to true. Setting bri to 0 is supported but it is recommended to use the range 1-255 and use on: false to turn off. The state response will never have the value 0 for bri.
16    #[serde(skip_serializing_if = "Option::is_none")]
17    #[serde(default = "none_function")]
18    pub bri: Option<u8>,
19
20    /// Duration of the crossfade between different colors/brightness levels. One unit is 100ms, so a value of 4 results in a transition of 400ms.
21    #[serde(skip_serializing_if = "Option::is_none")]
22    #[serde(default = "none_function")]
23    pub transition: Option<u8>,
24
25    /// Similar to transition, but applies to just the current API call. Not included in state response.
26    #[serde(skip_serializing_if = "Option::is_none")]
27    #[serde(default = "none_function")]
28    pub tt: Option<u8>,
29
30    /// -1 to 65535; ID of currently set preset. 1~17~ can be used to iterate through presets 1-17.
31    #[serde(skip_serializing_if = "Option::is_none")]
32    #[serde(default = "none_function")]
33    pub ps: Option<i32>,
34
35    /// 1 to 16 (250 in 0.11); Save current light config to specified preset slot. Not included in state response.
36    #[serde(skip_serializing_if = "Option::is_none")]
37    #[serde(default = "none_function")]
38    pub psave: Option<u8>,
39
40    /// -1 to 0; 	ID of currently set playlist. For now, this sets the preset cycle feature, -1 is off and 0 is on.
41    #[serde(skip_serializing_if = "Option::is_none")]
42    #[serde(default = "none_function")]
43    pub pl: Option<i8>,
44
45    /// Night light
46    #[serde(skip_serializing_if = "Option::is_none")]
47    #[serde(default = "none_function")]
48    pub nl: Option<Nl>,
49
50    /// UDP sync
51    #[serde(skip_serializing_if = "Option::is_none")]
52    #[serde(default = "none_function")]
53    pub udpn: Option<Udpn>,
54
55    /// If set to true in a JSON POST command, the response will contain the full JSON state object. Not included in state response
56    #[serde(skip_serializing_if = "Option::is_none")]
57    #[serde(default = "none_function")]
58    pub v: Option<bool>,
59
60    /// If set to true, device will reboot immediately. Not included in state response.
61    #[serde(skip_serializing_if = "Option::is_none")]
62    #[serde(default = "none_function")]
63    pub rb: Option<bool>,
64
65    /// If set to true, enters realtime mode and blanks the LEDs. The realtime timeout option does not have an effect when this command is used, WLED will stay in realtime mode until the state (color/effect/segments, excluding brightness) is changed. It is expected that {"live":false} is sent once live data sending is terminated. Not included in state response.
66    #[serde(skip_serializing_if = "Option::is_none")]
67    #[serde(default = "none_function")]
68    pub live: Option<bool>,
69
70    /// 0, 1, or 2; Live data override. 0 is off, 1 is override until live data ends, 2 is override until ESP reboot (available since 0.10.0)
71    #[serde(skip_serializing_if = "Option::is_none")]
72    #[serde(default = "none_function")]
73    pub lor: Option<u8>,
74
75    /// Set module time to unix timestamp. Not included in state response.
76    #[serde(skip_serializing_if = "Option::is_none")]
77    #[serde(default = "none_function")]
78    pub time: Option<u32>,
79
80    /// 0 to info.leds.maxseg-1; Main Segment
81    #[serde(skip_serializing_if = "Option::is_none")]
82    #[serde(default = "none_function")]
83    pub mainseg: Option<u8>,
84
85    /// Custom preset playlists. Not included in state response (available since 0.11.0)
86    #[serde(skip_serializing_if = "Option::is_none")]
87    #[serde(default = "none_function")]
88    pub playlist: Option<Playlist>,
89
90    /// Array of segment objects; Segments are individual parts of the LED strip. In 0.9.0 this will enables running different effects on differentparts of the strip.
91    #[serde(skip_serializing_if = "Option::is_none")]
92    #[serde(default = "none_function")]
93    pub seg: Option<Vec<Seg>>,
94}
95
96
97impl TryInto<String> for &State{
98    type Error = WledJsonApiError;
99    fn try_into(self) -> Result<String, WledJsonApiError> {
100        serde_json::to_string(self).map_err(|e| {WledJsonApiError::SerdeError(e)})
101    }
102}
103
104impl TryFrom<&str> for State{
105    type Error = WledJsonApiError;
106    fn try_from(str_in: &str) -> Result<State, WledJsonApiError> {
107        serde_json::from_str(str_in).map_err(|e| {WledJsonApiError::SerdeError(e)})
108    }
109}
110
111
112
113#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
114#[serde(rename_all = "camelCase")]
115pub struct Nl {
116    /// Nightlight currently active
117    #[serde(skip_serializing_if = "Option::is_none")]
118    #[serde(default = "none_function")]
119    pub on: Option<bool>,
120
121    /// Duration of nightlight in minutes
122    #[serde(skip_serializing_if = "Option::is_none")]
123    #[serde(default = "none_function")]
124    pub dur: Option<u8>,
125
126    /// If true, the light will gradually dim over the course of the nightlight duration. If false, it will instantly turn to the target brightness once the duration has elapsed. Removed in 0.13.0 (use mode instead)
127    #[serde(skip_serializing_if = "Option::is_none")]
128    #[serde(default = "none_function")]
129    pub fade: Option<bool>,
130
131    /// 0 to 3; Nightlight mode (0: instant, 1: fade, 2: color fade, 3: sunrise) (available since 0.10.2)
132    #[serde(skip_serializing_if = "Option::is_none")]
133    #[serde(default = "none_function")]
134    pub mode: Option<u8>,
135
136    /// Target brightness of nightlight feature
137    #[serde(skip_serializing_if = "Option::is_none")]
138    #[serde(default = "none_function")]
139    pub tbri: Option<u8>,
140
141    /// -1 to 15300; Remaining nightlight duration in seconds, -1 if not active. Only in state response, can not be set.
142    #[serde(skip_serializing)]
143    #[serde(default = "none_function")]
144    pub rem: Option<i16>,
145}
146
147
148#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
149#[serde(rename_all = "camelCase")]
150pub struct Udpn {
151
152    /// Send WLED broadcast (UDP sync) packet on state change
153    #[serde(skip_serializing_if = "Option::is_none")]
154    #[serde(default = "none_function")]
155    pub send: Option<bool>,
156
157    /// Receive broadcast packets
158    #[serde(skip_serializing_if = "Option::is_none")]
159    #[serde(default = "none_function")]
160    pub recv: Option<bool>,
161
162    /// Bitfield for broadcast send groups 1-8
163    #[serde(skip_serializing_if = "Option::is_none")]
164    #[serde(default = "none_function")]
165    pub sgrp: Option<u8>,
166
167    /// Bitfield for broadcast receive groups 1-8
168    #[serde(skip_serializing_if = "Option::is_none")]
169    #[serde(default = "none_function")]
170    pub rgrp: Option<u8>,
171
172    /// Don't send a broadcast packet (applies to just the current API call). Not included in state response.
173    #[serde(skip_serializing_if = "Option::is_none")]
174    #[serde(default = "none_function")]
175    pub nn: Option<bool>,
176}
177
178#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
179#[serde(rename_all = "camelCase")]
180pub struct Seg {
181    /// -1 to info.maxseg -1; Zero-indexed ID of the segment. May be omitted, in that case the ID will be inferred from the order of the segment objects in the seg array. -1 means apply to all selected segments
182    #[serde(skip_serializing_if = "Option::is_none")]
183    #[serde(default = "none_function")]
184    pub id: Option<i16>,
185
186    /// 0 to info.leds.count -1; LED the segment starts at.
187    #[serde(skip_serializing_if = "Option::is_none")]
188    #[serde(default = "none_function")]
189    pub start: Option<u16>,
190
191    /// 0 to info.leds.count; LED the segment stops at, not included in range. If stop is set to a lower or equal value than start (setting to 0 is recommended), the segment is invalidated and deleted.
192    #[serde(skip_serializing_if = "Option::is_none")]
193    #[serde(default = "none_function")]
194    pub stop: Option<u16>,
195
196    /// 0 to info.leds.count; Length of the segment (stop - start). stop has preference, so if it is included, len is ignored.
197    #[serde(skip_serializing)] // this feild is ignored if stop is sent, so don't risk sending bad shit
198    #[serde(default = "none_function")]
199    pub len: Option<u16>,
200
201    /// Grouping (how many consecutive LEDs of the same segment will be grouped to the same color)
202    #[serde(skip_serializing_if = "Option::is_none")]
203    #[serde(default = "none_function")]
204    pub grp: Option<u8>,
205
206    /// Spacing (how many LEDs are turned off and skipped between each group)
207    #[serde(skip_serializing_if = "Option::is_none")]
208    #[serde(default = "none_function")]
209    pub spc: Option<u8>,
210
211    /// -len+1 to len; 	Offset (how many LEDs to rotate the virtual start of the segments, available since 0.13.0)
212    #[serde(skip_serializing_if = "Option::is_none")]
213    #[serde(default = "none_function")]
214    pub of: Option<i16>,
215
216    /// Turns on and off the individual segment. (available since 0.10.0)
217    #[serde(skip_serializing_if = "Option::is_none")]
218    #[serde(default = "none_function")]
219    pub on: Option<bool>,
220
221    /// freezes/unfreezes the current effect
222    #[serde(skip_serializing_if = "Option::is_none")]
223    #[serde(default = "none_function")]
224    pub frz: Option<bool>,
225
226    /// Sets the individual segment brightness (available since 0.10.0)
227    #[serde(skip_serializing_if = "Option::is_none")]
228    #[serde(default = "none_function")]
229    pub bri: Option<u8>,
230
231    /// 0 to 255 or 1900 to 10091; White spectrum color temperature (available since 0.13.0)
232    #[serde(skip_serializing_if = "Option::is_none")]
233    #[serde(default = "none_function")]
234    pub cct: Option<u16>,
235
236    /// Undocumented?????? TODO
237    ///
238    /// // 14-15 : 0-3 UI segment sets/groups
239    ///     -WLED source
240    #[serde(skip_serializing_if = "Option::is_none")]
241    #[serde(default = "none_function")]
242    pub set: Option<u8>,
243
244    /// The name of the segment. Names are not present by default.
245    /// if this is none, use "Segment{id}" to match the WLED UI
246    #[serde(skip_serializing_if = "Option::is_none")]
247    #[serde(default = "none_function")]
248    #[serde(rename = "n")]
249    pub name: Option<String>,
250
251    /// Array that has up to 3 color arrays as elements, the primary, secondary (background) and tertiary colors of the segment. Each color is an array of 3 or 4 bytes, which represent an RGB(W) color.
252    #[serde(skip_serializing_if = "Option::is_none")]
253    #[serde(default = "none_function")]
254    pub col: Option<Vec<Vec<u8>>>,
255
256    /// 0 to info.fxcount -1; ID of the effect or ~ to increment, ~- to decrement, or r for random.
257    #[serde(skip_serializing_if = "Option::is_none")]
258    #[serde(default = "none_function")]
259    pub fx: Option<u16>,
260
261    /// Relative effect speed. ~ to increment, ~- to decrement. ~10 to increment by 10, ~-10 to decrement by 10.
262    #[serde(skip_serializing_if = "Option::is_none")]
263    #[serde(default = "none_function")]
264    pub sx: Option<u8>,
265
266    /// Effect intensity. ~ to increment, ~- to decrement. ~10 to increment by 10, ~-10 to decrement by 10.
267    #[serde(skip_serializing_if = "Option::is_none")]
268    #[serde(default = "none_function")]
269    pub ix: Option<u8>,
270
271    /// 0 to info.palcount -1; ID of the color palette or ~ to increment, ~- to decrement, or r for random.
272    #[serde(skip_serializing_if = "Option::is_none")]
273    #[serde(default = "none_function")]
274    pub pal: Option<u16>,
275
276    /// Effect custom slider 1. Custom sliders are hidden or displayed and labeled based on effect metadata.
277    #[serde(skip_serializing_if = "Option::is_none")]
278    #[serde(default = "none_function")]
279    pub c1: Option<u8>,
280
281    /// Effect custom slider 2.
282    #[serde(skip_serializing_if = "Option::is_none")]
283    #[serde(default = "none_function")]
284    pub c2: Option<u8>,
285
286    /// 0 to 31; Effect custom slider 3.
287    #[serde(skip_serializing_if = "Option::is_none")]
288    #[serde(default = "none_function")]
289    pub c3: Option<u8>,
290
291    /// true if the segment is selected. Selected segments will have their state (color/FX) updated by APIs that don't support segments (e.g. UDP sync, HTTP API). If no segment is selected, the first segment (id:0) will behave as if selected. WLED will report the state of the first (lowest id) segment that is selected to APIs (HTTP, MQTT, Blynk...), or mainseg in case no segment is selected and for the UDP API. Live data is always applied to all LEDs regardless of segment configuration.
292    #[serde(skip_serializing_if = "Option::is_none")]
293    #[serde(default = "none_function")]
294    pub sel: Option<bool>,
295
296    /// Flips the segment, causing animations to change direction.
297    #[serde(skip_serializing_if = "Option::is_none")]
298    #[serde(default = "none_function")]
299    pub rev: Option<bool>,
300
301    /// Mirrors the segment (available since 0.10.2)
302    #[serde(skip_serializing_if = "Option::is_none")]
303    #[serde(default = "none_function")]
304    pub mi: Option<bool>,
305
306    /// Effect option 1. Custom options are hidden or displayed and labeled based on effect metadata.
307    #[serde(skip_serializing_if = "Option::is_none")]
308    #[serde(default = "none_function")]
309    pub o1: Option<bool>,
310
311    /// Effect option 2.
312    #[serde(skip_serializing_if = "Option::is_none")]
313    #[serde(default = "none_function")]
314    pub o2: Option<bool>,
315
316    /// Effect option 3.
317    #[serde(skip_serializing_if = "Option::is_none")]
318    #[serde(default = "none_function")]
319    pub o3: Option<bool>,
320
321    /// 0 to 3; Setting of the sound simulation type for audio enhanced effects. (0: 'BeatSin', 1: 'WeWillRockYou', 2: '10_3', 3: '14_3') (as of 0.14.0-b1, there are these 4 types defined)
322    #[serde(skip_serializing_if = "Option::is_none")]
323    #[serde(default = "none_function")]
324    pub si: Option<u8>,
325
326    /// 0 to 4 [map1D2D.count]; Setting of segment field 'Expand 1D FX'. (0: Pixels, 1: Bar, 2: Arc, 3: Corner)
327    #[serde(skip_serializing_if = "Option::is_none")]
328    #[serde(default = "none_function")]
329    pub m12: Option<u8>,
330}
331
332
333
334
335#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
336#[serde(rename_all = "camelCase")]
337pub struct Playlist {
338    /// Array of preset ID integers to be applied in this order.
339    #[serde(skip_serializing_if = "Option::is_none")]
340    #[serde(default = "none_function")]
341    pub ps: Option<Vec<u8>>,
342
343    /// Array of time each preset should be kept, in tenths of seconds. If only one integer is supplied, all presets will be kept for that time.Defaults to 10 seconds if not provided.
344    #[serde(skip_serializing_if = "Option::is_none")]
345    #[serde(default = "none_function")]
346    pub dur: Option<Vec<u32>>,
347
348    /// Array of time each preset should transition to the next one, in tenths of seconds. If only one integer is supplied, all presets will transition for that time. Defaults to the current transition time if not provided.
349    #[serde(skip_serializing_if = "Option::is_none")]
350    #[serde(default = "none_function")]
351    pub transition: Option<u8>,
352
353    /// How many times the entire playlist should cycle before finishing. Set to 0 for an indefinite cycle. Default to indefinite if not provided.
354    #[serde(skip_serializing_if = "Option::is_none")]
355    #[serde(default = "none_function")]
356    pub repeat: Option<u16>,
357
358    /// Single preset ID to apply after the playlist finished. Has no effect when an indefinite cycle is set. If not provided, the light will stay on the last preset of the playlist.
359    #[serde(skip_serializing_if = "Option::is_none")]
360    #[serde(default = "none_function")]
361    pub end: Option<u8>,
362}
363
364
365#[cfg(test)]
366mod tests {
367    use crate::structures::state::State;
368
369    #[test]
370    fn it_works() {
371        let s = r#"{"on":true,"bri":128,"transition":7,"ps":-1,"pl":-1,"nl":{"on":false,"dur":60,"mode":1,"tbri":0,"rem":-1},"udpn":{"send":false,"recv":true,"sgrp":1,"rgrp":1},"lor":0,"mainseg":0,"seg":[{"id":0,"start":0,"stop":6,"len":6,"grp":1,"spc":0,"of":0,"on":true,"frz":false,"bri":255,"cct":127,"set":0,"col":[[255,160,0],[0,0,0],[0,0,0]],"fx":0,"sx":128,"ix":128,"pal":0,"c1":128,"c2":128,"c3":16,"sel":true,"rev":false,"mi":false,"o1":false,"o2":false,"o3":false,"si":0,"m12":0}]}"#;
372        println!("og string: {:?}", s);
373        let a: &State = &State::try_from(s).unwrap();
374        println!("State object: {:?}", a);
375        let b: String = a.try_into().unwrap();
376        println!("converted object: {:?}", b);
377
378
379    }
380}