From d38e4ddb4cc82bf4a371e75ddb54c5c2922f8a0d Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sun, 5 Jul 2026 17:18:49 -0400 Subject: [PATCH] Clear displayed_etag on etag-less full refresh An etag-less full upload (or auto-complete) changes the panel pixels but left displayed_etag at its previous value, since it was only assigned inside the `hasNewEtag && newEtag != 0` guard. A later partial update (0x76) from another client whose oldEtag happened to match that stale value would pass the mismatch check and diff against the wrong, outdated base image, causing silent visual corruption. On a successful refresh with no valid etag, clear displayed_etag to 0 (invalid/unknown) so any subsequent partial gets a clean ETAG mismatch and falls back to a full upload. Behavior when a real etag is supplied is unchanged. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_012g2e8mr132vcizx92WsgiR --- src/display_service.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/display_service.cpp b/src/display_service.cpp index e508d44..b7daf6c 100644 --- a/src/display_service.cpp +++ b/src/display_service.cpp @@ -1751,7 +1751,13 @@ void handleDirectWriteEnd(uint8_t* data, uint16_t len) { esp32_restart_ble_advertising(); #endif if (refreshSuccess) { + // A successful refresh changed the panel image. Commit the new etag + // when the client supplied a valid one; otherwise clear the stale etag + // (etag-less full upload / auto-complete) so a later partial update + // gets a clean ETAG mismatch and falls back to a full upload instead + // of diffing against the wrong, now-outdated base image. if (hasNewEtag && newEtag != 0) displayed_etag = newEtag; + else displayed_etag = 0; uint8_t refreshResponse[] = {0x00, 0x73}; sendResponse(refreshResponse, sizeof(refreshResponse)); } else {