FastLED 3.9.15
Loading...
Searching...
No Matches

◆ parseSegmentFields()

void fl::wled::parseSegmentFields ( const fl::json & segJson,
WLEDSegment & seg )

Parse all fields from a segment JSON object into a WLEDSegment.

Parameters
segJsonJSON object containing segment fields
segOutput: WLEDSegment to populate with parsed data

Parses all WLED segment properties including:

  • Position (start, stop, len)
  • State (on, brightness)
  • Colors (col array, individual LEDs)
  • Effects (fx, sx, ix, pal, c1, c2, c3)
  • Layout (grp, spc, of)
  • Flags (sel, rev, mi, o1, o2, o3, rpt)
  • Other (cct, si, m12, name)

Definition at line 67 of file json_helpers.cpp.hpp.

67 {
68 // Extract basic properties
69 if (segJson.contains("start") && segJson["start"].is_int()) {
70 i64 startInt = segJson["start"] | 0;
71 if (startInt < 0) startInt = 0;
72 if (startInt > 65535) startInt = 65535;
73 seg.mStart = static_cast<u16>(startInt);
74 }
75
76 if (segJson.contains("stop") && segJson["stop"].is_int()) {
77 i64 stopInt = segJson["stop"] | 0;
78 if (stopInt < 0) stopInt = 0;
79 if (stopInt > 65535) stopInt = 65535;
80 seg.mStop = static_cast<u16>(stopInt);
81 }
82
83 if (segJson.contains("len") && segJson["len"].is_int()) {
84 i64 lenInt = segJson["len"] | 0;
85 if (lenInt < 0) lenInt = 0;
86 if (lenInt > 65535) lenInt = 65535;
87 seg.mLen = static_cast<u16>(lenInt);
88 }
89
90 if (segJson.contains("grp") && segJson["grp"].is_int()) {
91 i64 grpInt = segJson["grp"] | 1;
92 if (grpInt < 1) grpInt = 1;
93 if (grpInt > 255) grpInt = 255;
94 seg.mGrp = static_cast<u8>(grpInt);
95 }
96
97 if (segJson.contains("spc") && segJson["spc"].is_int()) {
98 i64 spcInt = segJson["spc"] | 0;
99 if (spcInt < 0) spcInt = 0;
100 if (spcInt > 255) spcInt = 255;
101 seg.mSpc = static_cast<u8>(spcInt);
102 }
103
104 if (segJson.contains("of") && segJson["of"].is_int()) {
105 i64 ofInt = segJson["of"] | 0;
106 if (ofInt < 0) ofInt = 0;
107 if (ofInt > 65535) ofInt = 65535;
108 seg.mOf = static_cast<u16>(ofInt);
109 }
110
111 if (segJson.contains("on") && segJson["on"].is_bool()) {
112 seg.mOn = segJson["on"] | true;
113 }
114
115 if (segJson.contains("bri") && segJson["bri"].is_int()) {
116 i64 briInt = segJson["bri"] | 255;
117 if (briInt < 0) briInt = 0;
118 if (briInt > 255) briInt = 255;
119 seg.mBri = static_cast<u8>(briInt);
120 }
121
122 if (segJson.contains("cct") && segJson["cct"].is_int()) {
123 i64 cctInt = segJson["cct"] | 0;
124 if (cctInt < 0) cctInt = 0;
125 if (cctInt > 65535) cctInt = 65535;
126 seg.mCct = static_cast<u16>(cctInt);
127 }
128
129 // Effect properties
130 if (segJson.contains("fx") && segJson["fx"].is_int()) {
131 i64 fxInt = segJson["fx"] | 0;
132 if (fxInt < 0) fxInt = 0;
133 if (fxInt > 255) fxInt = 255;
134 seg.mFx = static_cast<u8>(fxInt);
135 }
136
137 if (segJson.contains("sx") && segJson["sx"].is_int()) {
138 i64 sxInt = segJson["sx"] | 128;
139 if (sxInt < 0) sxInt = 0;
140 if (sxInt > 255) sxInt = 255;
141 seg.mSx = static_cast<u8>(sxInt);
142 }
143
144 if (segJson.contains("ix") && segJson["ix"].is_int()) {
145 i64 ixInt = segJson["ix"] | 128;
146 if (ixInt < 0) ixInt = 0;
147 if (ixInt > 255) ixInt = 255;
148 seg.mIx = static_cast<u8>(ixInt);
149 }
150
151 if (segJson.contains("pal") && segJson["pal"].is_int()) {
152 i64 palInt = segJson["pal"] | 0;
153 if (palInt < 0) palInt = 0;
154 if (palInt > 255) palInt = 255;
155 seg.mPal = static_cast<u8>(palInt);
156 }
157
158 if (segJson.contains("c1") && segJson["c1"].is_int()) {
159 i64 c1Int = segJson["c1"] | 128;
160 if (c1Int < 0) c1Int = 0;
161 if (c1Int > 255) c1Int = 255;
162 seg.mC1 = static_cast<u8>(c1Int);
163 }
164
165 if (segJson.contains("c2") && segJson["c2"].is_int()) {
166 i64 c2Int = segJson["c2"] | 128;
167 if (c2Int < 0) c2Int = 0;
168 if (c2Int > 255) c2Int = 255;
169 seg.mC2 = static_cast<u8>(c2Int);
170 }
171
172 if (segJson.contains("c3") && segJson["c3"].is_int()) {
173 i64 c3Int = segJson["c3"] | 16;
174 if (c3Int < 0) c3Int = 0;
175 if (c3Int > 255) c3Int = 255;
176 seg.mC3 = static_cast<u8>(c3Int);
177 }
178
179 // Boolean flags
180 if (segJson.contains("sel") && segJson["sel"].is_bool()) {
181 seg.mSel = segJson["sel"] | false;
182 }
183
184 if (segJson.contains("rev") && segJson["rev"].is_bool()) {
185 seg.mRev = segJson["rev"] | false;
186 }
187
188 if (segJson.contains("mi") && segJson["mi"].is_bool()) {
189 seg.mMi = segJson["mi"] | false;
190 }
191
192 if (segJson.contains("o1") && segJson["o1"].is_bool()) {
193 seg.mO1 = segJson["o1"] | false;
194 }
195
196 if (segJson.contains("o2") && segJson["o2"].is_bool()) {
197 seg.mO2 = segJson["o2"] | false;
198 }
199
200 if (segJson.contains("o3") && segJson["o3"].is_bool()) {
201 seg.mO3 = segJson["o3"] | false;
202 }
203
204 if (segJson.contains("si") && segJson["si"].is_int()) {
205 i64 siInt = segJson["si"] | 0;
206 if (siInt < 0) siInt = 0;
207 if (siInt > 3) siInt = 3;
208 seg.mSi = static_cast<u8>(siInt);
209 }
210
211 if (segJson.contains("m12") && segJson["m12"].is_int()) {
212 i64 m12Int = segJson["m12"] | 0;
213 if (m12Int < 0) m12Int = 0;
214 if (m12Int > 3) m12Int = 3;
215 seg.mM12 = static_cast<u8>(m12Int);
216 }
217
218 if (segJson.contains("rpt") && segJson["rpt"].is_bool()) {
219 seg.mRpt = segJson["rpt"] | false;
220 }
221
222 if (segJson.contains("n") && segJson["n"].is_string()) {
223 seg.mName = segJson["n"] | fl::string("");
224 }
225
226 // Parse "col" field (color slots)
227 if (segJson.contains("col") && segJson["col"].is_array()) {
228 seg.mColors.clear();
229 for (size_t i = 0; i < segJson["col"].size(); i++) {
230 const fl::json& colJson = segJson["col"][i];
231
232 if (colJson.is_array()) {
233 // RGB(W) array format: [R,G,B] or [R,G,B,W]
234 fl::vector<u8> color;
235 for (size_t j = 0; j < colJson.size() && j < 4; j++) {
236 if (colJson[j].is_int()) {
237 i64 val = colJson[j] | 0;
238 if (val < 0) val = 0;
239 if (val > 255) val = 255;
240 color.push_back(static_cast<u8>(val));
241 }
242 }
243 if (color.size() >= 3) {
244 seg.mColors.push_back(color);
245 }
246 } else if (colJson.is_string()) {
247 // Hex string format: "RRGGBB" or "#RRGGBB"
248 fl::string hexStr = colJson | fl::string("");
249 u8 r, g, b;
250 if (parseHexColor(hexStr, r, g, b)) {
251 fl::vector<u8> color;
252 color.push_back(r);
253 color.push_back(g);
254 color.push_back(b);
255 seg.mColors.push_back(color);
256 } else {
257 FL_WARN("WLED: invalid hex color string: " << hexStr);
258 }
259 }
260 }
261 }
262
263 // Parse "i" field (individual LED control)
264 if (segJson.contains("i") && segJson["i"].is_array()) {
266
267 size_t ledIndex = 0;
268 for (size_t i = 0; i < segJson["i"].size(); i++) {
269 const fl::json& ledJson = segJson["i"][i];
270
271 if (!ledJson.is_string()) {
272 continue;
273 }
274
275 fl::string ledStr = ledJson | fl::string("");
276
277 // Check for indexed or range format: "RRGGBB|index" or "RRGGBB|start-end"
278 size_t pipePos = ledStr.find('|');
279
280 fl::string hexStr;
281 size_t startIdx = ledIndex;
282 size_t endIdx = ledIndex;
283
284 if (pipePos != fl::string::npos) {
285 // Has index/range specifier
286 hexStr = ledStr.substr(0, pipePos);
287 fl::string indexStr = ledStr.substr(pipePos + 1);
288
289 // Check for range: "start-end"
290 size_t dashPos = indexStr.find('-');
291 if (dashPos != fl::string::npos) {
292 // Range format
293 fl::string startStr = indexStr.substr(0, dashPos);
294 fl::string endStr = indexStr.substr(dashPos + 1);
295
296 // Parse start and end indices
297 char* endptr;
298 long startVal = fl::strtol(startStr.c_str(), &endptr, 10);
299 if (endptr == startStr.c_str() || startVal < 0) {
300 FL_WARN("WLED: invalid range start index: " << startStr);
301 continue;
302 }
303
304 long endVal = fl::strtol(endStr.c_str(), &endptr, 10);
305 if (endptr == endStr.c_str() || endVal < 0) {
306 FL_WARN("WLED: invalid range end index: " << endStr);
307 continue;
308 }
309
310 startIdx = static_cast<size_t>(startVal);
311 endIdx = static_cast<size_t>(endVal);
312 } else {
313 // Single index format
314 char* endptr;
315 long idxVal = fl::strtol(indexStr.c_str(), &endptr, 10);
316 if (endptr == indexStr.c_str() || idxVal < 0) {
317 FL_WARN("WLED: invalid LED index: " << indexStr);
318 continue;
319 }
320 startIdx = endIdx = static_cast<size_t>(idxVal);
321 }
322 } else {
323 // Sequential format (no index specifier)
324 hexStr = ledStr;
325 ledIndex++;
326 }
327
328 // Parse hex color
329 u8 r, g, b;
330 if (!parseHexColor(hexStr, r, g, b)) {
331 FL_WARN("WLED: invalid hex color in individual LED: " << hexStr);
332 continue;
333 }
334
335 // Ensure array is large enough
336 size_t maxIdx = (endIdx > startIdx) ? endIdx : startIdx;
337 if (seg.mIndividualLeds.size() <= maxIdx) {
338 seg.mIndividualLeds.resize(maxIdx + 1);
339 }
340
341 // Set LEDs in range
342 for (size_t idx = startIdx; idx <= endIdx; idx++) {
343 seg.mIndividualLeds[idx].clear();
344 seg.mIndividualLeds[idx].push_back(r);
345 seg.mIndividualLeds[idx].push_back(g);
346 seg.mIndividualLeds[idx].push_back(b);
347 }
348 }
349 }
350}
fl::size find(const char &value) const FL_NOEXCEPT
const char * c_str() const FL_NOEXCEPT
bool is_array() const FL_NOEXCEPT
Definition json.h:246
size_t size() const FL_NOEXCEPT
Definition json.h:633
bool is_string() const FL_NOEXCEPT
Definition json.h:245
bool contains(size_t idx) const FL_NOEXCEPT
Definition json.h:625
string substr(fl::size start, fl::size length) const FL_NOEXCEPT
static constexpr fl::size npos
Definition string.h:195
fl::size size() const FL_NOEXCEPT
void clear() FL_NOEXCEPT
Definition vector.h:634
void push_back(const T &value) FL_NOEXCEPT
Definition vector.h:624
void resize(fl::size n) FL_NOEXCEPT
Definition vector.h:593
fl::i64 i64
Definition s16x16x4.h:222
#define FL_WARN(X)
Definition log.h:276
bool parseHexColor(const fl::string &hexStr, u8 &r, u8 &g, u8 &b)
Parse hex color string to RGB components.
unsigned char u8
Definition stdint.h:131
fl::i64 i64
Definition s16x16x4.h:222
long strtol(const char *str, char **endptr, int base)
fl::vector< fl::vector< u8 > > mColors
Definition segment.h:24
fl::string mName
Definition segment.h:54
fl::vector< fl::vector< u8 > > mIndividualLeds
Definition segment.h:58

