The dev-only cap that forced every-1-min polling regardless of the app's
schedule is removed. The device now sleeps for whatever X-Interval-Ms
the server hands back (driven by rotationIntervalMinutes / wakeTimes),
clamped to [30s, 25h] as a safety net against malformed values.
Renamed FETCH_INTERVAL_MS to FETCH_INTERVAL_MS_FALLBACK — it's now
*only* used when the header is absent (rare; rolling deploy / hand-
crafted response). Added SLEEP_CLAMP_MIN/MAX for the bounds.
Tests FW-09 and FW-10 flipped to lock the new behavior; added FW-10b
covering sub-MIN clamping (battery protection if server sends 1000ms).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three bugs fixed:
- NVS img_id now written before epd_init/draw; new draw_needed flag in NVS
survives power-loss mid-refresh so next boot re-draws from LittleFS instead
of showing stale content
- epd_sleep() now only called when display was initialized this cycle,
preventing a 60 s wait_busy() timeout on every 304 poll
- esp_task_wdt_reset() added to wait_busy() loop so the ~20 s 6-color
refresh no longer triggers the task watchdog
Also extracts normal_operation into operation.h template and adds
a native PlatformIO test suite (16 tests) covering the full response matrix.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>