From f4c568b615433e81ff10e2a4c4c3ed65f469f91c Mon Sep 17 00:00:00 2001 From: Wessel Nieboer Date: Fri, 6 Feb 2026 03:48:15 +0100 Subject: [PATCH] Fix orphan blob accumulation on firmware upgrade Before PR#1495, blobs were written for every advert regardless of whether the advertiser became a contact. Nodes upgrading from older firmware (e.g., v1.11.0) have thousands of orphan blobs consuming storage space. This adds a one-time cleanup on first boot that: - Iterates all blob files in /bl/ - Deletes any blob that doesn't match a current contact's pub_key - Creates a marker file to prevent running again Affects ESP32 and RP2040 platforms (which use /bl/ directory). --- examples/companion_radio/MyMesh.cpp | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/examples/companion_radio/MyMesh.cpp b/examples/companion_radio/MyMesh.cpp index 60a5a75f..c305bbde 100644 --- a/examples/companion_radio/MyMesh.cpp +++ b/examples/companion_radio/MyMesh.cpp @@ -929,6 +929,35 @@ void MyMesh::begin(bool has_display) { resetContacts(); _store->loadContacts(this); bootstrapRTCfromContacts(); + +#if defined(ESP32) || defined(RP2040_PLATFORM) + // One-time cleanup of orphan blobs from pre-v1.13 firmware + FILESYSTEM* fs = _store->getPrimaryFS(); + if (!fs->exists("/bl/.cleaned")) { + MESH_DEBUG_PRINTLN("Cleaning orphan blobs..."); + File root = _store->openRead("/bl"); + if (root) { + for (File f = root.openNextFile(); f; f = root.openNextFile()) { + const char* name = f.name(); + f.close(); + uint8_t key[8]; + if (name[0] != '.' && strlen(name) == 16 && mesh::Utils::fromHex(key, 8, name)) { + bool found = false; + for (int i = 0; i < num_contacts && !found; i++) + found = (memcmp(contacts[i].id.pub_key, key, 8) == 0); + if (!found) _store->deleteBlobByKey(key, 8); + } + } + root.close(); + } +#if defined(ESP32) + File m = fs->open("/bl/.cleaned", "w", true); +#else + File m = fs->open("/bl/.cleaned", "w"); +#endif + if (m) m.close(); + } +#endif addChannel("Public", PUBLIC_GROUP_PSK); // pre-configure Andy's public channel _store->loadChannels(this);