From 1b793d1f234a11d012273f23dda7b2a639bda300 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 30 Jul 2025 06:29:03 -0500 Subject: [PATCH 1/8] Update protobufs (#7508) Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com> --- protobufs | 2 +- src/mesh/generated/meshtastic/mesh.pb.h | 3 +++ src/mesh/generated/meshtastic/module_config.pb.h | 9 ++++++--- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/protobufs b/protobufs index 9bac2886f..1ecf94da9 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit 9bac2886f9344f25716921467a82e8b0326107cd +Subproject commit 1ecf94da9898ea0b8f2745bfe6bda2a8f2ca4073 diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h index 8e6524042..f915a1db3 100644 --- a/src/mesh/generated/meshtastic/mesh.pb.h +++ b/src/mesh/generated/meshtastic/mesh.pb.h @@ -267,6 +267,9 @@ typedef enum _meshtastic_HardwareModel { meshtastic_HardwareModel_RAK3312 = 106, /* Elecrow ThinkNode M5 https://www.elecrow.com/wiki/ThinkNode_M5_Meshtastic_LoRa_Signal_Transceiver_ESP32-S3.html */ meshtastic_HardwareModel_THINKNODE_M5 = 107, + /* MeshSolar is an integrated power management and communication solution designed for outdoor low-power devices. + https://heltec.org/project/meshsolar/ */ + meshtastic_HardwareModel_HELTEC_MESH_SOLAR = 108, /* ------------------------------------------------------------------------------------------------------------------------------------------ Reserved ID For developing private Ports. These will show up in live traffic sparsely, so we can use a high number. Keep it within 8 bits. ------------------------------------------------------------------------------------------------------------------------------------------ */ diff --git a/src/mesh/generated/meshtastic/module_config.pb.h b/src/mesh/generated/meshtastic/module_config.pb.h index e8ae48072..b27f5f515 100644 --- a/src/mesh/generated/meshtastic/module_config.pb.h +++ b/src/mesh/generated/meshtastic/module_config.pb.h @@ -82,7 +82,10 @@ typedef enum _meshtastic_ModuleConfig_SerialConfig_Serial_Mode { meshtastic_ModuleConfig_SerialConfig_Serial_Mode_WS85 = 6, /* VE.Direct is a serial protocol used by Victron Energy products https://beta.ivc.no/wiki/index.php/Victron_VE_Direct_DIY_Cable */ - meshtastic_ModuleConfig_SerialConfig_Serial_Mode_VE_DIRECT = 7 + meshtastic_ModuleConfig_SerialConfig_Serial_Mode_VE_DIRECT = 7, + /* Used to configure and view some parameters of MeshSolar. +https://heltec.org/project/meshsolar/ */ + meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MS_CONFIG = 8 } meshtastic_ModuleConfig_SerialConfig_Serial_Mode; /* TODO: REPLACE */ @@ -472,8 +475,8 @@ extern "C" { #define _meshtastic_ModuleConfig_SerialConfig_Serial_Baud_ARRAYSIZE ((meshtastic_ModuleConfig_SerialConfig_Serial_Baud)(meshtastic_ModuleConfig_SerialConfig_Serial_Baud_BAUD_921600+1)) #define _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MIN meshtastic_ModuleConfig_SerialConfig_Serial_Mode_DEFAULT -#define _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MAX meshtastic_ModuleConfig_SerialConfig_Serial_Mode_VE_DIRECT -#define _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_ARRAYSIZE ((meshtastic_ModuleConfig_SerialConfig_Serial_Mode)(meshtastic_ModuleConfig_SerialConfig_Serial_Mode_VE_DIRECT+1)) +#define _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MAX meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MS_CONFIG +#define _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_ARRAYSIZE ((meshtastic_ModuleConfig_SerialConfig_Serial_Mode)(meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MS_CONFIG+1)) #define _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_NONE #define _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MAX meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_BACK From 7d926da98c6e3699d9fe8c20f193977ccbbccebf Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Wed, 30 Jul 2025 07:40:27 -0500 Subject: [PATCH 2/8] Heartbeat response (#7506) * Heartbeat response * Move it * Add debug log for visibility --- src/mesh/PhoneAPI.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/mesh/PhoneAPI.cpp b/src/mesh/PhoneAPI.cpp index 83becb037..305689fff 100644 --- a/src/mesh/PhoneAPI.cpp +++ b/src/mesh/PhoneAPI.cpp @@ -31,6 +31,9 @@ #include "Throttle.h" #include +// Flag to indicate a heartbeat was received and we should send queue status +bool heartbeatReceived = false; + PhoneAPI::PhoneAPI() { lastContactMsec = millis(); @@ -155,6 +158,7 @@ bool PhoneAPI::handleToRadio(const uint8_t *buf, size_t bufLength) #endif case meshtastic_ToRadio_heartbeat_tag: LOG_DEBUG("Got client heartbeat"); + heartbeatReceived = true; break; default: // Ignore nop messages @@ -194,6 +198,17 @@ size_t PhoneAPI::getFromRadio(uint8_t *buf) // In case we send a FromRadio packet memset(&fromRadioScratch, 0, sizeof(fromRadioScratch)); + // Respond to heartbeat by sending queue status + if (heartbeatReceived) { + memset(&fromRadioScratch, 0, sizeof(fromRadioScratch)); + fromRadioScratch.which_payload_variant = meshtastic_FromRadio_queueStatus_tag; + fromRadioScratch.queueStatus = router->getQueueStatus(); + heartbeatReceived = false; + size_t numbytes = pb_encode_to_bytes(buf, meshtastic_FromRadio_size, &meshtastic_FromRadio_msg, &fromRadioScratch); + LOG_DEBUG("FromRadio=STATE_SEND_QUEUE_STATUS, numbytes=%u", numbytes); + return numbytes; + } + // Advance states as needed switch (state) { case STATE_SEND_NOTHING: From 4c901033b2bc4e67e330cf8927b90760014aedde Mon Sep 17 00:00:00 2001 From: Tom Fifield Date: Wed, 30 Jul 2025 22:47:00 +1000 Subject: [PATCH 3/8] Workaround Webserver needing to stay up while Wifi is turned off (#7484) Expertly triaged by @philon- , turning off wifi using the HTTP API did not work. That was because we only served the HTTP API if Wifi was deemed to be available, but mid-way through turning it off Wifi was still available, but the configuration we were checking said it wasn't. This patch introduces an additional way the system can determine if Wifi is available, by referring to the WiFi.status(). This means that in that limbo state where Wifi has been set to be turned off, but the configuration has not been saved and it is still up, the HTTP API will stay up long enough to save the configuration. Fixes https://github.com/meshtastic/firmware/issues/6965 --- src/mesh/wifi/WiFiAPClient.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/mesh/wifi/WiFiAPClient.cpp b/src/mesh/wifi/WiFiAPClient.cpp index 7a56c258b..1133ad424 100644 --- a/src/mesh/wifi/WiFiAPClient.cpp +++ b/src/mesh/wifi/WiFiAPClient.cpp @@ -235,6 +235,11 @@ bool isWifiAvailable() #ifdef USE_WS5500 } else if (config.network.eth_enabled) { return true; +#endif +#ifndef ARCH_PORTDUINO + } else if (WiFi.status() == WL_CONNECTED) { + // it's likely we have wifi now, but user intends to turn it off in config! + return true; #endif } else { return false; From bdedd0e1fec17da0953a93637425e2f6a75da328 Mon Sep 17 00:00:00 2001 From: Tom Fifield Date: Thu, 31 Jul 2025 12:21:10 +1000 Subject: [PATCH 4/8] Airoha GPS - ignore estimated fixes (#7429) TinyGPS Fix Quality has this information: 0 - fix not available, 1 - GPS fix, 2 - Differential GPS fix (values above 2 are 2.3 features) 3 = PPS fix 4 = Real Time Kinematic 5 = Float RTK 6 = estimated (dead reckoning) 7 = Manual input mode 8 = Simulation mode the previous Airoha code would allow quality >0 , which includes estimated positions. These wouldn't be passed through to the mesh due to other checks, but would affect the Airoha GPS_FIX_HOLD_TIME calculations. Changes the calculation to 1 >= quality <=5 . --- src/gps/GPS.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gps/GPS.cpp b/src/gps/GPS.cpp index f3624c627..ae74f0fe2 100644 --- a/src/gps/GPS.cpp +++ b/src/gps/GPS.cpp @@ -1511,7 +1511,7 @@ bool GPS::lookForTime() #ifdef GNSS_AIROHA uint8_t fix = reader.fixQuality(); - if (fix > 0) { + if (fix >= 1 && fix <= 5) { if (lastFixStartMsec > 0) { if (Throttle::isWithinTimespanMs(lastFixStartMsec, GPS_FIX_HOLD_TIME)) { return false; @@ -1566,7 +1566,7 @@ bool GPS::lookForLocation() #ifdef GNSS_AIROHA if ((config.position.gps_update_interval * 1000) >= (GPS_FIX_HOLD_TIME * 2)) { uint8_t fix = reader.fixQuality(); - if (fix > 0) { + if (fix >= 1 && fix <= 5) { if (lastFixStartMsec > 0) { if (Throttle::isWithinTimespanMs(lastFixStartMsec, GPS_FIX_HOLD_TIME)) { return false; From 956a0f102b054e081238853ddc6465826489f3a5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 31 Jul 2025 06:00:58 -0500 Subject: [PATCH 5/8] Update platformio/ststm32 to v19.3.0 (#7512) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- arch/stm32/stm32.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/stm32/stm32.ini b/arch/stm32/stm32.ini index 153ca9f3e..d91607a7d 100644 --- a/arch/stm32/stm32.ini +++ b/arch/stm32/stm32.ini @@ -2,7 +2,7 @@ extends = arduino_base platform = # renovate: datasource=custom.pio depName=platformio/ststm32 packageName=platformio/platform/ststm32 - platformio/ststm32@19.2.0 + platformio/ststm32@19.3.0 platform_packages = # TODO renovate platformio/framework-arduinoststm32@https://github.com/stm32duino/Arduino_Core_STM32/archive/2.10.1.zip From 10bd10b9d1c4b8c2cb73e7a97bb5740b62e0e4a5 Mon Sep 17 00:00:00 2001 From: mikecarper <135079168+mikecarper@users.noreply.github.com> Date: Thu, 31 Jul 2025 04:02:09 -0700 Subject: [PATCH 6/8] bugfix Syntax error: "(" unexpected in device-update.sh (#7514) * Update device-update.sh to use /bin/bash * Update meshtasticd.postinst to use /bin/bash * Update meshtasticd.postrm to use /bin/bash --- bin/device-update.sh | 2 +- debian/meshtasticd.postinst | 2 +- debian/meshtasticd.postrm | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bin/device-update.sh b/bin/device-update.sh index ce0b5e434..2196d3af9 100755 --- a/bin/device-update.sh +++ b/bin/device-update.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash PYTHON=${PYTHON:-$(which python3 python|head -n 1)} CHANGE_MODE=false diff --git a/debian/meshtasticd.postinst b/debian/meshtasticd.postinst index fe0dbc332..d569cb43e 100755 --- a/debian/meshtasticd.postinst +++ b/debian/meshtasticd.postinst @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # postinst script for meshtasticd # # see: dh_installdeb(1) diff --git a/debian/meshtasticd.postrm b/debian/meshtasticd.postrm index bb2c32a5b..dc25680a8 100755 --- a/debian/meshtasticd.postrm +++ b/debian/meshtasticd.postrm @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # postrm script for meshtasticd # # see: dh_installdeb(1) From 88655ffc4432b8a63c3acdef6e1af22fd09bfb2b Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Thu, 31 Jul 2025 07:34:41 -0500 Subject: [PATCH 7/8] Move BLE toggle menu option and add confirmation for canned messages in L1 (#7516) * Move bluetooth to system menu and add confirmation for canned messages * Cruft * Handle else * Warn * Fixed screen reset --- src/graphics/draw/MenuHandler.cpp | 33 +++++++++++++++---- src/graphics/draw/MenuHandler.h | 1 + src/modules/CannedMessageModule.cpp | 21 +++++++++++- .../nrf52840/seeed_wio_tracker_L1/variant.h | 2 ++ 4 files changed, 49 insertions(+), 8 deletions(-) diff --git a/src/graphics/draw/MenuHandler.cpp b/src/graphics/draw/MenuHandler.cpp index cf19c4825..b7bd068c4 100644 --- a/src/graphics/draw/MenuHandler.cpp +++ b/src/graphics/draw/MenuHandler.cpp @@ -14,7 +14,9 @@ #include "modules/AdminModule.h" #include "modules/CannedMessageModule.h" #include "modules/KeyVerificationModule.h" + #include "modules/TraceRouteModule.h" +#include extern uint16_t TFT_MESH; @@ -118,6 +120,22 @@ void menuHandler::TwelveHourPicker() screen->showOverlayBanner(bannerOptions); } +// Reusable confirmation prompt function +void menuHandler::showConfirmationBanner(const char *message, std::function onConfirm) +{ + static const char *confirmOptions[] = {"No", "Yes"}; + BannerOverlayOptions confirmBanner; + confirmBanner.message = message; + confirmBanner.optionsArrayPtr = confirmOptions; + confirmBanner.optionsCount = 2; + confirmBanner.bannerCallback = [onConfirm](int confirmSelected) -> void { + if (confirmSelected == 1) { + onConfirm(); + } + }; + screen->showOverlayBanner(confirmBanner); +} + void menuHandler::ClockFacePicker() { static const char *optionsArray[] = {"Back", "Digital", "Analog"}; @@ -294,7 +312,7 @@ void menuHandler::messageResponseMenu() void menuHandler::homeBaseMenu() { - enum optionsNumbers { Back, Backlight, Position, Preset, Freetext, Bluetooth, Sleep, enumEnd }; + enum optionsNumbers { Back, Backlight, Position, Preset, Freetext, Sleep, enumEnd }; static const char *optionsArray[enumEnd] = {"Back"}; static int optionsEnumArray[enumEnd] = {Back}; @@ -316,8 +334,6 @@ void menuHandler::homeBaseMenu() optionsArray[options] = "New Freetext Msg"; optionsEnumArray[options++] = Freetext; } - optionsArray[options] = "Bluetooth Toggle"; - optionsEnumArray[options++] = Bluetooth; BannerOverlayOptions bannerOptions; bannerOptions.message = "Home Action"; @@ -342,9 +358,6 @@ void menuHandler::homeBaseMenu() cannedMessageModule->LaunchWithDestination(NODENUM_BROADCAST); } else if (selected == Freetext) { cannedMessageModule->LaunchFreetextWithDestination(NODENUM_BROADCAST); - } else if (selected == Bluetooth) { - menuQueue = bluetooth_toggle_menu; - screen->runNow(); } }; screen->showOverlayBanner(bannerOptions); @@ -381,7 +394,7 @@ void menuHandler::textMessageBaseMenu() void menuHandler::systemBaseMenu() { - enum optionsNumbers { Back, Notifications, ScreenOptions, PowerMenu, Test, enumEnd }; + enum optionsNumbers { Back, Notifications, ScreenOptions, Bluetooth, PowerMenu, Test, enumEnd }; static const char *optionsArray[enumEnd] = {"Back"}; static int optionsEnumArray[enumEnd] = {Back}; int options = 1; @@ -394,6 +407,9 @@ void menuHandler::systemBaseMenu() optionsEnumArray[options++] = ScreenOptions; #endif + optionsArray[options] = "Bluetooth Toggle"; + optionsEnumArray[options++] = Bluetooth; + optionsArray[options] = "Reboot/Shutdown"; optionsEnumArray[options++] = PowerMenu; @@ -420,6 +436,9 @@ void menuHandler::systemBaseMenu() } else if (selected == Test) { menuHandler::menuQueue = menuHandler::test_menu; screen->runNow(); + } else if (selected == Bluetooth) { + menuQueue = bluetooth_toggle_menu; + screen->runNow(); } else if (selected == Back && !test_enabled) { test_count++; if (test_count > 4) { diff --git a/src/graphics/draw/MenuHandler.h b/src/graphics/draw/MenuHandler.h index 2e4923241..87a0b055e 100644 --- a/src/graphics/draw/MenuHandler.h +++ b/src/graphics/draw/MenuHandler.h @@ -43,6 +43,7 @@ class menuHandler static void LoraRegionPicker(uint32_t duration = 30000); static void handleMenuSwitch(OLEDDisplay *display); + static void showConfirmationBanner(const char *message, std::function onConfirm); static void clockMenu(); static void TZPicker(); static void TwelveHourPicker(); diff --git a/src/modules/CannedMessageModule.cpp b/src/modules/CannedMessageModule.cpp index ed930db41..f7846ebbf 100644 --- a/src/modules/CannedMessageModule.cpp +++ b/src/modules/CannedMessageModule.cpp @@ -595,8 +595,27 @@ bool CannedMessageModule::handleMessageSelectorInput(const InputEvent *event, bo // Normal canned message selection if (runState == CANNED_MESSAGE_RUN_STATE_INACTIVE || runState == CANNED_MESSAGE_RUN_STATE_DISABLED) { } else { + // Show confirmation dialog before sending canned message + NodeNum destNode = dest; + ChannelIndex chan = channel; +#if CANNED_MESSAGE_ADD_CONFIRMATION + graphics::menuHandler::showConfirmationBanner("Send message?", [this, destNode, chan, current]() { + this->sendText(destNode, chan, current, false); + payload = runState; + runState = CANNED_MESSAGE_RUN_STATE_INACTIVE; + currentMessageIndex = -1; + + // Notify UI to regenerate frame set and redraw + UIFrameEvent e; + e.action = UIFrameEvent::Action::REGENERATE_FRAMESET; + notifyObservers(&e); + screen->forceDisplay(); + }); +#else payload = runState; runState = CANNED_MESSAGE_RUN_STATE_ACTION_SELECT; +#endif + // Do not immediately set runState; wait for confirmation handled = true; } } @@ -1711,7 +1730,7 @@ void CannedMessageModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *st // Text: split by words and wrap inside word if needed String text = token.second; pos = 0; - while (pos < text.length()) { + while (pos < static_cast(text.length())) { // Find next space (or end) int spacePos = text.indexOf(' ', pos); int endPos = (spacePos == -1) ? text.length() : spacePos + 1; // Include space diff --git a/variants/nrf52840/seeed_wio_tracker_L1/variant.h b/variants/nrf52840/seeed_wio_tracker_L1/variant.h index 0c5964c5a..c5647caa8 100644 --- a/variants/nrf52840/seeed_wio_tracker_L1/variant.h +++ b/variants/nrf52840/seeed_wio_tracker_L1/variant.h @@ -162,6 +162,8 @@ static const uint8_t SCL = PIN_WIRE_SCL; #define CANNED_MESSAGE_MODULE_ENABLE 1 +#define CANNED_MESSAGE_ADD_CONFIRMATION 1 + // trackball #define HAS_TRACKBALL 1 #define TB_UP 25 From 5107531425675421bb893496c0227fad3e2dd77c Mon Sep 17 00:00:00 2001 From: HarukiToreda <116696711+HarukiToreda@users.noreply.github.com> Date: Thu, 31 Jul 2025 08:36:03 -0400 Subject: [PATCH 8/8] Remember destination fix (#7427) * T-watch screen misalignment fix * Trunk fix * Rember Last Receipient Node or channel When a new freetext or preset message is sent and a destination is selected, the next message would forget the previously selected destination and would need to be selected again. With this fix it will remember the last destination selected until changed again. * Fix for reply function to remember last messaged * trunk check --------- Co-authored-by: Jonathan Bennett Co-authored-by: Jason P Co-authored-by: Ben Meadors --- src/modules/CannedMessageModule.cpp | 41 +++++++++++++++++++++++++++++ src/modules/CannedMessageModule.h | 1 + 2 files changed, 42 insertions(+) diff --git a/src/modules/CannedMessageModule.cpp b/src/modules/CannedMessageModule.cpp index f7846ebbf..b6cb1b0e3 100644 --- a/src/modules/CannedMessageModule.cpp +++ b/src/modules/CannedMessageModule.cpp @@ -40,6 +40,9 @@ extern ScanI2C::DeviceAddress cardkb_found; extern bool graphics::isMuted; static const char *cannedMessagesConfigFile = "/prefs/cannedConf.proto"; +static NodeNum lastDest = NODENUM_BROADCAST; +static uint8_t lastChannel = 0; +static bool lastDestSet = false; meshtastic_CannedMessageModuleConfig cannedMessageModuleConfig; @@ -63,8 +66,18 @@ CannedMessageModule::CannedMessageModule() void CannedMessageModule::LaunchWithDestination(NodeNum newDest, uint8_t newChannel) { + // Use the requested destination, unless it's "broadcast" and we have a previous node/channel + if (newDest == NODENUM_BROADCAST && lastDestSet) { + newDest = lastDest; + newChannel = lastChannel; + } dest = newDest; channel = newChannel; + lastDest = dest; + lastChannel = channel; + lastDestSet = true; + + // Rest of function unchanged... // Always select the first real canned message on activation int firstRealMsgIdx = 0; for (int i = 0; i < messagesCount; ++i) { @@ -84,10 +97,28 @@ void CannedMessageModule::LaunchWithDestination(NodeNum newDest, uint8_t newChan notifyObservers(&e); } +void CannedMessageModule::LaunchRepeatDestination() +{ + if (!lastDestSet) { + LaunchWithDestination(NODENUM_BROADCAST, 0); + } else { + LaunchWithDestination(lastDest, lastChannel); + } +} + void CannedMessageModule::LaunchFreetextWithDestination(NodeNum newDest, uint8_t newChannel) { + // Use the requested destination, unless it's "broadcast" and we have a previous node/channel + if (newDest == NODENUM_BROADCAST && lastDestSet) { + newDest = lastDest; + newChannel = lastChannel; + } dest = newDest; channel = newChannel; + lastDest = dest; + lastChannel = channel; + lastDestSet = true; + runState = CANNED_MESSAGE_RUN_STATE_FREETEXT; requestFocus(); UIFrameEvent e; @@ -479,6 +510,9 @@ int CannedMessageModule::handleDestinationSelectionInput(const InputEvent *event if (destIndex < static_cast(activeChannelIndices.size())) { dest = NODENUM_BROADCAST; channel = activeChannelIndices[destIndex]; + lastDest = dest; + lastChannel = channel; + lastDestSet = true; } else { int nodeIndex = destIndex - static_cast(activeChannelIndices.size()); if (nodeIndex >= 0 && nodeIndex < static_cast(filteredNodes.size())) { @@ -486,6 +520,10 @@ int CannedMessageModule::handleDestinationSelectionInput(const InputEvent *event if (selectedNode) { dest = selectedNode->num; channel = selectedNode->channel; + // Already saves here, but for clarity, also: + lastDest = dest; + lastChannel = channel; + lastDestSet = true; } } } @@ -846,6 +884,9 @@ int CannedMessageModule::handleEmotePickerInput(const InputEvent *event) void CannedMessageModule::sendText(NodeNum dest, ChannelIndex channel, const char *message, bool wantReplies) { + lastDest = dest; + lastChannel = channel; + lastDestSet = true; // === Prepare packet === meshtastic_MeshPacket *p = allocDataPacket(); p->to = dest; diff --git a/src/modules/CannedMessageModule.h b/src/modules/CannedMessageModule.h index 55a0a1185..5b0481ac7 100644 --- a/src/modules/CannedMessageModule.h +++ b/src/modules/CannedMessageModule.h @@ -59,6 +59,7 @@ class CannedMessageModule : public SinglePortModule, public Observable