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