FastLED 3.10.8
Loading...
Searching...
No Matches
wled.cpp.hpp
Go to the documentation of this file.
1// ok no header
2#include "fl/fx/wled.h"
3#include "fl/log/log.h"
4#include "fl/log/log.h"
5#include "fl/stl/compiler_control.h" // IWYU pragma: keep - FL_UNUSED
6#include "fl/stl/noexcept.h"
7namespace fl {
8
9// WLED Constructor and Stub Implementations
10
12 : Remote(
13 [this]() { return stubRequestSource(); },
14 [this](const fl::json& response) { stubResponseSink(response); }
15 ) {}
16
18 FL_ERROR("WLED::stubRequestSource: Not implemented - provide a real RequestSource callback");
19 return fl::nullopt;
20}
21
23 FL_UNUSED(response); // only consumed by FL_ERROR, a no-op on small platforms
24 FL_ERROR("WLED::stubResponseSink: Not implemented - provide a real ResponseSink callback");
25}
26
27// WLED State Management
28
29void WLED::setState(const fl::json& wledState) FL_NO_EXCEPT {
30 if (!wledState.has_value()) {
31 FL_WARN("WLED: setState called with invalid JSON");
32 return;
33 }
34
35 // Extract "on" field (bool) - optional, keep existing if missing
36 if (wledState.contains("on") && wledState["on"].is_bool()) {
37 bool newOn = wledState["on"] | mWledOn;
38 if (newOn != mWledOn) {
39 mWledOn = newOn;
40 FL_DBG("WLED: on=" << ((mWledOn ? "true" : "false")));
41 }
42 }
43
44 // Extract "bri" field (0-255) - optional, keep existing if missing
45 if (wledState.contains("bri")) {
46 if (wledState["bri"].is_int()) {
47 i64 briInt = wledState["bri"] | static_cast<i64>(mWledBri);
48 // Clamp to valid range 0-255
49 if (briInt < 0) {
50 FL_WARN("WLED: brightness " << briInt << " out of range, clamping to 0");
51 briInt = 0;
52 } else if (briInt > 255) {
53 FL_WARN("WLED: brightness " << briInt << " out of range, clamping to 255");
54 briInt = 255;
55 }
56 u8 newBri = static_cast<u8>(briInt);
57 if (newBri != mWledBri) {
58 mWledBri = newBri;
59 FL_DBG("WLED: bri=" << (static_cast<int>(mWledBri)));
60 }
61 } else {
62 FL_WARN("WLED: 'bri' field has invalid type (expected int)");
63 }
64 }
65
66 // Extract "transition" field (0-65535) - optional, keep existing if missing
67 if (wledState.contains("transition")) {
68 if (wledState["transition"].is_int()) {
69 i64 transInt = wledState["transition"] | static_cast<i64>(mTransition);
70 // Clamp to valid range 0-65535
71 if (transInt < 0) {
72 FL_WARN("WLED: transition " << transInt << " out of range, clamping to 0");
73 transInt = 0;
74 } else if (transInt > 65535) {
75 FL_WARN("WLED: transition " << transInt << " out of range, clamping to 65535");
76 transInt = 65535;
77 }
78 u16 newTransition = static_cast<u16>(transInt);
79 if (newTransition != mTransition) {
80 mTransition = newTransition;
81 FL_DBG("WLED: transition=" << mTransition);
82 }
83 } else {
84 FL_WARN("WLED: 'transition' field has invalid type (expected int)");
85 }
86 }
87
88 // Extract "ps" field (preset ID: -1 to 250) - optional, keep existing if missing
89 if (wledState.contains("ps")) {
90 if (wledState["ps"].is_int()) {
91 i64 psInt = wledState["ps"] | static_cast<i64>(mPreset);
92 // Clamp to valid range -1 to 250
93 if (psInt < -1) {
94 FL_WARN("WLED: preset " << psInt << " out of range, clamping to -1");
95 psInt = -1;
96 } else if (psInt > 250) {
97 FL_WARN("WLED: preset " << psInt << " out of range, clamping to 250");
98 psInt = 250;
99 }
100 i16 newPreset = static_cast<i16>(psInt);
101 if (newPreset != mPreset) {
102 mPreset = newPreset;
103 FL_DBG("WLED: ps=" << mPreset);
104 }
105 } else {
106 FL_WARN("WLED: 'ps' field has invalid type (expected int)");
107 }
108 }
109
110 // Extract "pl" field (playlist ID: -1 to 250) - optional, keep existing if missing
111 if (wledState.contains("pl")) {
112 if (wledState["pl"].is_int()) {
113 i64 plInt = wledState["pl"] | static_cast<i64>(mPlaylist);
114 // Clamp to valid range -1 to 250
115 if (plInt < -1) {
116 FL_WARN("WLED: playlist " << plInt << " out of range, clamping to -1");
117 plInt = -1;
118 } else if (plInt > 250) {
119 FL_WARN("WLED: playlist " << plInt << " out of range, clamping to 250");
120 plInt = 250;
121 }
122 i16 newPlaylist = static_cast<i16>(plInt);
123 if (newPlaylist != mPlaylist) {
124 mPlaylist = newPlaylist;
125 FL_DBG("WLED: pl=" << mPlaylist);
126 }
127 } else {
128 FL_WARN("WLED: 'pl' field has invalid type (expected int)");
129 }
130 }
131
132 // Extract "lor" field (live override: 0-2) - optional, keep existing if missing
133 if (wledState.contains("lor")) {
134 if (wledState["lor"].is_int()) {
135 i64 lorInt = wledState["lor"] | static_cast<i64>(mLiveOverride);
136 // Clamp to valid range 0-2
137 if (lorInt < 0) {
138 FL_WARN("WLED: live override " << lorInt << " out of range, clamping to 0");
139 lorInt = 0;
140 } else if (lorInt > 2) {
141 FL_WARN("WLED: live override " << lorInt << " out of range, clamping to 2");
142 lorInt = 2;
143 }
144 u8 newLiveOverride = static_cast<u8>(lorInt);
145 if (newLiveOverride != mLiveOverride) {
146 mLiveOverride = newLiveOverride;
147 FL_DBG("WLED: lor=" << (static_cast<int>(mLiveOverride)));
148 }
149 } else {
150 FL_WARN("WLED: 'lor' field has invalid type (expected int)");
151 }
152 }
153
154 // Extract "mainseg" field (main segment: 0-255) - optional, keep existing if missing
155 if (wledState.contains("mainseg")) {
156 if (wledState["mainseg"].is_int()) {
157 i64 mainsegInt = wledState["mainseg"] | static_cast<i64>(mMainSegment);
158 // Clamp to valid range 0-255
159 if (mainsegInt < 0) {
160 FL_WARN("WLED: main segment " << mainsegInt << " out of range, clamping to 0");
161 mainsegInt = 0;
162 } else if (mainsegInt > 255) {
163 FL_WARN("WLED: main segment " << mainsegInt << " out of range, clamping to 255");
164 mainsegInt = 255;
165 }
166 u8 newMainSegment = static_cast<u8>(mainsegInt);
167 if (newMainSegment != mMainSegment) {
168 mMainSegment = newMainSegment;
169 FL_DBG("WLED: mainseg=" << (static_cast<int>(mMainSegment)));
170 }
171 } else {
172 FL_WARN("WLED: 'mainseg' field has invalid type (expected int)");
173 }
174 }
175
176 // Extract "nl" field (nightlight object) - optional
177 if (wledState.contains("nl")) {
178 if (wledState["nl"].is_object()) {
179 const fl::json& nl = wledState["nl"];
180
181 // Extract "on" field (bool)
182 if (nl.contains("on") && nl["on"].is_bool()) {
183 bool newNlOn = nl["on"] | mNightlightOn;
184 if (newNlOn != mNightlightOn) {
185 mNightlightOn = newNlOn;
186 FL_DBG("WLED: nl.on=" << ((mNightlightOn ? "true" : "false")));
187 }
188 }
189
190 // Extract "dur" field (1-255 minutes)
191 if (nl.contains("dur")) {
192 if (nl["dur"].is_int()) {
193 i64 durInt = nl["dur"] | static_cast<i64>(mNightlightDuration);
194 // Clamp to valid range 1-255
195 if (durInt < 1) {
196 FL_WARN("WLED: nl.dur " << durInt << " out of range, clamping to 1");
197 durInt = 1;
198 } else if (durInt > 255) {
199 FL_WARN("WLED: nl.dur " << durInt << " out of range, clamping to 255");
200 durInt = 255;
201 }
202 u8 newDur = static_cast<u8>(durInt);
203 if (newDur != mNightlightDuration) {
204 mNightlightDuration = newDur;
205 FL_DBG("WLED: nl.dur=" << (static_cast<int>(mNightlightDuration)));
206 }
207 } else {
208 FL_WARN("WLED: 'nl.dur' field has invalid type (expected int)");
209 }
210 }
211
212 // Extract "mode" field (0-3)
213 if (nl.contains("mode")) {
214 if (nl["mode"].is_int()) {
215 i64 modeInt = nl["mode"] | static_cast<i64>(mNightlightMode);
216 // Clamp to valid range 0-3
217 if (modeInt < 0) {
218 FL_WARN("WLED: nl.mode " << modeInt << " out of range, clamping to 0");
219 modeInt = 0;
220 } else if (modeInt > 3) {
221 FL_WARN("WLED: nl.mode " << modeInt << " out of range, clamping to 3");
222 modeInt = 3;
223 }
224 u8 newMode = static_cast<u8>(modeInt);
225 if (newMode != mNightlightMode) {
226 mNightlightMode = newMode;
227 FL_DBG("WLED: nl.mode=" << (static_cast<int>(mNightlightMode)));
228 }
229 } else {
230 FL_WARN("WLED: 'nl.mode' field has invalid type (expected int)");
231 }
232 }
233
234 // Extract "tbri" field (0-255 target brightness)
235 if (nl.contains("tbri")) {
236 if (nl["tbri"].is_int()) {
237 i64 tbriInt = nl["tbri"] | static_cast<i64>(mNightlightTargetBrightness);
238 // Clamp to valid range 0-255
239 if (tbriInt < 0) {
240 FL_WARN("WLED: nl.tbri " << tbriInt << " out of range, clamping to 0");
241 tbriInt = 0;
242 } else if (tbriInt > 255) {
243 FL_WARN("WLED: nl.tbri " << tbriInt << " out of range, clamping to 255");
244 tbriInt = 255;
245 }
246 u8 newTbri = static_cast<u8>(tbriInt);
247 if (newTbri != mNightlightTargetBrightness) {
249 FL_DBG("WLED: nl.tbri=" << (static_cast<int>(mNightlightTargetBrightness)));
250 }
251 } else {
252 FL_WARN("WLED: 'nl.tbri' field has invalid type (expected int)");
253 }
254 }
255 } else {
256 FL_WARN("WLED: 'nl' field has invalid type (expected object)");
257 }
258 }
259
260 // Extract "udpn" field (UDP sync settings) - optional
261 if (wledState.contains("udpn")) {
262 if (wledState["udpn"].is_object()) {
263 const fl::json& udpn = wledState["udpn"];
264
265 // Extract "send" field (bool)
266 if (udpn.contains("send") && udpn["send"].is_bool()) {
267 bool newSend = udpn["send"] | mUdpSend;
268 if (newSend != mUdpSend) {
269 mUdpSend = newSend;
270 FL_DBG("WLED: udpn.send=" << ((mUdpSend ? "true" : "false")));
271 }
272 }
273
274 // Extract "recv" field (bool)
275 if (udpn.contains("recv") && udpn["recv"].is_bool()) {
276 bool newRecv = udpn["recv"] | mUdpReceive;
277 if (newRecv != mUdpReceive) {
278 mUdpReceive = newRecv;
279 FL_DBG("WLED: udpn.recv=" << ((mUdpReceive ? "true" : "false")));
280 }
281 }
282 } else {
283 FL_WARN("WLED: 'udpn' field has invalid type (expected object)");
284 }
285 }
286
287 // Extract "playlist" field (playlist configuration) - optional
288 if (wledState.contains("playlist")) {
289 if (wledState["playlist"].is_object()) {
290 const fl::json& pl = wledState["playlist"];
291
292 // Extract "ps" field (array of preset IDs)
293 if (pl.contains("ps") && pl["ps"].is_array()) {
294 mPlaylistPresets.clear();
295 for (size_t i = 0; i < pl["ps"].size(); i++) {
296 if (pl["ps"][i].is_int()) {
297 i64 psInt = pl["ps"][i] | -1;
298 // Clamp to valid range -1 to 250
299 if (psInt < -1) psInt = -1;
300 if (psInt > 250) psInt = 250;
301 mPlaylistPresets.push_back(static_cast<i16>(psInt));
302 }
303 }
304 FL_DBG("WLED: playlist.ps count=" << mPlaylistPresets.size());
305 }
306
307 // Extract "dur" field (array of durations in seconds)
308 if (pl.contains("dur") && pl["dur"].is_array()) {
309 mPlaylistDurations.clear();
310 for (size_t i = 0; i < pl["dur"].size(); i++) {
311 if (pl["dur"][i].is_int()) {
312 i64 durInt = pl["dur"][i] | 0;
313 if (durInt < 0) durInt = 0;
314 if (durInt > 65535) durInt = 65535;
315 mPlaylistDurations.push_back(static_cast<u16>(durInt));
316 }
317 }
318 }
319
320 // Extract "transition" field (array of transitions in ×100ms)
321 if (pl.contains("transition") && pl["transition"].is_array()) {
322 mPlaylistTransitions.clear();
323 for (size_t i = 0; i < pl["transition"].size(); i++) {
324 if (pl["transition"][i].is_int()) {
325 i64 transInt = pl["transition"][i] | 0;
326 if (transInt < 0) transInt = 0;
327 if (transInt > 65535) transInt = 65535;
328 mPlaylistTransitions.push_back(static_cast<u16>(transInt));
329 }
330 }
331 }
332
333 // Extract "repeat" field
334 if (pl.contains("repeat") && pl["repeat"].is_int()) {
335 i64 repeatInt = pl["repeat"] | 0;
336 if (repeatInt < 0) repeatInt = 0;
337 if (repeatInt > 65535) repeatInt = 65535;
338 mPlaylistRepeat = static_cast<u16>(repeatInt);
339 FL_DBG("WLED: playlist.repeat=" << mPlaylistRepeat);
340 }
341
342 // Extract "end" field
343 if (pl.contains("end") && pl["end"].is_int()) {
344 i64 endInt = pl["end"] | -1;
345 if (endInt < -1) endInt = -1;
346 if (endInt > 250) endInt = 250;
347 mPlaylistEnd = static_cast<i16>(endInt);
348 FL_DBG("WLED: playlist.end=" << mPlaylistEnd);
349 }
350
351 // Extract "r" field (randomize)
352 if (pl.contains("r") && pl["r"].is_bool()) {
353 mPlaylistRandomize = pl["r"] | false;
354 FL_DBG("WLED: playlist.r=" << ((mPlaylistRandomize ? "true" : "false")));
355 }
356 } else {
357 FL_WARN("WLED: 'playlist' field has invalid type (expected object)");
358 }
359 }
360
361 // Extract "seg" field (segment array) - optional
362 if (wledState.contains("seg")) {
363 if (wledState["seg"].is_array()) {
364 for (size_t i = 0; i < wledState["seg"].size(); i++) {
365 const fl::json& segJson = wledState["seg"][i];
366 if (!segJson.is_object()) {
367 FL_WARN("WLED: segment at index " << i << " is not an object");
368 continue;
369 }
370
371 // Extract segment ID (required for updates)
372 u8 segId = 0;
373 if (segJson.contains("id") && segJson["id"].is_int()) {
374 i64 idInt = segJson["id"] | 0;
375 if (idInt < 0) idInt = 0;
376 if (idInt > 255) idInt = 255;
377 segId = static_cast<u8>(idInt);
378 } else {
379 // If no ID provided, use index
380 segId = static_cast<u8>(i);
381 }
382
383 // Find existing segment or create new one
384 WLEDSegment* seg = nullptr;
385 for (size_t j = 0; j < mSegments.size(); j++) {
386 if (mSegments[j].mId == segId) {
387 seg = &mSegments[j];
388 break;
389 }
390 }
391 if (!seg) {
392 // Create new segment
393 WLEDSegment newSeg;
394 newSeg.mId = segId;
395 mSegments.push_back(newSeg);
396 seg = &mSegments[mSegments.size() - 1];
397 }
398
399 // Parse segment fields using helper function
400 wled::parseSegmentFields(segJson, *seg);
401 }
402 } else {
403 FL_WARN("WLED: 'seg' field has invalid type (expected array)");
404 }
405 }
406}
407
410 state.set("on", mWledOn);
411 state.set("bri", static_cast<i64>(mWledBri));
412 state.set("transition", static_cast<i64>(mTransition));
413 state.set("ps", static_cast<i64>(mPreset));
414 state.set("pl", static_cast<i64>(mPlaylist));
415 state.set("lor", static_cast<i64>(mLiveOverride));
416 state.set("mainseg", static_cast<i64>(mMainSegment));
417
418 // Nightlight object
420 nl.set("on", mNightlightOn);
421 nl.set("dur", static_cast<i64>(mNightlightDuration));
422 nl.set("mode", static_cast<i64>(mNightlightMode));
423 nl.set("tbri", static_cast<i64>(mNightlightTargetBrightness));
424 state.set("nl", nl);
425
426 // UDP sync settings
427 fl::json udpn = fl::json::object();
428 udpn.set("send", mUdpSend);
429 udpn.set("recv", mUdpReceive);
430 state.set("udpn", udpn);
431
432 // Playlist configuration (if present)
433 if (hasPlaylistConfig()) {
434 state.set("playlist", getPlaylistConfig());
435 }
436
437 // Segments
438 if (!mSegments.empty()) {
439 fl::json segments = fl::json::array();
440 for (const auto& seg : mSegments) {
441 fl::json segJson = fl::json::object();
442
443 segJson.set("id", static_cast<i64>(seg.mId));
444 segJson.set("start", static_cast<i64>(seg.mStart));
445 segJson.set("stop", static_cast<i64>(seg.mStop));
446 segJson.set("len", static_cast<i64>(seg.mLen));
447 segJson.set("grp", static_cast<i64>(seg.mGrp));
448 segJson.set("spc", static_cast<i64>(seg.mSpc));
449 segJson.set("of", static_cast<i64>(seg.mOf));
450 segJson.set("on", seg.mOn);
451 segJson.set("bri", static_cast<i64>(seg.mBri));
452 segJson.set("cct", static_cast<i64>(seg.mCct));
453
454 // Effect properties
455 segJson.set("fx", static_cast<i64>(seg.mFx));
456 segJson.set("sx", static_cast<i64>(seg.mSx));
457 segJson.set("ix", static_cast<i64>(seg.mIx));
458 segJson.set("pal", static_cast<i64>(seg.mPal));
459 segJson.set("c1", static_cast<i64>(seg.mC1));
460 segJson.set("c2", static_cast<i64>(seg.mC2));
461 segJson.set("c3", static_cast<i64>(seg.mC3));
462
463 // Boolean flags
464 segJson.set("sel", seg.mSel);
465 segJson.set("rev", seg.mRev);
466 segJson.set("mi", seg.mMi);
467 segJson.set("o1", seg.mO1);
468 segJson.set("o2", seg.mO2);
469 segJson.set("o3", seg.mO3);
470 segJson.set("si", static_cast<i64>(seg.mSi));
471 segJson.set("m12", static_cast<i64>(seg.mM12));
472 segJson.set("rpt", seg.mRpt);
473
474 if (!seg.mName.empty()) {
475 segJson.set("n", seg.mName);
476 }
477
478 // Colors
479 if (!seg.mColors.empty()) {
480 fl::json colors = fl::json::array();
481 for (const auto& color : seg.mColors) {
482 if (color.size() >= 3) {
483 fl::json colorArray = fl::json::array();
484 for (size_t i = 0; i < color.size(); i++) {
485 colorArray.push_back(fl::json(static_cast<i64>(color[i])));
486 }
487 colors.push_back(colorArray);
488 }
489 }
490 segJson.set("col", colors);
491 }
492
493 // Individual LEDs
494 if (!seg.mIndividualLeds.empty()) {
496 for (const auto& led : seg.mIndividualLeds) {
497 if (led.size() >= 3) {
498 fl::string hexColor = wled::rgbToHex(led[0], led[1], led[2]);
499 leds.push_back(fl::json(hexColor.c_str()));
500 }
501 }
502 segJson.set("i", leds);
503 }
504
505 segments.push_back(segJson);
506 }
507 state.set("seg", segments);
508 }
509
510 return state;
511}
512
514 fl::json playlist = fl::json::object();
515
516 // Preset IDs
517 if (!mPlaylistPresets.empty()) {
519 for (const auto& preset : mPlaylistPresets) {
520 ps.push_back(fl::json(static_cast<i64>(preset)));
521 }
522 playlist.set("ps", ps);
523 }
524
525 // Durations
526 if (!mPlaylistDurations.empty()) {
528 for (const auto& duration : mPlaylistDurations) {
529 dur.push_back(fl::json(static_cast<i64>(duration)));
530 }
531 playlist.set("dur", dur);
532 }
533
534 // Transitions
535 if (!mPlaylistTransitions.empty()) {
536 fl::json trans = fl::json::array();
537 for (const auto& transition : mPlaylistTransitions) {
538 trans.push_back(fl::json(static_cast<i64>(transition)));
539 }
540 playlist.set("transition", trans);
541 }
542
543 // Other properties
544 playlist.set("repeat", static_cast<i64>(mPlaylistRepeat));
545 playlist.set("end", static_cast<i64>(mPlaylistEnd));
546 playlist.set("r", mPlaylistRandomize);
547
548 return playlist;
549}
550
552 for (const auto& seg : mSegments) {
553 if (seg.mId == id) {
554 return &seg;
555 }
556 }
557 return nullptr;
558}
559
560} // namespace fl
CRGB leds[1]
TestState state
Remote(RequestSource source, ResponseSink sink) FL_NO_EXCEPT
Construct with I/O callbacks.
fl::vector< u16 > mPlaylistDurations
Definition wled.h:448
fl::json getState() const FL_NO_EXCEPT
Get current WLED state as JSON object.
Definition wled.cpp.hpp:408
bool mNightlightOn
Definition wled.h:441
fl::vector< u16 > mPlaylistTransitions
Definition wled.h:449
const WLEDSegment * findSegmentById(u8 id) const FL_NO_EXCEPT
Find segment by ID.
Definition wled.cpp.hpp:551
bool hasPlaylistConfig() const FL_NO_EXCEPT
Check if playlist is active.
Definition wled.h:372
u8 mWledBri
Definition wled.h:433
i16 mPlaylistEnd
Definition wled.h:451
u8 mLiveOverride
Definition wled.h:437
u16 mTransition
Definition wled.h:434
fl::optional< fl::json > stubRequestSource() FL_NO_EXCEPT
Stub request source callback.
Definition wled.cpp.hpp:17
u8 mNightlightTargetBrightness
Definition wled.h:444
fl::json getPlaylistConfig() const FL_NO_EXCEPT
Get playlist configuration.
Definition wled.cpp.hpp:513
void setState(const fl::json &wledState) FL_NO_EXCEPT
Set WLED state from JSON object.
Definition wled.cpp.hpp:29
u8 mNightlightDuration
Definition wled.h:442
bool mUdpSend
Definition wled.h:455
bool mUdpReceive
Definition wled.h:456
i16 mPreset
Definition wled.h:435
i16 mPlaylist
Definition wled.h:436
WLED() FL_NO_EXCEPT
Construct WLED with default stub I/O callbacks.
Definition wled.cpp.hpp:11
fl::vector< i16 > mPlaylistPresets
Definition wled.h:447
bool mWledOn
Definition wled.h:432
bool mPlaylistRandomize
Definition wled.h:452
u16 mPlaylistRepeat
Definition wled.h:450
fl::vector< WLEDSegment > mSegments
Definition wled.h:459
u8 mMainSegment
Definition wled.h:438
u8 mNightlightMode
Definition wled.h:443
void stubResponseSink(const fl::json &response) FL_NO_EXCEPT
Stub response sink callback.
Definition wled.cpp.hpp:22
const char * c_str() const FL_NO_EXCEPT
bool is_object() const FL_NO_EXCEPT
Definition json.h:391
size_t size() const FL_NO_EXCEPT
Definition json.h:798
void set(const fl::string &key, const json &value) FL_NO_EXCEPT
Definition json.h:866
bool is_int() const FL_NO_EXCEPT
Definition json.h:383
bool is_array() const FL_NO_EXCEPT
Definition json.h:389
void push_back(const json &value) FL_NO_EXCEPT
Definition json.h:918
bool contains(size_t idx) const FL_NO_EXCEPT
Definition json.h:790
bool is_bool() const FL_NO_EXCEPT
Definition json.h:382
static json object() FL_NO_EXCEPT
Definition json.h:857
static json array() FL_NO_EXCEPT
Definition json.h:853
#define FL_UNUSED(x)
fl::UISlider transition("Transition", 0.0f, 0.0f, 1.0f, 0.01f)
P ps[MAXP]
Definition Luminova.h:57
#define FL_WARN(...)
Definition log.h:437
#define FL_DBG
Definition log.h:553
#define FL_ERROR(...)
Definition log.h:373
Centralized logging categories for FastLED hardware interfaces and subsystems.
fl::string rgbToHex(u8 r, u8 g, u8 b) FL_NO_EXCEPT
Convert RGB components to hex string.
void parseSegmentFields(const fl::json &segJson, WLEDSegment &seg) FL_NO_EXCEPT
Parse all fields from a segment JSON object into a WLEDSegment.
unsigned char u8
Definition stdint.h:131
u8 u8 fract8 blur_amount FL_NO_EXCEPT
Definition blur.h:186
Optional< T > optional
Definition optional.h:16
constexpr nullopt_t nullopt
Definition optional.h:13
Base definition for an LED controller.
Definition crgb.hpp:179
WLED segment configuration.
Definition segment.h:15
fl::i64 i64
Definition stdint.h:221