From 9b0fbcf1d9daba7fadc4bc27e479399e507aa116 Mon Sep 17 00:00:00 2001 From: ford-jones Date: Thu, 21 Aug 2025 11:55:53 +1200 Subject: [PATCH 01/39] Enabled deletion of files created by the range-test module --- src/modules/RangeTestModule.cpp | 19 ++++++++++++++++++- src/modules/RangeTestModule.h | 5 +++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/modules/RangeTestModule.cpp b/src/modules/RangeTestModule.cpp index 6f3d69acf..2f8659db0 100644 --- a/src/modules/RangeTestModule.cpp +++ b/src/modules/RangeTestModule.cpp @@ -298,4 +298,21 @@ bool RangeTestModuleRadio::appendFile(const meshtastic_MeshPacket &mp) #endif return 1; -} \ No newline at end of file +} + +bool RangeTestModuleRadio::removeFile() +{ +#ifdef ARCH_ESP32 + char *fp = "/static/rangetest.csv"; + if (FSCom.exists(fp)) { + LOG_INFO("Deleting previous range test."); + bool result = FSCom.remove(fp); + if (!result) { + LOG_ERROR("Failed to delete rangeTest.csv"); + return 0; + } + } +#endif + + return 1; +}; \ No newline at end of file diff --git a/src/modules/RangeTestModule.h b/src/modules/RangeTestModule.h index b632d343e..0512e70a8 100644 --- a/src/modules/RangeTestModule.h +++ b/src/modules/RangeTestModule.h @@ -44,6 +44,11 @@ class RangeTestModuleRadio : public SinglePortModule */ bool appendFile(const meshtastic_MeshPacket &mp); + /** + * Cleanup range test data from filesystem + */ + bool removeFile(); + protected: /** Called to handle a particular incoming message From f6bb1977bc8ad4bc663c4a71f117ca1aea2ec156 Mon Sep 17 00:00:00 2001 From: ford-jones Date: Thu, 21 Aug 2025 12:00:19 +1200 Subject: [PATCH 02/39] Use string constants in place of char* --- src/modules/RangeTestModule.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/modules/RangeTestModule.cpp b/src/modules/RangeTestModule.cpp index 2f8659db0..38f29e93b 100644 --- a/src/modules/RangeTestModule.cpp +++ b/src/modules/RangeTestModule.cpp @@ -303,16 +303,16 @@ bool RangeTestModuleRadio::appendFile(const meshtastic_MeshPacket &mp) bool RangeTestModuleRadio::removeFile() { #ifdef ARCH_ESP32 - char *fp = "/static/rangetest.csv"; - if (FSCom.exists(fp)) { + if (FSCom.exists("/static/rangetest.csv")) { LOG_INFO("Deleting previous range test."); - bool result = FSCom.remove(fp); + bool result = FSCom.remove("/static/rangetest.csv"); if (!result) { LOG_ERROR("Failed to delete rangeTest.csv"); return 0; } + LOG_INFO("Range test removed."); } #endif return 1; -}; \ No newline at end of file +} \ No newline at end of file From e6a2df5b6d90e4c7991103a1a78e9b35713c7aee Mon Sep 17 00:00:00 2001 From: ford-jones Date: Thu, 21 Aug 2025 12:01:45 +1200 Subject: [PATCH 03/39] Check filesystem mounted --- src/modules/RangeTestModule.cpp | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/modules/RangeTestModule.cpp b/src/modules/RangeTestModule.cpp index 38f29e93b..415614dd2 100644 --- a/src/modules/RangeTestModule.cpp +++ b/src/modules/RangeTestModule.cpp @@ -303,15 +303,24 @@ bool RangeTestModuleRadio::appendFile(const meshtastic_MeshPacket &mp) bool RangeTestModuleRadio::removeFile() { #ifdef ARCH_ESP32 - if (FSCom.exists("/static/rangetest.csv")) { - LOG_INFO("Deleting previous range test."); - bool result = FSCom.remove("/static/rangetest.csv"); - if (!result) { - LOG_ERROR("Failed to delete rangeTest.csv"); - return 0; - } - LOG_INFO("Range test removed."); + if (!FSBegin()) { + LOG_DEBUG("An Error has occurred while mounting the filesystem"); + return 0; } + + if (!FSCom.exists("/static/rangetest.csv")) { + LOG_DEBUG("No range tests found."); + return 0; + } + + LOG_INFO("Deleting previous range test."); + bool result = FSCom.remove("/static/rangetest.csv"); + + if (!result) { + LOG_ERROR("Failed to delete range test."); + return 0; + } + LOG_INFO("Range test removed."); #endif return 1; From 236d2b92dcf40f37d357c1db802a0fec9a104aa6 Mon Sep 17 00:00:00 2001 From: ford-jones Date: Thu, 21 Aug 2025 12:12:13 +1200 Subject: [PATCH 04/39] Enable protobufs to include rangetest deletion configuration --- src/mesh/generated/meshtastic/deviceonly.pb.h | 2 +- src/mesh/generated/meshtastic/localonly.pb.h | 2 +- src/mesh/generated/meshtastic/module_config.pb.h | 13 +++++++++---- src/modules/RangeTestModule.cpp | 4 +++- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/mesh/generated/meshtastic/deviceonly.pb.h b/src/mesh/generated/meshtastic/deviceonly.pb.h index f47091384..9b6330596 100644 --- a/src/mesh/generated/meshtastic/deviceonly.pb.h +++ b/src/mesh/generated/meshtastic/deviceonly.pb.h @@ -360,7 +360,7 @@ extern const pb_msgdesc_t meshtastic_BackupPreferences_msg; /* Maximum encoded size of messages (where known) */ /* meshtastic_NodeDatabase_size depends on runtime parameters */ #define MESHTASTIC_MESHTASTIC_DEVICEONLY_PB_H_MAX_SIZE meshtastic_BackupPreferences_size -#define meshtastic_BackupPreferences_size 2271 +#define meshtastic_BackupPreferences_size 2273 #define meshtastic_ChannelFile_size 718 #define meshtastic_DeviceState_size 1737 #define meshtastic_NodeInfoLite_size 196 diff --git a/src/mesh/generated/meshtastic/localonly.pb.h b/src/mesh/generated/meshtastic/localonly.pb.h index ca8dcd5fb..da224fb94 100644 --- a/src/mesh/generated/meshtastic/localonly.pb.h +++ b/src/mesh/generated/meshtastic/localonly.pb.h @@ -188,7 +188,7 @@ extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg; /* Maximum encoded size of messages (where known) */ #define MESHTASTIC_MESHTASTIC_LOCALONLY_PB_H_MAX_SIZE meshtastic_LocalConfig_size #define meshtastic_LocalConfig_size 747 -#define meshtastic_LocalModuleConfig_size 669 +#define meshtastic_LocalModuleConfig_size 671 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/generated/meshtastic/module_config.pb.h b/src/mesh/generated/meshtastic/module_config.pb.h index b27f5f515..468a31a59 100644 --- a/src/mesh/generated/meshtastic/module_config.pb.h +++ b/src/mesh/generated/meshtastic/module_config.pb.h @@ -317,6 +317,9 @@ typedef struct _meshtastic_ModuleConfig_RangeTestConfig { /* Bool value indicating that this node should save a RangeTest.csv file. ESP32 Only */ bool save; + /* Bool indicating that the node should cleanup / destroy it's RangeTest.csv file. + ESP32 Only */ + bool clear; } meshtastic_ModuleConfig_RangeTestConfig; /* Configuration for both device and environment metrics */ @@ -519,7 +522,7 @@ extern "C" { #define meshtastic_ModuleConfig_SerialConfig_init_default {0, 0, 0, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Baud_MIN, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MIN, 0} #define meshtastic_ModuleConfig_ExternalNotificationConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_ModuleConfig_StoreForwardConfig_init_default {0, 0, 0, 0, 0, 0} -#define meshtastic_ModuleConfig_RangeTestConfig_init_default {0, 0, 0} +#define meshtastic_ModuleConfig_RangeTestConfig_init_default {0, 0, 0, 0} #define meshtastic_ModuleConfig_TelemetryConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_ModuleConfig_CannedMessageConfig_init_default {0, 0, 0, 0, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, 0, 0, "", 0} #define meshtastic_ModuleConfig_AmbientLightingConfig_init_default {0, 0, 0, 0, 0} @@ -535,7 +538,7 @@ extern "C" { #define meshtastic_ModuleConfig_SerialConfig_init_zero {0, 0, 0, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Baud_MIN, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MIN, 0} #define meshtastic_ModuleConfig_ExternalNotificationConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_ModuleConfig_StoreForwardConfig_init_zero {0, 0, 0, 0, 0, 0} -#define meshtastic_ModuleConfig_RangeTestConfig_init_zero {0, 0, 0} +#define meshtastic_ModuleConfig_RangeTestConfig_init_zero {0, 0, 0, 0} #define meshtastic_ModuleConfig_TelemetryConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_ModuleConfig_CannedMessageConfig_init_zero {0, 0, 0, 0, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, 0, 0, "", 0} #define meshtastic_ModuleConfig_AmbientLightingConfig_init_zero {0, 0, 0, 0, 0} @@ -610,6 +613,7 @@ extern "C" { #define meshtastic_ModuleConfig_RangeTestConfig_enabled_tag 1 #define meshtastic_ModuleConfig_RangeTestConfig_sender_tag 2 #define meshtastic_ModuleConfig_RangeTestConfig_save_tag 3 +#define meshtastic_ModuleConfig_RangeTestConfig_clear_tag 4 #define meshtastic_ModuleConfig_TelemetryConfig_device_update_interval_tag 1 #define meshtastic_ModuleConfig_TelemetryConfig_environment_update_interval_tag 2 #define meshtastic_ModuleConfig_TelemetryConfig_environment_measurement_enabled_tag 3 @@ -803,7 +807,8 @@ X(a, STATIC, SINGULAR, BOOL, is_server, 6) #define meshtastic_ModuleConfig_RangeTestConfig_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, BOOL, enabled, 1) \ X(a, STATIC, SINGULAR, UINT32, sender, 2) \ -X(a, STATIC, SINGULAR, BOOL, save, 3) +X(a, STATIC, SINGULAR, BOOL, save, 3) \ +X(a, STATIC, SINGULAR, BOOL, clear, 4) #define meshtastic_ModuleConfig_RangeTestConfig_CALLBACK NULL #define meshtastic_ModuleConfig_RangeTestConfig_DEFAULT NULL @@ -901,7 +906,7 @@ extern const pb_msgdesc_t meshtastic_RemoteHardwarePin_msg; #define meshtastic_ModuleConfig_MapReportSettings_size 14 #define meshtastic_ModuleConfig_NeighborInfoConfig_size 10 #define meshtastic_ModuleConfig_PaxcounterConfig_size 30 -#define meshtastic_ModuleConfig_RangeTestConfig_size 10 +#define meshtastic_ModuleConfig_RangeTestConfig_size 12 #define meshtastic_ModuleConfig_RemoteHardwareConfig_size 96 #define meshtastic_ModuleConfig_SerialConfig_size 28 #define meshtastic_ModuleConfig_StoreForwardConfig_size 24 diff --git a/src/modules/RangeTestModule.cpp b/src/modules/RangeTestModule.cpp index 415614dd2..25aa3c443 100644 --- a/src/modules/RangeTestModule.cpp +++ b/src/modules/RangeTestModule.cpp @@ -144,7 +144,9 @@ ProcessMessage RangeTestModuleRadio::handleReceived(const meshtastic_MeshPacket if (moduleConfig.range_test.save) { appendFile(mp); - } + } else if (moduleConfig.range_test.clear) { + removeFile(); + }; /* NodeInfoLite *n = nodeDB->getMeshNode(getFrom(&mp)); From caf21800758e951582d29a2728e9dbad488ee756 Mon Sep 17 00:00:00 2001 From: ford-jones Date: Thu, 21 Aug 2025 19:28:52 +1200 Subject: [PATCH 05/39] If specified, Clean out range test results on module init --- src/modules/RangeTestModule.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/modules/RangeTestModule.cpp b/src/modules/RangeTestModule.cpp index 25aa3c443..c3d070602 100644 --- a/src/modules/RangeTestModule.cpp +++ b/src/modules/RangeTestModule.cpp @@ -41,12 +41,12 @@ int32_t RangeTestModule::runOnce() // moduleConfig.range_test.enabled = 1; // moduleConfig.range_test.sender = 30; // moduleConfig.range_test.save = 1; + // moduleConfig.range_test.clear = 1; // Fixed position is useful when testing indoors. // config.position.fixed_position = 1; uint32_t senderHeartbeat = moduleConfig.range_test.sender * 1000; - if (moduleConfig.range_test.enabled) { if (firstTime) { @@ -54,6 +54,11 @@ int32_t RangeTestModule::runOnce() firstTime = 0; + if (moduleConfig.range_test.clear) { + // User wants to delete previous range test(s) + LOG_INFO("Range Test Module - Clearing out previous test file"); + rangeTestModuleRadio->removeFile(); + } if (moduleConfig.range_test.sender) { LOG_INFO("Init Range Test Module -- Sender"); started = millis(); // make a note of when we started @@ -141,12 +146,9 @@ ProcessMessage RangeTestModuleRadio::handleReceived(const meshtastic_MeshPacket */ if (!isFromUs(&mp)) { - if (moduleConfig.range_test.save) { appendFile(mp); - } else if (moduleConfig.range_test.clear) { - removeFile(); - }; + } /* NodeInfoLite *n = nodeDB->getMeshNode(getFrom(&mp)); From 35d9e68053eac668c017eb4fc33d11999a5cef2b Mon Sep 17 00:00:00 2001 From: ford-jones Date: Thu, 21 Aug 2025 11:55:53 +1200 Subject: [PATCH 06/39] Enabled deletion of files created by the range-test module --- src/modules/RangeTestModule.cpp | 19 ++++++++++++++++++- src/modules/RangeTestModule.h | 5 +++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/modules/RangeTestModule.cpp b/src/modules/RangeTestModule.cpp index 6f3d69acf..2f8659db0 100644 --- a/src/modules/RangeTestModule.cpp +++ b/src/modules/RangeTestModule.cpp @@ -298,4 +298,21 @@ bool RangeTestModuleRadio::appendFile(const meshtastic_MeshPacket &mp) #endif return 1; -} \ No newline at end of file +} + +bool RangeTestModuleRadio::removeFile() +{ +#ifdef ARCH_ESP32 + char *fp = "/static/rangetest.csv"; + if (FSCom.exists(fp)) { + LOG_INFO("Deleting previous range test."); + bool result = FSCom.remove(fp); + if (!result) { + LOG_ERROR("Failed to delete rangeTest.csv"); + return 0; + } + } +#endif + + return 1; +}; \ No newline at end of file diff --git a/src/modules/RangeTestModule.h b/src/modules/RangeTestModule.h index b632d343e..0512e70a8 100644 --- a/src/modules/RangeTestModule.h +++ b/src/modules/RangeTestModule.h @@ -44,6 +44,11 @@ class RangeTestModuleRadio : public SinglePortModule */ bool appendFile(const meshtastic_MeshPacket &mp); + /** + * Cleanup range test data from filesystem + */ + bool removeFile(); + protected: /** Called to handle a particular incoming message From 7b24d3163610dda9f3c4a75294553370df9936f4 Mon Sep 17 00:00:00 2001 From: ford-jones Date: Thu, 21 Aug 2025 12:00:19 +1200 Subject: [PATCH 07/39] Use string constants in place of char* --- src/modules/RangeTestModule.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/modules/RangeTestModule.cpp b/src/modules/RangeTestModule.cpp index 2f8659db0..38f29e93b 100644 --- a/src/modules/RangeTestModule.cpp +++ b/src/modules/RangeTestModule.cpp @@ -303,16 +303,16 @@ bool RangeTestModuleRadio::appendFile(const meshtastic_MeshPacket &mp) bool RangeTestModuleRadio::removeFile() { #ifdef ARCH_ESP32 - char *fp = "/static/rangetest.csv"; - if (FSCom.exists(fp)) { + if (FSCom.exists("/static/rangetest.csv")) { LOG_INFO("Deleting previous range test."); - bool result = FSCom.remove(fp); + bool result = FSCom.remove("/static/rangetest.csv"); if (!result) { LOG_ERROR("Failed to delete rangeTest.csv"); return 0; } + LOG_INFO("Range test removed."); } #endif return 1; -}; \ No newline at end of file +} \ No newline at end of file From 8e32d5807748ece03cd0397370a73e1071d67bb8 Mon Sep 17 00:00:00 2001 From: ford-jones Date: Thu, 21 Aug 2025 12:01:45 +1200 Subject: [PATCH 08/39] Check filesystem mounted --- src/modules/RangeTestModule.cpp | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/modules/RangeTestModule.cpp b/src/modules/RangeTestModule.cpp index 38f29e93b..415614dd2 100644 --- a/src/modules/RangeTestModule.cpp +++ b/src/modules/RangeTestModule.cpp @@ -303,15 +303,24 @@ bool RangeTestModuleRadio::appendFile(const meshtastic_MeshPacket &mp) bool RangeTestModuleRadio::removeFile() { #ifdef ARCH_ESP32 - if (FSCom.exists("/static/rangetest.csv")) { - LOG_INFO("Deleting previous range test."); - bool result = FSCom.remove("/static/rangetest.csv"); - if (!result) { - LOG_ERROR("Failed to delete rangeTest.csv"); - return 0; - } - LOG_INFO("Range test removed."); + if (!FSBegin()) { + LOG_DEBUG("An Error has occurred while mounting the filesystem"); + return 0; } + + if (!FSCom.exists("/static/rangetest.csv")) { + LOG_DEBUG("No range tests found."); + return 0; + } + + LOG_INFO("Deleting previous range test."); + bool result = FSCom.remove("/static/rangetest.csv"); + + if (!result) { + LOG_ERROR("Failed to delete range test."); + return 0; + } + LOG_INFO("Range test removed."); #endif return 1; From 9d560fe9e1f9fe2a39437ccfea079a051430cfc3 Mon Sep 17 00:00:00 2001 From: ford-jones Date: Thu, 21 Aug 2025 12:12:13 +1200 Subject: [PATCH 09/39] Enable protobufs to include rangetest deletion configuration --- src/mesh/generated/meshtastic/deviceonly.pb.h | 2 +- src/mesh/generated/meshtastic/localonly.pb.h | 2 +- src/mesh/generated/meshtastic/module_config.pb.h | 13 +++++++++---- src/modules/RangeTestModule.cpp | 4 +++- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/mesh/generated/meshtastic/deviceonly.pb.h b/src/mesh/generated/meshtastic/deviceonly.pb.h index f47091384..9b6330596 100644 --- a/src/mesh/generated/meshtastic/deviceonly.pb.h +++ b/src/mesh/generated/meshtastic/deviceonly.pb.h @@ -360,7 +360,7 @@ extern const pb_msgdesc_t meshtastic_BackupPreferences_msg; /* Maximum encoded size of messages (where known) */ /* meshtastic_NodeDatabase_size depends on runtime parameters */ #define MESHTASTIC_MESHTASTIC_DEVICEONLY_PB_H_MAX_SIZE meshtastic_BackupPreferences_size -#define meshtastic_BackupPreferences_size 2271 +#define meshtastic_BackupPreferences_size 2273 #define meshtastic_ChannelFile_size 718 #define meshtastic_DeviceState_size 1737 #define meshtastic_NodeInfoLite_size 196 diff --git a/src/mesh/generated/meshtastic/localonly.pb.h b/src/mesh/generated/meshtastic/localonly.pb.h index ca8dcd5fb..da224fb94 100644 --- a/src/mesh/generated/meshtastic/localonly.pb.h +++ b/src/mesh/generated/meshtastic/localonly.pb.h @@ -188,7 +188,7 @@ extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg; /* Maximum encoded size of messages (where known) */ #define MESHTASTIC_MESHTASTIC_LOCALONLY_PB_H_MAX_SIZE meshtastic_LocalConfig_size #define meshtastic_LocalConfig_size 747 -#define meshtastic_LocalModuleConfig_size 669 +#define meshtastic_LocalModuleConfig_size 671 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/generated/meshtastic/module_config.pb.h b/src/mesh/generated/meshtastic/module_config.pb.h index b27f5f515..468a31a59 100644 --- a/src/mesh/generated/meshtastic/module_config.pb.h +++ b/src/mesh/generated/meshtastic/module_config.pb.h @@ -317,6 +317,9 @@ typedef struct _meshtastic_ModuleConfig_RangeTestConfig { /* Bool value indicating that this node should save a RangeTest.csv file. ESP32 Only */ bool save; + /* Bool indicating that the node should cleanup / destroy it's RangeTest.csv file. + ESP32 Only */ + bool clear; } meshtastic_ModuleConfig_RangeTestConfig; /* Configuration for both device and environment metrics */ @@ -519,7 +522,7 @@ extern "C" { #define meshtastic_ModuleConfig_SerialConfig_init_default {0, 0, 0, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Baud_MIN, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MIN, 0} #define meshtastic_ModuleConfig_ExternalNotificationConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_ModuleConfig_StoreForwardConfig_init_default {0, 0, 0, 0, 0, 0} -#define meshtastic_ModuleConfig_RangeTestConfig_init_default {0, 0, 0} +#define meshtastic_ModuleConfig_RangeTestConfig_init_default {0, 0, 0, 0} #define meshtastic_ModuleConfig_TelemetryConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_ModuleConfig_CannedMessageConfig_init_default {0, 0, 0, 0, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, 0, 0, "", 0} #define meshtastic_ModuleConfig_AmbientLightingConfig_init_default {0, 0, 0, 0, 0} @@ -535,7 +538,7 @@ extern "C" { #define meshtastic_ModuleConfig_SerialConfig_init_zero {0, 0, 0, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Baud_MIN, 0, _meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MIN, 0} #define meshtastic_ModuleConfig_ExternalNotificationConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_ModuleConfig_StoreForwardConfig_init_zero {0, 0, 0, 0, 0, 0} -#define meshtastic_ModuleConfig_RangeTestConfig_init_zero {0, 0, 0} +#define meshtastic_ModuleConfig_RangeTestConfig_init_zero {0, 0, 0, 0} #define meshtastic_ModuleConfig_TelemetryConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_ModuleConfig_CannedMessageConfig_init_zero {0, 0, 0, 0, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, 0, 0, "", 0} #define meshtastic_ModuleConfig_AmbientLightingConfig_init_zero {0, 0, 0, 0, 0} @@ -610,6 +613,7 @@ extern "C" { #define meshtastic_ModuleConfig_RangeTestConfig_enabled_tag 1 #define meshtastic_ModuleConfig_RangeTestConfig_sender_tag 2 #define meshtastic_ModuleConfig_RangeTestConfig_save_tag 3 +#define meshtastic_ModuleConfig_RangeTestConfig_clear_tag 4 #define meshtastic_ModuleConfig_TelemetryConfig_device_update_interval_tag 1 #define meshtastic_ModuleConfig_TelemetryConfig_environment_update_interval_tag 2 #define meshtastic_ModuleConfig_TelemetryConfig_environment_measurement_enabled_tag 3 @@ -803,7 +807,8 @@ X(a, STATIC, SINGULAR, BOOL, is_server, 6) #define meshtastic_ModuleConfig_RangeTestConfig_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, BOOL, enabled, 1) \ X(a, STATIC, SINGULAR, UINT32, sender, 2) \ -X(a, STATIC, SINGULAR, BOOL, save, 3) +X(a, STATIC, SINGULAR, BOOL, save, 3) \ +X(a, STATIC, SINGULAR, BOOL, clear, 4) #define meshtastic_ModuleConfig_RangeTestConfig_CALLBACK NULL #define meshtastic_ModuleConfig_RangeTestConfig_DEFAULT NULL @@ -901,7 +906,7 @@ extern const pb_msgdesc_t meshtastic_RemoteHardwarePin_msg; #define meshtastic_ModuleConfig_MapReportSettings_size 14 #define meshtastic_ModuleConfig_NeighborInfoConfig_size 10 #define meshtastic_ModuleConfig_PaxcounterConfig_size 30 -#define meshtastic_ModuleConfig_RangeTestConfig_size 10 +#define meshtastic_ModuleConfig_RangeTestConfig_size 12 #define meshtastic_ModuleConfig_RemoteHardwareConfig_size 96 #define meshtastic_ModuleConfig_SerialConfig_size 28 #define meshtastic_ModuleConfig_StoreForwardConfig_size 24 diff --git a/src/modules/RangeTestModule.cpp b/src/modules/RangeTestModule.cpp index 415614dd2..25aa3c443 100644 --- a/src/modules/RangeTestModule.cpp +++ b/src/modules/RangeTestModule.cpp @@ -144,7 +144,9 @@ ProcessMessage RangeTestModuleRadio::handleReceived(const meshtastic_MeshPacket if (moduleConfig.range_test.save) { appendFile(mp); - } + } else if (moduleConfig.range_test.clear) { + removeFile(); + }; /* NodeInfoLite *n = nodeDB->getMeshNode(getFrom(&mp)); From 4dfcd61d461870b5a2be73b8a3980c1b181f40f9 Mon Sep 17 00:00:00 2001 From: ford-jones Date: Thu, 21 Aug 2025 19:28:52 +1200 Subject: [PATCH 10/39] If specified, Clean out range test results on module init --- src/modules/RangeTestModule.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/modules/RangeTestModule.cpp b/src/modules/RangeTestModule.cpp index 25aa3c443..c3d070602 100644 --- a/src/modules/RangeTestModule.cpp +++ b/src/modules/RangeTestModule.cpp @@ -41,12 +41,12 @@ int32_t RangeTestModule::runOnce() // moduleConfig.range_test.enabled = 1; // moduleConfig.range_test.sender = 30; // moduleConfig.range_test.save = 1; + // moduleConfig.range_test.clear = 1; // Fixed position is useful when testing indoors. // config.position.fixed_position = 1; uint32_t senderHeartbeat = moduleConfig.range_test.sender * 1000; - if (moduleConfig.range_test.enabled) { if (firstTime) { @@ -54,6 +54,11 @@ int32_t RangeTestModule::runOnce() firstTime = 0; + if (moduleConfig.range_test.clear) { + // User wants to delete previous range test(s) + LOG_INFO("Range Test Module - Clearing out previous test file"); + rangeTestModuleRadio->removeFile(); + } if (moduleConfig.range_test.sender) { LOG_INFO("Init Range Test Module -- Sender"); started = millis(); // make a note of when we started @@ -141,12 +146,9 @@ ProcessMessage RangeTestModuleRadio::handleReceived(const meshtastic_MeshPacket */ if (!isFromUs(&mp)) { - if (moduleConfig.range_test.save) { appendFile(mp); - } else if (moduleConfig.range_test.clear) { - removeFile(); - }; + } /* NodeInfoLite *n = nodeDB->getMeshNode(getFrom(&mp)); From 142abb2a4e04d5cfde75ef034db12d4dc25f04a8 Mon Sep 17 00:00:00 2001 From: ford-jones Date: Wed, 3 Sep 2025 12:06:35 +1200 Subject: [PATCH 11/39] Updated naming to match protobuf --- src/mesh/generated/meshtastic/module_config.pb.h | 6 +++--- src/modules/RangeTestModule.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mesh/generated/meshtastic/module_config.pb.h b/src/mesh/generated/meshtastic/module_config.pb.h index 468a31a59..16c4c230c 100644 --- a/src/mesh/generated/meshtastic/module_config.pb.h +++ b/src/mesh/generated/meshtastic/module_config.pb.h @@ -319,7 +319,7 @@ typedef struct _meshtastic_ModuleConfig_RangeTestConfig { bool save; /* Bool indicating that the node should cleanup / destroy it's RangeTest.csv file. ESP32 Only */ - bool clear; + bool clear_on_reboot; } meshtastic_ModuleConfig_RangeTestConfig; /* Configuration for both device and environment metrics */ @@ -613,7 +613,7 @@ extern "C" { #define meshtastic_ModuleConfig_RangeTestConfig_enabled_tag 1 #define meshtastic_ModuleConfig_RangeTestConfig_sender_tag 2 #define meshtastic_ModuleConfig_RangeTestConfig_save_tag 3 -#define meshtastic_ModuleConfig_RangeTestConfig_clear_tag 4 +#define meshtastic_ModuleConfig_RangeTestConfig_clear_on_reboot_tag 4 #define meshtastic_ModuleConfig_TelemetryConfig_device_update_interval_tag 1 #define meshtastic_ModuleConfig_TelemetryConfig_environment_update_interval_tag 2 #define meshtastic_ModuleConfig_TelemetryConfig_environment_measurement_enabled_tag 3 @@ -808,7 +808,7 @@ X(a, STATIC, SINGULAR, BOOL, is_server, 6) X(a, STATIC, SINGULAR, BOOL, enabled, 1) \ X(a, STATIC, SINGULAR, UINT32, sender, 2) \ X(a, STATIC, SINGULAR, BOOL, save, 3) \ -X(a, STATIC, SINGULAR, BOOL, clear, 4) +X(a, STATIC, SINGULAR, BOOL, clear_on_reboot, 4) #define meshtastic_ModuleConfig_RangeTestConfig_CALLBACK NULL #define meshtastic_ModuleConfig_RangeTestConfig_DEFAULT NULL diff --git a/src/modules/RangeTestModule.cpp b/src/modules/RangeTestModule.cpp index c3d070602..c119cd8c4 100644 --- a/src/modules/RangeTestModule.cpp +++ b/src/modules/RangeTestModule.cpp @@ -54,7 +54,7 @@ int32_t RangeTestModule::runOnce() firstTime = 0; - if (moduleConfig.range_test.clear) { + if (moduleConfig.range_test.clear_on_reboot) { // User wants to delete previous range test(s) LOG_INFO("Range Test Module - Clearing out previous test file"); rangeTestModuleRadio->removeFile(); From ba582d6ef4b475f7bcc4929894bfae4090cc5ee7 Mon Sep 17 00:00:00 2001 From: ford-jones Date: Wed, 3 Sep 2025 12:23:59 +1200 Subject: [PATCH 12/39] Protobuf naming reflected in config-switch --- src/modules/RangeTestModule.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/RangeTestModule.cpp b/src/modules/RangeTestModule.cpp index c119cd8c4..20e243584 100644 --- a/src/modules/RangeTestModule.cpp +++ b/src/modules/RangeTestModule.cpp @@ -41,7 +41,7 @@ int32_t RangeTestModule::runOnce() // moduleConfig.range_test.enabled = 1; // moduleConfig.range_test.sender = 30; // moduleConfig.range_test.save = 1; - // moduleConfig.range_test.clear = 1; + // moduleConfig.range_test.clear_on_reboot = 1; // Fixed position is useful when testing indoors. // config.position.fixed_position = 1; From c62f262f632d90724bb9d76d581655b9affa67af Mon Sep 17 00:00:00 2001 From: ford-jones Date: Wed, 3 Sep 2025 13:38:39 +1200 Subject: [PATCH 13/39] Trunk fmt --- src/SerialConsole.cpp | 7 +++---- src/mesh/StreamAPI.h | 6 +++--- variants/esp32s3/t-deck-pro/variant.h | 15 +++++++------ .../nrf52840/heltec_mesh_solar/variant.cpp | 2 +- variants/nrf52840/heltec_mesh_solar/variant.h | 21 +++++++++---------- 5 files changed, 24 insertions(+), 27 deletions(-) diff --git a/src/SerialConsole.cpp b/src/SerialConsole.cpp index 093a24678..2e6ae68a5 100644 --- a/src/SerialConsole.cpp +++ b/src/SerialConsole.cpp @@ -65,10 +65,9 @@ SerialConsole::SerialConsole() : StreamAPI(&Port), RedirectablePrint(&Port), con int32_t SerialConsole::runOnce() { #ifdef HELTEC_MESH_SOLAR - //After enabling the mesh solar serial port module configuration, command processing is handled by the serial port module. - if(moduleConfig.serial.enabled && moduleConfig.serial.override_console_serial_port - && moduleConfig.serial.mode==meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MS_CONFIG) - { + // After enabling the mesh solar serial port module configuration, command processing is handled by the serial port module. + if (moduleConfig.serial.enabled && moduleConfig.serial.override_console_serial_port && + moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MS_CONFIG) { return 250; } #endif diff --git a/src/mesh/StreamAPI.h b/src/mesh/StreamAPI.h index 547dd0175..4ca2c197f 100644 --- a/src/mesh/StreamAPI.h +++ b/src/mesh/StreamAPI.h @@ -50,15 +50,15 @@ class StreamAPI : public PhoneAPI * phone. */ virtual int32_t runOncePart(); - virtual int32_t runOncePart(char *buf,uint16_t bufLen); + virtual int32_t runOncePart(char *buf, uint16_t bufLen); private: /** * Read any rx chars from the link and call handleToRadio */ int32_t readStream(); - int32_t readStream(char *buf,uint16_t bufLen); - int32_t handleRecStream(char *buf,uint16_t bufLen); + int32_t readStream(char *buf, uint16_t bufLen); + int32_t handleRecStream(char *buf, uint16_t bufLen); /** * call getFromRadio() and deliver encapsulated packets to the Stream diff --git a/variants/esp32s3/t-deck-pro/variant.h b/variants/esp32s3/t-deck-pro/variant.h index abe0a772a..35cb99435 100644 --- a/variants/esp32s3/t-deck-pro/variant.h +++ b/variants/esp32s3/t-deck-pro/variant.h @@ -93,11 +93,10 @@ // Internally the TTGO module hooks the SX1262-DIO2 in to control the TX/RX switch (which is the default for the sx1262interface // code) -#define MODEM_POWER_EN 41 -#define MODEM_PWRKEY 40 -#define MODEM_RST 9 -#define MODEM_RI 7 -#define MODEM_DTR 8 -#define MODEM_RX 10 -#define MODEM_TX 11 - +#define MODEM_POWER_EN 41 +#define MODEM_PWRKEY 40 +#define MODEM_RST 9 +#define MODEM_RI 7 +#define MODEM_DTR 8 +#define MODEM_RX 10 +#define MODEM_TX 11 diff --git a/variants/nrf52840/heltec_mesh_solar/variant.cpp b/variants/nrf52840/heltec_mesh_solar/variant.cpp index 8236d7cf4..05d7a32e2 100644 --- a/variants/nrf52840/heltec_mesh_solar/variant.cpp +++ b/variants/nrf52840/heltec_mesh_solar/variant.cpp @@ -32,5 +32,5 @@ const uint32_t g_ADigitalPinMap[] = { void initVariant() { - pinMode(BQ4050_EMERGENCY_SHUTDOWN_PIN, INPUT); + pinMode(BQ4050_EMERGENCY_SHUTDOWN_PIN, INPUT); } diff --git a/variants/nrf52840/heltec_mesh_solar/variant.h b/variants/nrf52840/heltec_mesh_solar/variant.h index 33c2b2556..4165bc349 100644 --- a/variants/nrf52840/heltec_mesh_solar/variant.h +++ b/variants/nrf52840/heltec_mesh_solar/variant.h @@ -39,16 +39,15 @@ extern "C" { #define NUM_ANALOG_INPUTS (1) #define NUM_ANALOG_OUTPUTS (0) - #define PIN_LED1 (0 + 12) // green (confirmed on 1.0 board) #define LED_BLUE PIN_LED1 // fake for bluefruit library #define LED_GREEN PIN_LED1 #define LED_BUILTIN LED_GREEN -#define LED_STATE_ON 0 // State when LED is lit +#define LED_STATE_ON 0 // State when LED is lit #define HAS_NEOPIXEL // Enable the use of neopixels #define NEOPIXEL_COUNT 1 // How many neopixels are connected -#define NEOPIXEL_DATA (32+15) // gpio pin used to send data to the neopixels +#define NEOPIXEL_DATA (32 + 15) // gpio pin used to send data to the neopixels #define NEOPIXEL_TYPE (NEO_GRB + NEO_KHZ800) // type of neopixels in use /* @@ -74,13 +73,13 @@ No longer populated on PCB // I2C bus 0 // Routed to footprint for PCF8563TS RTC // Not populated on T114 V1, maybe in future? -#define PIN_WIRE_SDA (0 + 6) // P0.26 +#define PIN_WIRE_SDA (0 + 6) // P0.26 #define PIN_WIRE_SCL (0 + 26) // P0.26 // I2C bus 1 // Available on header pins, for general use #define PIN_WIRE1_SDA (0 + 30) // P0.30 -#define PIN_WIRE1_SCL (0 + 5) // P0.13 +#define PIN_WIRE1_SCL (0 + 5) // P0.13 /* * Lora radio @@ -89,14 +88,14 @@ No longer populated on PCB #define USE_SX1262 // #define USE_SX1268 #define SX126X_CS (0 + 24) // FIXME - we really should define LORA_CS instead -#define LORA_CS (0 + 24) +#define LORA_CS (0 + 24) #define SX126X_DIO1 (0 + 20) // Note DIO2 is attached internally to the module to an analog switch for TX/RX switching // #define SX1262_DIO3 (0 + 21) // This is used as an *output* from the sx1262 and connected internally to power the tcxo, do not drive from the // main // CPU? -#define SX126X_BUSY (0 + 17) +#define SX126X_BUSY (0 + 17) #define SX126X_RESET (0 + 25) // Not really an E22 but TTGO seems to be trying to clone that #define SX126X_DIO2_AS_RF_SWITCH @@ -134,16 +133,16 @@ No longer populated on PCB // For LORA, spi 0 #define PIN_SPI_MISO (0 + 23) #define PIN_SPI_MOSI (0 + 22) -#define PIN_SPI_SCK (0 + 19) +#define PIN_SPI_SCK (0 + 19) // #define PIN_PWR_EN (0 + 6) // To debug via the segger JLINK console rather than the CDC-ACM serial device // #define USE_SEGGER -#define BQ4050_SDA_PIN (32+1) // I2C data line pin -#define BQ4050_SCL_PIN (32+0) // I2C clock line pin -#define BQ4050_EMERGENCY_SHUTDOWN_PIN (32+3) // Emergency shutdown pin +#define BQ4050_SDA_PIN (32 + 1) // I2C data line pin +#define BQ4050_SCL_PIN (32 + 0) // I2C clock line pin +#define BQ4050_EMERGENCY_SHUTDOWN_PIN (32 + 3) // Emergency shutdown pin #define HAS_RTC 0 #ifdef __cplusplus From b75e8913e0854dd6e78fb2735e2e2adc7c77e675 Mon Sep 17 00:00:00 2001 From: ford-jones Date: Tue, 9 Sep 2025 13:14:20 +1200 Subject: [PATCH 14/39] Fix: Compile latest protobufs --- src/mesh/generated/meshtastic/config.pb.h | 10 +++++----- src/mesh/generated/meshtastic/telemetry.pb.h | 8 +++++--- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/mesh/generated/meshtastic/config.pb.h b/src/mesh/generated/meshtastic/config.pb.h index c8202bdc9..59e55db3f 100644 --- a/src/mesh/generated/meshtastic/config.pb.h +++ b/src/mesh/generated/meshtastic/config.pb.h @@ -212,10 +212,10 @@ typedef enum _meshtastic_Config_DisplayConfig_OledType { meshtastic_Config_DisplayConfig_OledType_OLED_SSD1306 = 1, /* Default / Autodetect */ meshtastic_Config_DisplayConfig_OledType_OLED_SH1106 = 2, - /* Can not be auto detected but set by proto. Used for 128x128 screens */ - meshtastic_Config_DisplayConfig_OledType_OLED_SH1107 = 3, /* Can not be auto detected but set by proto. Used for 128x64 screens */ - meshtastic_Config_DisplayConfig_OledType_OLED_SH1107_128_64 = 4 + meshtastic_Config_DisplayConfig_OledType_OLED_SH1107 = 3, + /* Can not be auto detected but set by proto. Used for 128x128 screens */ + meshtastic_Config_DisplayConfig_OledType_OLED_SH1107_128_128 = 4 } meshtastic_Config_DisplayConfig_OledType; typedef enum _meshtastic_Config_DisplayConfig_DisplayMode { @@ -687,8 +687,8 @@ extern "C" { #define _meshtastic_Config_DisplayConfig_DisplayUnits_ARRAYSIZE ((meshtastic_Config_DisplayConfig_DisplayUnits)(meshtastic_Config_DisplayConfig_DisplayUnits_IMPERIAL+1)) #define _meshtastic_Config_DisplayConfig_OledType_MIN meshtastic_Config_DisplayConfig_OledType_OLED_AUTO -#define _meshtastic_Config_DisplayConfig_OledType_MAX meshtastic_Config_DisplayConfig_OledType_OLED_SH1107_128_64 -#define _meshtastic_Config_DisplayConfig_OledType_ARRAYSIZE ((meshtastic_Config_DisplayConfig_OledType)(meshtastic_Config_DisplayConfig_OledType_OLED_SH1107_128_64+1)) +#define _meshtastic_Config_DisplayConfig_OledType_MAX meshtastic_Config_DisplayConfig_OledType_OLED_SH1107_128_128 +#define _meshtastic_Config_DisplayConfig_OledType_ARRAYSIZE ((meshtastic_Config_DisplayConfig_OledType)(meshtastic_Config_DisplayConfig_OledType_OLED_SH1107_128_128+1)) #define _meshtastic_Config_DisplayConfig_DisplayMode_MIN meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT #define _meshtastic_Config_DisplayConfig_DisplayMode_MAX meshtastic_Config_DisplayConfig_DisplayMode_COLOR diff --git a/src/mesh/generated/meshtastic/telemetry.pb.h b/src/mesh/generated/meshtastic/telemetry.pb.h index f758995c2..9af095e78 100644 --- a/src/mesh/generated/meshtastic/telemetry.pb.h +++ b/src/mesh/generated/meshtastic/telemetry.pb.h @@ -99,7 +99,9 @@ typedef enum _meshtastic_TelemetrySensorType { /* Sensirion SFA30 Formaldehyde sensor */ meshtastic_TelemetrySensorType_SFA30 = 42, /* SEN5X PM SENSORS */ - meshtastic_TelemetrySensorType_SEN5X = 43 + meshtastic_TelemetrySensorType_SEN5X = 43, + /* TSL2561 light sensor */ + meshtastic_TelemetrySensorType_TSL2561 = 44 } meshtastic_TelemetrySensorType; /* Struct definitions */ @@ -434,8 +436,8 @@ extern "C" { /* Helper constants for enums */ #define _meshtastic_TelemetrySensorType_MIN meshtastic_TelemetrySensorType_SENSOR_UNSET -#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_SEN5X -#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_SEN5X+1)) +#define _meshtastic_TelemetrySensorType_MAX meshtastic_TelemetrySensorType_TSL2561 +#define _meshtastic_TelemetrySensorType_ARRAYSIZE ((meshtastic_TelemetrySensorType)(meshtastic_TelemetrySensorType_TSL2561+1)) From 901bcc24ee1a21211fde8eb8c140a9394741cd5f Mon Sep 17 00:00:00 2001 From: ford-jones Date: Fri, 19 Sep 2025 22:17:03 +1200 Subject: [PATCH 15/39] Reflect requirement of ESP32 hardware in rangetest logs --- src/modules/RangeTestModule.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/modules/RangeTestModule.cpp b/src/modules/RangeTestModule.cpp index 4dd95a7a3..3d78d0dc9 100644 --- a/src/modules/RangeTestModule.cpp +++ b/src/modules/RangeTestModule.cpp @@ -299,9 +299,14 @@ bool RangeTestModuleRadio::appendFile(const meshtastic_MeshPacket &mp) fileToAppend.printf("\"%s\"\n", p.payload.bytes); fileToAppend.flush(); fileToAppend.close(); -#endif return 1; + +#else + LOG_ERROR("Failed to store range test results - feature only available for ESP32"); + + return 0; +#endif } bool RangeTestModuleRadio::removeFile() @@ -325,7 +330,11 @@ bool RangeTestModuleRadio::removeFile() return 0; } LOG_INFO("Range test removed."); -#endif return 1; +#else + LOG_ERROR("Failed to remove range test results - feature only available for ESP32"); + + return 0; +#endif } \ No newline at end of file From 2ccf91f443f3098b2228c9a54f6dbc0eee0678b1 Mon Sep 17 00:00:00 2001 From: ford-jones Date: Sat, 20 Sep 2025 14:38:05 +1200 Subject: [PATCH 16/39] Regen protos --- protobufs | 2 +- src/mesh/generated/meshtastic/config.pb.h | 49 ++++++++++++------- .../generated/meshtastic/device_ui.pb.cpp | 2 - src/mesh/generated/meshtastic/device_ui.pb.h | 45 ++--------------- src/mesh/generated/meshtastic/deviceonly.pb.h | 2 +- src/mesh/generated/meshtastic/localonly.pb.h | 4 +- src/mesh/generated/meshtastic/mesh.pb.h | 8 +-- .../generated/meshtastic/module_config.pb.h | 13 ++--- 8 files changed, 45 insertions(+), 80 deletions(-) diff --git a/protobufs b/protobufs index 46b81e822..a84657c22 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit 46b81e822af1b8e408f437092337f129dee693e6 +Subproject commit a84657c220421536f18d11fc5edf680efadbceeb diff --git a/src/mesh/generated/meshtastic/config.pb.h b/src/mesh/generated/meshtastic/config.pb.h index 0453ecad2..59e55db3f 100644 --- a/src/mesh/generated/meshtastic/config.pb.h +++ b/src/mesh/generated/meshtastic/config.pb.h @@ -173,10 +173,28 @@ typedef enum _meshtastic_Config_NetworkConfig_ProtocolFlags { meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST = 1 } meshtastic_Config_NetworkConfig_ProtocolFlags; -/* Deprecated in 2.7.4: Unused */ -typedef enum _meshtastic_Config_DisplayConfig_DeprecatedGpsCoordinateFormat { - meshtastic_Config_DisplayConfig_DeprecatedGpsCoordinateFormat_UNUSED = 0 -} meshtastic_Config_DisplayConfig_DeprecatedGpsCoordinateFormat; +/* How the GPS coordinates are displayed on the OLED screen. */ +typedef enum _meshtastic_Config_DisplayConfig_GpsCoordinateFormat { + /* GPS coordinates are displayed in the normal decimal degrees format: + DD.DDDDDD DDD.DDDDDD */ + meshtastic_Config_DisplayConfig_GpsCoordinateFormat_DEC = 0, + /* GPS coordinates are displayed in the degrees minutes seconds format: + DD°MM'SS"C DDD°MM'SS"C, where C is the compass point representing the locations quadrant */ + meshtastic_Config_DisplayConfig_GpsCoordinateFormat_DMS = 1, + /* Universal Transverse Mercator format: + ZZB EEEEEE NNNNNNN, where Z is zone, B is band, E is easting, N is northing */ + meshtastic_Config_DisplayConfig_GpsCoordinateFormat_UTM = 2, + /* Military Grid Reference System format: + ZZB CD EEEEE NNNNN, where Z is zone, B is band, C is the east 100k square, D is the north 100k square, + E is easting, N is northing */ + meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MGRS = 3, + /* Open Location Code (aka Plus Codes). */ + meshtastic_Config_DisplayConfig_GpsCoordinateFormat_OLC = 4, + /* Ordnance Survey Grid Reference (the National Grid System of the UK). + Format: AB EEEEE NNNNN, where A is the east 100k square, B is the north 100k square, + E is the easting, N is the northing */ + meshtastic_Config_DisplayConfig_GpsCoordinateFormat_OSGR = 5 +} meshtastic_Config_DisplayConfig_GpsCoordinateFormat; /* Unit display preference */ typedef enum _meshtastic_Config_DisplayConfig_DisplayUnits { @@ -473,7 +491,7 @@ typedef struct _meshtastic_Config_DisplayConfig { uint32_t screen_on_secs; /* Deprecated in 2.7.4: Unused How the GPS coordinates are formatted on the OLED screen. */ - meshtastic_Config_DisplayConfig_DeprecatedGpsCoordinateFormat gps_format; + meshtastic_Config_DisplayConfig_GpsCoordinateFormat gps_format; /* Automatically toggles to the next page on the screen like a carousel, based the specified interval in seconds. Potentially useful for devices without user buttons. */ uint32_t auto_screen_carousel_secs; @@ -497,9 +515,6 @@ typedef struct _meshtastic_Config_DisplayConfig { /* If false (default), the device will display the time in 24-hour format on screen. If true, the device will display the time in 12-hour format on screen. */ bool use_12h_clock; - /* If false (default), the device will use short names for various display screens. - If true, node names will show in long format */ - bool use_long_node_name; } meshtastic_Config_DisplayConfig; /* Lora Config */ @@ -663,9 +678,9 @@ extern "C" { #define _meshtastic_Config_NetworkConfig_ProtocolFlags_MAX meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST #define _meshtastic_Config_NetworkConfig_ProtocolFlags_ARRAYSIZE ((meshtastic_Config_NetworkConfig_ProtocolFlags)(meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST+1)) -#define _meshtastic_Config_DisplayConfig_DeprecatedGpsCoordinateFormat_MIN meshtastic_Config_DisplayConfig_DeprecatedGpsCoordinateFormat_UNUSED -#define _meshtastic_Config_DisplayConfig_DeprecatedGpsCoordinateFormat_MAX meshtastic_Config_DisplayConfig_DeprecatedGpsCoordinateFormat_UNUSED -#define _meshtastic_Config_DisplayConfig_DeprecatedGpsCoordinateFormat_ARRAYSIZE ((meshtastic_Config_DisplayConfig_DeprecatedGpsCoordinateFormat)(meshtastic_Config_DisplayConfig_DeprecatedGpsCoordinateFormat_UNUSED+1)) +#define _meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MIN meshtastic_Config_DisplayConfig_GpsCoordinateFormat_DEC +#define _meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MAX meshtastic_Config_DisplayConfig_GpsCoordinateFormat_OSGR +#define _meshtastic_Config_DisplayConfig_GpsCoordinateFormat_ARRAYSIZE ((meshtastic_Config_DisplayConfig_GpsCoordinateFormat)(meshtastic_Config_DisplayConfig_GpsCoordinateFormat_OSGR+1)) #define _meshtastic_Config_DisplayConfig_DisplayUnits_MIN meshtastic_Config_DisplayConfig_DisplayUnits_METRIC #define _meshtastic_Config_DisplayConfig_DisplayUnits_MAX meshtastic_Config_DisplayConfig_DisplayUnits_IMPERIAL @@ -706,7 +721,7 @@ extern "C" { #define meshtastic_Config_NetworkConfig_address_mode_ENUMTYPE meshtastic_Config_NetworkConfig_AddressMode -#define meshtastic_Config_DisplayConfig_gps_format_ENUMTYPE meshtastic_Config_DisplayConfig_DeprecatedGpsCoordinateFormat +#define meshtastic_Config_DisplayConfig_gps_format_ENUMTYPE meshtastic_Config_DisplayConfig_GpsCoordinateFormat #define meshtastic_Config_DisplayConfig_units_ENUMTYPE meshtastic_Config_DisplayConfig_DisplayUnits #define meshtastic_Config_DisplayConfig_oled_ENUMTYPE meshtastic_Config_DisplayConfig_OledType #define meshtastic_Config_DisplayConfig_displaymode_ENUMTYPE meshtastic_Config_DisplayConfig_DisplayMode @@ -727,7 +742,7 @@ extern "C" { #define meshtastic_Config_PowerConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_Config_NetworkConfig_init_default {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_default, "", 0, 0} #define meshtastic_Config_NetworkConfig_IpV4Config_init_default {0, 0, 0, 0} -#define meshtastic_Config_DisplayConfig_init_default {0, _meshtastic_Config_DisplayConfig_DeprecatedGpsCoordinateFormat_MIN, 0, 0, 0, _meshtastic_Config_DisplayConfig_DisplayUnits_MIN, _meshtastic_Config_DisplayConfig_OledType_MIN, _meshtastic_Config_DisplayConfig_DisplayMode_MIN, 0, 0, _meshtastic_Config_DisplayConfig_CompassOrientation_MIN, 0, 0} +#define meshtastic_Config_DisplayConfig_init_default {0, _meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _meshtastic_Config_DisplayConfig_DisplayUnits_MIN, _meshtastic_Config_DisplayConfig_OledType_MIN, _meshtastic_Config_DisplayConfig_DisplayMode_MIN, 0, 0, _meshtastic_Config_DisplayConfig_CompassOrientation_MIN, 0} #define meshtastic_Config_LoRaConfig_init_default {0, _meshtastic_Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _meshtastic_Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0} #define meshtastic_Config_BluetoothConfig_init_default {0, _meshtastic_Config_BluetoothConfig_PairingMode_MIN, 0} #define meshtastic_Config_SecurityConfig_init_default {{0, {0}}, {0, {0}}, 0, {{0, {0}}, {0, {0}}, {0, {0}}}, 0, 0, 0, 0} @@ -738,7 +753,7 @@ extern "C" { #define meshtastic_Config_PowerConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_Config_NetworkConfig_init_zero {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_zero, "", 0, 0} #define meshtastic_Config_NetworkConfig_IpV4Config_init_zero {0, 0, 0, 0} -#define meshtastic_Config_DisplayConfig_init_zero {0, _meshtastic_Config_DisplayConfig_DeprecatedGpsCoordinateFormat_MIN, 0, 0, 0, _meshtastic_Config_DisplayConfig_DisplayUnits_MIN, _meshtastic_Config_DisplayConfig_OledType_MIN, _meshtastic_Config_DisplayConfig_DisplayMode_MIN, 0, 0, _meshtastic_Config_DisplayConfig_CompassOrientation_MIN, 0, 0} +#define meshtastic_Config_DisplayConfig_init_zero {0, _meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _meshtastic_Config_DisplayConfig_DisplayUnits_MIN, _meshtastic_Config_DisplayConfig_OledType_MIN, _meshtastic_Config_DisplayConfig_DisplayMode_MIN, 0, 0, _meshtastic_Config_DisplayConfig_CompassOrientation_MIN, 0} #define meshtastic_Config_LoRaConfig_init_zero {0, _meshtastic_Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _meshtastic_Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0} #define meshtastic_Config_BluetoothConfig_init_zero {0, _meshtastic_Config_BluetoothConfig_PairingMode_MIN, 0} #define meshtastic_Config_SecurityConfig_init_zero {{0, {0}}, {0, {0}}, 0, {{0, {0}}, {0, {0}}, {0, {0}}}, 0, 0, 0, 0} @@ -805,7 +820,6 @@ extern "C" { #define meshtastic_Config_DisplayConfig_wake_on_tap_or_motion_tag 10 #define meshtastic_Config_DisplayConfig_compass_orientation_tag 11 #define meshtastic_Config_DisplayConfig_use_12h_clock_tag 12 -#define meshtastic_Config_DisplayConfig_use_long_node_name_tag 13 #define meshtastic_Config_LoRaConfig_use_preset_tag 1 #define meshtastic_Config_LoRaConfig_modem_preset_tag 2 #define meshtastic_Config_LoRaConfig_bandwidth_tag 3 @@ -951,8 +965,7 @@ X(a, STATIC, SINGULAR, UENUM, displaymode, 8) \ X(a, STATIC, SINGULAR, BOOL, heading_bold, 9) \ X(a, STATIC, SINGULAR, BOOL, wake_on_tap_or_motion, 10) \ X(a, STATIC, SINGULAR, UENUM, compass_orientation, 11) \ -X(a, STATIC, SINGULAR, BOOL, use_12h_clock, 12) \ -X(a, STATIC, SINGULAR, BOOL, use_long_node_name, 13) +X(a, STATIC, SINGULAR, BOOL, use_12h_clock, 12) #define meshtastic_Config_DisplayConfig_CALLBACK NULL #define meshtastic_Config_DisplayConfig_DEFAULT NULL @@ -1030,7 +1043,7 @@ extern const pb_msgdesc_t meshtastic_Config_SessionkeyConfig_msg; #define MESHTASTIC_MESHTASTIC_CONFIG_PB_H_MAX_SIZE meshtastic_Config_size #define meshtastic_Config_BluetoothConfig_size 10 #define meshtastic_Config_DeviceConfig_size 100 -#define meshtastic_Config_DisplayConfig_size 34 +#define meshtastic_Config_DisplayConfig_size 32 #define meshtastic_Config_LoRaConfig_size 85 #define meshtastic_Config_NetworkConfig_IpV4Config_size 20 #define meshtastic_Config_NetworkConfig_size 204 diff --git a/src/mesh/generated/meshtastic/device_ui.pb.cpp b/src/mesh/generated/meshtastic/device_ui.pb.cpp index 01940265f..2fc8d9461 100644 --- a/src/mesh/generated/meshtastic/device_ui.pb.cpp +++ b/src/mesh/generated/meshtastic/device_ui.pb.cpp @@ -28,5 +28,3 @@ PB_BIND(meshtastic_Map, meshtastic_Map, AUTO) - - diff --git a/src/mesh/generated/meshtastic/device_ui.pb.h b/src/mesh/generated/meshtastic/device_ui.pb.h index d9eb90773..8313438f8 100644 --- a/src/mesh/generated/meshtastic/device_ui.pb.h +++ b/src/mesh/generated/meshtastic/device_ui.pb.h @@ -66,40 +66,12 @@ typedef enum _meshtastic_Language { meshtastic_Language_UKRAINIAN = 16, /* Bulgarian */ meshtastic_Language_BULGARIAN = 17, - /* Czech */ - meshtastic_Language_CZECH = 18, /* Simplified Chinese (experimental) */ meshtastic_Language_SIMPLIFIED_CHINESE = 30, /* Traditional Chinese (experimental) */ meshtastic_Language_TRADITIONAL_CHINESE = 31 } meshtastic_Language; -/* How the GPS coordinates are displayed on the OLED screen. */ -typedef enum _meshtastic_DeviceUIConfig_GpsCoordinateFormat { - /* GPS coordinates are displayed in the normal decimal degrees format: - DD.DDDDDD DDD.DDDDDD */ - meshtastic_DeviceUIConfig_GpsCoordinateFormat_DEC = 0, - /* GPS coordinates are displayed in the degrees minutes seconds format: - DD°MM'SS"C DDD°MM'SS"C, where C is the compass point representing the locations quadrant */ - meshtastic_DeviceUIConfig_GpsCoordinateFormat_DMS = 1, - /* Universal Transverse Mercator format: - ZZB EEEEEE NNNNNNN, where Z is zone, B is band, E is easting, N is northing */ - meshtastic_DeviceUIConfig_GpsCoordinateFormat_UTM = 2, - /* Military Grid Reference System format: - ZZB CD EEEEE NNNNN, where Z is zone, B is band, C is the east 100k square, D is the north 100k square, - E is easting, N is northing */ - meshtastic_DeviceUIConfig_GpsCoordinateFormat_MGRS = 3, - /* Open Location Code (aka Plus Codes). */ - meshtastic_DeviceUIConfig_GpsCoordinateFormat_OLC = 4, - /* Ordnance Survey Grid Reference (the National Grid System of the UK). - Format: AB EEEEE NNNNN, where A is the east 100k square, B is the north 100k square, - E is the easting, N is the northing */ - meshtastic_DeviceUIConfig_GpsCoordinateFormat_OSGR = 5, - /* Maidenhead Locator System - Described here: https://en.wikipedia.org/wiki/Maidenhead_Locator_System */ - meshtastic_DeviceUIConfig_GpsCoordinateFormat_MLS = 6 -} meshtastic_DeviceUIConfig_GpsCoordinateFormat; - /* Struct definitions */ typedef struct _meshtastic_NodeFilter { /* Filter unknown nodes */ @@ -189,8 +161,6 @@ typedef struct _meshtastic_DeviceUIConfig { /* Clockface analog style true for analog clockface, false for digital clockface */ bool is_clockface_analog; - /* How the GPS coordinates are formatted on the OLED screen. */ - meshtastic_DeviceUIConfig_GpsCoordinateFormat gps_format; } meshtastic_DeviceUIConfig; @@ -211,14 +181,9 @@ extern "C" { #define _meshtastic_Language_MAX meshtastic_Language_TRADITIONAL_CHINESE #define _meshtastic_Language_ARRAYSIZE ((meshtastic_Language)(meshtastic_Language_TRADITIONAL_CHINESE+1)) -#define _meshtastic_DeviceUIConfig_GpsCoordinateFormat_MIN meshtastic_DeviceUIConfig_GpsCoordinateFormat_DEC -#define _meshtastic_DeviceUIConfig_GpsCoordinateFormat_MAX meshtastic_DeviceUIConfig_GpsCoordinateFormat_MLS -#define _meshtastic_DeviceUIConfig_GpsCoordinateFormat_ARRAYSIZE ((meshtastic_DeviceUIConfig_GpsCoordinateFormat)(meshtastic_DeviceUIConfig_GpsCoordinateFormat_MLS+1)) - #define meshtastic_DeviceUIConfig_theme_ENUMTYPE meshtastic_Theme #define meshtastic_DeviceUIConfig_language_ENUMTYPE meshtastic_Language #define meshtastic_DeviceUIConfig_compass_mode_ENUMTYPE meshtastic_CompassMode -#define meshtastic_DeviceUIConfig_gps_format_ENUMTYPE meshtastic_DeviceUIConfig_GpsCoordinateFormat @@ -226,12 +191,12 @@ extern "C" { /* Initializer values for message structs */ -#define meshtastic_DeviceUIConfig_init_default {0, 0, 0, 0, 0, 0, _meshtastic_Theme_MIN, 0, 0, 0, _meshtastic_Language_MIN, false, meshtastic_NodeFilter_init_default, false, meshtastic_NodeHighlight_init_default, {0, {0}}, false, meshtastic_Map_init_default, _meshtastic_CompassMode_MIN, 0, 0, _meshtastic_DeviceUIConfig_GpsCoordinateFormat_MIN} +#define meshtastic_DeviceUIConfig_init_default {0, 0, 0, 0, 0, 0, _meshtastic_Theme_MIN, 0, 0, 0, _meshtastic_Language_MIN, false, meshtastic_NodeFilter_init_default, false, meshtastic_NodeHighlight_init_default, {0, {0}}, false, meshtastic_Map_init_default, _meshtastic_CompassMode_MIN, 0, 0} #define meshtastic_NodeFilter_init_default {0, 0, 0, 0, 0, "", 0} #define meshtastic_NodeHighlight_init_default {0, 0, 0, 0, ""} #define meshtastic_GeoPoint_init_default {0, 0, 0} #define meshtastic_Map_init_default {false, meshtastic_GeoPoint_init_default, "", 0} -#define meshtastic_DeviceUIConfig_init_zero {0, 0, 0, 0, 0, 0, _meshtastic_Theme_MIN, 0, 0, 0, _meshtastic_Language_MIN, false, meshtastic_NodeFilter_init_zero, false, meshtastic_NodeHighlight_init_zero, {0, {0}}, false, meshtastic_Map_init_zero, _meshtastic_CompassMode_MIN, 0, 0, _meshtastic_DeviceUIConfig_GpsCoordinateFormat_MIN} +#define meshtastic_DeviceUIConfig_init_zero {0, 0, 0, 0, 0, 0, _meshtastic_Theme_MIN, 0, 0, 0, _meshtastic_Language_MIN, false, meshtastic_NodeFilter_init_zero, false, meshtastic_NodeHighlight_init_zero, {0, {0}}, false, meshtastic_Map_init_zero, _meshtastic_CompassMode_MIN, 0, 0} #define meshtastic_NodeFilter_init_zero {0, 0, 0, 0, 0, "", 0} #define meshtastic_NodeHighlight_init_zero {0, 0, 0, 0, ""} #define meshtastic_GeoPoint_init_zero {0, 0, 0} @@ -274,7 +239,6 @@ extern "C" { #define meshtastic_DeviceUIConfig_compass_mode_tag 16 #define meshtastic_DeviceUIConfig_screen_rgb_color_tag 17 #define meshtastic_DeviceUIConfig_is_clockface_analog_tag 18 -#define meshtastic_DeviceUIConfig_gps_format_tag 19 /* Struct field encoding specification for nanopb */ #define meshtastic_DeviceUIConfig_FIELDLIST(X, a) \ @@ -295,8 +259,7 @@ X(a, STATIC, SINGULAR, BYTES, calibration_data, 14) \ X(a, STATIC, OPTIONAL, MESSAGE, map_data, 15) \ X(a, STATIC, SINGULAR, UENUM, compass_mode, 16) \ X(a, STATIC, SINGULAR, UINT32, screen_rgb_color, 17) \ -X(a, STATIC, SINGULAR, BOOL, is_clockface_analog, 18) \ -X(a, STATIC, SINGULAR, UENUM, gps_format, 19) +X(a, STATIC, SINGULAR, BOOL, is_clockface_analog, 18) #define meshtastic_DeviceUIConfig_CALLBACK NULL #define meshtastic_DeviceUIConfig_DEFAULT NULL #define meshtastic_DeviceUIConfig_node_filter_MSGTYPE meshtastic_NodeFilter @@ -353,7 +316,7 @@ extern const pb_msgdesc_t meshtastic_Map_msg; /* Maximum encoded size of messages (where known) */ #define MESHTASTIC_MESHTASTIC_DEVICE_UI_PB_H_MAX_SIZE meshtastic_DeviceUIConfig_size -#define meshtastic_DeviceUIConfig_size 204 +#define meshtastic_DeviceUIConfig_size 201 #define meshtastic_GeoPoint_size 33 #define meshtastic_Map_size 58 #define meshtastic_NodeFilter_size 47 diff --git a/src/mesh/generated/meshtastic/deviceonly.pb.h b/src/mesh/generated/meshtastic/deviceonly.pb.h index 7fab82ff7..9b6330596 100644 --- a/src/mesh/generated/meshtastic/deviceonly.pb.h +++ b/src/mesh/generated/meshtastic/deviceonly.pb.h @@ -360,7 +360,7 @@ extern const pb_msgdesc_t meshtastic_BackupPreferences_msg; /* Maximum encoded size of messages (where known) */ /* meshtastic_NodeDatabase_size depends on runtime parameters */ #define MESHTASTIC_MESHTASTIC_DEVICEONLY_PB_H_MAX_SIZE meshtastic_BackupPreferences_size -#define meshtastic_BackupPreferences_size 2277 +#define meshtastic_BackupPreferences_size 2273 #define meshtastic_ChannelFile_size 718 #define meshtastic_DeviceState_size 1737 #define meshtastic_NodeInfoLite_size 196 diff --git a/src/mesh/generated/meshtastic/localonly.pb.h b/src/mesh/generated/meshtastic/localonly.pb.h index 3ab6f02c1..da224fb94 100644 --- a/src/mesh/generated/meshtastic/localonly.pb.h +++ b/src/mesh/generated/meshtastic/localonly.pb.h @@ -187,8 +187,8 @@ extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg; /* Maximum encoded size of messages (where known) */ #define MESHTASTIC_MESHTASTIC_LOCALONLY_PB_H_MAX_SIZE meshtastic_LocalConfig_size -#define meshtastic_LocalConfig_size 749 -#define meshtastic_LocalModuleConfig_size 673 +#define meshtastic_LocalConfig_size 747 +#define meshtastic_LocalModuleConfig_size 671 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h index 6292ce070..2a4e77870 100644 --- a/src/mesh/generated/meshtastic/mesh.pb.h +++ b/src/mesh/generated/meshtastic/mesh.pb.h @@ -259,8 +259,8 @@ typedef enum _meshtastic_HardwareModel { meshtastic_HardwareModel_T_DECK_PRO = 102, /* Lilygo TLora Pager */ meshtastic_HardwareModel_T_LORA_PAGER = 103, - /* M5Stack Reserved */ - meshtastic_HardwareModel_M5STACK_RESERVED = 104, /* 0x68 */ + /* GAT562 Mesh Trial Tracker */ + meshtastic_HardwareModel_GAT562_MESH_TRIAL_TRACKER = 104, /* RAKwireless WisMesh Tag */ meshtastic_HardwareModel_WISMESH_TAG = 105, /* RAKwireless WisBlock Core RAK3312 https://docs.rakwireless.com/product-categories/wisduo/rak3112-module/overview/ */ @@ -274,10 +274,6 @@ typedef enum _meshtastic_HardwareModel { meshtastic_HardwareModel_T_ECHO_LITE = 109, /* New Heltec LoRA32 with ESP32-S3 CPU */ meshtastic_HardwareModel_HELTEC_V4 = 110, - /* M5Stack C6L */ - meshtastic_HardwareModel_M5STACK_C6L = 111, - /* M5Stack Cardputer Adv */ - meshtastic_HardwareModel_M5STACK_CARDPUTER_ADV = 112, /* ------------------------------------------------------------------------------------------------------------------------------------------ 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 47d3b5baa..16c4c230c 100644 --- a/src/mesh/generated/meshtastic/module_config.pb.h +++ b/src/mesh/generated/meshtastic/module_config.pb.h @@ -356,9 +356,6 @@ typedef struct _meshtastic_ModuleConfig_TelemetryConfig { uint32_t health_update_interval; /* Enable/Disable the health telemetry module on-device display */ bool health_screen_enabled; - /* Enable/Disable the device telemetry module to send metrics to the mesh - Note: We will still send telemtry to the connected phone / client every minute over the API */ - bool device_telemetry_enabled; } meshtastic_ModuleConfig_TelemetryConfig; /* Canned Messages Module Config */ @@ -526,7 +523,7 @@ extern "C" { #define meshtastic_ModuleConfig_ExternalNotificationConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_ModuleConfig_StoreForwardConfig_init_default {0, 0, 0, 0, 0, 0} #define meshtastic_ModuleConfig_RangeTestConfig_init_default {0, 0, 0, 0} -#define meshtastic_ModuleConfig_TelemetryConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#define meshtastic_ModuleConfig_TelemetryConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_ModuleConfig_CannedMessageConfig_init_default {0, 0, 0, 0, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, 0, 0, "", 0} #define meshtastic_ModuleConfig_AmbientLightingConfig_init_default {0, 0, 0, 0, 0} #define meshtastic_RemoteHardwarePin_init_default {0, "", _meshtastic_RemoteHardwarePinType_MIN} @@ -542,7 +539,7 @@ extern "C" { #define meshtastic_ModuleConfig_ExternalNotificationConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_ModuleConfig_StoreForwardConfig_init_zero {0, 0, 0, 0, 0, 0} #define meshtastic_ModuleConfig_RangeTestConfig_init_zero {0, 0, 0, 0} -#define meshtastic_ModuleConfig_TelemetryConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#define meshtastic_ModuleConfig_TelemetryConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_ModuleConfig_CannedMessageConfig_init_zero {0, 0, 0, 0, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, 0, 0, "", 0} #define meshtastic_ModuleConfig_AmbientLightingConfig_init_zero {0, 0, 0, 0, 0} #define meshtastic_RemoteHardwarePin_init_zero {0, "", _meshtastic_RemoteHardwarePinType_MIN} @@ -630,7 +627,6 @@ extern "C" { #define meshtastic_ModuleConfig_TelemetryConfig_health_measurement_enabled_tag 11 #define meshtastic_ModuleConfig_TelemetryConfig_health_update_interval_tag 12 #define meshtastic_ModuleConfig_TelemetryConfig_health_screen_enabled_tag 13 -#define meshtastic_ModuleConfig_TelemetryConfig_device_telemetry_enabled_tag 14 #define meshtastic_ModuleConfig_CannedMessageConfig_rotary1_enabled_tag 1 #define meshtastic_ModuleConfig_CannedMessageConfig_inputbroker_pin_a_tag 2 #define meshtastic_ModuleConfig_CannedMessageConfig_inputbroker_pin_b_tag 3 @@ -829,8 +825,7 @@ X(a, STATIC, SINGULAR, UINT32, power_update_interval, 9) \ X(a, STATIC, SINGULAR, BOOL, power_screen_enabled, 10) \ X(a, STATIC, SINGULAR, BOOL, health_measurement_enabled, 11) \ X(a, STATIC, SINGULAR, UINT32, health_update_interval, 12) \ -X(a, STATIC, SINGULAR, BOOL, health_screen_enabled, 13) \ -X(a, STATIC, SINGULAR, BOOL, device_telemetry_enabled, 14) +X(a, STATIC, SINGULAR, BOOL, health_screen_enabled, 13) #define meshtastic_ModuleConfig_TelemetryConfig_CALLBACK NULL #define meshtastic_ModuleConfig_TelemetryConfig_DEFAULT NULL @@ -915,7 +910,7 @@ extern const pb_msgdesc_t meshtastic_RemoteHardwarePin_msg; #define meshtastic_ModuleConfig_RemoteHardwareConfig_size 96 #define meshtastic_ModuleConfig_SerialConfig_size 28 #define meshtastic_ModuleConfig_StoreForwardConfig_size 24 -#define meshtastic_ModuleConfig_TelemetryConfig_size 48 +#define meshtastic_ModuleConfig_TelemetryConfig_size 46 #define meshtastic_ModuleConfig_size 227 #define meshtastic_RemoteHardwarePin_size 21 From 22b71a1e9508ce6681ffc6d709ca0508bb4a14b0 Mon Sep 17 00:00:00 2001 From: ford-jones Date: Sat, 20 Sep 2025 17:52:41 +1200 Subject: [PATCH 17/39] Pull latest changes from https://github.com/meshtastic/protobufs.git --- protobufs | 2 +- src/mesh/generated/meshtastic/config.pb.h | 49 +++++++------------ .../generated/meshtastic/device_ui.pb.cpp | 2 + src/mesh/generated/meshtastic/device_ui.pb.h | 45 +++++++++++++++-- src/mesh/generated/meshtastic/deviceonly.pb.h | 2 +- src/mesh/generated/meshtastic/localonly.pb.h | 4 +- src/mesh/generated/meshtastic/mesh.pb.h | 8 ++- .../generated/meshtastic/module_config.pb.h | 13 +++-- 8 files changed, 80 insertions(+), 45 deletions(-) diff --git a/protobufs b/protobufs index a84657c22..46b81e822 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit a84657c220421536f18d11fc5edf680efadbceeb +Subproject commit 46b81e822af1b8e408f437092337f129dee693e6 diff --git a/src/mesh/generated/meshtastic/config.pb.h b/src/mesh/generated/meshtastic/config.pb.h index 59e55db3f..0453ecad2 100644 --- a/src/mesh/generated/meshtastic/config.pb.h +++ b/src/mesh/generated/meshtastic/config.pb.h @@ -173,28 +173,10 @@ typedef enum _meshtastic_Config_NetworkConfig_ProtocolFlags { meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST = 1 } meshtastic_Config_NetworkConfig_ProtocolFlags; -/* How the GPS coordinates are displayed on the OLED screen. */ -typedef enum _meshtastic_Config_DisplayConfig_GpsCoordinateFormat { - /* GPS coordinates are displayed in the normal decimal degrees format: - DD.DDDDDD DDD.DDDDDD */ - meshtastic_Config_DisplayConfig_GpsCoordinateFormat_DEC = 0, - /* GPS coordinates are displayed in the degrees minutes seconds format: - DD°MM'SS"C DDD°MM'SS"C, where C is the compass point representing the locations quadrant */ - meshtastic_Config_DisplayConfig_GpsCoordinateFormat_DMS = 1, - /* Universal Transverse Mercator format: - ZZB EEEEEE NNNNNNN, where Z is zone, B is band, E is easting, N is northing */ - meshtastic_Config_DisplayConfig_GpsCoordinateFormat_UTM = 2, - /* Military Grid Reference System format: - ZZB CD EEEEE NNNNN, where Z is zone, B is band, C is the east 100k square, D is the north 100k square, - E is easting, N is northing */ - meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MGRS = 3, - /* Open Location Code (aka Plus Codes). */ - meshtastic_Config_DisplayConfig_GpsCoordinateFormat_OLC = 4, - /* Ordnance Survey Grid Reference (the National Grid System of the UK). - Format: AB EEEEE NNNNN, where A is the east 100k square, B is the north 100k square, - E is the easting, N is the northing */ - meshtastic_Config_DisplayConfig_GpsCoordinateFormat_OSGR = 5 -} meshtastic_Config_DisplayConfig_GpsCoordinateFormat; +/* Deprecated in 2.7.4: Unused */ +typedef enum _meshtastic_Config_DisplayConfig_DeprecatedGpsCoordinateFormat { + meshtastic_Config_DisplayConfig_DeprecatedGpsCoordinateFormat_UNUSED = 0 +} meshtastic_Config_DisplayConfig_DeprecatedGpsCoordinateFormat; /* Unit display preference */ typedef enum _meshtastic_Config_DisplayConfig_DisplayUnits { @@ -491,7 +473,7 @@ typedef struct _meshtastic_Config_DisplayConfig { uint32_t screen_on_secs; /* Deprecated in 2.7.4: Unused How the GPS coordinates are formatted on the OLED screen. */ - meshtastic_Config_DisplayConfig_GpsCoordinateFormat gps_format; + meshtastic_Config_DisplayConfig_DeprecatedGpsCoordinateFormat gps_format; /* Automatically toggles to the next page on the screen like a carousel, based the specified interval in seconds. Potentially useful for devices without user buttons. */ uint32_t auto_screen_carousel_secs; @@ -515,6 +497,9 @@ typedef struct _meshtastic_Config_DisplayConfig { /* If false (default), the device will display the time in 24-hour format on screen. If true, the device will display the time in 12-hour format on screen. */ bool use_12h_clock; + /* If false (default), the device will use short names for various display screens. + If true, node names will show in long format */ + bool use_long_node_name; } meshtastic_Config_DisplayConfig; /* Lora Config */ @@ -678,9 +663,9 @@ extern "C" { #define _meshtastic_Config_NetworkConfig_ProtocolFlags_MAX meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST #define _meshtastic_Config_NetworkConfig_ProtocolFlags_ARRAYSIZE ((meshtastic_Config_NetworkConfig_ProtocolFlags)(meshtastic_Config_NetworkConfig_ProtocolFlags_UDP_BROADCAST+1)) -#define _meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MIN meshtastic_Config_DisplayConfig_GpsCoordinateFormat_DEC -#define _meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MAX meshtastic_Config_DisplayConfig_GpsCoordinateFormat_OSGR -#define _meshtastic_Config_DisplayConfig_GpsCoordinateFormat_ARRAYSIZE ((meshtastic_Config_DisplayConfig_GpsCoordinateFormat)(meshtastic_Config_DisplayConfig_GpsCoordinateFormat_OSGR+1)) +#define _meshtastic_Config_DisplayConfig_DeprecatedGpsCoordinateFormat_MIN meshtastic_Config_DisplayConfig_DeprecatedGpsCoordinateFormat_UNUSED +#define _meshtastic_Config_DisplayConfig_DeprecatedGpsCoordinateFormat_MAX meshtastic_Config_DisplayConfig_DeprecatedGpsCoordinateFormat_UNUSED +#define _meshtastic_Config_DisplayConfig_DeprecatedGpsCoordinateFormat_ARRAYSIZE ((meshtastic_Config_DisplayConfig_DeprecatedGpsCoordinateFormat)(meshtastic_Config_DisplayConfig_DeprecatedGpsCoordinateFormat_UNUSED+1)) #define _meshtastic_Config_DisplayConfig_DisplayUnits_MIN meshtastic_Config_DisplayConfig_DisplayUnits_METRIC #define _meshtastic_Config_DisplayConfig_DisplayUnits_MAX meshtastic_Config_DisplayConfig_DisplayUnits_IMPERIAL @@ -721,7 +706,7 @@ extern "C" { #define meshtastic_Config_NetworkConfig_address_mode_ENUMTYPE meshtastic_Config_NetworkConfig_AddressMode -#define meshtastic_Config_DisplayConfig_gps_format_ENUMTYPE meshtastic_Config_DisplayConfig_GpsCoordinateFormat +#define meshtastic_Config_DisplayConfig_gps_format_ENUMTYPE meshtastic_Config_DisplayConfig_DeprecatedGpsCoordinateFormat #define meshtastic_Config_DisplayConfig_units_ENUMTYPE meshtastic_Config_DisplayConfig_DisplayUnits #define meshtastic_Config_DisplayConfig_oled_ENUMTYPE meshtastic_Config_DisplayConfig_OledType #define meshtastic_Config_DisplayConfig_displaymode_ENUMTYPE meshtastic_Config_DisplayConfig_DisplayMode @@ -742,7 +727,7 @@ extern "C" { #define meshtastic_Config_PowerConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_Config_NetworkConfig_init_default {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_default, "", 0, 0} #define meshtastic_Config_NetworkConfig_IpV4Config_init_default {0, 0, 0, 0} -#define meshtastic_Config_DisplayConfig_init_default {0, _meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _meshtastic_Config_DisplayConfig_DisplayUnits_MIN, _meshtastic_Config_DisplayConfig_OledType_MIN, _meshtastic_Config_DisplayConfig_DisplayMode_MIN, 0, 0, _meshtastic_Config_DisplayConfig_CompassOrientation_MIN, 0} +#define meshtastic_Config_DisplayConfig_init_default {0, _meshtastic_Config_DisplayConfig_DeprecatedGpsCoordinateFormat_MIN, 0, 0, 0, _meshtastic_Config_DisplayConfig_DisplayUnits_MIN, _meshtastic_Config_DisplayConfig_OledType_MIN, _meshtastic_Config_DisplayConfig_DisplayMode_MIN, 0, 0, _meshtastic_Config_DisplayConfig_CompassOrientation_MIN, 0, 0} #define meshtastic_Config_LoRaConfig_init_default {0, _meshtastic_Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _meshtastic_Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0} #define meshtastic_Config_BluetoothConfig_init_default {0, _meshtastic_Config_BluetoothConfig_PairingMode_MIN, 0} #define meshtastic_Config_SecurityConfig_init_default {{0, {0}}, {0, {0}}, 0, {{0, {0}}, {0, {0}}, {0, {0}}}, 0, 0, 0, 0} @@ -753,7 +738,7 @@ extern "C" { #define meshtastic_Config_PowerConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_Config_NetworkConfig_init_zero {0, "", "", "", 0, _meshtastic_Config_NetworkConfig_AddressMode_MIN, false, meshtastic_Config_NetworkConfig_IpV4Config_init_zero, "", 0, 0} #define meshtastic_Config_NetworkConfig_IpV4Config_init_zero {0, 0, 0, 0} -#define meshtastic_Config_DisplayConfig_init_zero {0, _meshtastic_Config_DisplayConfig_GpsCoordinateFormat_MIN, 0, 0, 0, _meshtastic_Config_DisplayConfig_DisplayUnits_MIN, _meshtastic_Config_DisplayConfig_OledType_MIN, _meshtastic_Config_DisplayConfig_DisplayMode_MIN, 0, 0, _meshtastic_Config_DisplayConfig_CompassOrientation_MIN, 0} +#define meshtastic_Config_DisplayConfig_init_zero {0, _meshtastic_Config_DisplayConfig_DeprecatedGpsCoordinateFormat_MIN, 0, 0, 0, _meshtastic_Config_DisplayConfig_DisplayUnits_MIN, _meshtastic_Config_DisplayConfig_OledType_MIN, _meshtastic_Config_DisplayConfig_DisplayMode_MIN, 0, 0, _meshtastic_Config_DisplayConfig_CompassOrientation_MIN, 0, 0} #define meshtastic_Config_LoRaConfig_init_zero {0, _meshtastic_Config_LoRaConfig_ModemPreset_MIN, 0, 0, 0, 0, _meshtastic_Config_LoRaConfig_RegionCode_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0}, 0, 0} #define meshtastic_Config_BluetoothConfig_init_zero {0, _meshtastic_Config_BluetoothConfig_PairingMode_MIN, 0} #define meshtastic_Config_SecurityConfig_init_zero {{0, {0}}, {0, {0}}, 0, {{0, {0}}, {0, {0}}, {0, {0}}}, 0, 0, 0, 0} @@ -820,6 +805,7 @@ extern "C" { #define meshtastic_Config_DisplayConfig_wake_on_tap_or_motion_tag 10 #define meshtastic_Config_DisplayConfig_compass_orientation_tag 11 #define meshtastic_Config_DisplayConfig_use_12h_clock_tag 12 +#define meshtastic_Config_DisplayConfig_use_long_node_name_tag 13 #define meshtastic_Config_LoRaConfig_use_preset_tag 1 #define meshtastic_Config_LoRaConfig_modem_preset_tag 2 #define meshtastic_Config_LoRaConfig_bandwidth_tag 3 @@ -965,7 +951,8 @@ X(a, STATIC, SINGULAR, UENUM, displaymode, 8) \ X(a, STATIC, SINGULAR, BOOL, heading_bold, 9) \ X(a, STATIC, SINGULAR, BOOL, wake_on_tap_or_motion, 10) \ X(a, STATIC, SINGULAR, UENUM, compass_orientation, 11) \ -X(a, STATIC, SINGULAR, BOOL, use_12h_clock, 12) +X(a, STATIC, SINGULAR, BOOL, use_12h_clock, 12) \ +X(a, STATIC, SINGULAR, BOOL, use_long_node_name, 13) #define meshtastic_Config_DisplayConfig_CALLBACK NULL #define meshtastic_Config_DisplayConfig_DEFAULT NULL @@ -1043,7 +1030,7 @@ extern const pb_msgdesc_t meshtastic_Config_SessionkeyConfig_msg; #define MESHTASTIC_MESHTASTIC_CONFIG_PB_H_MAX_SIZE meshtastic_Config_size #define meshtastic_Config_BluetoothConfig_size 10 #define meshtastic_Config_DeviceConfig_size 100 -#define meshtastic_Config_DisplayConfig_size 32 +#define meshtastic_Config_DisplayConfig_size 34 #define meshtastic_Config_LoRaConfig_size 85 #define meshtastic_Config_NetworkConfig_IpV4Config_size 20 #define meshtastic_Config_NetworkConfig_size 204 diff --git a/src/mesh/generated/meshtastic/device_ui.pb.cpp b/src/mesh/generated/meshtastic/device_ui.pb.cpp index 2fc8d9461..01940265f 100644 --- a/src/mesh/generated/meshtastic/device_ui.pb.cpp +++ b/src/mesh/generated/meshtastic/device_ui.pb.cpp @@ -28,3 +28,5 @@ PB_BIND(meshtastic_Map, meshtastic_Map, AUTO) + + diff --git a/src/mesh/generated/meshtastic/device_ui.pb.h b/src/mesh/generated/meshtastic/device_ui.pb.h index 8313438f8..d9eb90773 100644 --- a/src/mesh/generated/meshtastic/device_ui.pb.h +++ b/src/mesh/generated/meshtastic/device_ui.pb.h @@ -66,12 +66,40 @@ typedef enum _meshtastic_Language { meshtastic_Language_UKRAINIAN = 16, /* Bulgarian */ meshtastic_Language_BULGARIAN = 17, + /* Czech */ + meshtastic_Language_CZECH = 18, /* Simplified Chinese (experimental) */ meshtastic_Language_SIMPLIFIED_CHINESE = 30, /* Traditional Chinese (experimental) */ meshtastic_Language_TRADITIONAL_CHINESE = 31 } meshtastic_Language; +/* How the GPS coordinates are displayed on the OLED screen. */ +typedef enum _meshtastic_DeviceUIConfig_GpsCoordinateFormat { + /* GPS coordinates are displayed in the normal decimal degrees format: + DD.DDDDDD DDD.DDDDDD */ + meshtastic_DeviceUIConfig_GpsCoordinateFormat_DEC = 0, + /* GPS coordinates are displayed in the degrees minutes seconds format: + DD°MM'SS"C DDD°MM'SS"C, where C is the compass point representing the locations quadrant */ + meshtastic_DeviceUIConfig_GpsCoordinateFormat_DMS = 1, + /* Universal Transverse Mercator format: + ZZB EEEEEE NNNNNNN, where Z is zone, B is band, E is easting, N is northing */ + meshtastic_DeviceUIConfig_GpsCoordinateFormat_UTM = 2, + /* Military Grid Reference System format: + ZZB CD EEEEE NNNNN, where Z is zone, B is band, C is the east 100k square, D is the north 100k square, + E is easting, N is northing */ + meshtastic_DeviceUIConfig_GpsCoordinateFormat_MGRS = 3, + /* Open Location Code (aka Plus Codes). */ + meshtastic_DeviceUIConfig_GpsCoordinateFormat_OLC = 4, + /* Ordnance Survey Grid Reference (the National Grid System of the UK). + Format: AB EEEEE NNNNN, where A is the east 100k square, B is the north 100k square, + E is the easting, N is the northing */ + meshtastic_DeviceUIConfig_GpsCoordinateFormat_OSGR = 5, + /* Maidenhead Locator System + Described here: https://en.wikipedia.org/wiki/Maidenhead_Locator_System */ + meshtastic_DeviceUIConfig_GpsCoordinateFormat_MLS = 6 +} meshtastic_DeviceUIConfig_GpsCoordinateFormat; + /* Struct definitions */ typedef struct _meshtastic_NodeFilter { /* Filter unknown nodes */ @@ -161,6 +189,8 @@ typedef struct _meshtastic_DeviceUIConfig { /* Clockface analog style true for analog clockface, false for digital clockface */ bool is_clockface_analog; + /* How the GPS coordinates are formatted on the OLED screen. */ + meshtastic_DeviceUIConfig_GpsCoordinateFormat gps_format; } meshtastic_DeviceUIConfig; @@ -181,9 +211,14 @@ extern "C" { #define _meshtastic_Language_MAX meshtastic_Language_TRADITIONAL_CHINESE #define _meshtastic_Language_ARRAYSIZE ((meshtastic_Language)(meshtastic_Language_TRADITIONAL_CHINESE+1)) +#define _meshtastic_DeviceUIConfig_GpsCoordinateFormat_MIN meshtastic_DeviceUIConfig_GpsCoordinateFormat_DEC +#define _meshtastic_DeviceUIConfig_GpsCoordinateFormat_MAX meshtastic_DeviceUIConfig_GpsCoordinateFormat_MLS +#define _meshtastic_DeviceUIConfig_GpsCoordinateFormat_ARRAYSIZE ((meshtastic_DeviceUIConfig_GpsCoordinateFormat)(meshtastic_DeviceUIConfig_GpsCoordinateFormat_MLS+1)) + #define meshtastic_DeviceUIConfig_theme_ENUMTYPE meshtastic_Theme #define meshtastic_DeviceUIConfig_language_ENUMTYPE meshtastic_Language #define meshtastic_DeviceUIConfig_compass_mode_ENUMTYPE meshtastic_CompassMode +#define meshtastic_DeviceUIConfig_gps_format_ENUMTYPE meshtastic_DeviceUIConfig_GpsCoordinateFormat @@ -191,12 +226,12 @@ extern "C" { /* Initializer values for message structs */ -#define meshtastic_DeviceUIConfig_init_default {0, 0, 0, 0, 0, 0, _meshtastic_Theme_MIN, 0, 0, 0, _meshtastic_Language_MIN, false, meshtastic_NodeFilter_init_default, false, meshtastic_NodeHighlight_init_default, {0, {0}}, false, meshtastic_Map_init_default, _meshtastic_CompassMode_MIN, 0, 0} +#define meshtastic_DeviceUIConfig_init_default {0, 0, 0, 0, 0, 0, _meshtastic_Theme_MIN, 0, 0, 0, _meshtastic_Language_MIN, false, meshtastic_NodeFilter_init_default, false, meshtastic_NodeHighlight_init_default, {0, {0}}, false, meshtastic_Map_init_default, _meshtastic_CompassMode_MIN, 0, 0, _meshtastic_DeviceUIConfig_GpsCoordinateFormat_MIN} #define meshtastic_NodeFilter_init_default {0, 0, 0, 0, 0, "", 0} #define meshtastic_NodeHighlight_init_default {0, 0, 0, 0, ""} #define meshtastic_GeoPoint_init_default {0, 0, 0} #define meshtastic_Map_init_default {false, meshtastic_GeoPoint_init_default, "", 0} -#define meshtastic_DeviceUIConfig_init_zero {0, 0, 0, 0, 0, 0, _meshtastic_Theme_MIN, 0, 0, 0, _meshtastic_Language_MIN, false, meshtastic_NodeFilter_init_zero, false, meshtastic_NodeHighlight_init_zero, {0, {0}}, false, meshtastic_Map_init_zero, _meshtastic_CompassMode_MIN, 0, 0} +#define meshtastic_DeviceUIConfig_init_zero {0, 0, 0, 0, 0, 0, _meshtastic_Theme_MIN, 0, 0, 0, _meshtastic_Language_MIN, false, meshtastic_NodeFilter_init_zero, false, meshtastic_NodeHighlight_init_zero, {0, {0}}, false, meshtastic_Map_init_zero, _meshtastic_CompassMode_MIN, 0, 0, _meshtastic_DeviceUIConfig_GpsCoordinateFormat_MIN} #define meshtastic_NodeFilter_init_zero {0, 0, 0, 0, 0, "", 0} #define meshtastic_NodeHighlight_init_zero {0, 0, 0, 0, ""} #define meshtastic_GeoPoint_init_zero {0, 0, 0} @@ -239,6 +274,7 @@ extern "C" { #define meshtastic_DeviceUIConfig_compass_mode_tag 16 #define meshtastic_DeviceUIConfig_screen_rgb_color_tag 17 #define meshtastic_DeviceUIConfig_is_clockface_analog_tag 18 +#define meshtastic_DeviceUIConfig_gps_format_tag 19 /* Struct field encoding specification for nanopb */ #define meshtastic_DeviceUIConfig_FIELDLIST(X, a) \ @@ -259,7 +295,8 @@ X(a, STATIC, SINGULAR, BYTES, calibration_data, 14) \ X(a, STATIC, OPTIONAL, MESSAGE, map_data, 15) \ X(a, STATIC, SINGULAR, UENUM, compass_mode, 16) \ X(a, STATIC, SINGULAR, UINT32, screen_rgb_color, 17) \ -X(a, STATIC, SINGULAR, BOOL, is_clockface_analog, 18) +X(a, STATIC, SINGULAR, BOOL, is_clockface_analog, 18) \ +X(a, STATIC, SINGULAR, UENUM, gps_format, 19) #define meshtastic_DeviceUIConfig_CALLBACK NULL #define meshtastic_DeviceUIConfig_DEFAULT NULL #define meshtastic_DeviceUIConfig_node_filter_MSGTYPE meshtastic_NodeFilter @@ -316,7 +353,7 @@ extern const pb_msgdesc_t meshtastic_Map_msg; /* Maximum encoded size of messages (where known) */ #define MESHTASTIC_MESHTASTIC_DEVICE_UI_PB_H_MAX_SIZE meshtastic_DeviceUIConfig_size -#define meshtastic_DeviceUIConfig_size 201 +#define meshtastic_DeviceUIConfig_size 204 #define meshtastic_GeoPoint_size 33 #define meshtastic_Map_size 58 #define meshtastic_NodeFilter_size 47 diff --git a/src/mesh/generated/meshtastic/deviceonly.pb.h b/src/mesh/generated/meshtastic/deviceonly.pb.h index 9b6330596..7fab82ff7 100644 --- a/src/mesh/generated/meshtastic/deviceonly.pb.h +++ b/src/mesh/generated/meshtastic/deviceonly.pb.h @@ -360,7 +360,7 @@ extern const pb_msgdesc_t meshtastic_BackupPreferences_msg; /* Maximum encoded size of messages (where known) */ /* meshtastic_NodeDatabase_size depends on runtime parameters */ #define MESHTASTIC_MESHTASTIC_DEVICEONLY_PB_H_MAX_SIZE meshtastic_BackupPreferences_size -#define meshtastic_BackupPreferences_size 2273 +#define meshtastic_BackupPreferences_size 2277 #define meshtastic_ChannelFile_size 718 #define meshtastic_DeviceState_size 1737 #define meshtastic_NodeInfoLite_size 196 diff --git a/src/mesh/generated/meshtastic/localonly.pb.h b/src/mesh/generated/meshtastic/localonly.pb.h index da224fb94..3ab6f02c1 100644 --- a/src/mesh/generated/meshtastic/localonly.pb.h +++ b/src/mesh/generated/meshtastic/localonly.pb.h @@ -187,8 +187,8 @@ extern const pb_msgdesc_t meshtastic_LocalModuleConfig_msg; /* Maximum encoded size of messages (where known) */ #define MESHTASTIC_MESHTASTIC_LOCALONLY_PB_H_MAX_SIZE meshtastic_LocalConfig_size -#define meshtastic_LocalConfig_size 747 -#define meshtastic_LocalModuleConfig_size 671 +#define meshtastic_LocalConfig_size 749 +#define meshtastic_LocalModuleConfig_size 673 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h index 2a4e77870..6292ce070 100644 --- a/src/mesh/generated/meshtastic/mesh.pb.h +++ b/src/mesh/generated/meshtastic/mesh.pb.h @@ -259,8 +259,8 @@ typedef enum _meshtastic_HardwareModel { meshtastic_HardwareModel_T_DECK_PRO = 102, /* Lilygo TLora Pager */ meshtastic_HardwareModel_T_LORA_PAGER = 103, - /* GAT562 Mesh Trial Tracker */ - meshtastic_HardwareModel_GAT562_MESH_TRIAL_TRACKER = 104, + /* M5Stack Reserved */ + meshtastic_HardwareModel_M5STACK_RESERVED = 104, /* 0x68 */ /* RAKwireless WisMesh Tag */ meshtastic_HardwareModel_WISMESH_TAG = 105, /* RAKwireless WisBlock Core RAK3312 https://docs.rakwireless.com/product-categories/wisduo/rak3112-module/overview/ */ @@ -274,6 +274,10 @@ typedef enum _meshtastic_HardwareModel { meshtastic_HardwareModel_T_ECHO_LITE = 109, /* New Heltec LoRA32 with ESP32-S3 CPU */ meshtastic_HardwareModel_HELTEC_V4 = 110, + /* M5Stack C6L */ + meshtastic_HardwareModel_M5STACK_C6L = 111, + /* M5Stack Cardputer Adv */ + meshtastic_HardwareModel_M5STACK_CARDPUTER_ADV = 112, /* ------------------------------------------------------------------------------------------------------------------------------------------ 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 16c4c230c..47d3b5baa 100644 --- a/src/mesh/generated/meshtastic/module_config.pb.h +++ b/src/mesh/generated/meshtastic/module_config.pb.h @@ -356,6 +356,9 @@ typedef struct _meshtastic_ModuleConfig_TelemetryConfig { uint32_t health_update_interval; /* Enable/Disable the health telemetry module on-device display */ bool health_screen_enabled; + /* Enable/Disable the device telemetry module to send metrics to the mesh + Note: We will still send telemtry to the connected phone / client every minute over the API */ + bool device_telemetry_enabled; } meshtastic_ModuleConfig_TelemetryConfig; /* Canned Messages Module Config */ @@ -523,7 +526,7 @@ extern "C" { #define meshtastic_ModuleConfig_ExternalNotificationConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_ModuleConfig_StoreForwardConfig_init_default {0, 0, 0, 0, 0, 0} #define meshtastic_ModuleConfig_RangeTestConfig_init_default {0, 0, 0, 0} -#define meshtastic_ModuleConfig_TelemetryConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#define meshtastic_ModuleConfig_TelemetryConfig_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_ModuleConfig_CannedMessageConfig_init_default {0, 0, 0, 0, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, 0, 0, "", 0} #define meshtastic_ModuleConfig_AmbientLightingConfig_init_default {0, 0, 0, 0, 0} #define meshtastic_RemoteHardwarePin_init_default {0, "", _meshtastic_RemoteHardwarePinType_MIN} @@ -539,7 +542,7 @@ extern "C" { #define meshtastic_ModuleConfig_ExternalNotificationConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_ModuleConfig_StoreForwardConfig_init_zero {0, 0, 0, 0, 0, 0} #define meshtastic_ModuleConfig_RangeTestConfig_init_zero {0, 0, 0, 0} -#define meshtastic_ModuleConfig_TelemetryConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#define meshtastic_ModuleConfig_TelemetryConfig_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} #define meshtastic_ModuleConfig_CannedMessageConfig_init_zero {0, 0, 0, 0, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, _meshtastic_ModuleConfig_CannedMessageConfig_InputEventChar_MIN, 0, 0, "", 0} #define meshtastic_ModuleConfig_AmbientLightingConfig_init_zero {0, 0, 0, 0, 0} #define meshtastic_RemoteHardwarePin_init_zero {0, "", _meshtastic_RemoteHardwarePinType_MIN} @@ -627,6 +630,7 @@ extern "C" { #define meshtastic_ModuleConfig_TelemetryConfig_health_measurement_enabled_tag 11 #define meshtastic_ModuleConfig_TelemetryConfig_health_update_interval_tag 12 #define meshtastic_ModuleConfig_TelemetryConfig_health_screen_enabled_tag 13 +#define meshtastic_ModuleConfig_TelemetryConfig_device_telemetry_enabled_tag 14 #define meshtastic_ModuleConfig_CannedMessageConfig_rotary1_enabled_tag 1 #define meshtastic_ModuleConfig_CannedMessageConfig_inputbroker_pin_a_tag 2 #define meshtastic_ModuleConfig_CannedMessageConfig_inputbroker_pin_b_tag 3 @@ -825,7 +829,8 @@ X(a, STATIC, SINGULAR, UINT32, power_update_interval, 9) \ X(a, STATIC, SINGULAR, BOOL, power_screen_enabled, 10) \ X(a, STATIC, SINGULAR, BOOL, health_measurement_enabled, 11) \ X(a, STATIC, SINGULAR, UINT32, health_update_interval, 12) \ -X(a, STATIC, SINGULAR, BOOL, health_screen_enabled, 13) +X(a, STATIC, SINGULAR, BOOL, health_screen_enabled, 13) \ +X(a, STATIC, SINGULAR, BOOL, device_telemetry_enabled, 14) #define meshtastic_ModuleConfig_TelemetryConfig_CALLBACK NULL #define meshtastic_ModuleConfig_TelemetryConfig_DEFAULT NULL @@ -910,7 +915,7 @@ extern const pb_msgdesc_t meshtastic_RemoteHardwarePin_msg; #define meshtastic_ModuleConfig_RemoteHardwareConfig_size 96 #define meshtastic_ModuleConfig_SerialConfig_size 28 #define meshtastic_ModuleConfig_StoreForwardConfig_size 24 -#define meshtastic_ModuleConfig_TelemetryConfig_size 46 +#define meshtastic_ModuleConfig_TelemetryConfig_size 48 #define meshtastic_ModuleConfig_size 227 #define meshtastic_RemoteHardwarePin_size 21 From 1fc07607cb7f6b141245fbb8b08f0a14b425ae6b Mon Sep 17 00:00:00 2001 From: GUVWAF Date: Sat, 20 Sep 2025 13:02:43 +0200 Subject: [PATCH 18/39] Make sure next-hop is only set when they received us directly --- src/mesh/FloodingRouter.cpp | 3 +-- src/mesh/NextHopRouter.cpp | 11 +++++++---- src/mesh/PacketHistory.cpp | 32 ++++++++++++++++++++------------ src/mesh/PacketHistory.h | 10 ++++------ 4 files changed, 32 insertions(+), 24 deletions(-) diff --git a/src/mesh/FloodingRouter.cpp b/src/mesh/FloodingRouter.cpp index f805055c8..0f4b57983 100644 --- a/src/mesh/FloodingRouter.cpp +++ b/src/mesh/FloodingRouter.cpp @@ -102,8 +102,7 @@ void FloodingRouter::perhapsRebroadcast(const meshtastic_MeshPacket *p) LOG_INFO("Rebroadcast received floodmsg"); // Note: we are careful to resend using the original senders node id - // We are careful not to call our hooked version of send() - because we don't want to check this again - Router::send(tosend); + send(tosend); } else { LOG_DEBUG("No rebroadcast: Role = CLIENT_MUTE or Rebroadcast Mode = NONE"); } diff --git a/src/mesh/NextHopRouter.cpp b/src/mesh/NextHopRouter.cpp index 9bb8b240c..084452eed 100644 --- a/src/mesh/NextHopRouter.cpp +++ b/src/mesh/NextHopRouter.cpp @@ -76,11 +76,14 @@ void NextHopRouter::sniffReceived(const meshtastic_MeshPacket *p, const meshtast if (origTx) { // Either relayer of ACK was also a relayer of the packet, or we were the *only* relayer and the ACK came directly // from the destination - if (wasRelayer(p->relay_node, p->decoded.request_id, p->to) || - (p->hop_start != 0 && p->hop_start == p->hop_limit && - wasSoleRelayer(ourRelayID, p->decoded.request_id, p->to))) { + bool wasAlreadyRelayer = wasRelayer(p->relay_node, p->decoded.request_id, p->to); + bool weWereSoleRelayer = false; + bool weWereRelayer = wasRelayer(ourRelayID, p->decoded.request_id, p->to, &weWereSoleRelayer); + if ((weWereRelayer && wasAlreadyRelayer) || + (p->hop_start != 0 && p->hop_start == p->hop_limit && weWereSoleRelayer)) { if (origTx->next_hop != p->relay_node) { // Not already set - LOG_INFO("Update next hop of 0x%x to 0x%x based on ACK/reply", p->from, p->relay_node); + LOG_INFO("Update next hop of 0x%x to 0x%x based on ACK/reply (was relayer %d we were sole %d)", p->from, + p->relay_node, wasAlreadyRelayer, weWereSoleRelayer); origTx->next_hop = p->relay_node; } } diff --git a/src/mesh/PacketHistory.cpp b/src/mesh/PacketHistory.cpp index 735386d79..09b1f84c9 100644 --- a/src/mesh/PacketHistory.cpp +++ b/src/mesh/PacketHistory.cpp @@ -66,7 +66,13 @@ bool PacketHistory::wasSeenRecently(const meshtastic_MeshPacket *p, bool withUpd r.id = p->id; r.sender = getFrom(p); // If 0 then use our ID r.next_hop = p->next_hop; - r.relayed_by[0] = p->relay_node; + bool weWillRelay = false; + uint8_t ourRelayID = nodeDB->getLastByteOfNodeNum(nodeDB->getNodeNum()); + if (p->relay_node == ourRelayID) { // If the relay_node is us, store it + weWillRelay = true; + r.ourTxHopLimit = p->hop_limit; + r.relayed_by[0] = p->relay_node; + } r.rxTimeMsec = millis(); // if (r.rxTimeMsec == 0) // =0 every 49.7 days? 0 is special @@ -82,8 +88,6 @@ bool PacketHistory::wasSeenRecently(const meshtastic_MeshPacket *p, bool withUpd bool seenRecently = (found != NULL); // If found -> the packet was seen recently if (seenRecently) { - uint8_t ourRelayID = nodeDB->getLastByteOfNodeNum(nodeDB->getNodeNum()); // Get our relay ID from our node number - if (wasFallback) { // If it was seen with a next-hop not set to us and now it's NO_NEXT_HOP_PREFERENCE, and the relayer relayed already // before, it's a fallback to flooding. If we didn't already relay and the next-hop neither, we might need to handle @@ -125,11 +129,23 @@ bool PacketHistory::wasSeenRecently(const meshtastic_MeshPacket *p, bool withUpd found->sender, found->id, found->next_hop, found->relayed_by[0], found->relayed_by[1], found->relayed_by[2], millis() - found->rxTimeMsec); #endif + // Only update the relayer if it heard us directly (meaning hopLimit is decreased by 1) + uint8_t startIdx = weWillRelay ? 1 : 0; + if (!weWillRelay) { + bool weWereRelayer = wasRelayer(ourRelayID, *found); + // We were a relayer and the packet came in with a hop limit that is one less than when we sent it out + if (weWereRelayer && p->hop_limit == found->ourTxHopLimit - 1) { + r.relayed_by[0] = p->relay_node; + startIdx = 1; // Start copying existing relayers from index 1 + } + // keep the original ourTxHopLimit + r.ourTxHopLimit = found->ourTxHopLimit; + } // Add the existing relayed_by to the new record for (uint8_t i = 0; i < (NUM_RELAYERS - 1); i++) { if (found->relayed_by[i] != 0) - r.relayed_by[i + 1] = found->relayed_by[i]; + r.relayed_by[i + startIdx] = found->relayed_by[i]; } r.next_hop = found->next_hop; // keep the original next_hop (such that we check whether we were originally asked) #if VERBOSE_PACKET_HISTORY @@ -352,14 +368,6 @@ bool PacketHistory::wasRelayer(const uint8_t relayer, const PacketRecord &r, boo return found; } -// Check if a certain node was the *only* relayer of a packet in the history given an ID and sender -bool PacketHistory::wasSoleRelayer(const uint8_t relayer, const uint32_t id, const NodeNum sender) -{ - bool wasSole = false; - wasRelayer(relayer, id, sender, &wasSole); - return wasSole; -} - // Remove a relayer from the list of relayers of a packet in the history given an ID and sender void PacketHistory::removeRelayer(const uint8_t relayer, const uint32_t id, const NodeNum sender) { diff --git a/src/mesh/PacketHistory.h b/src/mesh/PacketHistory.h index 4b53c8f6a..20aac9999 100644 --- a/src/mesh/PacketHistory.h +++ b/src/mesh/PacketHistory.h @@ -2,8 +2,8 @@ #include "NodeDB.h" -#define NUM_RELAYERS \ - 3 // Number of relayer we keep track of. Use 3 to be efficient with memory alignment of PacketRecord to 16 bytes +// Number of relayers we keep track of. Use 6 to be efficient with memory alignment of PacketRecord to 20 bytes +#define NUM_RELAYERS 6 /** * This is a mixin that adds a record of past packets we have seen @@ -16,8 +16,9 @@ class PacketHistory PacketId id; uint32_t rxTimeMsec; // Unix time in msecs - the time we received it, 0 means empty uint8_t next_hop; // The next hop asked for this packet + uint8_t ourTxHopLimit; // The hop limit of the packet when we first transmitted it uint8_t relayed_by[NUM_RELAYERS]; // Array of nodes that relayed this packet - }; // 4B + 4B + 4B + 1B + 3B = 16B + }; // 4B + 4B + 4B + 1B + 1B + 6B = 20B uint32_t recentPacketsCapacity = 0; // Can be set in constructor, no need to recompile. Used to allocate memory for mx_recentPackets. @@ -59,9 +60,6 @@ class PacketHistory * @return true if node was indeed a relayer, false if not */ bool wasRelayer(const uint8_t relayer, const uint32_t id, const NodeNum sender, bool *wasSole = nullptr); - // Check if a certain node was the *only* relayer of a packet in the history given an ID and sender - bool wasSoleRelayer(const uint8_t relayer, const uint32_t id, const NodeNum sender); - // Remove a relayer from the list of relayers of a packet in the history given an ID and sender void removeRelayer(const uint8_t relayer, const uint32_t id, const NodeNum sender); From 14e64d6b9e0987c62e1ec6e1bf62b5b57dc27b3a Mon Sep 17 00:00:00 2001 From: Links2004 Date: Wed, 24 Sep 2025 16:45:40 +0200 Subject: [PATCH 19/39] move SerialConsole to event based trigger --- arch/esp32/esp32.ini | 1 + src/SerialConsole.cpp | 29 ++++++++++++++++++++++++----- src/SerialConsole.h | 3 +++ 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/arch/esp32/esp32.ini b/arch/esp32/esp32.ini index 8990053eb..d2c933461 100644 --- a/arch/esp32/esp32.ini +++ b/arch/esp32/esp32.ini @@ -36,6 +36,7 @@ build_flags = -DCONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE=8192 -DESP_OPENSSL_SUPPRESS_LEGACY_WARNING -DSERIAL_BUFFER_SIZE=4096 + -DSERIAL_HAS_ON_RECEIVE -DLIBPAX_ARDUINO -DLIBPAX_WIFI -DLIBPAX_BLE diff --git a/src/SerialConsole.cpp b/src/SerialConsole.cpp index 093a24678..2e8c8ab61 100644 --- a/src/SerialConsole.cpp +++ b/src/SerialConsole.cpp @@ -22,7 +22,10 @@ SerialConsole *console; void consoleInit() { - new SerialConsole(); // Must be dynamically allocated because we are now inheriting from thread + auto sc = new SerialConsole(); // Must be dynamically allocated because we are now inheriting from thread +#ifdef SERIAL_HAS_ON_RECEIVE + Port.onReceive([sc]() { sc->rxInt(); }); +#endif DEBUG_PORT.rpInit(); // Simply sets up semaphore } @@ -65,14 +68,18 @@ SerialConsole::SerialConsole() : StreamAPI(&Port), RedirectablePrint(&Port), con int32_t SerialConsole::runOnce() { #ifdef HELTEC_MESH_SOLAR - //After enabling the mesh solar serial port module configuration, command processing is handled by the serial port module. - if(moduleConfig.serial.enabled && moduleConfig.serial.override_console_serial_port - && moduleConfig.serial.mode==meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MS_CONFIG) - { + // After enabling the mesh solar serial port module configuration, command processing is handled by the serial port module. + if (moduleConfig.serial.enabled && moduleConfig.serial.override_console_serial_port && + moduleConfig.serial.mode == meshtastic_ModuleConfig_SerialConfig_Serial_Mode_MS_CONFIG) { return 250; } #endif +#ifdef SERIAL_HAS_ON_RECEIVE + int32_t delay = runOncePart(); + return Port.available() ? delay : INT32_MAX; +#else return runOncePart(); +#endif } void SerialConsole::flush() @@ -80,6 +87,18 @@ void SerialConsole::flush() Port.flush(); } +// trigger tx of serial data +void SerialConsole::onNowHasData(uint32_t fromRadioNum) +{ + setIntervalFromNow(0); +} + +// trigger rx of serial data +void SerialConsole::rxInt() +{ + setIntervalFromNow(0); +} + // For the serial port we can't really detect if any client is on the other side, so instead just look for recent messages bool SerialConsole::checkIsConnected() { diff --git a/src/SerialConsole.h b/src/SerialConsole.h index f1e636c9d..98577e4bc 100644 --- a/src/SerialConsole.h +++ b/src/SerialConsole.h @@ -32,11 +32,14 @@ class SerialConsole : public StreamAPI, public RedirectablePrint, private concur virtual int32_t runOnce() override; void flush(); + void rxInt(); protected: /// Check the current underlying physical link to see if the client is currently connected virtual bool checkIsConnected() override; + virtual void onNowHasData(uint32_t fromRadioNum) override; + /// Possibly switch to protobufs if we see a valid protobuf message virtual void log_to_serial(const char *logLevel, const char *format, va_list arg); }; From 91e2e3f0e8a33c840a0d7de09a60cca68c4d7647 Mon Sep 17 00:00:00 2001 From: Links2004 Date: Wed, 24 Sep 2025 16:47:49 +0200 Subject: [PATCH 20/39] remove OSThread from BuzzerFeedbackThread --- src/buzz/BuzzerFeedbackThread.cpp | 19 ++----------------- src/buzz/BuzzerFeedbackThread.h | 9 +-------- 2 files changed, 3 insertions(+), 25 deletions(-) diff --git a/src/buzz/BuzzerFeedbackThread.cpp b/src/buzz/BuzzerFeedbackThread.cpp index 12b30a705..afa8c96e2 100644 --- a/src/buzz/BuzzerFeedbackThread.cpp +++ b/src/buzz/BuzzerFeedbackThread.cpp @@ -5,7 +5,7 @@ BuzzerFeedbackThread *buzzerFeedbackThread; -BuzzerFeedbackThread::BuzzerFeedbackThread() : OSThread("BuzzerFeedback") +BuzzerFeedbackThread::BuzzerFeedbackThread() { if (inputBroker) inputObserver.observe(inputBroker); @@ -19,10 +19,6 @@ int BuzzerFeedbackThread::handleInputEvent(const InputEvent *event) return 0; // Let other handlers process the event } - // Track last event time for potential future use - lastEventTime = millis(); - needsUpdate = true; - // Handle different input events with appropriate buzzer feedback switch (event->inputEvent) { case INPUT_BROKER_USER_PRESS: @@ -61,15 +57,4 @@ int BuzzerFeedbackThread::handleInputEvent(const InputEvent *event) } return 0; // Allow other handlers to process the event -} - -int32_t BuzzerFeedbackThread::runOnce() -{ - // This thread is primarily event-driven, but we can use runOnce - // for any periodic tasks if needed in the future - - needsUpdate = false; - - // Run every 100ms when active, less frequently when idle - return needsUpdate ? 100 : 1000; -} +} \ No newline at end of file diff --git a/src/buzz/BuzzerFeedbackThread.h b/src/buzz/BuzzerFeedbackThread.h index dedea9860..7dc08ead5 100644 --- a/src/buzz/BuzzerFeedbackThread.h +++ b/src/buzz/BuzzerFeedbackThread.h @@ -4,7 +4,7 @@ #include "concurrency/OSThread.h" #include "input/InputBroker.h" -class BuzzerFeedbackThread : public concurrency::OSThread +class BuzzerFeedbackThread { CallbackObserver inputObserver = CallbackObserver(this, &BuzzerFeedbackThread::handleInputEvent); @@ -12,13 +12,6 @@ class BuzzerFeedbackThread : public concurrency::OSThread public: BuzzerFeedbackThread(); int handleInputEvent(const InputEvent *event); - - protected: - virtual int32_t runOnce() override; - - private: - uint32_t lastEventTime = 0; - bool needsUpdate = false; }; extern BuzzerFeedbackThread *buzzerFeedbackThread; From 0b4a28866b2772e4dafa873c5f3fe28d94fb8c55 Mon Sep 17 00:00:00 2001 From: Links2004 Date: Wed, 24 Sep 2025 16:56:09 +0200 Subject: [PATCH 21/39] add optional debug logging to see which OSThread / loops have what delays --- platformio.ini | 1 + src/concurrency/OSThread.cpp | 4 +++- src/main.cpp | 3 +++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index bd2e8fa37..f6c0f3867 100644 --- a/platformio.ini +++ b/platformio.ini @@ -56,6 +56,7 @@ build_flags = -Wno-missing-field-initializers #-DBUILD_EPOCH=$UNIX_TIME ; set in platformio-custom.py now #-D OLED_PL=1 #-D DEBUG_HEAP=1 ; uncomment to add free heap space / memory leak debugging logs + #-D DEBUG_LOOP_TIMING=1 ; uncomment to add main loop timing logs monitor_speed = 115200 monitor_filters = direct diff --git a/src/concurrency/OSThread.cpp b/src/concurrency/OSThread.cpp index 5aee03bbf..ce9a256b7 100644 --- a/src/concurrency/OSThread.cpp +++ b/src/concurrency/OSThread.cpp @@ -90,7 +90,9 @@ void OSThread::run() if (heap < newHeap) LOG_HEAP("++++++ Thread %s freed heap %d -> %d (%d) ++++++", ThreadName.c_str(), heap, newHeap, newHeap - heap); #endif - +#ifdef DEBUG_LOOP_TIMING + LOG_DEBUG("====== Thread next run in: %d", newDelay); +#endif runned(); if (newDelay >= 0) diff --git a/src/main.cpp b/src/main.cpp index 5a1b361b3..635664eb7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1607,6 +1607,9 @@ void loop() // We want to sleep as long as possible here - because it saves power if (!runASAP && loopCanSleep()) { +#ifdef DEBUG_LOOP_TIMING + LOG_DEBUG("main loop delay: %d", delayMsec); +#endif mainDelay.delay(delayMsec); } } From 85cdcad1940943f0ed4fb6bccb874f203c5c8bcc Mon Sep 17 00:00:00 2001 From: Links2004 Date: Wed, 24 Sep 2025 16:58:15 +0200 Subject: [PATCH 22/39] only run the ButtonThread if a button is pressed --- src/input/ButtonThread.cpp | 7 ++++++- src/main.cpp | 6 ++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/input/ButtonThread.cpp b/src/input/ButtonThread.cpp index 32882f7ae..1d26e0758 100644 --- a/src/input/ButtonThread.cpp +++ b/src/input/ButtonThread.cpp @@ -274,7 +274,12 @@ int32_t ButtonThread::runOnce() } } btnEvent = BUTTON_EVENT_NONE; - return 50; + + // only pull when the button is pressed, we get notified via IRQ on a new press + if (!userButton.isIdle() || waitingForLongPress) { + return 50; + } + return INT32_MAX; } /* diff --git a/src/main.cpp b/src/main.cpp index 635664eb7..38c8e8ca5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1002,6 +1002,7 @@ void setup() config.pullupSense = INPUT_PULLUP; config.intRoutine = []() { UserButtonThread->userButton.tick(); + UserButtonThread->setIntervalFromNow(0); runASAP = true; BaseType_t higherWake = 0; mainDelay.interruptFromISR(&higherWake); @@ -1022,6 +1023,7 @@ void setup() touchConfig.pullupSense = pullup_sense; touchConfig.intRoutine = []() { TouchButtonThread->userButton.tick(); + TouchButtonThread->setIntervalFromNow(0); runASAP = true; BaseType_t higherWake = 0; mainDelay.interruptFromISR(&higherWake); @@ -1041,6 +1043,7 @@ void setup() cancelConfig.pullupSense = pullup_sense; cancelConfig.intRoutine = []() { CancelButtonThread->userButton.tick(); + CancelButtonThread->setIntervalFromNow(0); runASAP = true; BaseType_t higherWake = 0; mainDelay.interruptFromISR(&higherWake); @@ -1061,6 +1064,7 @@ void setup() backConfig.pullupSense = pullup_sense; backConfig.intRoutine = []() { BackButtonThread->userButton.tick(); + BackButtonThread->setIntervalFromNow(0); runASAP = true; BaseType_t higherWake = 0; mainDelay.interruptFromISR(&higherWake); @@ -1095,6 +1099,7 @@ void setup() userConfig.pullupSense = pullup_sense; userConfig.intRoutine = []() { UserButtonThread->userButton.tick(); + UserButtonThread->setIntervalFromNow(0); runASAP = true; BaseType_t higherWake = 0; mainDelay.interruptFromISR(&higherWake); @@ -1112,6 +1117,7 @@ void setup() userConfigNoScreen.pullupSense = pullup_sense; userConfigNoScreen.intRoutine = []() { UserButtonThread->userButton.tick(); + UserButtonThread->setIntervalFromNow(0); runASAP = true; BaseType_t higherWake = 0; mainDelay.interruptFromISR(&higherWake); From 2fdc0d0928ca52b139f948f231395d0f393aed79 Mon Sep 17 00:00:00 2001 From: Links2004 Date: Wed, 24 Sep 2025 17:02:52 +0200 Subject: [PATCH 23/39] save CPU cycles in ExternalNotificationModule e.g. no need for a 25ms loop when we only blink a LED at 1sec --- src/modules/ExternalNotificationModule.cpp | 25 +++++++++++----------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/modules/ExternalNotificationModule.cpp b/src/modules/ExternalNotificationModule.cpp index 2f2934984..4b5b160be 100644 --- a/src/modules/ExternalNotificationModule.cpp +++ b/src/modules/ExternalNotificationModule.cpp @@ -69,7 +69,7 @@ bool ascending = true; #endif #define EXT_NOTIFICATION_MODULE_OUTPUT_MS 1000 -#define EXT_NOTIFICATION_DEFAULT_THREAD_MS 25 +#define EXT_NOTIFICATION_FAST_THREAD_MS 25 #define ASCII_BELL 0x07 @@ -88,7 +88,7 @@ int32_t ExternalNotificationModule::runOnce() if (!moduleConfig.external_notification.enabled) { return INT32_MAX; // we don't need this thread here... } else { - + uint32_t delay = EXT_NOTIFICATION_MODULE_OUTPUT_MS; bool isPlaying = rtttl::isPlaying(); #ifdef HAS_I2S isPlaying = rtttl::isPlaying() || audioThread->isPlaying(); @@ -116,21 +116,16 @@ int32_t ExternalNotificationModule::runOnce() // If the output is turned on, turn it back off after the given period of time. if (isNagging) { - if (externalTurnedOn[0] + (moduleConfig.external_notification.output_ms ? moduleConfig.external_notification.output_ms - : EXT_NOTIFICATION_MODULE_OUTPUT_MS) < - millis()) { + delay = (moduleConfig.external_notification.output_ms ? moduleConfig.external_notification.output_ms + : EXT_NOTIFICATION_MODULE_OUTPUT_MS); + if (externalTurnedOn[0] + delay < millis()) { setExternalState(0, !getExternal(0)); } - if (externalTurnedOn[1] + (moduleConfig.external_notification.output_ms ? moduleConfig.external_notification.output_ms - : EXT_NOTIFICATION_MODULE_OUTPUT_MS) < - millis()) { + if (externalTurnedOn[1] + delay < millis()) { setExternalState(1, !getExternal(1)); } // Only toggle buzzer output if not using PWM mode (to avoid conflict with RTTTL) - if (!moduleConfig.external_notification.use_pwm && - externalTurnedOn[2] + (moduleConfig.external_notification.output_ms ? moduleConfig.external_notification.output_ms - : EXT_NOTIFICATION_MODULE_OUTPUT_MS) < - millis()) { + if (!moduleConfig.external_notification.use_pwm && externalTurnedOn[2] + delay < millis()) { LOG_DEBUG("EXTERNAL 2 %d compared to %d", externalTurnedOn[2] + moduleConfig.external_notification.output_ms, millis()); setExternalState(2, !getExternal(2)); @@ -181,6 +176,8 @@ int32_t ExternalNotificationModule::runOnce() colorState = 1; } } + // we need fast updates for the color change + delay = EXT_NOTIFICATION_FAST_THREAD_MS; #endif #ifdef T_WATCH_S3 @@ -206,9 +203,11 @@ int32_t ExternalNotificationModule::runOnce() // start the song again if we have time left rtttl::begin(config.device.buzzer_gpio, rtttlConfig.ringtone); } + // we need fast updates to play the RTTTL + delay = EXT_NOTIFICATION_FAST_THREAD_MS; } - return EXT_NOTIFICATION_DEFAULT_THREAD_MS; + return delay; } } From bb6f19dddf9edafb92e9852369ce873061c6792c Mon Sep 17 00:00:00 2001 From: Links2004 Date: Wed, 24 Sep 2025 17:06:56 +0200 Subject: [PATCH 24/39] the BluetoothPhoneAPI runOnce is triggerd by events any way no need to loop --- src/nimble/NimbleBluetooth.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/nimble/NimbleBluetooth.cpp b/src/nimble/NimbleBluetooth.cpp index 0c4e30785..5524765f3 100644 --- a/src/nimble/NimbleBluetooth.cpp +++ b/src/nimble/NimbleBluetooth.cpp @@ -53,7 +53,8 @@ class BluetoothPhoneAPI : public PhoneAPI, public concurrency::OSThread hasChecked = true; } - return 100; + // the run is triggered via NimbleBluetoothToRadioCallback and NimbleBluetoothFromRadioCallback + return INT32_MAX; } /** * Subclasses can use this as a hook to provide custom notifications for their transport (i.e. bluetooth notifies) From 17ecd69416a115a4fc1ff72553d11875d84e19bc Mon Sep 17 00:00:00 2001 From: Links2004 Date: Wed, 24 Sep 2025 21:07:48 +0200 Subject: [PATCH 25/39] onReceive does only exist for HardwareSerial not for USB CDC serial but we can at least check for USB connection in a longer interval --- src/SerialConsole.cpp | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/SerialConsole.cpp b/src/SerialConsole.cpp index 2e8c8ab61..51dbcb7be 100644 --- a/src/SerialConsole.cpp +++ b/src/SerialConsole.cpp @@ -6,6 +6,14 @@ #include "configuration.h" #include "time.h" +#if defined(ARDUINO_USB_CDC_ON_BOOT) && ARDUINO_USB_CDC_ON_BOOT +#define IS_USB_SERIAL +#ifdef SERIAL_HAS_ON_RECEIVE +#undef SERIAL_HAS_ON_RECEIVE +#endif +#include "HWCDC.h" +#endif + #ifdef RP2040_SLOW_CLOCK #define Port Serial2 #else @@ -23,7 +31,9 @@ SerialConsole *console; void consoleInit() { auto sc = new SerialConsole(); // Must be dynamically allocated because we are now inheriting from thread -#ifdef SERIAL_HAS_ON_RECEIVE + +#if defined(SERIAL_HAS_ON_RECEIVE) + // onReceive does only exist for HardwareSerial not for USB CDC serial Port.onReceive([sc]() { sc->rxInt(); }); #endif DEBUG_PORT.rpInit(); // Simply sets up semaphore @@ -74,11 +84,14 @@ int32_t SerialConsole::runOnce() return 250; } #endif -#ifdef SERIAL_HAS_ON_RECEIVE + int32_t delay = runOncePart(); +#if defined(SERIAL_HAS_ON_RECEIVE) return Port.available() ? delay : INT32_MAX; +#elif defined(IS_USB_SERIAL) + return HWCDC::isPlugged() ? delay : (1000 * 20); #else - return runOncePart(); + return delay; #endif } From 12c3ddf457a80390107e1cf253cf58fca03fbcdd Mon Sep 17 00:00:00 2001 From: GUVWAF Date: Thu, 25 Sep 2025 19:54:29 +0200 Subject: [PATCH 26/39] Resolve comments --- src/mesh/PacketHistory.cpp | 51 +++++++++++++++++++++++++++++++++----- src/mesh/PacketHistory.h | 11 +++++++- 2 files changed, 55 insertions(+), 7 deletions(-) diff --git a/src/mesh/PacketHistory.cpp b/src/mesh/PacketHistory.cpp index 09b1f84c9..97ed82b3d 100644 --- a/src/mesh/PacketHistory.cpp +++ b/src/mesh/PacketHistory.cpp @@ -66,11 +66,12 @@ bool PacketHistory::wasSeenRecently(const meshtastic_MeshPacket *p, bool withUpd r.id = p->id; r.sender = getFrom(p); // If 0 then use our ID r.next_hop = p->next_hop; + setHighestHopLimit(r, p->hop_limit); bool weWillRelay = false; uint8_t ourRelayID = nodeDB->getLastByteOfNodeNum(nodeDB->getNodeNum()); if (p->relay_node == ourRelayID) { // If the relay_node is us, store it weWillRelay = true; - r.ourTxHopLimit = p->hop_limit; + setOurTxHopLimit(r, p->hop_limit); r.relayed_by[0] = p->relay_node; } @@ -134,18 +135,35 @@ bool PacketHistory::wasSeenRecently(const meshtastic_MeshPacket *p, bool withUpd if (!weWillRelay) { bool weWereRelayer = wasRelayer(ourRelayID, *found); // We were a relayer and the packet came in with a hop limit that is one less than when we sent it out - if (weWereRelayer && p->hop_limit == found->ourTxHopLimit - 1) { + if (weWereRelayer && (p->hop_limit == getOurTxHopLimit(*found) || p->hop_limit == getOurTxHopLimit(*found) - 1)) { r.relayed_by[0] = p->relay_node; startIdx = 1; // Start copying existing relayers from index 1 } // keep the original ourTxHopLimit - r.ourTxHopLimit = found->ourTxHopLimit; + setOurTxHopLimit(r, getOurTxHopLimit(*found)); } - // Add the existing relayed_by to the new record - for (uint8_t i = 0; i < (NUM_RELAYERS - 1); i++) { - if (found->relayed_by[i] != 0) + // Preserve the highest hop_limit we've ever seen for this packet so upgrades aren't lost when a later copy has + // fewer hops remaining. + if (getHighestHopLimit(*found) > getHighestHopLimit(r)) + setHighestHopLimit(r, getHighestHopLimit(*found)); + + // Add the existing relayed_by to the new record, avoiding duplicates + for (uint8_t i = 0; i < (NUM_RELAYERS - startIdx); i++) { + if (found->relayed_by[i] == 0) + continue; + + bool exists = false; + for (uint8_t j = 0; j < NUM_RELAYERS; j++) { + if (r.relayed_by[j] == found->relayed_by[i]) { + exists = true; + break; + } + } + + if (!exists) { r.relayed_by[i + startIdx] = found->relayed_by[i]; + } } r.next_hop = found->next_hop; // keep the original next_hop (such that we check whether we were originally asked) #if VERBOSE_PACKET_HISTORY @@ -409,3 +427,24 @@ void PacketHistory::removeRelayer(const uint8_t relayer, const uint32_t id, cons found->id, found->relayed_by[0], found->relayed_by[1], found->relayed_by[2], relayer, i != j); #endif } + +// Getters and setters for hop limit fields packed in hop_limit +inline uint8_t PacketHistory::getHighestHopLimit(PacketRecord &r) +{ + return r.hop_limit & HOP_LIMIT_HIGHEST_MASK; +} + +inline void PacketHistory::setHighestHopLimit(PacketRecord &r, uint8_t hopLimit) +{ + r.hop_limit = (r.hop_limit & ~HOP_LIMIT_HIGHEST_MASK) | (hopLimit & HOP_LIMIT_HIGHEST_MASK); +} + +inline uint8_t PacketHistory::getOurTxHopLimit(PacketRecord &r) +{ + return (r.hop_limit & HOP_LIMIT_OUR_TX_MASK) >> HOP_LIMIT_OUR_TX_SHIFT; +} + +inline void PacketHistory::setOurTxHopLimit(PacketRecord &r, uint8_t hopLimit) +{ + r.hop_limit = (r.hop_limit & ~HOP_LIMIT_OUR_TX_MASK) | ((hopLimit << HOP_LIMIT_OUR_TX_SHIFT) & HOP_LIMIT_OUR_TX_MASK); +} \ No newline at end of file diff --git a/src/mesh/PacketHistory.h b/src/mesh/PacketHistory.h index 20aac9999..08a625fe1 100644 --- a/src/mesh/PacketHistory.h +++ b/src/mesh/PacketHistory.h @@ -4,6 +4,9 @@ // Number of relayers we keep track of. Use 6 to be efficient with memory alignment of PacketRecord to 20 bytes #define NUM_RELAYERS 6 +#define HOP_LIMIT_HIGHEST_MASK 0x07 // Bits 0-2 +#define HOP_LIMIT_OUR_TX_MASK 0x38 // Bits 3-5 +#define HOP_LIMIT_OUR_TX_SHIFT 3 // Bits 3-5 /** * This is a mixin that adds a record of past packets we have seen @@ -16,7 +19,8 @@ class PacketHistory PacketId id; uint32_t rxTimeMsec; // Unix time in msecs - the time we received it, 0 means empty uint8_t next_hop; // The next hop asked for this packet - uint8_t ourTxHopLimit; // The hop limit of the packet when we first transmitted it + uint8_t hop_limit; // bit 0-2: Highest hop limit observed for this packet, + // bit 3-5: our hop limit when we first transmitted it uint8_t relayed_by[NUM_RELAYERS]; // Array of nodes that relayed this packet }; // 4B + 4B + 4B + 1B + 1B + 6B = 20B @@ -39,6 +43,11 @@ class PacketHistory * @return true if node was indeed a relayer, false if not */ bool wasRelayer(const uint8_t relayer, const PacketRecord &r, bool *wasSole = nullptr); + uint8_t getHighestHopLimit(PacketRecord &r); + void setHighestHopLimit(PacketRecord &r, uint8_t hopLimit); + uint8_t getOurTxHopLimit(PacketRecord &r); + void setOurTxHopLimit(PacketRecord &r, uint8_t hopLimit); + PacketHistory(const PacketHistory &); // non construction-copyable PacketHistory &operator=(const PacketHistory &); // non copyable public: From 06240596833a31b08b9e95530027b3708a7d635f Mon Sep 17 00:00:00 2001 From: Jason P Date: Fri, 26 Sep 2025 11:17:15 -0500 Subject: [PATCH 27/39] Saving changes are required (#8122) --- src/graphics/draw/MenuHandler.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/graphics/draw/MenuHandler.cpp b/src/graphics/draw/MenuHandler.cpp index 7c4f4e05f..43b3fb8ab 100644 --- a/src/graphics/draw/MenuHandler.cpp +++ b/src/graphics/draw/MenuHandler.cpp @@ -852,24 +852,31 @@ void menuHandler::GPSFormatMenu() bannerOptions.bannerCallback = [](int selected) -> void { if (selected == 1) { uiconfig.gps_format = meshtastic_DeviceUIConfig_GpsCoordinateFormat_DEC; + saveUIConfig(); service->reloadConfig(SEGMENT_CONFIG); } else if (selected == 2) { uiconfig.gps_format = meshtastic_DeviceUIConfig_GpsCoordinateFormat_DMS; + saveUIConfig(); service->reloadConfig(SEGMENT_CONFIG); } else if (selected == 3) { uiconfig.gps_format = meshtastic_DeviceUIConfig_GpsCoordinateFormat_UTM; + saveUIConfig(); service->reloadConfig(SEGMENT_CONFIG); } else if (selected == 4) { uiconfig.gps_format = meshtastic_DeviceUIConfig_GpsCoordinateFormat_MGRS; + saveUIConfig(); service->reloadConfig(SEGMENT_CONFIG); } else if (selected == 5) { uiconfig.gps_format = meshtastic_DeviceUIConfig_GpsCoordinateFormat_OLC; + saveUIConfig(); service->reloadConfig(SEGMENT_CONFIG); } else if (selected == 6) { uiconfig.gps_format = meshtastic_DeviceUIConfig_GpsCoordinateFormat_OSGR; + saveUIConfig(); service->reloadConfig(SEGMENT_CONFIG); } else if (selected == 7) { uiconfig.gps_format = meshtastic_DeviceUIConfig_GpsCoordinateFormat_MLS; + saveUIConfig(); service->reloadConfig(SEGMENT_CONFIG); } else { menuQueue = position_base_menu; From 2f1198ddf3a5558f31ccde577edf763a8e80f8f1 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 26 Sep 2025 11:17:38 -0500 Subject: [PATCH 28/39] Upgrade trunk (#8118) Co-authored-by: vidplace7 <1779290+vidplace7@users.noreply.github.com> --- .trunk/trunk.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index e9bbba9ff..4e9de6a02 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -9,7 +9,7 @@ plugins: lint: enabled: - checkov@3.2.471 - - renovate@41.127.2 + - renovate@41.130.1 - prettier@3.6.2 - trufflehog@3.90.8 - yamllint@1.37.1 From bc3db1b5c137db93088476467219fc1ab36e4932 Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Fri, 26 Sep 2025 18:23:09 -0500 Subject: [PATCH 29/39] Properly output the TCXO Voltage in yaml (#8128) --- src/platform/portduino/PortduinoGlue.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/portduino/PortduinoGlue.h b/src/platform/portduino/PortduinoGlue.h index 106900c48..ec6209487 100644 --- a/src/platform/portduino/PortduinoGlue.h +++ b/src/platform/portduino/PortduinoGlue.h @@ -224,7 +224,7 @@ extern struct portduino_config_struct { out << YAML::Key << "RF95_MAX_POWER" << YAML::Value << rf95_max_power; out << YAML::Key << "DIO2_AS_RF_SWITCH" << YAML::Value << dio2_as_rf_switch; if (dio3_tcxo_voltage != 0) - out << YAML::Key << "DIO3_TCXO_VOLTAGE" << YAML::Value << dio3_tcxo_voltage; + out << YAML::Key << "DIO3_TCXO_VOLTAGE" << YAML::Value << YAML::Precision(3) << (float)dio3_tcxo_voltage / 1000; if (lora_usb_pid != 0x5512) out << YAML::Key << "USB_PID" << YAML::Value << YAML::Hex << lora_usb_pid; if (lora_usb_vid != 0x1A86) From a2d86454d3c67599953b37354bb727b944ce0abd Mon Sep 17 00:00:00 2001 From: WillyJL Date: Sat, 27 Sep 2025 07:07:38 +0200 Subject: [PATCH 30/39] I2S: Fix silent RTTTL regression (#8129) --- src/AudioThread.h | 1 + src/modules/ExternalNotificationModule.cpp | 11 +++++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/AudioThread.h b/src/AudioThread.h index 286729909..cb1f804ac 100644 --- a/src/AudioThread.h +++ b/src/AudioThread.h @@ -26,6 +26,7 @@ class AudioThread : public concurrency::OSThread i2sRtttl->begin(rtttlFile, audioOut); } + // Also handles actually playing the RTTTL, needs to be called in loop bool isPlaying() { if (i2sRtttl != nullptr) { diff --git a/src/modules/ExternalNotificationModule.cpp b/src/modules/ExternalNotificationModule.cpp index 4b5b160be..1279078b1 100644 --- a/src/modules/ExternalNotificationModule.cpp +++ b/src/modules/ExternalNotificationModule.cpp @@ -89,11 +89,12 @@ int32_t ExternalNotificationModule::runOnce() return INT32_MAX; // we don't need this thread here... } else { uint32_t delay = EXT_NOTIFICATION_MODULE_OUTPUT_MS; - bool isPlaying = rtttl::isPlaying(); + bool isRtttlPlaying = rtttl::isPlaying(); #ifdef HAS_I2S - isPlaying = rtttl::isPlaying() || audioThread->isPlaying(); + // audioThread->isPlaying() also handles actually playing the RTTTL, needs to be called in loop + isRtttlPlaying = isRtttlPlaying || audioThread->isPlaying(); #endif - if ((nagCycleCutoff < millis()) && !isPlaying) { + if ((nagCycleCutoff < millis()) && !isRtttlPlaying) { // let the song finish if we reach timeout nagCycleCutoff = UINT32_MAX; LOG_INFO("Turning off external notification: "); @@ -187,12 +188,14 @@ int32_t ExternalNotificationModule::runOnce() // Play RTTTL over i2s audio interface if enabled as buzzer #ifdef HAS_I2S - if (moduleConfig.external_notification.use_i2s_as_buzzer && canBuzz()) { + if (moduleConfig.external_notification.use_i2s_as_buzzer) { if (audioThread->isPlaying()) { // Continue playing } else if (isNagging && (nagCycleCutoff >= millis())) { audioThread->beginRttl(rtttlConfig.ringtone, strlen_P(rtttlConfig.ringtone)); } + // we need fast updates to play the RTTTL + delay = EXT_NOTIFICATION_FAST_THREAD_MS; } #endif // now let the PWM buzzer play From ab00e991f6bd616f572f25686acb830c63749b76 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Sat, 27 Sep 2025 07:09:24 -0500 Subject: [PATCH 31/39] Revert cross-preset default-key bridging with UDP and disable UDP by default (#8130) * Revert cross-preset UDP bridging * Don't enable UDP by default --- src/mesh/NodeDB.cpp | 2 +- src/mesh/Router.cpp | 29 ----------------------------- 2 files changed, 1 insertion(+), 30 deletions(-) diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 97dfb3e52..a7172f4d1 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -701,7 +701,7 @@ void NodeDB::installDefaultConfig(bool preserveKey = false) #ifdef USERPREFS_NETWORK_ENABLED_PROTOCOLS config.network.enabled_protocols = USERPREFS_NETWORK_ENABLED_PROTOCOLS; #else - config.network.enabled_protocols = 1; + config.network.enabled_protocols = 0; #endif #endif diff --git a/src/mesh/Router.cpp b/src/mesh/Router.cpp index 171c383ba..145b4dde8 100644 --- a/src/mesh/Router.cpp +++ b/src/mesh/Router.cpp @@ -483,35 +483,6 @@ DecodeState perhapsDecode(meshtastic_MeshPacket *p) } } -#if HAS_UDP_MULTICAST - // Fallback: for UDP multicast, try default preset names with default PSK if normal channel match failed - if (!decrypted && p->transport_mechanism == meshtastic_MeshPacket_TransportMechanism_TRANSPORT_MULTICAST_UDP) { - if (channels.setDefaultPresetCryptoForHash(p->channel)) { - memcpy(bytes, p->encrypted.bytes, rawSize); - crypto->decrypt(p->from, p->id, rawSize, bytes); - - meshtastic_Data decodedtmp; - memset(&decodedtmp, 0, sizeof(decodedtmp)); - if (pb_decode_from_bytes(bytes, rawSize, &meshtastic_Data_msg, &decodedtmp) && - decodedtmp.portnum != meshtastic_PortNum_UNKNOWN_APP) { - p->decoded = decodedtmp; - p->which_payload_variant = meshtastic_MeshPacket_decoded_tag; - // Map to our local default channel index (name+PSK default), not necessarily primary - ChannelIndex defaultIndex = channels.getPrimaryIndex(); - for (ChannelIndex i = 0; i < channels.getNumChannels(); ++i) { - if (channels.isDefaultChannel(i)) { - defaultIndex = i; - break; - } - } - chIndex = defaultIndex; - decrypted = true; - } else { - LOG_WARN("UDP fallback decode attempted but failed for hash 0x%x", p->channel); - } - } - } -#endif if (decrypted) { // parsing was successful p->channel = chIndex; // change to store the index instead of the hash From e8627b2d0124e96aa8dc055f44cef1c7ff47058b Mon Sep 17 00:00:00 2001 From: Dzmitry Plashchynski Date: Sat, 27 Sep 2025 15:56:52 +0300 Subject: [PATCH 32/39] UIRenderer: display "No GPS present" only on the first line to avoid duplication --- src/graphics/draw/UIRenderer.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/graphics/draw/UIRenderer.cpp b/src/graphics/draw/UIRenderer.cpp index 988e7eb53..2ccc0f861 100644 --- a/src/graphics/draw/UIRenderer.cpp +++ b/src/graphics/draw/UIRenderer.cpp @@ -125,8 +125,10 @@ void UIRenderer::drawGpsCoordinates(OLEDDisplay *display, int16_t x, int16_t y, char displayLine[32]; if (!gps->getIsConnected() && !config.position.fixed_position) { - strcpy(displayLine, "No GPS present"); - display->drawString(x, y, displayLine); + if (strcmp(mode, "line1") == 0) { + strcpy(displayLine, "No GPS present"); + display->drawString(x, y, displayLine); + } } else if (!gps->getHasLock() && !config.position.fixed_position) { if (strcmp(mode, "line1") == 0) { strcpy(displayLine, "No GPS Lock"); From 045176789e2c4fe50ce4b8ce8a44b4bbfc710cdc Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Sat, 27 Sep 2025 08:32:43 -0500 Subject: [PATCH 33/39] Fix int comparison and client_base base should really not be on this list --- src/mesh/Router.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mesh/Router.cpp b/src/mesh/Router.cpp index 145b4dde8..7f17737e5 100644 --- a/src/mesh/Router.cpp +++ b/src/mesh/Router.cpp @@ -90,7 +90,7 @@ bool Router::shouldDecrementHopLimit(const meshtastic_MeshPacket *p) // For subsequent hops, check if previous relay is a favorite router // Optimized search for favorite routers with matching last byte // Check ordering optimized for IoT devices (cheapest checks first) - for (int i = 0; i < nodeDB->getNumMeshNodes(); i++) { + for (size_t i = 0; i < nodeDB->getNumMeshNodes(); i++) { meshtastic_NodeInfoLite *node = nodeDB->getMeshNodeByIndex(i); if (!node) continue; @@ -105,7 +105,7 @@ bool Router::shouldDecrementHopLimit(const meshtastic_MeshPacket *p) // Check 3: role check (moderate cost - multiple comparisons) if (!IS_ONE_OF(node->user.role, meshtastic_Config_DeviceConfig_Role_ROUTER, - meshtastic_Config_DeviceConfig_Role_ROUTER_LATE, meshtastic_Config_DeviceConfig_Role_CLIENT_BASE)) { + meshtastic_Config_DeviceConfig_Role_ROUTER_LATE)) { continue; } From bc516ebbacf9cb1cf112c55386771863ef2121a5 Mon Sep 17 00:00:00 2001 From: dfsx1 <60702962+dfsx1@users.noreply.github.com> Date: Sat, 27 Sep 2025 13:33:07 +0000 Subject: [PATCH 34/39] Remove memcpy (#8079) Obsolete since #7652 returns false for mismatching keys Co-authored-by: dfsx1 Co-authored-by: Ben Meadors --- src/mesh/NodeDB.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index a7172f4d1..b512ae675 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -1667,9 +1667,6 @@ bool NodeDB::updateUser(uint32_t nodeId, meshtastic_User &p, uint8_t channelInde return false; } LOG_INFO("Public Key set for node, not updating!"); - // we copy the key into the incoming packet, to prevent overwrite - p.public_key.size = 32; - memcpy(p.public_key.bytes, info->user.public_key.bytes, 32); } else if (p.public_key.size == 32) { LOG_INFO("Update Node Pubkey!"); } From 067939ca24ee3f40f8be9e8fa5bfc215a1a17272 Mon Sep 17 00:00:00 2001 From: Jason P Date: Sun, 28 Sep 2025 06:11:01 -0500 Subject: [PATCH 35/39] Correct altitudeLine getting clobbered in the great merge (#8138) * Correct altitudeLine getting clobbered in the great merge * Fix variable usage in altitude calculation --- src/graphics/draw/UIRenderer.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/graphics/draw/UIRenderer.cpp b/src/graphics/draw/UIRenderer.cpp index 2ccc0f861..ff8cd20c5 100644 --- a/src/graphics/draw/UIRenderer.cpp +++ b/src/graphics/draw/UIRenderer.cpp @@ -1105,6 +1105,18 @@ void UIRenderer::drawCompassAndLocationScreen(OLEDDisplay *display, OLEDDisplayU // === Fourth Row: Line 2 GPS Info === UIRenderer::drawGpsCoordinates(display, x, getTextPositions(display)[line++], gpsStatus, "line2"); } + + // === Final Row: Altitude === + char altitudeLine[32] = {0}; + int32_t alt = (strcmp(displayLine, "Phone GPS") == 0 && ourNode && nodeDB->hasValidPosition(ourNode)) + ? ourNode->position.altitude + : geoCoord.getAltitude(); + if (config.display.units == meshtastic_Config_DisplayConfig_DisplayUnits_IMPERIAL) { + snprintf(altitudeLine, sizeof(altitudeLine), "Alt: %.0fft", alt * METERS_TO_FEET); + } else { + snprintf(altitudeLine, sizeof(altitudeLine), "Alt: %.0im", alt); + } + display->drawString(x, getTextPositions(display)[line++], altitudeLine); } #if !defined(M5STACK_UNITC6L) // === Draw Compass if heading is valid === From 8717c60f13e640d4b9367cd0ddc02765e6d457ca Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 28 Sep 2025 07:35:56 -0500 Subject: [PATCH 36/39] Update protobufs (#8142) Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com> --- protobufs | 2 +- src/mesh/generated/meshtastic/apponly.pb.h | 2 +- src/mesh/generated/meshtastic/channel.pb.h | 14 +++++++++----- src/mesh/generated/meshtastic/config.pb.h | 3 ++- src/mesh/generated/meshtastic/deviceonly.pb.h | 4 ++-- 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/protobufs b/protobufs index 46b81e822..082bb7cfe 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit 46b81e822af1b8e408f437092337f129dee693e6 +Subproject commit 082bb7cfeb2cba9d41be139cd324c4b43a14b3f9 diff --git a/src/mesh/generated/meshtastic/apponly.pb.h b/src/mesh/generated/meshtastic/apponly.pb.h index f4c33bd79..db9dedaaf 100644 --- a/src/mesh/generated/meshtastic/apponly.pb.h +++ b/src/mesh/generated/meshtastic/apponly.pb.h @@ -55,7 +55,7 @@ extern const pb_msgdesc_t meshtastic_ChannelSet_msg; /* Maximum encoded size of messages (where known) */ #define MESHTASTIC_MESHTASTIC_APPONLY_PB_H_MAX_SIZE meshtastic_ChannelSet_size -#define meshtastic_ChannelSet_size 679 +#define meshtastic_ChannelSet_size 695 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/generated/meshtastic/channel.pb.h b/src/mesh/generated/meshtastic/channel.pb.h index ca4310bf1..d5573a1e2 100644 --- a/src/mesh/generated/meshtastic/channel.pb.h +++ b/src/mesh/generated/meshtastic/channel.pb.h @@ -97,6 +97,8 @@ typedef struct _meshtastic_ChannelSettings { /* Per-channel module settings. */ bool has_module_settings; meshtastic_ModuleSettings module_settings; + /* Whether or not we should receive notifactions / alerts through this channel */ + bool mute; } meshtastic_ChannelSettings; /* A pair of a channel number, mode and the (sharable) settings for that channel */ @@ -128,10 +130,10 @@ extern "C" { /* Initializer values for message structs */ -#define meshtastic_ChannelSettings_init_default {0, {0, {0}}, "", 0, 0, 0, false, meshtastic_ModuleSettings_init_default} +#define meshtastic_ChannelSettings_init_default {0, {0, {0}}, "", 0, 0, 0, false, meshtastic_ModuleSettings_init_default, 0} #define meshtastic_ModuleSettings_init_default {0, 0} #define meshtastic_Channel_init_default {0, false, meshtastic_ChannelSettings_init_default, _meshtastic_Channel_Role_MIN} -#define meshtastic_ChannelSettings_init_zero {0, {0, {0}}, "", 0, 0, 0, false, meshtastic_ModuleSettings_init_zero} +#define meshtastic_ChannelSettings_init_zero {0, {0, {0}}, "", 0, 0, 0, false, meshtastic_ModuleSettings_init_zero, 0} #define meshtastic_ModuleSettings_init_zero {0, 0} #define meshtastic_Channel_init_zero {0, false, meshtastic_ChannelSettings_init_zero, _meshtastic_Channel_Role_MIN} @@ -145,6 +147,7 @@ extern "C" { #define meshtastic_ChannelSettings_uplink_enabled_tag 5 #define meshtastic_ChannelSettings_downlink_enabled_tag 6 #define meshtastic_ChannelSettings_module_settings_tag 7 +#define meshtastic_ChannelSettings_mute_tag 8 #define meshtastic_Channel_index_tag 1 #define meshtastic_Channel_settings_tag 2 #define meshtastic_Channel_role_tag 3 @@ -157,7 +160,8 @@ X(a, STATIC, SINGULAR, STRING, name, 3) \ X(a, STATIC, SINGULAR, FIXED32, id, 4) \ X(a, STATIC, SINGULAR, BOOL, uplink_enabled, 5) \ X(a, STATIC, SINGULAR, BOOL, downlink_enabled, 6) \ -X(a, STATIC, OPTIONAL, MESSAGE, module_settings, 7) +X(a, STATIC, OPTIONAL, MESSAGE, module_settings, 7) \ +X(a, STATIC, SINGULAR, BOOL, mute, 8) #define meshtastic_ChannelSettings_CALLBACK NULL #define meshtastic_ChannelSettings_DEFAULT NULL #define meshtastic_ChannelSettings_module_settings_MSGTYPE meshtastic_ModuleSettings @@ -187,8 +191,8 @@ extern const pb_msgdesc_t meshtastic_Channel_msg; /* Maximum encoded size of messages (where known) */ #define MESHTASTIC_MESHTASTIC_CHANNEL_PB_H_MAX_SIZE meshtastic_Channel_size -#define meshtastic_ChannelSettings_size 72 -#define meshtastic_Channel_size 87 +#define meshtastic_ChannelSettings_size 74 +#define meshtastic_Channel_size 89 #define meshtastic_ModuleSettings_size 8 #ifdef __cplusplus diff --git a/src/mesh/generated/meshtastic/config.pb.h b/src/mesh/generated/meshtastic/config.pb.h index 0453ecad2..327568316 100644 --- a/src/mesh/generated/meshtastic/config.pb.h +++ b/src/mesh/generated/meshtastic/config.pb.h @@ -26,7 +26,8 @@ typedef enum _meshtastic_Config_DeviceConfig_Role { meshtastic_Config_DeviceConfig_Role_ROUTER_CLIENT = 3, /* Description: Infrastructure node for extending network coverage by relaying messages with minimal overhead. Not visible in Nodes list. Technical Details: Mesh packets will simply be rebroadcasted over this node. Nodes configured with this role will not originate NodeInfo, Position, Telemetry - or any other packet type. They will simply rebroadcast any mesh packets on the same frequency, channel num, spread factor, and coding rate. */ + or any other packet type. They will simply rebroadcast any mesh packets on the same frequency, channel num, spread factor, and coding rate. + Deprecated in v2.7.11 because it creates "holes" in the mesh rebroadcast chain. */ meshtastic_Config_DeviceConfig_Role_REPEATER = 4, /* Description: Broadcasts GPS position packets as priority. Technical Details: Position Mesh packets will be prioritized higher and sent more frequently by default. diff --git a/src/mesh/generated/meshtastic/deviceonly.pb.h b/src/mesh/generated/meshtastic/deviceonly.pb.h index 7fab82ff7..b5b116137 100644 --- a/src/mesh/generated/meshtastic/deviceonly.pb.h +++ b/src/mesh/generated/meshtastic/deviceonly.pb.h @@ -360,8 +360,8 @@ extern const pb_msgdesc_t meshtastic_BackupPreferences_msg; /* Maximum encoded size of messages (where known) */ /* meshtastic_NodeDatabase_size depends on runtime parameters */ #define MESHTASTIC_MESHTASTIC_DEVICEONLY_PB_H_MAX_SIZE meshtastic_BackupPreferences_size -#define meshtastic_BackupPreferences_size 2277 -#define meshtastic_ChannelFile_size 718 +#define meshtastic_BackupPreferences_size 2293 +#define meshtastic_ChannelFile_size 734 #define meshtastic_DeviceState_size 1737 #define meshtastic_NodeInfoLite_size 196 #define meshtastic_PositionLite_size 28 From 033fc0c8f392d203194cbb8d5a93fea03977db64 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Sun, 28 Sep 2025 13:13:07 -0500 Subject: [PATCH 37/39] Validate CR and SF lora config (#8146) * Validate CR and SF lora config * No zero-bw * Update src/modules/AdminModule.cpp Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Fix braces --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/modules/AdminModule.cpp | 45 +++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/src/modules/AdminModule.cpp b/src/modules/AdminModule.cpp index 79ea7bc0c..1e2d4ebe8 100644 --- a/src/modules/AdminModule.cpp +++ b/src/modules/AdminModule.cpp @@ -707,20 +707,40 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c) #endif config.display = c.payload_variant.display; break; - case meshtastic_Config_lora_tag: + + case meshtastic_Config_lora_tag: { + // Wrap the entire case in a block to scope variables and avoid crossing initialization + auto oldLoraConfig = config.lora; + auto validatedLora = c.payload_variant.lora; + LOG_INFO("Set config: LoRa"); config.has_lora = true; + + if (validatedLora.coding_rate < 4 || validatedLora.coding_rate > 8) { + LOG_WARN("Invalid coding_rate %d, setting to 5", validatedLora.coding_rate); + validatedLora.coding_rate = 5; + } + + if (validatedLora.spread_factor < 7 || validatedLora.spread_factor > 12) { + LOG_WARN("Invalid spread_factor %d, setting to 11", validatedLora.spread_factor); + validatedLora.spread_factor = 11; + } + + if (validatedLora.bandwidth == 0) { + int originalBandwidth = validatedLora.bandwidth; + validatedLora.bandwidth = myRegion->wideLora ? 800 : 250; + LOG_WARN("Invalid bandwidth %d, setting to default", originalBandwidth); + } + // If no lora radio parameters change, don't need to reboot - if (config.lora.use_preset == c.payload_variant.lora.use_preset && config.lora.region == c.payload_variant.lora.region && - config.lora.modem_preset == c.payload_variant.lora.modem_preset && - config.lora.bandwidth == c.payload_variant.lora.bandwidth && - config.lora.spread_factor == c.payload_variant.lora.spread_factor && - config.lora.coding_rate == c.payload_variant.lora.coding_rate && - config.lora.tx_power == c.payload_variant.lora.tx_power && - config.lora.frequency_offset == c.payload_variant.lora.frequency_offset && - config.lora.override_frequency == c.payload_variant.lora.override_frequency && - config.lora.channel_num == c.payload_variant.lora.channel_num && - config.lora.sx126x_rx_boosted_gain == c.payload_variant.lora.sx126x_rx_boosted_gain) { + if (oldLoraConfig.use_preset == validatedLora.use_preset && oldLoraConfig.region == validatedLora.region && + oldLoraConfig.modem_preset == validatedLora.modem_preset && oldLoraConfig.bandwidth == validatedLora.bandwidth && + oldLoraConfig.spread_factor == validatedLora.spread_factor && + oldLoraConfig.coding_rate == validatedLora.coding_rate && oldLoraConfig.tx_power == validatedLora.tx_power && + oldLoraConfig.frequency_offset == validatedLora.frequency_offset && + oldLoraConfig.override_frequency == validatedLora.override_frequency && + oldLoraConfig.channel_num == validatedLora.channel_num && + oldLoraConfig.sx126x_rx_boosted_gain == validatedLora.sx126x_rx_boosted_gain) { requiresReboot = false; } @@ -739,7 +759,7 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c) digitalWrite(RF95_FAN_EN, HIGH ^ 0); } #endif - config.lora = c.payload_variant.lora; + config.lora = validatedLora; // If we're setting region for the first time, init the region and regenerate the keys if (isRegionUnset && config.lora.region > meshtastic_Config_LoRaConfig_RegionCode_UNSET) { if (!owner.is_licensed) { @@ -771,6 +791,7 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c) } } break; + } case meshtastic_Config_bluetooth_tag: LOG_INFO("Set config: Bluetooth"); config.has_bluetooth = true; From a15d6547678272726f5338f232183411008a1844 Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Sun, 28 Sep 2025 15:30:53 -0500 Subject: [PATCH 38/39] Finish deprecating the Repeater role behavior (#8144) * Finish deprecating the Repeater role behavior * Validate * Fixed bad if/else block * Get your crap together! --- src/DisplayFormatters.cpp | 3 - src/gps/GPS.cpp | 5 - src/main.cpp | 12 +- src/mesh/FloodingRouter.cpp | 5 +- src/mesh/FloodingRouter.h | 2 +- src/mesh/MeshService.cpp | 7 +- src/mesh/NextHopRouter.cpp | 5 +- src/mesh/NodeDB.cpp | 10 +- src/mesh/RadioInterface.cpp | 5 +- src/mesh/Router.cpp | 4 - src/modules/AdminModule.cpp | 15 +- src/modules/Modules.cpp | 219 ++++++++++------------ src/modules/NodeInfoModule.cpp | 5 - src/modules/RoutingModule.cpp | 2 - src/modules/Telemetry/DeviceTelemetry.cpp | 5 - src/modules/Telemetry/HostMetrics.cpp | 4 - src/sleep.cpp | 3 +- userPrefs.jsonc | 2 +- 18 files changed, 126 insertions(+), 187 deletions(-) diff --git a/src/DisplayFormatters.cpp b/src/DisplayFormatters.cpp index 5193e1cb4..246cf0022 100644 --- a/src/DisplayFormatters.cpp +++ b/src/DisplayFormatters.cpp @@ -76,9 +76,6 @@ const char *DisplayFormatters::getDeviceRole(meshtastic_Config_DeviceConfig_Role case meshtastic_Config_DeviceConfig_Role_ROUTER_LATE: return "Router Late"; break; - case meshtastic_Config_DeviceConfig_Role_REPEATER: - return "Repeater"; - break; default: return "Unknown"; break; diff --git a/src/gps/GPS.cpp b/src/gps/GPS.cpp index 3bf2710fe..0487d1fea 100644 --- a/src/gps/GPS.cpp +++ b/src/gps/GPS.cpp @@ -1104,11 +1104,6 @@ int32_t GPS::runOnce() publishUpdate(); } - // Repeaters have no need for GPS - if (config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER) { - return disable(); - } - if (whileActive()) { // if we have received valid NMEA claim we are connected setConnected(); diff --git a/src/main.cpp b/src/main.cpp index 38c8e8ca5..29a608dfe 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -793,14 +793,7 @@ void setup() } #endif - // If we're taking on the repeater role, use NextHopRouter and turn off 3V3_S rail because peripherals are not needed - if (config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER) { - router = new NextHopRouter(); -#ifdef PIN_3V3_EN - digitalWrite(PIN_3V3_EN, LOW); -#endif - } else - router = new ReliableRouter(); + router = new ReliableRouter(); // only play start melody when role is not tracker or sensor if (config.power.is_power_saving == true && @@ -926,8 +919,7 @@ void setup() if (sensor_detected == false) { #endif if (HAS_GPS) { - if (config.device.role != meshtastic_Config_DeviceConfig_Role_REPEATER && - config.position.gps_mode != meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT) { + if (config.position.gps_mode != meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT) { gps = GPS::createGps(); if (gps) { gpsStatus->observe(&gps->newStatus); diff --git a/src/mesh/FloodingRouter.cpp b/src/mesh/FloodingRouter.cpp index 3caee78f8..5d2d7653a 100644 --- a/src/mesh/FloodingRouter.cpp +++ b/src/mesh/FloodingRouter.cpp @@ -81,9 +81,8 @@ bool FloodingRouter::shouldFilterReceived(const meshtastic_MeshPacket *p) bool FloodingRouter::roleAllowsCancelingDupe(const meshtastic_MeshPacket *p) { if (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER || - config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER || config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER_LATE) { - // ROUTER, REPEATER, ROUTER_LATE should never cancel relaying a packet (i.e. we should always rebroadcast), + // ROUTER, ROUTER_LATE should never cancel relaying a packet (i.e. we should always rebroadcast), // even if we've heard another station rebroadcast it already. return false; } @@ -102,7 +101,7 @@ bool FloodingRouter::roleAllowsCancelingDupe(const meshtastic_MeshPacket *p) void FloodingRouter::perhapsCancelDupe(const meshtastic_MeshPacket *p) { if (p->transport_mechanism == meshtastic_MeshPacket_TransportMechanism_TRANSPORT_LORA && roleAllowsCancelingDupe(p)) { - // cancel rebroadcast of this message *if* there was already one, unless we're a router/repeater! + // cancel rebroadcast of this message *if* there was already one, unless we're a router! // But only LoRa packets should be able to trigger this. if (Router::cancelSending(p->from, p->id)) txRelayCanceled++; diff --git a/src/mesh/FloodingRouter.h b/src/mesh/FloodingRouter.h index 30ad5945b..eaf71d294 100644 --- a/src/mesh/FloodingRouter.h +++ b/src/mesh/FloodingRouter.h @@ -59,7 +59,7 @@ class FloodingRouter : public Router */ virtual void sniffReceived(const meshtastic_MeshPacket *p, const meshtastic_Routing *c) override; - // Return false for roles like ROUTER or REPEATER which should always rebroadcast even when we've heard another rebroadcast of + // Return false for roles like ROUTER which should always rebroadcast even when we've heard another rebroadcast of // the same packet bool roleAllowsCancelingDupe(const meshtastic_MeshPacket *p); diff --git a/src/mesh/MeshService.cpp b/src/mesh/MeshService.cpp index a138ad1d1..1b2af082d 100644 --- a/src/mesh/MeshService.cpp +++ b/src/mesh/MeshService.cpp @@ -85,12 +85,11 @@ int MeshService::handleFromRadio(const meshtastic_MeshPacket *mp) powerFSM.trigger(EVENT_PACKET_FOR_PHONE); // Possibly keep the node from sleeping nodeDB->updateFrom(*mp); // update our DB state based off sniffing every RX packet from the radio - bool isPreferredRebroadcaster = - IS_ONE_OF(config.device.role, meshtastic_Config_DeviceConfig_Role_ROUTER, meshtastic_Config_DeviceConfig_Role_REPEATER); + bool isPreferredRebroadcaster = config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER; if (mp->which_payload_variant == meshtastic_MeshPacket_decoded_tag && mp->decoded.portnum == meshtastic_PortNum_TELEMETRY_APP && mp->decoded.request_id > 0) { - LOG_DEBUG("Received telemetry response. Skip sending our NodeInfo"); // because this potentially a Repeater which will - // ignore our request for its NodeInfo + LOG_DEBUG("Received telemetry response. Skip sending our NodeInfo"); + // ignore our request for its NodeInfo } else if (mp->which_payload_variant == meshtastic_MeshPacket_decoded_tag && !nodeDB->getMeshNode(mp->from)->has_user && nodeInfoModule && !isPreferredRebroadcaster && !nodeDB->isFull()) { if (airTime->isTxAllowedChannelUtil(true)) { diff --git a/src/mesh/NextHopRouter.cpp b/src/mesh/NextHopRouter.cpp index 4ae0a818e..cb483bc97 100644 --- a/src/mesh/NextHopRouter.cpp +++ b/src/mesh/NextHopRouter.cpp @@ -170,7 +170,6 @@ bool NextHopRouter::perhapsRelay(const meshtastic_MeshPacket *p) */ uint8_t NextHopRouter::getNextHop(NodeNum to, uint8_t relay_node) { - // When we're a repeater router->sniffReceived will call NextHopRouter directly without checking for broadcast if (isBroadcast(to)) return NO_NEXT_HOP_PREFERENCE; @@ -208,7 +207,7 @@ bool NextHopRouter::roleAllowsCancelingFromTxQueue(const meshtastic_MeshPacket * { // Return true if we're allowed to cancel a packet in the txQueue (so we may never transmit it even once) - // Return false for roles like ROUTER, REPEATER, ROUTER_LATE which should always transmit the packet at least once. + // Return false for roles like ROUTER, ROUTER_LATE which should always transmit the packet at least once. return roleAllowsCancelingDupe(p); // same logic as FloodingRouter::roleAllowsCancelingDupe } @@ -221,7 +220,7 @@ bool NextHopRouter::stopRetransmission(GlobalPacketId key) /* Only when we already transmitted a packet via LoRa, we will cancel the packet in the Tx queue to avoid canceling a transmission if it was ACKed super fast via MQTT */ if (old->numRetransmissions < NUM_RELIABLE_RETX - 1) { - // We only cancel it if we are the original sender or if we're not a router(_late)/repeater + // We only cancel it if we are the original sender or if we're not a router(_late) if (isFromUs(p) || roleAllowsCancelingFromTxQueue(p)) { // remove the 'original' (identified by originator and packet->id) from the txqueue and free it cancelSending(getFrom(p), p->id); diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index b512ae675..a32ee37f9 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -554,10 +554,9 @@ void NodeDB::installDefaultConfig(bool preserveKey = false) #endif #ifdef USERPREFS_CONFIG_DEVICE_ROLE - // Restrict ROUTER*, LOST AND FOUND, and REPEATER roles for security reasons + // Restrict ROUTER*, LOST AND FOUND roles for security reasons if (IS_ONE_OF(USERPREFS_CONFIG_DEVICE_ROLE, meshtastic_Config_DeviceConfig_Role_ROUTER, - meshtastic_Config_DeviceConfig_Role_ROUTER_LATE, meshtastic_Config_DeviceConfig_Role_REPEATER, - meshtastic_Config_DeviceConfig_Role_LOST_AND_FOUND)) { + meshtastic_Config_DeviceConfig_Role_ROUTER_LATE, meshtastic_Config_DeviceConfig_Role_LOST_AND_FOUND)) { LOG_WARN("ROUTER roles are restricted, falling back to CLIENT role"); config.device.role = meshtastic_Config_DeviceConfig_Role_CLIENT; } else { @@ -906,11 +905,6 @@ void NodeDB::installRoleDefaults(meshtastic_Config_DeviceConfig_Role role) moduleConfig.telemetry.device_update_interval = ONE_DAY; owner.has_is_unmessagable = true; owner.is_unmessagable = true; - } else if (role == meshtastic_Config_DeviceConfig_Role_REPEATER) { - owner.has_is_unmessagable = true; - owner.is_unmessagable = true; - config.display.screen_on_secs = 1; - config.device.rebroadcast_mode = meshtastic_Config_DeviceConfig_RebroadcastMode_CORE_PORTNUMS_ONLY; } else if (role == meshtastic_Config_DeviceConfig_Role_SENSOR) { owner.has_is_unmessagable = true; owner.is_unmessagable = true; diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index 31c68c302..5233b8698 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -317,9 +317,8 @@ uint32_t RadioInterface::getTxDelayMsecWeightedWorst(float snr) /** Returns true if we should rebroadcast early like a ROUTER */ bool RadioInterface::shouldRebroadcastEarlyLikeRouter(meshtastic_MeshPacket *p) { - // If we are a ROUTER or REPEATER, we always rebroadcast early - if (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER || - config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER) { + // If we are a ROUTER, we always rebroadcast early + if (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER) { return true; } diff --git a/src/mesh/Router.cpp b/src/mesh/Router.cpp index 7f17737e5..8f9fb28f9 100644 --- a/src/mesh/Router.cpp +++ b/src/mesh/Router.cpp @@ -399,10 +399,6 @@ DecodeState perhapsDecode(meshtastic_MeshPacket *p) { concurrency::LockGuard g(cryptLock); - if (config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER && - config.device.rebroadcast_mode == meshtastic_Config_DeviceConfig_RebroadcastMode_ALL_SKIP_DECODING) - return DecodeState::DECODE_FAILURE; - if (config.device.rebroadcast_mode == meshtastic_Config_DeviceConfig_RebroadcastMode_KNOWN_ONLY && (nodeDB->getMeshNode(p->from) == NULL || !nodeDB->getMeshNode(p->from)->has_user)) { LOG_DEBUG("Node 0x%x not in nodeDB-> Rebroadcast mode KNOWN_ONLY will ignore packet", p->from); diff --git a/src/modules/AdminModule.cpp b/src/modules/AdminModule.cpp index 1e2d4ebe8..7544db121 100644 --- a/src/modules/AdminModule.cpp +++ b/src/modules/AdminModule.cpp @@ -611,10 +611,9 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c) } config.device = c.payload_variant.device; if (config.device.rebroadcast_mode == meshtastic_Config_DeviceConfig_RebroadcastMode_NONE && - IS_ONE_OF(config.device.role, meshtastic_Config_DeviceConfig_Role_ROUTER, - meshtastic_Config_DeviceConfig_Role_REPEATER)) { + config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER) { config.device.rebroadcast_mode = meshtastic_Config_DeviceConfig_RebroadcastMode_ALL; - const char *warning = "Rebroadcast mode can't be set to NONE for a router or repeater"; + const char *warning = "Rebroadcast mode can't be set to NONE for a router"; LOG_WARN(warning); sendWarning(warning); } @@ -627,8 +626,9 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c) LOG_DEBUG("Tried to set node_info_broadcast_secs too low, setting to %d", min_node_info_broadcast_secs); config.device.node_info_broadcast_secs = min_node_info_broadcast_secs; } - // Router Client is deprecated; Set it to client - if (c.payload_variant.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER_CLIENT) { + // Router Client and Repeater deprecated; Set it to client + if (IS_ONE_OF(c.payload_variant.device.role, meshtastic_Config_DeviceConfig_Role_ROUTER_CLIENT, + meshtastic_Config_DeviceConfig_Role_REPEATER)) { config.device.role = meshtastic_Config_DeviceConfig_Role_CLIENT; if (moduleConfig.store_forward.enabled && !moduleConfig.store_forward.is_server) { moduleConfig.store_forward.is_server = true; @@ -637,10 +637,9 @@ void AdminModule::handleSetConfig(const meshtastic_Config &c) } } #if USERPREFS_EVENT_MODE - // If we're in event mode, nobody is a Router or Repeater + // If we're in event mode, nobody is a Router or Router Late if (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER || - config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER_LATE || - config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER) { + config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER_LATE) { config.device.role = meshtastic_Config_DeviceConfig_Role_CLIENT; } #endif diff --git a/src/modules/Modules.cpp b/src/modules/Modules.cpp index bd8997493..02962dd59 100644 --- a/src/modules/Modules.cpp +++ b/src/modules/Modules.cpp @@ -112,204 +112,191 @@ */ void setupModules() { - if (config.device.role != meshtastic_Config_DeviceConfig_Role_REPEATER) { #if (HAS_BUTTON || ARCH_PORTDUINO) && !MESHTASTIC_EXCLUDE_INPUTBROKER - if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) { - inputBroker = new InputBroker(); - systemCommandsModule = new SystemCommandsModule(); - buzzerFeedbackThread = new BuzzerFeedbackThread(); - } + if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) { + inputBroker = new InputBroker(); + systemCommandsModule = new SystemCommandsModule(); + buzzerFeedbackThread = new BuzzerFeedbackThread(); + } #endif #if !MESHTASTIC_EXCLUDE_ADMIN - adminModule = new AdminModule(); + adminModule = new AdminModule(); #endif #if !MESHTASTIC_EXCLUDE_NODEINFO - nodeInfoModule = new NodeInfoModule(); + nodeInfoModule = new NodeInfoModule(); #endif #if !MESHTASTIC_EXCLUDE_GPS - positionModule = new PositionModule(); + positionModule = new PositionModule(); #endif #if !MESHTASTIC_EXCLUDE_WAYPOINT - waypointModule = new WaypointModule(); + waypointModule = new WaypointModule(); #endif #if !MESHTASTIC_EXCLUDE_TEXTMESSAGE - textMessageModule = new TextMessageModule(); + textMessageModule = new TextMessageModule(); #endif #if !MESHTASTIC_EXCLUDE_TRACEROUTE - traceRouteModule = new TraceRouteModule(); + traceRouteModule = new TraceRouteModule(); #endif #if !MESHTASTIC_EXCLUDE_NEIGHBORINFO - if (moduleConfig.has_neighbor_info && moduleConfig.neighbor_info.enabled) { - neighborInfoModule = new NeighborInfoModule(); - } + if (moduleConfig.has_neighbor_info && moduleConfig.neighbor_info.enabled) { + neighborInfoModule = new NeighborInfoModule(); + } #endif #if !MESHTASTIC_EXCLUDE_DETECTIONSENSOR - if (moduleConfig.has_detection_sensor && moduleConfig.detection_sensor.enabled) { - detectionSensorModule = new DetectionSensorModule(); - } + if (moduleConfig.has_detection_sensor && moduleConfig.detection_sensor.enabled) { + detectionSensorModule = new DetectionSensorModule(); + } #endif #if !MESHTASTIC_EXCLUDE_ATAK - if (IS_ONE_OF(config.device.role, meshtastic_Config_DeviceConfig_Role_TAK, - meshtastic_Config_DeviceConfig_Role_TAK_TRACKER)) { - atakPluginModule = new AtakPluginModule(); - } + if (IS_ONE_OF(config.device.role, meshtastic_Config_DeviceConfig_Role_TAK, meshtastic_Config_DeviceConfig_Role_TAK_TRACKER)) { + atakPluginModule = new AtakPluginModule(); + } #endif #if !MESHTASTIC_EXCLUDE_PKI - keyVerificationModule = new KeyVerificationModule(); + keyVerificationModule = new KeyVerificationModule(); #endif #if !MESHTASTIC_EXCLUDE_DROPZONE - dropzoneModule = new DropzoneModule(); + dropzoneModule = new DropzoneModule(); #endif #if !MESHTASTIC_EXCLUDE_GENERIC_THREAD_MODULE - new GenericThreadModule(); + new GenericThreadModule(); #endif - // Note: if the rest of meshtastic doesn't need to explicitly use your module, you do not need to assign the instance - // to a global variable. + // Note: if the rest of meshtastic doesn't need to explicitly use your module, you do not need to assign the instance + // to a global variable. #if !MESHTASTIC_EXCLUDE_REMOTEHARDWARE - new RemoteHardwareModule(); + new RemoteHardwareModule(); #endif #if !MESHTASTIC_EXCLUDE_POWERSTRESS - new PowerStressModule(); + new PowerStressModule(); #endif - // Example: Put your module here - // new ReplyModule(); + // Example: Put your module here + // new ReplyModule(); #if (HAS_BUTTON || ARCH_PORTDUINO) && !MESHTASTIC_EXCLUDE_INPUTBROKER - if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) { - rotaryEncoderInterruptImpl1 = new RotaryEncoderInterruptImpl1(); - if (!rotaryEncoderInterruptImpl1->init()) { - delete rotaryEncoderInterruptImpl1; - rotaryEncoderInterruptImpl1 = nullptr; - } + if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) { + rotaryEncoderInterruptImpl1 = new RotaryEncoderInterruptImpl1(); + if (!rotaryEncoderInterruptImpl1->init()) { + delete rotaryEncoderInterruptImpl1; + rotaryEncoderInterruptImpl1 = nullptr; + } #ifdef T_LORA_PAGER - // use a special FSM based rotary encoder version for T-LoRa Pager - rotaryEncoderImpl = new RotaryEncoderImpl(); - if (!rotaryEncoderImpl->init()) { - delete rotaryEncoderImpl; - rotaryEncoderImpl = nullptr; - } + // use a special FSM based rotary encoder version for T-LoRa Pager + rotaryEncoderImpl = new RotaryEncoderImpl(); + if (!rotaryEncoderImpl->init()) { + delete rotaryEncoderImpl; + rotaryEncoderImpl = nullptr; + } #else - upDownInterruptImpl1 = new UpDownInterruptImpl1(); - if (!upDownInterruptImpl1->init()) { - delete upDownInterruptImpl1; - upDownInterruptImpl1 = nullptr; - } + upDownInterruptImpl1 = new UpDownInterruptImpl1(); + if (!upDownInterruptImpl1->init()) { + delete upDownInterruptImpl1; + upDownInterruptImpl1 = nullptr; + } #endif - cardKbI2cImpl = new CardKbI2cImpl(); - cardKbI2cImpl->init(); + cardKbI2cImpl = new CardKbI2cImpl(); + cardKbI2cImpl->init(); #if defined(M5STACK_UNITC6L) - i2cButton = new i2cButtonThread("i2cButtonThread"); + i2cButton = new i2cButtonThread("i2cButtonThread"); #endif #ifdef INPUTBROKER_MATRIX_TYPE - kbMatrixImpl = new KbMatrixImpl(); - kbMatrixImpl->init(); + kbMatrixImpl = new KbMatrixImpl(); + kbMatrixImpl->init(); #endif // INPUTBROKER_MATRIX_TYPE #ifdef INPUTBROKER_SERIAL_TYPE - aSerialKeyboardImpl = new SerialKeyboardImpl(); - aSerialKeyboardImpl->init(); + aSerialKeyboardImpl = new SerialKeyboardImpl(); + aSerialKeyboardImpl->init(); #endif // INPUTBROKER_MATRIX_TYPE - } + } #endif // HAS_BUTTON #if ARCH_PORTDUINO - if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) { - seesawRotary = new SeesawRotary("SeesawRotary"); - if (!seesawRotary->init()) { - delete seesawRotary; - seesawRotary = nullptr; - } - aLinuxInputImpl = new LinuxInputImpl(); - aLinuxInputImpl->init(); + if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) { + seesawRotary = new SeesawRotary("SeesawRotary"); + if (!seesawRotary->init()) { + delete seesawRotary; + seesawRotary = nullptr; } + aLinuxInputImpl = new LinuxInputImpl(); + aLinuxInputImpl->init(); + } #endif #if !MESHTASTIC_EXCLUDE_INPUTBROKER && HAS_TRACKBALL - if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) { - trackballInterruptImpl1 = new TrackballInterruptImpl1(); - trackballInterruptImpl1->init(TB_DOWN, TB_UP, TB_LEFT, TB_RIGHT, TB_PRESS); - } + if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) { + trackballInterruptImpl1 = new TrackballInterruptImpl1(); + trackballInterruptImpl1->init(TB_DOWN, TB_UP, TB_LEFT, TB_RIGHT, TB_PRESS); + } #endif #ifdef INPUTBROKER_EXPRESSLRSFIVEWAY_TYPE - expressLRSFiveWayInput = new ExpressLRSFiveWay(); + expressLRSFiveWayInput = new ExpressLRSFiveWay(); #endif #if HAS_SCREEN && !MESHTASTIC_EXCLUDE_CANNEDMESSAGES - if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) { - cannedMessageModule = new CannedMessageModule(); - } + if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) { + cannedMessageModule = new CannedMessageModule(); + } #endif #if ARCH_PORTDUINO - new HostMetricsModule(); + new HostMetricsModule(); #endif #if HAS_TELEMETRY - new DeviceTelemetryModule(); + new DeviceTelemetryModule(); #endif #if HAS_TELEMETRY && HAS_SENSOR && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR - if (moduleConfig.has_telemetry && - (moduleConfig.telemetry.environment_measurement_enabled || moduleConfig.telemetry.environment_screen_enabled)) { - new EnvironmentTelemetryModule(); - } + if (moduleConfig.has_telemetry && + (moduleConfig.telemetry.environment_measurement_enabled || moduleConfig.telemetry.environment_screen_enabled)) { + new EnvironmentTelemetryModule(); + } #if __has_include("Adafruit_PM25AQI.h") - if (moduleConfig.has_telemetry && moduleConfig.telemetry.air_quality_enabled && - nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_PMSA003I].first > 0) { - new AirQualityTelemetryModule(); - } + if (moduleConfig.has_telemetry && moduleConfig.telemetry.air_quality_enabled && + nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_PMSA003I].first > 0) { + new AirQualityTelemetryModule(); + } #endif #if !MESHTASTIC_EXCLUDE_HEALTH_TELEMETRY - if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_MAX30102].first > 0 || - nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_MLX90614].first > 0) { - new HealthTelemetryModule(); - } + if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_MAX30102].first > 0 || + nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_MLX90614].first > 0) { + new HealthTelemetryModule(); + } #endif #endif #if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_POWER_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR - if (moduleConfig.has_telemetry && - (moduleConfig.telemetry.power_measurement_enabled || moduleConfig.telemetry.power_screen_enabled)) { - new PowerTelemetryModule(); - } + if (moduleConfig.has_telemetry && + (moduleConfig.telemetry.power_measurement_enabled || moduleConfig.telemetry.power_screen_enabled)) { + new PowerTelemetryModule(); + } #endif #if (defined(ARCH_ESP32) || defined(ARCH_NRF52) || defined(ARCH_RP2040) || defined(ARCH_STM32WL)) && \ !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) #if !MESHTASTIC_EXCLUDE_SERIAL - if (moduleConfig.has_serial && moduleConfig.serial.enabled && - config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) { - new SerialModule(); - } + if (moduleConfig.has_serial && moduleConfig.serial.enabled && + config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) { + new SerialModule(); + } #endif #endif #ifdef ARCH_ESP32 - // Only run on an esp32 based device. + // Only run on an esp32 based device. #if defined(USE_SX1280) && !MESHTASTIC_EXCLUDE_AUDIO - audioModule = new AudioModule(); + audioModule = new AudioModule(); #endif #if !MESHTASTIC_EXCLUDE_PAXCOUNTER - if (moduleConfig.has_paxcounter && moduleConfig.paxcounter.enabled) { - paxcounterModule = new PaxcounterModule(); - } + if (moduleConfig.has_paxcounter && moduleConfig.paxcounter.enabled) { + paxcounterModule = new PaxcounterModule(); + } #endif #endif #if defined(ARCH_ESP32) || defined(ARCH_PORTDUINO) #if !MESHTASTIC_EXCLUDE_STOREFORWARD - if (moduleConfig.has_store_forward && moduleConfig.store_forward.enabled) { - storeForwardModule = new StoreForwardModule(); - } + if (moduleConfig.has_store_forward && moduleConfig.store_forward.enabled) { + storeForwardModule = new StoreForwardModule(); + } #endif #endif #if !MESHTASTIC_EXCLUDE_EXTERNALNOTIFICATION - externalNotificationModule = new ExternalNotificationModule(); + externalNotificationModule = new ExternalNotificationModule(); #endif #if !MESHTASTIC_EXCLUDE_RANGETEST && !MESHTASTIC_EXCLUDE_GPS - if (moduleConfig.has_range_test && moduleConfig.range_test.enabled) - new RangeTestModule(); + if (moduleConfig.has_range_test && moduleConfig.range_test.enabled) + new RangeTestModule(); #endif - } else { -#if !MESHTASTIC_EXCLUDE_ADMIN - adminModule = new AdminModule(); -#endif -#if HAS_TELEMETRY - new DeviceTelemetryModule(); -#endif -#if !MESHTASTIC_EXCLUDE_TRACEROUTE - traceRouteModule = new TraceRouteModule(); -#endif - } // NOTE! This module must be added LAST because it likes to check for replies from other modules and avoid sending extra // acks routingModule = new RoutingModule(); diff --git a/src/modules/NodeInfoModule.cpp b/src/modules/NodeInfoModule.cpp index 276a11b3a..2c3c274d2 100644 --- a/src/modules/NodeInfoModule.cpp +++ b/src/modules/NodeInfoModule.cpp @@ -94,11 +94,6 @@ meshtastic_MeshPacket *NodeInfoModule::allocReply() u.public_key.bytes[0] = 0; u.public_key.size = 0; } - // Coerce unmessagable for Repeater role - if (u.role == meshtastic_Config_DeviceConfig_Role_REPEATER) { - u.has_is_unmessagable = true; - u.is_unmessagable = true; - } LOG_INFO("Send owner %s/%s/%s", u.id, u.long_name, u.short_name); lastSentToMesh = millis(); diff --git a/src/modules/RoutingModule.cpp b/src/modules/RoutingModule.cpp index e7e92c79a..fbe3a9cee 100644 --- a/src/modules/RoutingModule.cpp +++ b/src/modules/RoutingModule.cpp @@ -42,8 +42,6 @@ bool RoutingModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, mesh meshtastic_MeshPacket *RoutingModule::allocReply() { - if (config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER) - return NULL; assert(currentRequest); return NULL; diff --git a/src/modules/Telemetry/DeviceTelemetry.cpp b/src/modules/Telemetry/DeviceTelemetry.cpp index 98d5b19d0..ad148b759 100644 --- a/src/modules/Telemetry/DeviceTelemetry.cpp +++ b/src/modules/Telemetry/DeviceTelemetry.cpp @@ -26,7 +26,6 @@ int32_t DeviceTelemetryModule::runOnce() Default::getConfiguredOrDefaultMsScaled(moduleConfig.telemetry.device_update_interval, default_telemetry_broadcast_interval_secs, numOnlineNodes))) && airTime->isTxAllowedChannelUtil(!isImpoliteRole) && airTime->isTxAllowedAirUtil() && - config.device.role != meshtastic_Config_DeviceConfig_Role_REPEATER && config.device.role != meshtastic_Config_DeviceConfig_Role_CLIENT_HIDDEN) { sendTelemetry(); lastSentToMesh = uptimeLastMs; @@ -44,10 +43,6 @@ int32_t DeviceTelemetryModule::runOnce() bool DeviceTelemetryModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_Telemetry *t) { - // Don't worry about storing telemetry in NodeDB if we're a repeater - if (config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER) - return false; - if (t->which_variant == meshtastic_Telemetry_device_metrics_tag) { #if defined(DEBUG_PORT) && !defined(DEBUG_MUTE) const char *sender = getSenderShortName(mp); diff --git a/src/modules/Telemetry/HostMetrics.cpp b/src/modules/Telemetry/HostMetrics.cpp index dcde495a2..577132006 100644 --- a/src/modules/Telemetry/HostMetrics.cpp +++ b/src/modules/Telemetry/HostMetrics.cpp @@ -22,10 +22,6 @@ int32_t HostMetricsModule::runOnce() bool HostMetricsModule::handleReceivedProtobuf(const meshtastic_MeshPacket &mp, meshtastic_Telemetry *t) { - // Don't worry about storing telemetry in NodeDB if we're a repeater - if (config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER) - return false; - if (t->which_variant == meshtastic_Telemetry_host_metrics_tag) { #if defined(DEBUG_PORT) && !defined(DEBUG_MUTE) const char *sender = getSenderShortName(mp); diff --git a/src/sleep.cpp b/src/sleep.cpp index 0f8931292..ec560cb90 100644 --- a/src/sleep.cpp +++ b/src/sleep.cpp @@ -532,8 +532,7 @@ void enableModemSleep() bool shouldLoraWake(uint32_t msecToWake) { - return msecToWake < portMAX_DELAY && (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER || - config.device.role == meshtastic_Config_DeviceConfig_Role_REPEATER); + return msecToWake < portMAX_DELAY && (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER); } void enableLoraInterrupt() diff --git a/userPrefs.jsonc b/userPrefs.jsonc index f6f3ef995..464eb968c 100644 --- a/userPrefs.jsonc +++ b/userPrefs.jsonc @@ -21,7 +21,7 @@ // "USERPREFS_CONFIG_LORA_REGION": "meshtastic_Config_LoRaConfig_RegionCode_US", // "USERPREFS_CONFIG_OWNER_LONG_NAME": "My Long Name", // "USERPREFS_CONFIG_OWNER_SHORT_NAME": "MLN", - // "USERPREFS_CONFIG_DEVICE_ROLE": "meshtastic_Config_DeviceConfig_Role_CLIENT", // Defaults to CLIENT. ROUTER*, LOST AND FOUND, and REPEATER roles are restricted. + // "USERPREFS_CONFIG_DEVICE_ROLE": "meshtastic_Config_DeviceConfig_Role_CLIENT", // Defaults to CLIENT. ROUTER*, and LOST AND FOUND roles are restricted. // "USERPREFS_EVENT_MODE": "1", // "USERPREFS_FIRMWARE_EDITION": "meshtastic_FirmwareEdition_BURNING_MAN", // "USERPREFS_FIXED_BLUETOOTH": "121212", From a1c658a467ee802b1fb64f8d82c6d335a379d986 Mon Sep 17 00:00:00 2001 From: Clive Blackledge Date: Sun, 28 Sep 2025 14:42:51 -0700 Subject: [PATCH 39/39] Bug / Send upgraded (duplicate) packets to phone if the queue removal failed. (#8148) * Add seenRecently = true if wasUpgraded is true but unable to remove from queue (i.e. already sent/processed). * Consistent comment between FloodingRouter and HopRouter --- src/mesh/FloodingRouter.cpp | 4 ++++ src/mesh/NextHopRouter.cpp | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/mesh/FloodingRouter.cpp b/src/mesh/FloodingRouter.cpp index 5d2d7653a..1d8ac247f 100644 --- a/src/mesh/FloodingRouter.cpp +++ b/src/mesh/FloodingRouter.cpp @@ -54,6 +54,10 @@ bool FloodingRouter::shouldFilterReceived(const meshtastic_MeshPacket *p) // We already enqueued the improved copy, so make sure the incoming packet stops here. return true; } + + // No queue entry was replaced by this upgraded copy, so treat it as a duplicate to avoid + // delivering the same packet to applications/phone twice with different hop limits. + seenRecently = true; } if (seenRecently) { diff --git a/src/mesh/NextHopRouter.cpp b/src/mesh/NextHopRouter.cpp index cb483bc97..0461d7eb6 100644 --- a/src/mesh/NextHopRouter.cpp +++ b/src/mesh/NextHopRouter.cpp @@ -64,6 +64,10 @@ bool NextHopRouter::shouldFilterReceived(const meshtastic_MeshPacket *p) // We already enqueued the improved copy, so make sure the incoming packet stops here. return true; } + + // No queue entry was replaced by this upgraded copy, so treat it as a duplicate to avoid + // delivering the same packet to applications/phone twice with different hop limits. + seenRecently = true; } if (seenRecently) {