References fl::basic_string::c_str(), fl::vector< T >::clear(), fl::json::contains(), fl::basic_string::find(), FL_WARN, fl::json::is_array(), fl::json::is_bool(), fl::json::is_int(), fl::json::is_string(), fl::WLEDSegment::mBri, fl::WLEDSegment::mC1, fl::WLEDSegment::mC2, fl::WLEDSegment::mC3, fl::WLEDSegment::mCct, fl::WLEDSegment::mColors, fl::WLEDSegment::mFx, fl::WLEDSegment::mGrp, fl::WLEDSegment::mIndividualLeds, fl::WLEDSegment::mIx, fl::WLEDSegment::mLen, fl::WLEDSegment::mM12, fl::WLEDSegment::mMi, fl::WLEDSegment::mName, fl::WLEDSegment::mO1, fl::WLEDSegment::mO2, fl::WLEDSegment::mO3, fl::WLEDSegment::mOf, fl::WLEDSegment::mOn, fl::WLEDSegment::mPal, fl::WLEDSegment::mRev, fl::WLEDSegment::mRpt, fl::WLEDSegment::mSel, fl::WLEDSegment::mSi, fl::WLEDSegment::mSpc, fl::WLEDSegment::mStart, fl::WLEDSegment::mStop, fl::WLEDSegment::mSx, fl::string::npos, parseHexColor(), fl::vector< T >::push_back(), fl::vector< T >::resize(), fl::json::size(), fl::vector_basic::size(), fl::strtol(), and fl::string::substr().

Referenced by fl::WLED::setState().

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