diff --git a/.github/workflows/test_native.yml b/.github/workflows/test_native.yml index 536d93665..dc05959fd 100644 --- a/.github/workflows/test_native.yml +++ b/.github/workflows/test_native.yml @@ -143,7 +143,7 @@ jobs: merge-multiple: true - name: Test Report - uses: dorny/test-reporter@v2.1.0 + uses: dorny/test-reporter@v2.1.1 with: name: PlatformIO Tests path: testreport.xml diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index 0986e6eb0..f0271c856 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -8,8 +8,8 @@ plugins: uri: https://github.com/trunk-io/plugins lint: enabled: - - checkov@3.2.447 - - renovate@41.23.4 + - checkov@3.2.450 + - renovate@41.29.1 - prettier@3.6.2 - trufflehog@3.89.2 - yamllint@1.37.1 diff --git a/bin/config.d/lora-ws-raspberry-pico-to-orangepi-03.yaml b/bin/config.d/lora-ws-raspberry-pico-to-orangepi-03.yaml new file mode 100644 index 000000000..37d7e27d2 --- /dev/null +++ b/bin/config.d/lora-ws-raspberry-pico-to-orangepi-03.yaml @@ -0,0 +1,52 @@ +# https://www.waveshare.com/pico-lora-sx1262-868m.htm +# http://www.orangepi.org/html/hardWare/computerAndMicrocontrollers/details/Orange-Pi-Zero-3.html +# +# See Orange Pi Zero3 manual, chapter 3.16, page 124 for 26-pin header pinout +# +# Pin Connection +# Waveshare Orange Pi Zero3 +# 36 3.3V 17 +# 15 MOSI 19 +# 16 MISO 21 +# 14 CLK 23 +# 38 GND 25 +# 4 BUSY 18 +# 20 RESET 22 +# 5 CS 24 +# 26 DIO1/IRQ 26 + +Lora: + Module: sx1262 # Waveshare Raspberry Pico Lora module + DIO2_AS_RF_SWITCH: true + DIO3_TCXO_VOLTAGE: true + # Specify either the spidev1_1 or the CS below, not both! + # On DietPi Linux, when using the user overlay dietpi-spi1_1.dtbo, CS will be configured with spidev1.1 + spidev: spidev1.1 # See Orange Pi Zero3 manual, chapter 3.18.3, page 130 +# CS: # CS PIN_24 -> chip 1, line 233 +# pin: 24 +# gpiochip: 1 +# line: 233 + SCK: # SCK PIN_23 -> chip 1, line 230 + pin: 23 + gpiochip: 1 + line: 230 + Busy: # BUSY PIN_18 -> chip 1, line 78 + pin: 18 + gpiochip: 1 + line: 78 + MOSI: # MOSI PIN_19 -> chip 1, line 231 + pin: 19 + gpiochip: 1 + line: 231 + MISO: # MISO PIN_21 -> chip 1, line 232 + pin: 21 + gpiochip: 1 + line: 232 + Reset: # NRST PIN_22 -> chip 1, line 71 + pin: 22 + gpiochip: 1 + line: 71 + IRQ: # DIO1 PIN_26 -> chip 1, line 74 + pin: 26 + gpiochip: 1 + line: 74 diff --git a/bin/org.meshtastic.meshtasticd.metainfo.xml b/bin/org.meshtastic.meshtasticd.metainfo.xml index 47082718a..291fe7a7c 100644 --- a/bin/org.meshtastic.meshtasticd.metainfo.xml +++ b/bin/org.meshtastic.meshtasticd.metainfo.xml @@ -87,6 +87,9 @@ + + https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.3 + https://github.com/meshtastic/firmware/releases?q=tag%3Av2.7.2 diff --git a/debian/changelog b/debian/changelog index 42488692b..b5009028a 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -meshtasticd (2.7.2.0) UNRELEASED; urgency=medium +meshtasticd (2.7.3.0) UNRELEASED; urgency=medium [ Austin Lane ] * Initial packaging @@ -28,4 +28,7 @@ meshtasticd (2.7.2.0) UNRELEASED; urgency=medium [ ] * GitHub Actions Automatic version bump - -- Fri, 04 Jul 2025 11:58:01 +0000 + [ Ubuntu ] + * GitHub Actions Automatic version bump + + -- Ubuntu Thu, 10 Jul 2025 16:29:27 +0000 diff --git a/platformio.ini b/platformio.ini index 89720f0ad..352d7e8d4 100644 --- a/platformio.ini +++ b/platformio.ini @@ -104,18 +104,18 @@ lib_deps = [radiolib_base] lib_deps = # renovate: datasource=custom.pio depName=RadioLib packageName=jgromes/library/RadioLib - jgromes/RadioLib@7.2.0 + jgromes/RadioLib@7.2.1 [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/8c7092c73425adfda1aac8c6960df06cd85f6d92.zip + https://github.com/meshtastic/device-ui/archive/404c6e06ecfda8dd2dc9e6d5fe417ae028f8029f.zip ; Common libs for environmental measurements in telemetry module [environmental_base] lib_deps = # renovate: datasource=custom.pio depName=Adafruit BusIO packageName=adafruit/library/Adafruit BusIO - adafruit/Adafruit BusIO@1.17.1 + adafruit/Adafruit BusIO@1.17.2 # renovate: datasource=custom.pio depName=Adafruit Unified Sensor packageName=adafruit/library/Adafruit Unified Sensor adafruit/Adafruit Unified Sensor@1.1.15 # renovate: datasource=custom.pio depName=Adafruit BMP280 packageName=adafruit/library/Adafruit BMP280 Library diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 2bade47b2..57ea64fa9 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -21,6 +21,7 @@ along with this program. If not, see . */ #include "Screen.h" +#include "NodeDB.h" #include "PowerMon.h" #include "Throttle.h" #include "configuration.h" @@ -44,7 +45,6 @@ along with this program. If not, see . #endif #include "FSCommon.h" #include "MeshService.h" -#include "NodeDB.h" #include "RadioLibInterface.h" #include "error.h" #include "gps/GeoCoord.h" @@ -1257,40 +1257,45 @@ int Screen::handleTextMessage(const meshtastic_MeshPacket *packet) devicestate.has_rx_text_message = true; // Needed to include the message frame hasUnreadMessage = true; // Enables mail icon in the header setFrames(FOCUS_PRESERVE); // Refresh frame list without switching view - forceDisplay(); // Forces screen redraw - // === Prepare banner content === - const meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(packet->from); - const char *longName = (node && node->has_user) ? node->user.long_name : nullptr; + // Only wake/force display if the configuration allows it + if (shouldWakeOnReceivedMessage()) { + setOn(true); // Wake up the screen first + forceDisplay(); // Forces screen redraw - const char *msgRaw = reinterpret_cast(packet->decoded.payload.bytes); + // === Prepare banner content === + const meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(packet->from); + const char *longName = (node && node->has_user) ? node->user.long_name : nullptr; - char banner[256]; + const char *msgRaw = reinterpret_cast(packet->decoded.payload.bytes); - // Check for bell character in message to determine alert type - bool isAlert = false; - for (size_t i = 0; i < packet->decoded.payload.size && i < 100; i++) { - if (msgRaw[i] == '\x07') { - isAlert = true; - break; + char banner[256]; + + // Check for bell character in message to determine alert type + bool isAlert = false; + for (size_t i = 0; i < packet->decoded.payload.size && i < 100; i++) { + if (msgRaw[i] == '\x07') { + isAlert = true; + break; + } } - } - if (isAlert) { - if (longName && longName[0]) { - snprintf(banner, sizeof(banner), "Alert Received from\n%s", longName); + if (isAlert) { + if (longName && longName[0]) { + snprintf(banner, sizeof(banner), "Alert Received from\n%s", longName); + } else { + strcpy(banner, "Alert Received"); + } } else { - strcpy(banner, "Alert Received"); + if (longName && longName[0]) { + snprintf(banner, sizeof(banner), "New Message from\n%s", longName); + } else { + strcpy(banner, "New Message"); + } } - } else { - if (longName && longName[0]) { - snprintf(banner, sizeof(banner), "New Message from\n%s", longName); - } else { - strcpy(banner, "New Message"); - } - } - screen->showSimpleBanner(banner, 3000); + screen->showSimpleBanner(banner, 3000); + } } } @@ -1423,3 +1428,23 @@ bool Screen::isOverlayBannerShowing() #else graphics::Screen::Screen(ScanI2C::DeviceAddress, meshtastic_Config_DisplayConfig_OledType, OLEDDISPLAY_GEOMETRY) {} #endif // HAS_SCREEN + +bool shouldWakeOnReceivedMessage() +{ + /* + The goal here is to determine when we do NOT wake up the screen on message received: + - Any ext. notifications are turned on + - If role is not client / client_mute + - If the battery level is very low + */ + if (moduleConfig.external_notification.enabled) { + return false; + } + if (!meshtastic_Config_DeviceConfig_Role_CLIENT && !meshtastic_Config_DeviceConfig_Role_CLIENT_MUTE) { + return false; + } + if (powerStatus && powerStatus->getBatteryChargePercent() < 10) { + return false; + } + return true; +} \ No newline at end of file diff --git a/src/graphics/Screen.h b/src/graphics/Screen.h index 4deeb7395..265900131 100644 --- a/src/graphics/Screen.h +++ b/src/graphics/Screen.h @@ -26,6 +26,8 @@ struct BannerOverlayOptions { }; } // namespace graphics +bool shouldWakeOnReceivedMessage(); + #if !HAS_SCREEN #include "power.h" namespace graphics diff --git a/src/graphics/draw/MenuHandler.cpp b/src/graphics/draw/MenuHandler.cpp index c3a035c4f..f6b250ebc 100644 --- a/src/graphics/draw/MenuHandler.cpp +++ b/src/graphics/draw/MenuHandler.cpp @@ -129,11 +129,11 @@ void menuHandler::ClockFacePicker() screen->runNow(); } else if (selected == Digital) { uiconfig.is_clockface_analog = false; - nodeDB->saveProto("/prefs/uiconfig.proto", meshtastic_DeviceUIConfig_size, &meshtastic_DeviceUIConfig_msg, &uiconfig); + saveUIConfig(); screen->setFrames(Screen::FOCUS_CLOCK); } else { uiconfig.is_clockface_analog = true; - nodeDB->saveProto("/prefs/uiconfig.proto", meshtastic_DeviceUIConfig_size, &meshtastic_DeviceUIConfig_msg, &uiconfig); + saveUIConfig(); screen->setFrames(Screen::FOCUS_CLOCK); } }; @@ -346,37 +346,28 @@ void menuHandler::homeBaseMenu() void menuHandler::systemBaseMenu() { - // Check if brightness is supported bool hasSupportBrightness = false; #if defined(ST7789_CS) || defined(USE_OLED) || defined(USE_SSD1306) || defined(USE_SH1106) || defined(USE_SH1107) || HAS_TFT hasSupportBrightness = true; #endif - enum optionsNumbers { Back, Beeps, Brightness, Reboot, Color, MUI, Test, enumEnd }; + enum optionsNumbers { Back, Notifications, ScreenOptions, PowerMenu, Test, enumEnd }; static const char *optionsArray[enumEnd] = {"Back"}; static int optionsEnumArray[enumEnd] = {Back}; int options = 1; - optionsArray[options] = "Reboot"; - optionsEnumArray[options++] = Reboot; - - optionsArray[options] = "Beeps Action"; - optionsEnumArray[options++] = Beeps; - - if (hasSupportBrightness) { - optionsArray[options] = "Brightness"; - optionsEnumArray[options++] = Brightness; - } - -#if defined(HELTEC_MESH_NODE_T114) || defined(HELTEC_VISION_MASTER_T190) || HAS_TFT - optionsArray[options] = "Screen Color"; - optionsEnumArray[options++] = Color; -#endif -#if HAS_TFT - optionsArray[options] = "Switch to MUI"; - optionsEnumArray[options++] = MUI; + optionsArray[options] = "Notifications"; + optionsEnumArray[options++] = Notifications; +#if defined(ST7789_CS) || defined(USE_OLED) || defined(USE_SSD1306) || defined(USE_SH1106) || defined(USE_SH1107) || \ + defined(HELTEC_MESH_NODE_T114) || defined(HELTEC_VISION_MASTER_T190) || HAS_TFT + optionsArray[options] = "Screen Options"; + optionsEnumArray[options++] = ScreenOptions; #endif + + optionsArray[options] = "Reboot/Shutdown"; + optionsEnumArray[options++] = PowerMenu; + if (test_enabled) { optionsArray[options] = "Test Menu"; optionsEnumArray[options++] = Test; @@ -388,20 +379,14 @@ void menuHandler::systemBaseMenu() bannerOptions.optionsCount = options; bannerOptions.optionsEnumPtr = optionsEnumArray; bannerOptions.bannerCallback = [](int selected) -> void { - if (selected == Beeps) { - menuHandler::menuQueue = menuHandler::buzzermodemenupicker; + if (selected == Notifications) { + menuHandler::menuQueue = menuHandler::notifications_menu; screen->runNow(); - } else if (selected == Brightness) { - menuHandler::menuQueue = menuHandler::brightness_picker; + } else if (selected == ScreenOptions) { + menuHandler::menuQueue = menuHandler::screen_options_menu; screen->runNow(); - } else if (selected == Reboot) { - menuHandler::menuQueue = menuHandler::reboot_menu; - screen->runNow(); - } else if (selected == MUI) { - menuHandler::menuQueue = menuHandler::mui_picker; - screen->runNow(); - } else if (selected == Color) { - menuHandler::menuQueue = menuHandler::tftcolormenupicker; + } else if (selected == PowerMenu) { + menuHandler::menuQueue = menuHandler::power_menu; screen->runNow(); } else if (selected == Test) { menuHandler::menuQueue = menuHandler::test_menu; @@ -533,22 +518,19 @@ void menuHandler::compassNorthMenu() if (selected == Dynamic) { if (uiconfig.compass_mode != meshtastic_CompassMode_DYNAMIC) { uiconfig.compass_mode = meshtastic_CompassMode_DYNAMIC; - nodeDB->saveProto("/prefs/uiconfig.proto", meshtastic_DeviceUIConfig_size, &meshtastic_DeviceUIConfig_msg, - &uiconfig); + saveUIConfig(); screen->setFrames(graphics::Screen::FOCUS_PRESERVE); } } else if (selected == Fixed) { if (uiconfig.compass_mode != meshtastic_CompassMode_FIXED_RING) { uiconfig.compass_mode = meshtastic_CompassMode_FIXED_RING; - nodeDB->saveProto("/prefs/uiconfig.proto", meshtastic_DeviceUIConfig_size, &meshtastic_DeviceUIConfig_msg, - &uiconfig); + saveUIConfig(); screen->setFrames(graphics::Screen::FOCUS_PRESERVE); } } else if (selected == Freeze) { if (uiconfig.compass_mode != meshtastic_CompassMode_FREEZE_HEADING) { uiconfig.compass_mode = meshtastic_CompassMode_FREEZE_HEADING; - nodeDB->saveProto("/prefs/uiconfig.proto", meshtastic_DeviceUIConfig_size, &meshtastic_DeviceUIConfig_msg, - &uiconfig); + saveUIConfig(); screen->setFrames(graphics::Screen::FOCUS_PRESERVE); } } else if (selected == Back) { @@ -610,7 +592,7 @@ void menuHandler::BuzzerModeMenu() { static const char *optionsArray[] = {"All Enabled", "Disabled", "Notifications", "System Only"}; BannerOverlayOptions bannerOptions; - bannerOptions.message = "Beep Action"; + bannerOptions.message = "Buzzer Mode"; bannerOptions.optionsArrayPtr = optionsArray; bannerOptions.optionsCount = 4; bannerOptions.bannerCallback = [](int selected) -> void { @@ -660,7 +642,7 @@ void menuHandler::BrightnessPickerMenu() #endif // Save to device - nodeDB->saveProto("/prefs/uiconfig.proto", meshtastic_DeviceUIConfig_size, &meshtastic_DeviceUIConfig_msg, &uiconfig); + saveUIConfig(); LOG_INFO("Screen brightness set to %d", uiconfig.screen_brightness); } @@ -671,13 +653,13 @@ void menuHandler::BrightnessPickerMenu() void menuHandler::switchToMUIMenu() { - static const char *optionsArray[] = {"Yes", "No"}; + static const char *optionsArray[] = {"No", "Yes"}; BannerOverlayOptions bannerOptions; bannerOptions.message = "Switch to MUI?"; bannerOptions.optionsArrayPtr = optionsArray; bannerOptions.optionsCount = 2; bannerOptions.bannerCallback = [](int selected) -> void { - if (selected == 0) { + if (selected == 1) { config.display.displaymode = meshtastic_Config_DisplayConfig_DisplayMode_COLOR; config.bluetooth.enabled = false; service->reloadConfig(SEGMENT_CONFIG); @@ -742,6 +724,9 @@ void menuHandler::TFTColorPickerMenu(OLEDDisplay *display) TFT_MESH_r = 255; TFT_MESH_g = 255; TFT_MESH_b = 255; + } else { + menuQueue = system_base_menu; + screen->runNow(); } #if defined(HELTEC_MESH_NODE_T114) || defined(HELTEC_VISION_MASTER_T190) || HAS_TFT @@ -771,7 +756,7 @@ void menuHandler::TFTColorPickerMenu(OLEDDisplay *display) uiconfig.screen_rgb_color = (TFT_MESH_r << 16) | (TFT_MESH_g << 8) | TFT_MESH_b; } LOG_INFO("Storing Value of %d to uiconfig.screen_rgb_color", uiconfig.screen_rgb_color); - nodeDB->saveProto("/prefs/uiconfig.proto", meshtastic_DeviceUIConfig_size, &meshtastic_DeviceUIConfig_msg, &uiconfig); + saveUIConfig(); } #endif }; @@ -790,6 +775,29 @@ void menuHandler::rebootMenu() IF_SCREEN(screen->showSimpleBanner("Rebooting...", 0)); nodeDB->saveToDisk(); rebootAtMsec = millis() + DEFAULT_REBOOT_SECONDS * 1000; + } else { + menuQueue = power_menu; + screen->runNow(); + } + }; + screen->showOverlayBanner(bannerOptions); +} + +void menuHandler::shutdownMenu() +{ + static const char *optionsArray[] = {"Back", "Confirm"}; + BannerOverlayOptions bannerOptions; + bannerOptions.message = "Shutdown Device?"; + bannerOptions.optionsArrayPtr = optionsArray; + bannerOptions.optionsCount = 2; + bannerOptions.bannerCallback = [](int selected) -> void { + if (selected == 1) { + IF_SCREEN(screen->showSimpleBanner("Shutting Down...", 0)); + nodeDB->saveToDisk(); + power->shutdown(); + } else { + menuQueue = power_menu; + screen->runNow(); } }; screen->showOverlayBanner(bannerOptions); @@ -888,6 +896,117 @@ void menuHandler::wifiToggleMenu() screen->showOverlayBanner(bannerOptions); } +void menuHandler::notificationsMenu() +{ + enum optionsNumbers { Back, BuzzerActions }; + static const char *optionsArray[] = {"Back", "Buzzer Actions"}; + static int optionsEnumArray[] = {Back, BuzzerActions}; + int options = 2; + + BannerOverlayOptions bannerOptions; + bannerOptions.message = "Notifications"; + bannerOptions.optionsArrayPtr = optionsArray; + bannerOptions.optionsCount = options; + bannerOptions.optionsEnumPtr = optionsEnumArray; + bannerOptions.bannerCallback = [](int selected) -> void { + if (selected == BuzzerActions) { + menuHandler::menuQueue = menuHandler::buzzermodemenupicker; + screen->runNow(); + } else { + menuQueue = system_base_menu; + screen->runNow(); + } + }; + screen->showOverlayBanner(bannerOptions); +} + +void menuHandler::screenOptionsMenu() +{ + // Check if brightness is supported + bool hasSupportBrightness = false; +#if defined(ST7789_CS) || defined(USE_OLED) || defined(USE_SSD1306) || defined(USE_SH1106) || defined(USE_SH1107) || HAS_TFT + hasSupportBrightness = true; +#endif + + enum optionsNumbers { Back, Brightness, ScreenColor }; + static const char *optionsArray[4] = {"Back"}; + static int optionsEnumArray[4] = {Back}; + int options = 1; + + // Only show brightness for B&W displays + if (hasSupportBrightness && !HAS_TFT) { + optionsArray[options] = "Brightness"; + optionsEnumArray[options++] = Brightness; + } + + // Only show screen color for TFT displays +#if defined(HELTEC_MESH_NODE_T114) || defined(HELTEC_VISION_MASTER_T190) || HAS_TFT + optionsArray[options] = "Screen Color"; + optionsEnumArray[options++] = ScreenColor; +#endif + + BannerOverlayOptions bannerOptions; + bannerOptions.message = "Screen Options"; + bannerOptions.optionsArrayPtr = optionsArray; + bannerOptions.optionsCount = options; + bannerOptions.optionsEnumPtr = optionsEnumArray; + bannerOptions.bannerCallback = [](int selected) -> void { + if (selected == Brightness) { + menuHandler::menuQueue = menuHandler::brightness_picker; + screen->runNow(); + } else if (selected == ScreenColor) { + menuHandler::menuQueue = menuHandler::tftcolormenupicker; + screen->runNow(); + } else { + menuQueue = system_base_menu; + screen->runNow(); + } + }; + screen->showOverlayBanner(bannerOptions); +} + +void menuHandler::powerMenu() +{ + + enum optionsNumbers { Back, Reboot, Shutdown, MUI }; + static const char *optionsArray[4] = {"Back"}; + static int optionsEnumArray[4] = {Back}; + int options = 1; + + optionsArray[options] = "Reboot"; + optionsEnumArray[options++] = Reboot; + + optionsArray[options] = "Shutdown"; + optionsEnumArray[options++] = Shutdown; + +#if HAS_TFT + optionsArray[options] = "Switch to MUI"; + optionsEnumArray[options++] = MUI; +#endif + + BannerOverlayOptions bannerOptions; + bannerOptions.message = "Reboot / Shutdown"; + bannerOptions.optionsArrayPtr = optionsArray; + bannerOptions.optionsCount = options; + bannerOptions.optionsEnumPtr = optionsEnumArray; + bannerOptions.bannerCallback = [](int selected) -> void { + if (selected == Reboot) { + menuHandler::menuQueue = menuHandler::reboot_menu; + screen->runNow(); + } else if (selected == Shutdown) { + menuHandler::menuQueue = menuHandler::shutdown_menu; + screen->runNow(); + } else if (selected == MUI) { + menuHandler::menuQueue = menuHandler::mui_picker; + screen->runNow(); + } else { + menuQueue = system_base_menu; + screen->runNow(); + } + }; + screen->showOverlayBanner(bannerOptions); +} + void menuHandler::keyVerificationInitMenu() { screen->showNodePicker("Node to Verify", 30000, @@ -941,6 +1060,9 @@ void menuHandler::handleMenuSwitch(OLEDDisplay *display) case clock_menu: clockMenu(); break; + case system_base_menu: + systemBaseMenu(); + break; case position_base_menu: positionBaseMenu(); break; @@ -970,6 +1092,9 @@ void menuHandler::handleMenuSwitch(OLEDDisplay *display) case reboot_menu: rebootMenu(); break; + case shutdown_menu: + shutdownMenu(); + break; case add_favorite: addFavoriteMenu(); break; @@ -994,6 +1119,15 @@ void menuHandler::handleMenuSwitch(OLEDDisplay *display) case bluetooth_toggle_menu: BluetoothToggleMenu(); break; + case notifications_menu: + notificationsMenu(); + break; + case screen_options_menu: + screenOptionsMenu(); + break; + case power_menu: + powerMenu(); + break; case throttle_message: screen->showSimpleBanner("Too Many Attempts\nTry again in 60 seconds.", 5000); break; @@ -1001,6 +1135,11 @@ void menuHandler::handleMenuSwitch(OLEDDisplay *display) menuQueue = menu_none; } +void menuHandler::saveUIConfig() +{ + nodeDB->saveProto("/prefs/uiconfig.proto", meshtastic_DeviceUIConfig_size, &meshtastic_DeviceUIConfig_msg, &uiconfig); +} + } // namespace graphics #endif \ No newline at end of file diff --git a/src/graphics/draw/MenuHandler.h b/src/graphics/draw/MenuHandler.h index 5846a3c91..2273dbbed 100644 --- a/src/graphics/draw/MenuHandler.h +++ b/src/graphics/draw/MenuHandler.h @@ -23,14 +23,19 @@ class menuHandler tftcolormenupicker, brightness_picker, reboot_menu, + shutdown_menu, add_favorite, remove_favorite, test_menu, number_test, wifi_toggle_menu, + bluetooth_toggle_menu, + notifications_menu, + screen_options_menu, + power_menu, + system_base_menu, key_verification_init, key_verification_final_prompt, - bluetooth_toggle_menu, throttle_message }; static screenMenus menuQueue; @@ -55,12 +60,19 @@ class menuHandler static void resetNodeDBMenu(); static void BrightnessPickerMenu(); static void rebootMenu(); + static void shutdownMenu(); static void addFavoriteMenu(); static void removeFavoriteMenu(); static void testMenu(); static void numberTest(); static void wifiBaseMenu(); static void wifiToggleMenu(); + static void notificationsMenu(); + static void screenOptionsMenu(); + static void powerMenu(); + + private: + static void saveUIConfig(); static void keyVerificationInitMenu(); static void keyVerificationFinalPrompt(); static void BluetoothToggleMenu(); diff --git a/src/graphics/niche/InkHUD/Events.cpp b/src/graphics/niche/InkHUD/Events.cpp index 2abe30793..cdda1638d 100644 --- a/src/graphics/niche/InkHUD/Events.cpp +++ b/src/graphics/niche/InkHUD/Events.cpp @@ -39,8 +39,8 @@ void InkHUD::Events::begin() void InkHUD::Events::onButtonShort() { // Audio feedback (via buzzer) - // Short low tone - playBoop(); + // Short tone + playChirp(); // Cancel any beeping, buzzing, blinking // Some button handling suppressed if we are dismissing an external notification (see below) bool dismissedExt = dismissExternalNotification(); @@ -64,8 +64,8 @@ void InkHUD::Events::onButtonShort() void InkHUD::Events::onButtonLong() { // Audio feedback (via buzzer) - // Low tone, longer than playBoop - playBeep(); + // Slightly longer than playChirp + playBoop(); // Check which system applet wants to handle the button press (if any) SystemApplet *consumer = nullptr; diff --git a/src/modules/ExternalNotificationModule.cpp b/src/modules/ExternalNotificationModule.cpp index 956508ce5..76566d4da 100644 --- a/src/modules/ExternalNotificationModule.cpp +++ b/src/modules/ExternalNotificationModule.cpp @@ -362,9 +362,8 @@ ExternalNotificationModule::ExternalNotificationModule() if (nodeDB->loadProto(rtttlConfigFile, meshtastic_RTTTLConfig_size, sizeof(meshtastic_RTTTLConfig), &meshtastic_RTTTLConfig_msg, &rtttlConfig) != LoadFileResult::LOAD_SUCCESS) { memset(rtttlConfig.ringtone, 0, sizeof(rtttlConfig.ringtone)); - strncpy(rtttlConfig.ringtone, - "24:d=32,o=5,b=565:f6,p,f6,4p,p,f6,p,f6,2p,p,b6,p,b6,p,b6,p,b6,p,b,p,b,p,b,p,b,p,b,p,b,p,b,p,b,1p.,2p.,p", - sizeof(rtttlConfig.ringtone)); + // The default ringtone is always loaded from userPrefs.jsonc + strncpy(rtttlConfig.ringtone, USERPREFS_RINGTONE, sizeof(rtttlConfig.ringtone)); } LOG_INFO("Init External Notification Module"); diff --git a/src/modules/KeyVerificationModule.cpp b/src/modules/KeyVerificationModule.cpp index f0ede345f..3b8225763 100644 --- a/src/modules/KeyVerificationModule.cpp +++ b/src/modules/KeyVerificationModule.cpp @@ -4,6 +4,7 @@ #include "RTC.h" #include "graphics/draw/MenuHandler.h" #include "main.h" +#include "meshUtils.h" #include "modules/AdminModule.h" #include @@ -85,9 +86,11 @@ bool KeyVerificationModule::handleReceivedProtobuf(const meshtastic_MeshPacket & sprintf(message, "Verification: \n"); generateVerificationCode(message + 15); LOG_INFO("Hash1 matches!"); - IF_SCREEN(static const char *optionsArray[] = {"Reject", "Accept"}; graphics::BannerOverlayOptions options; - options.message = message; options.durationMs = 30000; options.optionsArrayPtr = optionsArray; - options.optionsCount = 2; options.notificationType = graphics::notificationTypeEnum::selection_picker; + static const char *optionsArray[] = {"Reject", "Accept"}; + // Don't try to put the array definition in the macro. Does not work with curly braces. + IF_SCREEN(graphics::BannerOverlayOptions options; options.message = message; options.durationMs = 30000; + options.optionsArrayPtr = optionsArray; options.optionsCount = 2; + options.notificationType = graphics::notificationTypeEnum::selection_picker; options.bannerCallback = [=](int selected) { if (selected == 1) { diff --git a/src/modules/TextMessageModule.cpp b/src/modules/TextMessageModule.cpp index f1d01ad16..970f4429c 100644 --- a/src/modules/TextMessageModule.cpp +++ b/src/modules/TextMessageModule.cpp @@ -4,6 +4,7 @@ #include "PowerFSM.h" #include "buzz.h" #include "configuration.h" +#include "graphics/Screen.h" TextMessageModule *textMessageModule; ProcessMessage TextMessageModule::handleReceived(const meshtastic_MeshPacket &mp) @@ -17,7 +18,10 @@ ProcessMessage TextMessageModule::handleReceived(const meshtastic_MeshPacket &mp devicestate.rx_text_message = mp; devicestate.has_rx_text_message = true; - powerFSM.trigger(EVENT_RECEIVED_MSG); + // Only trigger screen wake if configuration allows it + if (shouldWakeOnReceivedMessage()) { + powerFSM.trigger(EVENT_RECEIVED_MSG); + } notifyObservers(&mp); return ProcessMessage::CONTINUE; // Let others look at this message also if they want diff --git a/userPrefs.jsonc b/userPrefs.jsonc index fc9e6ed72..c32bc7841 100644 --- a/userPrefs.jsonc +++ b/userPrefs.jsonc @@ -53,5 +53,6 @@ // "USERPREFS_MQTT_ENCRYPTION_ENABLED": "true", // "USERPREFS_MQTT_TLS_ENABLED": "false", // "USERPREFS_MQTT_ROOT_TOPIC": "event/REPLACEME", + "USERPREFS_RINGTONE": "24:d=32,o=5,b=565:f6,p,f6,4p,p,f6,p,f6,2p,p,b6,p,b6,p,b6,p,b6,p,b,p,b,p,b,p,b,p,b,p,b,p,b,p,b,1p.,2p.,p", "USERPREFS_TZ_STRING": "tzplaceholder " } diff --git a/variants/ELECROW-ThinkNode-M1/nicheGraphics.h b/variants/ELECROW-ThinkNode-M1/nicheGraphics.h index b4395114f..f64de9d07 100644 --- a/variants/ELECROW-ThinkNode-M1/nicheGraphics.h +++ b/variants/ELECROW-ThinkNode-M1/nicheGraphics.h @@ -104,11 +104,11 @@ void setupNicheGraphics() buttons->setHandlerDown(1, [backlight]() { backlight->peek(); }); buttons->setHandlerLongPress(1, [backlight]() { backlight->latch(); - playBeep(); + playBoop(); }); buttons->setHandlerShortPress(1, [backlight]() { backlight->off(); - playBoop(); + playChirp(); }); // Begin handling button events diff --git a/variants/heltec_vision_master_e213/nicheGraphics.h b/variants/heltec_vision_master_e213/nicheGraphics.h index 6a75ad90d..1b1291424 100644 --- a/variants/heltec_vision_master_e213/nicheGraphics.h +++ b/variants/heltec_vision_master_e213/nicheGraphics.h @@ -107,7 +107,7 @@ void setupNicheGraphics() buttons->setWiring(1, PIN_BUTTON2); buttons->setHandlerShortPress(1, [inkhud]() { inkhud->nextTile(); - playBoop(); + playChirp(); }); // Begin handling button events diff --git a/variants/heltec_vision_master_e290/nicheGraphics.h b/variants/heltec_vision_master_e290/nicheGraphics.h index f29873c15..61b08c740 100644 --- a/variants/heltec_vision_master_e290/nicheGraphics.h +++ b/variants/heltec_vision_master_e290/nicheGraphics.h @@ -104,7 +104,7 @@ void setupNicheGraphics() buttons->setWiring(1, PIN_BUTTON2); buttons->setHandlerShortPress(1, [inkhud]() { inkhud->nextTile(); - playBoop(); + playChirp(); }); // Begin handling button events diff --git a/variants/seeed_xiao_nrf52840_kit/platformio.ini b/variants/seeed_xiao_nrf52840_kit/platformio.ini index 8c4c5a57b..0e1e94cd5 100644 --- a/variants/seeed_xiao_nrf52840_kit/platformio.ini +++ b/variants/seeed_xiao_nrf52840_kit/platformio.ini @@ -1,4 +1,4 @@ -; Seeed Xiao BLE: https://www.digikey.com/en/products/detail/seeed-technology-co-ltd/102010448/16652893 +; Seeed Xiao BLE: https://wiki.seeedstudio.com/XIAO_BLE/ [env:seeed_xiao_nrf52840_kit] extends = nrf52840_base board = xiao_ble_sense diff --git a/version.properties b/version.properties index 69f2d6af5..5de810523 100644 --- a/version.properties +++ b/version.properties @@ -1,4 +1,4 @@ [VERSION] major = 2 minor = 7 -build = 2 +build = 3