fix: leave out /controller items that overflow instead of breaking the JSON

The formatter drops a value that doesn't fit but keeps appending the
commas and braces after it, so an oversized shade or group streamed
invalid JSON.  Check overflowed() after each unit, log the item and skip
it, and keep producing until a unit or the end so a skip never ends the
stream early.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
cjkas 2026-10-12 17:59:39 +02:00
parent 03eb3b3d99
commit ab0eba2035

View file

@ -533,8 +533,23 @@ private:
fmt.setBuffer(unit + offset, sizeof(unit) - offset);
}
// An item too big for the unit buffer is left out so the JSON stays valid.
// Skipping one produces nothing, so go on to the next until something is
// produced or the document is done.
void produceNext() {
consumed = 0;
do produceUnit(); while(unitLen == 0 && section != S_DONE);
}
// True when the unit just formatted didn't fit. It is logged and skipped.
bool overflowed(const char *what, uint8_t id) {
if(!fmt.overflowed()) return false;
ESP_LOGE(TAG, "/controller: %s %u doesn't fit in %u bytes, leaving it out", what, id, (unsigned)sizeof(unit));
unitLen = 0;
return true;
}
void produceUnit() {
unitLen = 0;
switch(section) {
case S_HEADER: {
@ -555,6 +570,8 @@ private:
serializeGitVersion(fmt);
fmt.endObject();
fmt.beginArray("rooms");
// Only fixed size values so this can't happen short of a bug.
if(fmt.overflowed()) ESP_LOGE(TAG, "/controller: header doesn't fit in %u bytes", (unsigned)sizeof(unit));
unitLen = fmt.length();
section = S_ROOMS;
idx = 0;
@ -577,6 +594,7 @@ private:
fmt.beginObject();
serializeRoom(&somfy.rooms[idx], fmt);
fmt.endObject();
if(overflowed("room", somfy.rooms[idx].roomId)) { idx++; return; }
unitLen = pos + fmt.length();
idx++;
firstInArray = false;
@ -599,6 +617,7 @@ private:
fmt.beginObject();
serializeShade(&somfy.shades[idx], fmt);
fmt.endObject();
if(overflowed("shade", somfy.shades[idx].getShadeId())) { idx++; return; }
unitLen = pos + fmt.length();
idx++;
firstInArray = false;
@ -622,6 +641,7 @@ private:
fmt.beginObject();
serializeGroupRef(g, fmt);
fmt.beginArray("linkedShades");
if(overflowed("group", g->getGroupId())) { idx++; return; }
unitLen = pos + fmt.length();
lsIdx = 0;
firstInArray = false;
@ -650,6 +670,7 @@ private:
fmt.beginObject();
serializeShadeRef(lshade, fmt);
fmt.endObject();
if(overflowed("linked shade", lshade->getShadeId())) { lsIdx++; return; }
unitLen = pos + fmt.length();
lsIdx++;
firstInLSArray = false;