From 0f38b01517f180844f47c2ab4ccbafdb8ac23018 Mon Sep 17 00:00:00 2001 From: Todd Herbert Date: Sun, 20 Apr 2025 19:03:11 +1200 Subject: [PATCH] Erase InkHUD settings on factory reset --- src/graphics/Screen.cpp | 3 --- src/graphics/niche/FlashData.h | 23 ++++++++++++++++++ src/graphics/niche/InkHUD/Events.cpp | 30 ++++++++++++++++++++++-- src/graphics/niche/InkHUD/Events.h | 9 +++++++ src/graphics/niche/InkHUD/docs/README.md | 4 ++++ src/modules/AdminModule.cpp | 4 +++- 6 files changed, 67 insertions(+), 6 deletions(-) diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index ad0b94efe..1ee0c0fdd 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -2840,9 +2840,6 @@ int Screen::handleInputEvent(const InputEvent *event) int Screen::handleAdminMessage(const meshtastic_AdminMessage *arg) { - // Note: only selected admin messages notify this observer - // If you wish to handle a new type of message, you should modify AdminModule.cpp first - switch (arg->which_payload_variant) { // Node removed manually (i.e. via app) case meshtastic_AdminMessage_remove_by_nodenum_tag: diff --git a/src/graphics/niche/FlashData.h b/src/graphics/niche/FlashData.h index 8a63c6108..a27c4aea0 100644 --- a/src/graphics/niche/FlashData.h +++ b/src/graphics/niche/FlashData.h @@ -135,6 +135,29 @@ template class FlashData } }; +// Erase contents of the NicheGraphics data directory +inline void clearFlashData() +{ + +#ifdef FSCom + File dir = FSCom.open("/NicheGraphics"); // Open the directory + File file = dir.openNextFile(); // Attempt to open the first file in the directory + + // While the directory still contains files + while (file) { + std::string path = "/NicheGraphics/"; + path += file.name(); + LOG_DEBUG("Erasing %s", path.c_str()); + file.close(); + FSCom.remove(path.c_str()); + + file = dir.openNextFile(); + } +#else + LOG_ERROR("ERROR: Filesystem not implemented\n"); +#endif +} + } // namespace NicheGraphics #endif \ No newline at end of file diff --git a/src/graphics/niche/InkHUD/Events.cpp b/src/graphics/niche/InkHUD/Events.cpp index ddd01b7e1..e5a9646e0 100644 --- a/src/graphics/niche/InkHUD/Events.cpp +++ b/src/graphics/niche/InkHUD/Events.cpp @@ -8,6 +8,7 @@ #include "./Applet.h" #include "./SystemApplet.h" +#include "graphics/niche/FlashData.h" using namespace NicheGraphics; @@ -25,6 +26,9 @@ void InkHUD::Events::begin() deepSleepObserver.observe(¬ifyDeepSleep); rebootObserver.observe(¬ifyReboot); textMessageObserver.observe(textMessageModule); +#if !MESHTASTIC_EXCLUDE_ADMIN + adminMessageObserver.observe(adminModule); +#endif #ifdef ARCH_ESP32 lightSleepObserver.observe(¬ifyLightSleep); #endif @@ -117,8 +121,13 @@ int InkHUD::Events::beforeReboot(void *unused) sa->onReboot(); } - inkhud->persistence->saveSettings(); - inkhud->persistence->saveLatestMessage(); + // Save settings to flash, or erase if factory reset in progress + if (!eraseOnReboot) { + inkhud->persistence->saveSettings(); + inkhud->persistence->saveLatestMessage(); + } else { + NicheGraphics::clearFlashData(); + } // Note: no forceUpdate call here // We don't have any final screen to draw, although LogoApplet::onReboot did already display a "rebooting" screen @@ -171,6 +180,23 @@ int InkHUD::Events::onReceiveTextMessage(const meshtastic_MeshPacket *packet) return 0; // Tell caller to continue notifying other observers. (No reason to abort this event) } +int InkHUD::Events::onAdminMessage(const meshtastic_AdminMessage *message) +{ + switch (message->which_payload_variant) { + // Factory reset + // Two possible messages. One preserves BLE bonds, other wipes. Both should clear InkHUD data. + case meshtastic_AdminMessage_factory_reset_device_tag: + case meshtastic_AdminMessage_factory_reset_config_tag: + eraseOnReboot = true; + break; + + default: + break; + } + + return 0; // Tell caller to continue notifying other observers. (No reason to abort this event) +} + #ifdef ARCH_ESP32 // Callback for lightSleepObserver // Make sure the display is not partway through an update when we begin light sleep diff --git a/src/graphics/niche/InkHUD/Events.h b/src/graphics/niche/InkHUD/Events.h index 6a6e9d7a2..44f1bef56 100644 --- a/src/graphics/niche/InkHUD/Events.h +++ b/src/graphics/niche/InkHUD/Events.h @@ -13,6 +13,7 @@ however this class handles general events which concern InkHUD as a whole, e.g. #include "configuration.h" +#include "Modules/AdminModule.h" #include "Observer.h" #include "./InkHUD.h" @@ -33,6 +34,7 @@ class Events int beforeDeepSleep(void *unused); // Prepare for shutdown int beforeReboot(void *unused); // Prepare for reboot int onReceiveTextMessage(const meshtastic_MeshPacket *packet); // Store most recent text message + int onAdminMessage(const meshtastic_AdminMessage *message); // Handle incoming admin messages #ifdef ARCH_ESP32 int beforeLightSleep(void *unused); // Prepare for light sleep #endif @@ -52,10 +54,17 @@ class Events CallbackObserver textMessageObserver = CallbackObserver(this, &Events::onReceiveTextMessage); + // Get notified of incoming admin messages, and handle any which are relevant to InkHUD + CallbackObserver adminMessageObserver = + CallbackObserver(this, &Events::onAdminMessage); + #ifdef ARCH_ESP32 // Get notified when the system is entering light sleep CallbackObserver lightSleepObserver = CallbackObserver(this, &Events::beforeLightSleep); #endif + + // If set, InkHUD's data will be erased during onReboot + bool eraseOnReboot = false; }; } // namespace NicheGraphics::InkHUD diff --git a/src/graphics/niche/InkHUD/docs/README.md b/src/graphics/niche/InkHUD/docs/README.md index 07fe6c942..a03c72e0e 100644 --- a/src/graphics/niche/InkHUD/docs/README.md +++ b/src/graphics/niche/InkHUD/docs/README.md @@ -502,6 +502,10 @@ Applets themselves do also listen separately for various events, but for the pur Button input is sometimes handled by a system applet. `InkHUD::Events` determines whether the button should be handled by a specific system applet, or should instead trigger a default behavior +#### Factory Reset + +The Events class handles the admin messages(s) which trigger factory reset. We set `Events::doFactoryReset = true`, which causes `Events::onReboot` to erase the contents of InkHUD's data directory. We do this because some applets (e.g. ThreadedMessageApplet) save their own data to flash, so if we erased earlier, that data would get re-written during reboot. + --- ### `InkHUD::Applet` diff --git a/src/modules/AdminModule.cpp b/src/modules/AdminModule.cpp index 88109bc78..650910542 100644 --- a/src/modules/AdminModule.cpp +++ b/src/modules/AdminModule.cpp @@ -284,7 +284,6 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta case meshtastic_AdminMessage_remove_by_nodenum_tag: { LOG_INFO("Client received remove_nodenum command"); nodeDB->removeNodeByNum(r->remove_by_nodenum); - this->notifyObservers(r); // Observed by screen break; } case meshtastic_AdminMessage_set_favorite_node_tag: { @@ -444,6 +443,9 @@ bool AdminModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshta myReply = allocErrorResponse(meshtastic_Routing_Error_NONE, &mp); } + // Allow any observers (e.g. the UI) to respond to this event + notifyObservers(r); + return handled; }