FastLED 3.10.6
Loading...
Searching...
No Matches

◆ toJson()

void fl::ScreenMap::toJson ( const fl::flat_map< string, ScreenMap > & segmentMaps,
fl::json * doc )
static

Definition at line 438 of file screenmap.cpp.hpp.

439 {
440
441#if FASTLED_NO_JSON
442 FL_WARN("ScreenMap::toJson called with FASTLED_NO_JSON");
443 return;
444#else
445 if (!doc) {
446 FL_WARN("ScreenMap::toJson called with nullptr doc");
447 return;
448 }
449
450 // Emits the v2 screenmap shape (issue ledmapper#143):
451 // { "version": 2,
452 // "groups": { "<name>": { "color": "#hex" } },
453 // "segments": [ { "id": "<name>", "group": "<name>",
454 // "x": [...], "y": [...], "diameter": ... } ] }
455 //
456 // `pin` is part of the v2 shape but is not emitted here -- see the note
457 // at the segment object below. Writing the example value from a comment
458 // as data is how it came to be there.
459 // Bilingual readers (`ScreenMap::ParseJson`, ledmapper) accept both v1
460 // and v2, so any existing on-disk v1 JSON keeps loading. v1 emission
461 // is no longer supported.
462 *doc = fl::json::object();
463
464 fl::json groupsObj = fl::json::object();
465 fl::json segmentsArr = fl::json::array();
466
467 // Distinct palette so each strip lights up differently in the editor
468 // preview without the user having to pick a colour. Cycle on overflow.
469 static const char *const kPalette[] = {
470 "#3b82f6", "#10b981", "#f59e0b", "#ef4444",
471 "#a855f7", "#06b6d4", "#ec4899", "#84cc16",
472 };
473 constexpr size_t kPaletteSize = sizeof(kPalette) / sizeof(kPalette[0]);
474
475 size_t idx = 0;
476 for (const auto& kv : segmentMaps) {
477 if (kv.second.getLength() == 0) {
478 FL_WARN("ScreenMap::toJson called with empty segment: %s", fl::string(kv.first));
479 continue;
480 }
481
482 const auto& name = kv.first;
483 const auto& segment = kv.second;
484 const float diameter = segment.getDiameter();
485
486 fl::json xArray = fl::json::array();
487 for (u16 i = 0; i < segment.getLength(); i++) {
488 xArray.push_back(fl::json(segment[i].x));
489 }
490 fl::json yArray = fl::json::array();
491 for (u16 i = 0; i < segment.getLength(); i++) {
492 yArray.push_back(fl::json(segment[i].y));
493 }
494
495 fl::json groupObj = fl::json::object();
496 groupObj.set("color", fl::json(fl::string(kPalette[idx % kPaletteSize])));
497 groupsObj.set(name, groupObj);
498
499 fl::json segmentObj = fl::json::object();
500 segmentObj.set("id", fl::json(fl::string(name)));
501 // No `pin`. The v2 shape carries one and the parser above drops it --
502 // it is wiring metadata with nowhere to live on this side -- so there
503 // is nothing here to write. What used to be written was the literal
504 // `"pin1"` from the shape example in the comment above, copied into
505 // the emitter as data.
506 //
507 // That is worse than omitting it, because it is wrong rather than
508 // absent. A three-segment file wired to pin1/pin2/pin3 came back with
509 // all three on pin1, and a numeric `"pin": 7` came back as the string
510 // `"pin1"`. A consumer reading that mis-wires a strip and has no way
511 // to tell; a consumer reading a missing optional key can see that it
512 // is missing.
513 //
514 // Carrying the value through instead is FastLED #3322, which needs
515 // somewhere on `ScreenMap` to put it and a decision about the
516 // `<int|str>` union. Until then this loses the field visibly rather
517 // than rewriting it silently.
518 segmentObj.set("group", fl::json(fl::string(name)));
519 segmentObj.set("x", xArray);
520 segmentObj.set("y", yArray);
521 // Only when there is one. `mDiameter` defaults to -1 as a sentinel
522 // meaning "unset", and writing that out publishes an impossible
523 // physical size: no LED is -1 units across. The parser already reads
524 // an absent key back as -1 (both the v1 and v2 paths default it), so
525 // omitting round-trips to exactly the same value inside FastLED and
526 // stops a consumer from having to know the sentinel.
527 //
528 // The field's own comment in screenmap.h asked for this and had the
529 // sense inverted -- "Only serialized if it's not > 0.0f" -- which is
530 // presumably how the writer came to do the opposite.
531 if (diameter > 0.0f) {
532 segmentObj.set("diameter", fl::json(diameter));
533 }
534 segmentsArr.push_back(segmentObj);
535
536 idx++;
537 }
538
539 doc->set("version", fl::json(i64(2)));
540 doc->set("groups", groupsObj);
541 doc->set("segments", segmentsArr);
542
543 fl::string debugStr = doc->to_string();
544 FL_WARN("ScreenMap::toJson generated JSON: %s", debugStr);
545#endif
546}
fl::string to_string() const FL_NO_EXCEPT
Definition json.h:836
void set(const fl::string &key, const json &value) FL_NO_EXCEPT
Definition json.h:866
void push_back(const json &value) FL_NO_EXCEPT
Definition json.h:918
static json object() FL_NO_EXCEPT
Definition json.h:857
static json array() FL_NO_EXCEPT
Definition json.h:853
#define FL_WARN(...)
Definition log.h:440
fl::i64 i64
Definition stdint.h:221

References fl::json::array(), FL_WARN, fl::json::object(), fl::json::push_back(), fl::json::set(), fl::json::to_string(), fl::x, and fl::y.

Referenced by toJsonStr().

+ Here is the call graph for this function:
+ Here is the caller graph for this function: