From c641beabd32f564f9064a520efd90afd1df524fa Mon Sep 17 00:00:00 2001 From: csrutil Date: Sat, 29 Nov 2025 16:37:10 +0800 Subject: [PATCH 1/8] https://github.com/meshcore-dev/MeshCore/issues/989 - persist GPS enabled state to preferences Add GPS configuration to NodePrefs structure and persist the GPS enabled state when toggled via UI. This ensures GPS settings are retained across device restarts. --- examples/companion_radio/DataStore.cpp | 4 ++++ examples/companion_radio/MyMesh.cpp | 7 +++++++ examples/companion_radio/NodePrefs.h | 2 ++ examples/companion_radio/ui-new/UITask.cpp | 3 +++ 4 files changed, 16 insertions(+) diff --git a/examples/companion_radio/DataStore.cpp b/examples/companion_radio/DataStore.cpp index 00e25cb2..7f5761f3 100644 --- a/examples/companion_radio/DataStore.cpp +++ b/examples/companion_radio/DataStore.cpp @@ -222,6 +222,8 @@ void DataStore::loadPrefsInt(const char *filename, NodePrefs& _prefs, double& no file.read(pad, 2); // 78 file.read((uint8_t *)&_prefs.ble_pin, sizeof(_prefs.ble_pin)); // 80 file.read((uint8_t *)&_prefs.buzzer_quiet, sizeof(_prefs.buzzer_quiet)); // 84 + file.read((uint8_t *)&_prefs.gps_enabled, sizeof(_prefs.gps_enabled)); // 85 + file.read((uint8_t *)&_prefs.gps_interval, sizeof(_prefs.gps_interval)); // 86 file.close(); } @@ -254,6 +256,8 @@ void DataStore::savePrefs(const NodePrefs& _prefs, double node_lat, double node_ file.write(pad, 2); // 78 file.write((uint8_t *)&_prefs.ble_pin, sizeof(_prefs.ble_pin)); // 80 file.write((uint8_t *)&_prefs.buzzer_quiet, sizeof(_prefs.buzzer_quiet)); // 84 + file.write((uint8_t *)&_prefs.gps_enabled, sizeof(_prefs.gps_enabled)); // 85 + file.write((uint8_t *)&_prefs.gps_interval, sizeof(_prefs.gps_interval)); // 86 file.close(); } diff --git a/examples/companion_radio/MyMesh.cpp b/examples/companion_radio/MyMesh.cpp index 09d866c9..a94975b3 100644 --- a/examples/companion_radio/MyMesh.cpp +++ b/examples/companion_radio/MyMesh.cpp @@ -739,6 +739,8 @@ MyMesh::MyMesh(mesh::Radio &radio, mesh::RNG &rng, mesh::RTCClock &rtc, SimpleMe _prefs.bw = LORA_BW; _prefs.cr = LORA_CR; _prefs.tx_power_dbm = LORA_TX_POWER; + _prefs.gps_enabled = 0; // GPS disabled by default + _prefs.gps_interval = 0; // No automatic GPS updates by default //_prefs.rx_delay_base = 10.0f; enable once new algo fixed } @@ -776,6 +778,7 @@ void MyMesh::begin(bool has_display) { _prefs.sf = constrain(_prefs.sf, 5, 12); _prefs.cr = constrain(_prefs.cr, 5, 8); _prefs.tx_power_dbm = constrain(_prefs.tx_power_dbm, 1, MAX_LORA_TX_POWER); + _prefs.gps_enabled = constrain(_prefs.gps_enabled, 0, 1); // Ensure boolean 0 or 1 #ifdef BLE_PIN_CODE // 123456 by default if (_prefs.ble_pin == 0) { @@ -803,6 +806,10 @@ void MyMesh::begin(bool has_display) { radio_set_params(_prefs.freq, _prefs.bw, _prefs.sf, _prefs.cr); radio_set_tx_power(_prefs.tx_power_dbm); + +#if ENV_INCLUDE_GPS == 1 + sensors.setSettingValue("gps", _prefs.gps_enabled ? "1" : "0"); +#endif } const char *MyMesh::getNodeName() { diff --git a/examples/companion_radio/NodePrefs.h b/examples/companion_radio/NodePrefs.h index 13c9f884..e9db5444 100644 --- a/examples/companion_radio/NodePrefs.h +++ b/examples/companion_radio/NodePrefs.h @@ -25,4 +25,6 @@ struct NodePrefs { // persisted to file uint32_t ble_pin; uint8_t advert_loc_policy; uint8_t buzzer_quiet; + uint8_t gps_enabled; // GPS enabled flag (0=disabled, 1=enabled) + uint32_t gps_interval; // GPS read interval in seconds }; \ No newline at end of file diff --git a/examples/companion_radio/ui-new/UITask.cpp b/examples/companion_radio/ui-new/UITask.cpp index 59a1b2de..4cc47e23 100644 --- a/examples/companion_radio/ui-new/UITask.cpp +++ b/examples/companion_radio/ui-new/UITask.cpp @@ -863,13 +863,16 @@ void UITask::toggleGPS() { if (strcmp(_sensors->getSettingName(i), "gps") == 0) { if (strcmp(_sensors->getSettingValue(i), "1") == 0) { _sensors->setSettingValue("gps", "0"); + _node_prefs->gps_enabled = 0; notify(UIEventType::ack); showAlert("GPS: Disabled", 800); } else { _sensors->setSettingValue("gps", "1"); + _node_prefs->gps_enabled = 1; notify(UIEventType::ack); showAlert("GPS: Enabled", 800); } + the_mesh.savePrefs(); _next_refresh = 0; break; } From 88fb173297d667894df4b21faffab84ddea14d7a Mon Sep 17 00:00:00 2001 From: csrutil Date: Sat, 29 Nov 2025 17:20:02 +0800 Subject: [PATCH 2/8] add configurable GPS update interval Make GPS update interval configurable via settings instead of using hardcoded 1 second value. The interval is persisted from preferences and can be adjusted at runtime through the sensor manager settings interface --- examples/companion_radio/MyMesh.cpp | 3 +++ src/helpers/sensors/EnvironmentSensorManager.cpp | 11 ++++++++++- src/helpers/sensors/EnvironmentSensorManager.h | 1 + 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/examples/companion_radio/MyMesh.cpp b/examples/companion_radio/MyMesh.cpp index a94975b3..be39b7fa 100644 --- a/examples/companion_radio/MyMesh.cpp +++ b/examples/companion_radio/MyMesh.cpp @@ -809,6 +809,9 @@ void MyMesh::begin(bool has_display) { #if ENV_INCLUDE_GPS == 1 sensors.setSettingValue("gps", _prefs.gps_enabled ? "1" : "0"); + char interval_str[12]; // Max: 24 hours = 86400 seconds (5 digits + null) + sprintf(interval_str, "%u", _prefs.gps_interval); + sensors.setSettingValue("gps_interval", interval_str); #endif } diff --git a/src/helpers/sensors/EnvironmentSensorManager.cpp b/src/helpers/sensors/EnvironmentSensorManager.cpp index bb675c27..53c381f7 100644 --- a/src/helpers/sensors/EnvironmentSensorManager.cpp +++ b/src/helpers/sensors/EnvironmentSensorManager.cpp @@ -521,6 +521,15 @@ bool EnvironmentSensorManager::setSettingValue(const char* name, const char* val } return true; } + if (strcmp(name, "gps_interval") == 0) { + uint32_t interval_seconds = atoi(value); + if (interval_seconds > 0) { + gps_update_interval_ms = interval_seconds * 1000; + } else { + gps_update_interval_ms = 1000; // Default to 1 second if 0 + } + return true; + } #endif return false; // not supported } @@ -708,7 +717,7 @@ void EnvironmentSensorManager::loop() { } #endif } - next_gps_update = millis() + 1000; + next_gps_update = millis() + gps_update_interval_ms; } #endif } diff --git a/src/helpers/sensors/EnvironmentSensorManager.h b/src/helpers/sensors/EnvironmentSensorManager.h index 5f1c08e2..6dd532e6 100644 --- a/src/helpers/sensors/EnvironmentSensorManager.h +++ b/src/helpers/sensors/EnvironmentSensorManager.h @@ -25,6 +25,7 @@ protected: bool gps_detected = false; bool gps_active = false; + uint32_t gps_update_interval_ms = 1000; // Default 1 second #if ENV_INCLUDE_GPS LocationProvider* _location; From 678915ef3b6ad3e9bb398bfa797b5c6f832f73f5 Mon Sep 17 00:00:00 2001 From: csrutil Date: Sat, 29 Nov 2025 17:29:59 +0800 Subject: [PATCH 3/8] add GPS interval validation and bounds checking --- examples/companion_radio/MyMesh.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/examples/companion_radio/MyMesh.cpp b/examples/companion_radio/MyMesh.cpp index be39b7fa..91bb7358 100644 --- a/examples/companion_radio/MyMesh.cpp +++ b/examples/companion_radio/MyMesh.cpp @@ -779,6 +779,7 @@ void MyMesh::begin(bool has_display) { _prefs.cr = constrain(_prefs.cr, 5, 8); _prefs.tx_power_dbm = constrain(_prefs.tx_power_dbm, 1, MAX_LORA_TX_POWER); _prefs.gps_enabled = constrain(_prefs.gps_enabled, 0, 1); // Ensure boolean 0 or 1 + _prefs.gps_interval = constrain(_prefs.gps_interval, 0, 86400); // Max 24 hours #ifdef BLE_PIN_CODE // 123456 by default if (_prefs.ble_pin == 0) { @@ -809,9 +810,11 @@ void MyMesh::begin(bool has_display) { #if ENV_INCLUDE_GPS == 1 sensors.setSettingValue("gps", _prefs.gps_enabled ? "1" : "0"); - char interval_str[12]; // Max: 24 hours = 86400 seconds (5 digits + null) - sprintf(interval_str, "%u", _prefs.gps_interval); - sensors.setSettingValue("gps_interval", interval_str); + if (_prefs.gps_interval > 0) { + char interval_str[12]; // Max: 24 hours = 86400 seconds (5 digits + null) + sprintf(interval_str, "%u", _prefs.gps_interval); + sensors.setSettingValue("gps_interval", interval_str); + } #endif } From 4aebc57add0c61a37e31bcf18b8a7c5620539785 Mon Sep 17 00:00:00 2001 From: csrutil Date: Sat, 29 Nov 2025 18:02:08 +0800 Subject: [PATCH 4/8] fixed gps init value --- examples/companion_radio/MyMesh.cpp | 9 --------- examples/companion_radio/main.cpp | 10 ++++++++++ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/examples/companion_radio/MyMesh.cpp b/examples/companion_radio/MyMesh.cpp index 91bb7358..035e06a7 100644 --- a/examples/companion_radio/MyMesh.cpp +++ b/examples/companion_radio/MyMesh.cpp @@ -807,15 +807,6 @@ void MyMesh::begin(bool has_display) { radio_set_params(_prefs.freq, _prefs.bw, _prefs.sf, _prefs.cr); radio_set_tx_power(_prefs.tx_power_dbm); - -#if ENV_INCLUDE_GPS == 1 - sensors.setSettingValue("gps", _prefs.gps_enabled ? "1" : "0"); - if (_prefs.gps_interval > 0) { - char interval_str[12]; // Max: 24 hours = 86400 seconds (5 digits + null) - sprintf(interval_str, "%u", _prefs.gps_interval); - sensors.setSettingValue("gps_interval", interval_str); - } -#endif } const char *MyMesh::getNodeName() { diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index 82c8c21d..15b461f3 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -216,6 +216,16 @@ void setup() { sensors.begin(); +#if ENV_INCLUDE_GPS == 1 + // Apply GPS preferences after sensors.begin() so gps_detected is set + sensors.setSettingValue("gps", the_mesh.getNodePrefs()->gps_enabled ? "1" : "0"); + if (the_mesh.getNodePrefs()->gps_interval > 0) { + char interval_str[12]; + sprintf(interval_str, "%u", the_mesh.getNodePrefs()->gps_interval); + sensors.setSettingValue("gps_interval", interval_str); + } +#endif + #ifdef DISPLAY_CLASS ui_task.begin(disp, &sensors, the_mesh.getNodePrefs()); // still want to pass this in as dependency, as prefs might be moved #endif From 39503ad0b48515e527d38ff2bf477b207b5bd1b5 Mon Sep 17 00:00:00 2001 From: csrutil Date: Sat, 29 Nov 2025 18:35:10 +0800 Subject: [PATCH 5/8] move GPS preference initialization to UITask --- examples/companion_radio/main.cpp | 10 ---------- examples/companion_radio/ui-new/UITask.cpp | 13 +++++++++++++ 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index 15b461f3..82c8c21d 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -216,16 +216,6 @@ void setup() { sensors.begin(); -#if ENV_INCLUDE_GPS == 1 - // Apply GPS preferences after sensors.begin() so gps_detected is set - sensors.setSettingValue("gps", the_mesh.getNodePrefs()->gps_enabled ? "1" : "0"); - if (the_mesh.getNodePrefs()->gps_interval > 0) { - char interval_str[12]; - sprintf(interval_str, "%u", the_mesh.getNodePrefs()->gps_interval); - sensors.setSettingValue("gps_interval", interval_str); - } -#endif - #ifdef DISPLAY_CLASS ui_task.begin(disp, &sensors, the_mesh.getNodePrefs()); // still want to pass this in as dependency, as prefs might be moved #endif diff --git a/examples/companion_radio/ui-new/UITask.cpp b/examples/companion_radio/ui-new/UITask.cpp index 4cc47e23..ebdeb6d3 100644 --- a/examples/companion_radio/ui-new/UITask.cpp +++ b/examples/companion_radio/ui-new/UITask.cpp @@ -537,6 +537,19 @@ void UITask::begin(DisplayDriver* display, SensorManager* sensors, NodePrefs* no #endif _node_prefs = node_prefs; + +#if ENV_INCLUDE_GPS == 1 + // Apply GPS preferences from stored prefs + if (_sensors != NULL && _node_prefs != NULL) { + _sensors->setSettingValue("gps", _node_prefs->gps_enabled ? "1" : "0"); + if (_node_prefs->gps_interval > 0) { + char interval_str[12]; // Max: 24 hours = 86400 seconds (5 digits + null) + sprintf(interval_str, "%u", _node_prefs->gps_interval); + _sensors->setSettingValue("gps_interval", interval_str); + } + } +#endif + if (_display != NULL) { _display->turnOn(); } From 62e180dc0fa1b5af9e55308bc91d60ec1fc98ba8 Mon Sep 17 00:00:00 2001 From: csrutil Date: Sat, 29 Nov 2025 19:02:00 +0800 Subject: [PATCH 6/8] changed ms to sec --- src/helpers/sensors/EnvironmentSensorManager.cpp | 6 +++--- src/helpers/sensors/EnvironmentSensorManager.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/helpers/sensors/EnvironmentSensorManager.cpp b/src/helpers/sensors/EnvironmentSensorManager.cpp index 53c381f7..2362eda7 100644 --- a/src/helpers/sensors/EnvironmentSensorManager.cpp +++ b/src/helpers/sensors/EnvironmentSensorManager.cpp @@ -524,9 +524,9 @@ bool EnvironmentSensorManager::setSettingValue(const char* name, const char* val if (strcmp(name, "gps_interval") == 0) { uint32_t interval_seconds = atoi(value); if (interval_seconds > 0) { - gps_update_interval_ms = interval_seconds * 1000; + gps_update_interval_sec = interval_seconds; } else { - gps_update_interval_ms = 1000; // Default to 1 second if 0 + gps_update_interval_sec = 1; // Default to 1 second if 0 } return true; } @@ -717,7 +717,7 @@ void EnvironmentSensorManager::loop() { } #endif } - next_gps_update = millis() + gps_update_interval_ms; + next_gps_update = millis() + gps_update_interval_sec; } #endif } diff --git a/src/helpers/sensors/EnvironmentSensorManager.h b/src/helpers/sensors/EnvironmentSensorManager.h index 6dd532e6..f176a33f 100644 --- a/src/helpers/sensors/EnvironmentSensorManager.h +++ b/src/helpers/sensors/EnvironmentSensorManager.h @@ -25,7 +25,7 @@ protected: bool gps_detected = false; bool gps_active = false; - uint32_t gps_update_interval_ms = 1000; // Default 1 second + uint32_t gps_update_interval_sec = 1; // Default 1 second #if ENV_INCLUDE_GPS LocationProvider* _location; From df3cb3d192ab655b467ecb22e4fb41c3041c1673 Mon Sep 17 00:00:00 2001 From: csrutil Date: Sat, 29 Nov 2025 20:29:52 +0800 Subject: [PATCH 7/8] _location->loop() should be in the next tick --- src/helpers/sensors/EnvironmentSensorManager.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/helpers/sensors/EnvironmentSensorManager.cpp b/src/helpers/sensors/EnvironmentSensorManager.cpp index 2362eda7..b072bcb0 100644 --- a/src/helpers/sensors/EnvironmentSensorManager.cpp +++ b/src/helpers/sensors/EnvironmentSensorManager.cpp @@ -695,9 +695,9 @@ void EnvironmentSensorManager::loop() { static long next_gps_update = 0; #if ENV_INCLUDE_GPS - _location->loop(); - if (millis() > next_gps_update) { + _location->loop(); + if(gps_active){ #ifdef RAK_WISBLOCK_GPS if ((i2cGPSFlag || serialGPSFlag) && _location->isValid()) { @@ -717,7 +717,7 @@ void EnvironmentSensorManager::loop() { } #endif } - next_gps_update = millis() + gps_update_interval_sec; + next_gps_update = millis() + (gps_update_interval_sec * 1000); } #endif } From cfb7ed876ca7a424d7d1007ebb271aa08765e77b Mon Sep 17 00:00:00 2001 From: csrutil Date: Sun, 30 Nov 2025 09:45:56 +0800 Subject: [PATCH 8/8] CMD_SET_CUSTOM_VAR will update gps and gps_interval --- examples/companion_radio/MyMesh.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/examples/companion_radio/MyMesh.cpp b/examples/companion_radio/MyMesh.cpp index 035e06a7..3aed2da7 100644 --- a/examples/companion_radio/MyMesh.cpp +++ b/examples/companion_radio/MyMesh.cpp @@ -1525,6 +1525,17 @@ void MyMesh::handleCmdFrame(size_t len) { *np++ = 0; // modify 'cmd_frame', replace ':' with null bool success = sensors.setSettingValue(sp, np); if (success) { + #if ENV_INCLUDE_GPS == 1 + // Update node preferences for GPS settings + if (strcmp(sp, "gps") == 0) { + _prefs.gps_enabled = (np[0] == '1') ? 1 : 0; + savePrefs(); + } else if (strcmp(sp, "gps_interval") == 0) { + uint32_t interval_seconds = atoi(np); + _prefs.gps_interval = constrain(interval_seconds, 0, 86400); + savePrefs(); + } + #endif writeOKFrame(); } else { writeErrFrame(ERR_CODE_ILLEGAL_ARG);