diff --git a/arch/portduino/portduino.ini b/arch/portduino/portduino.ini index 890169c28..6af3a7717 100644 --- a/arch/portduino/portduino.ini +++ b/arch/portduino/portduino.ini @@ -2,7 +2,7 @@ [portduino_base] platform = # renovate: datasource=git-refs depName=platform-native packageName=https://github.com/meshtastic/platform-native gitBranch=develop - https://github.com/meshtastic/platform-native/archive/e19f77e034590669feaaf26214667b76d0821d06.zip + https://github.com/meshtastic/platform-native/archive/622341c6de8a239704318b10c3dbb00c21a3eab3.zip framework = arduino build_src_filter = diff --git a/platformio.ini b/platformio.ini index 527140835..73a9bbe1f 100644 --- a/platformio.ini +++ b/platformio.ini @@ -108,7 +108,7 @@ lib_deps = [device-ui_base] lib_deps = # renovate: datasource=git-refs depName=meshtastic-device-ui packageName=https://github.com/meshtastic/device-ui gitBranch=master - https://github.com/meshtastic/device-ui/archive/8113d4ff5a63280834acfeb7584f179cdc6376b6.zip + https://github.com/meshtastic/device-ui/archive/33aa6890f7862d81c2bc1658f43eeea7a8081c6e.zip ; Common libs for environmental measurements in telemetry module [environmental_base] 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..d0bd35250 100644 --- a/src/graphics/niche/InkHUD/Events.cpp +++ b/src/graphics/niche/InkHUD/Events.cpp @@ -3,11 +3,13 @@ #include "./Events.h" #include "RTC.h" +#include "modules/AdminModule.h" #include "modules/TextMessageModule.h" #include "sleep.h" #include "./Applet.h" #include "./SystemApplet.h" +#include "graphics/niche/FlashData.h" using namespace NicheGraphics; @@ -25,6 +27,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 +122,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 +181,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..489135ea3 100644 --- a/src/graphics/niche/InkHUD/Events.h +++ b/src/graphics/niche/InkHUD/Events.h @@ -33,6 +33,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 +53,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..c3082add1 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::eraseOnReboot = 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/graphics/tftSetup.cpp b/src/graphics/tftSetup.cpp index a8d51bb82..b2e92bdae 100644 --- a/src/graphics/tftSetup.cpp +++ b/src/graphics/tftSetup.cpp @@ -43,10 +43,10 @@ void tftSetup(void) #else if (settingsMap[displayPanel] != no_screen) { DisplayDriverConfig displayConfig; - static char *panels[] = {"NOSCREEN", "X11", "ST7789", "ST7735", "ST7735S", "ST7796", - "ILI9341", "ILI9342", "ILI9486", "ILI9488", "HX8357D"}; + static char *panels[] = {"NOSCREEN", "X11", "FB", "ST7789", "ST7735", "ST7735S", + "ST7796", "ILI9341", "ILI9342", "ILI9486", "ILI9488", "HX8357D"}; static char *touch[] = {"NOTOUCH", "XPT2046", "STMPE610", "GT911", "FT5x06"}; -#ifdef USE_X11 +#if defined(USE_X11) if (settingsMap[displayPanel] == x11) { if (settingsMap[displayWidth] && settingsMap[displayHeight]) displayConfig = DisplayDriverConfig(DisplayDriverConfig::device_t::X11, (uint16_t)settingsMap[displayWidth], @@ -54,6 +54,14 @@ void tftSetup(void) else displayConfig.device(DisplayDriverConfig::device_t::X11); } else +#elif defined(USE_FRAMEBUFFER) + if (settingsMap[displayPanel] == fb) { + if (settingsMap[displayWidth] && settingsMap[displayHeight]) + displayConfig = DisplayDriverConfig(DisplayDriverConfig::device_t::FB, (uint16_t)settingsMap[displayWidth], + (uint16_t)settingsMap[displayHeight]); + else + displayConfig.device(DisplayDriverConfig::device_t::FB); + } else #endif { displayConfig.device(DisplayDriverConfig::device_t::CUSTOM_TFT) 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; } diff --git a/src/platform/portduino/PortduinoGlue.cpp b/src/platform/portduino/PortduinoGlue.cpp index 6d0972dc3..4b96e662a 100644 --- a/src/platform/portduino/PortduinoGlue.cpp +++ b/src/platform/portduino/PortduinoGlue.cpp @@ -531,6 +531,8 @@ bool loadConfig(const char *configPath) settingsMap[displayPanel] = hx8357d; else if (yamlConfig["Display"]["Panel"].as("") == "X11") settingsMap[displayPanel] = x11; + else if (yamlConfig["Display"]["Panel"].as("") == "FB") + settingsMap[displayPanel] = fb; settingsMap[displayHeight] = yamlConfig["Display"]["Height"].as(0); settingsMap[displayWidth] = yamlConfig["Display"]["Width"].as(0); settingsMap[displayDC] = yamlConfig["Display"]["DC"].as(-1); diff --git a/src/platform/portduino/PortduinoGlue.h b/src/platform/portduino/PortduinoGlue.h index f7239cb73..6393d7294 100644 --- a/src/platform/portduino/PortduinoGlue.h +++ b/src/platform/portduino/PortduinoGlue.h @@ -102,7 +102,7 @@ enum configNames { available_directory, mac_address }; -enum { no_screen, x11, st7789, st7735, st7735s, st7796, ili9341, ili9342, ili9486, ili9488, hx8357d }; +enum { no_screen, x11, fb, st7789, st7735, st7735s, st7796, ili9341, ili9342, ili9486, ili9488, hx8357d }; enum { no_touchscreen, xpt2046, stmpe610, gt911, ft5x06 }; enum { level_error, level_warn, level_info, level_debug, level_trace }; diff --git a/variants/portduino/platformio.ini b/variants/portduino/platformio.ini index 7a3392eb4..fe89ad6e6 100644 --- a/variants/portduino/platformio.ini +++ b/variants/portduino/platformio.ini @@ -43,6 +43,37 @@ build_src_filter = ${native_base.build_src_filter} - +[env:native-fb] +extends = native_base +build_type = release +lib_deps = + ${native_base.lib_deps} + ${device-ui_base.lib_deps} +board_level = extra +build_flags = ${native_base.build_flags} -Os -ffunction-sections -fdata-sections -Wl,--gc-sections + -D MESHTASTIC_EXCLUDE_CANNEDMESSAGES=1 + -D RAM_SIZE=8192 + -D USE_FRAMEBUFFER=1 + -D LV_COLOR_DEPTH=32 + -D HAS_TFT=1 + -D HAS_SCREEN=0 + -D LV_BUILD_TEST=0 + -D LV_USE_LOG=0 + -D LV_USE_EVDEV=1 + -D LV_LVGL_H_INCLUDE_SIMPLE + -D LV_CONF_INCLUDE_SIMPLE + -D LV_COMP_CONF_INCLUDE_SIMPLE + -D USE_LOG_DEBUG + -D LOG_DEBUG_INC=\"DebugConfiguration.h\" + -D USE_PACKET_API + -D VIEW_320x240 + -D MAP_FULL_REDRAW + !pkg-config --libs libulfius --silence-errors || : + !pkg-config --libs openssl --silence-errors || : +build_src_filter = + ${native_base.build_src_filter} + - + [env:native-tft-debug] extends = native_base build_type = debug