From 1aa8ae90fb2545a3522fd9ced033c9c76a21c243 Mon Sep 17 00:00:00 2001 From: Kevin Le Date: Fri, 25 Sep 2026 22:37:04 +0700 Subject: [PATCH 1/6] GPS PowerSaving v2: Added GPS wake up upon telemtry requests for companions. Bug fixes for "gps" CLI. --- examples/companion_radio/MyMesh.cpp | 4 ++ examples/companion_radio/NodePrefs.h | 1 + examples/companion_radio/main.cpp | 10 ++++ examples/simple_repeater/MyMesh.h | 7 --- examples/simple_repeater/main.cpp | 7 +-- examples/simple_room_server/MyMesh.h | 7 --- examples/simple_room_server/main.cpp | 7 +-- examples/simple_sensor/SensorMesh.h | 9 +-- examples/simple_sensor/main.cpp | 13 +++-- src/helpers/CommonCLI.cpp | 54 ++++++++--------- src/helpers/SensorManager.h | 3 +- .../sensors/EnvironmentSensorManager.cpp | 57 +++++++++--------- src/helpers/sensors/LocationProvider.h | 29 ++++++++-- variants/heltec_mesh_solar/target.cpp | 56 ++++++++---------- variants/heltec_tracker/target.cpp | 56 ++++++++---------- variants/t1000-e/target.cpp | 58 ++++++++----------- 16 files changed, 177 insertions(+), 201 deletions(-) diff --git a/examples/companion_radio/MyMesh.cpp b/examples/companion_radio/MyMesh.cpp index da07e3594..49d62c113 100644 --- a/examples/companion_radio/MyMesh.cpp +++ b/examples/companion_radio/MyMesh.cpp @@ -926,6 +926,7 @@ MyMesh::MyMesh(mesh::Radio &radio, mesh::RNG &rng, mesh::RTCClock &rtc, SimpleMe _prefs.rx_boosted_gain = 1; // enabled by default #endif #endif + _prefs.powersaving_enabled = 1; // Power Saving enabled by default } void MyMesh::begin(bool has_display) { @@ -1689,6 +1690,9 @@ void MyMesh::handleCmdFrame(size_t len) { } // query other sensors -- target specific + if (sensors.getLocationProvider() != NULL && sensors.getLocationProvider()->isPowerSavingEnabled()) { + sensors.getLocationProvider()->syncTime(); // Request for GPS sync if GPS is in PowerSaving + } sensors.querySensors(0xFF, telemetry); int i = 0; diff --git a/examples/companion_radio/NodePrefs.h b/examples/companion_radio/NodePrefs.h index 21766de82..ace3258f1 100644 --- a/examples/companion_radio/NodePrefs.h +++ b/examples/companion_radio/NodePrefs.h @@ -40,6 +40,7 @@ public: uint8_t autoadd_max_hops = 0; // 0 = no limit, 1 = direct (0 hops), N = up to N-1 hops (max 64) char default_scope_name[31]; uint8_t default_scope_key[16]; + uint8_t powersaving_enabled = 0; // Power Saving private: class RadioPrefs : public ConfigSerializer { // COPIED from CommonCLI (for now) diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index 02103bf85..2c7560dbe 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -236,6 +236,16 @@ void setup() { #endif the_mesh.startInterface(interface_manager); + +#if ENV_INCLUDE_GPS == 1 + // Apply PowerSaving profile for GPS + if (sensors.getLocationProvider() != NULL) { + // GPS on and off duration in seconds + sensors.getLocationProvider()->setPowerSavingProfile(the_mesh.getNodePrefs()->powersaving_enabled, 600, + 1800); // Max 10 minutes, 30 minutes + } +#endif + sensors.begin(); #if ENV_INCLUDE_GPS == 1 diff --git a/examples/simple_repeater/MyMesh.h b/examples/simple_repeater/MyMesh.h index f1cff542b..521ea15f4 100644 --- a/examples/simple_repeater/MyMesh.h +++ b/examples/simple_repeater/MyMesh.h @@ -163,13 +163,6 @@ protected: #if ENV_INCLUDE_GPS == 1 void applyGpsPrefs() { - // If powersaving on, apply powersaving to sensors - if (_prefs.powersaving_enabled) { - sensors.powersaving_enabled = true; - } else { - sensors.powersaving_enabled = false; - } - sensors.setSettingValue("gps", _prefs.gps_enabled?"1":"0"); } #endif diff --git a/examples/simple_repeater/main.cpp b/examples/simple_repeater/main.cpp index 3a9c480a0..5e877ba4f 100644 --- a/examples/simple_repeater/main.cpp +++ b/examples/simple_repeater/main.cpp @@ -105,12 +105,9 @@ void setup() { #if ENV_INCLUDE_GPS == 1 // Apply PowerSaving profile for GPS if (sensors.getLocationProvider() != NULL) { - // Let CLI "gps on" call setSettingValue to enable the PowerSaving mode - // sensors.powersaving_enabled = true; - // sensors.getLocationProvider()->enablePowerSaving(true); - // GPS on and off duration in seconds - sensors.getLocationProvider()->setPowerSavingProfile(600, 86400); // Max 10 minutes, 1 day + sensors.getLocationProvider()->setPowerSavingProfile(the_mesh.getNodePrefs()->powersaving_enabled, 600, + 86400); // Max 10 minutes, 1 day } #endif diff --git a/examples/simple_room_server/MyMesh.h b/examples/simple_room_server/MyMesh.h index 62c31be2d..0af82bdb4 100644 --- a/examples/simple_room_server/MyMesh.h +++ b/examples/simple_room_server/MyMesh.h @@ -168,13 +168,6 @@ protected: #if ENV_INCLUDE_GPS == 1 void applyGpsPrefs() { - // If powersaving on, apply powersaving to sensors - if (_prefs.powersaving_enabled) { - sensors.powersaving_enabled = true; - } else { - sensors.powersaving_enabled = false; - } - sensors.setSettingValue("gps", _prefs.gps_enabled?"1":"0"); } #endif diff --git a/examples/simple_room_server/main.cpp b/examples/simple_room_server/main.cpp index efa5c8b82..bdc3ad5e8 100644 --- a/examples/simple_room_server/main.cpp +++ b/examples/simple_room_server/main.cpp @@ -89,12 +89,9 @@ void setup() { #if ENV_INCLUDE_GPS == 1 // Apply PowerSaving profile for GPS if (sensors.getLocationProvider() != NULL) { - // Let CLI "gps on" call setSettingValue to enable the PowerSaving mode - // sensors.powersaving_enabled = true; - // sensors.getLocationProvider()->enablePowerSaving(true); - // GPS on and off duration in seconds - sensors.getLocationProvider()->setPowerSavingProfile(600, 86400); // Max 10 minutes, 1 day + sensors.getLocationProvider()->setPowerSavingProfile(the_mesh.getNodePrefs()->powersaving_enabled, 600, + 86400); // Max 10 minutes, 1 day } #endif diff --git a/examples/simple_sensor/SensorMesh.h b/examples/simple_sensor/SensorMesh.h index 44ba497b4..79b6d48c9 100644 --- a/examples/simple_sensor/SensorMesh.h +++ b/examples/simple_sensor/SensorMesh.h @@ -162,15 +162,8 @@ private: void sendAlert(const ClientInfo* c, Trigger* t); - #if ENV_INCLUDE_GPS == 1 +#if ENV_INCLUDE_GPS == 1 void applyGpsPrefs() { - // If powersaving on, apply powersaving to sensors - if (_prefs.powersaving_enabled) { - sensors.powersaving_enabled = true; - } else { - sensors.powersaving_enabled = false; - } - sensors.setSettingValue("gps", _prefs.gps_enabled?"1":"0"); } #endif diff --git a/examples/simple_sensor/main.cpp b/examples/simple_sensor/main.cpp index 69ecbf2eb..72f36fcd4 100644 --- a/examples/simple_sensor/main.cpp +++ b/examples/simple_sensor/main.cpp @@ -65,6 +65,12 @@ void setup() { external_watchdog.begin(); #endif +#if defined(MESH_DEBUG) && defined(NRF52_PLATFORM) + // give some extra time for serial to settle so + // boot debug messages can be seen on terminal + delay(5000); +#endif + #ifdef DISPLAY_CLASS if (display.begin()) { display.startFrame(); @@ -112,12 +118,9 @@ void setup() { #if ENV_INCLUDE_GPS == 1 // Apply PowerSaving profile for GPS if (sensors.getLocationProvider() != NULL) { - // Let CLI "gps on" call setSettingValue to enable the PowerSaving mode - // sensors.powersaving_enabled = true; - // sensors.getLocationProvider()->enablePowerSaving(true); - // GPS on and off duration in seconds - sensors.getLocationProvider()->setPowerSavingProfile(600, 86400); // Max 10 minutes, 1 day + sensors.getLocationProvider()->setPowerSavingProfile(the_mesh.getNodePrefs()->powersaving_enabled, 600, + 86400); // Max 10 minutes, 1 day } #endif diff --git a/src/helpers/CommonCLI.cpp b/src/helpers/CommonCLI.cpp index fc6e38d7a..e0d282c4c 100644 --- a/src/helpers/CommonCLI.cpp +++ b/src/helpers/CommonCLI.cpp @@ -397,38 +397,41 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, char* command, char* re int sats = l->satellitesCount(); bool active = !strcmp(_sensors->getSettingByKey("gps") ?: "0", "1"); // Use "0" if GPS setting is not found - if (_prefs->powersaving_enabled && l->isPowerSavingEnabled()) { // GPS Power Saving - if (enabled) { - unsigned long mins = (l->getNextSleep() - millis()) / 60000UL; - sprintf(reply, "on (powersaving, sleep in %luh %lum), %s, %s, %d sats", - mins / 60UL, - mins % 60UL, - active ? "active" : "deactivated", - fix ? "fix" : "no fix", - sats); - } else { - unsigned long mins = (l->getNextWake() - millis()) / 60000UL; - sprintf(reply, "off (powersaving, wake in %luh %lum)", - mins / 60UL, - mins % 60UL); - } + if (l->isPowerSavingEnabled()) { // GPS Power Saving + if(active) { + if (enabled) { + unsigned long mins = (l->getNextSleep() - millis()) / 60000UL; + sprintf(reply, "on, powered (powersaving, sleep in %luh %lum), %s, %d sats", + mins / 60UL, + mins % 60UL, + fix ? "fix" : "no fix", + sats); + } else { + unsigned long mins = (l->getNextWake() - millis()) / 60000UL; + sprintf(reply, "on, unpowered (powersaving, wake in %luh %lum)", + mins / 60UL, + mins % 60UL); + } - // "last sync" from GPS - DateTime dt = DateTime(l->getLastValidTimeSync()); - if (dt.unixtime() == 0) { - sprintf(reply + strlen(reply), ", last sync: none"); + // "last sync" from GPS + DateTime dt = DateTime(l->getLastValidTimeSync()); + if (dt.unixtime() == 0) { + sprintf(reply + strlen(reply), ", last sync: none"); + } else { + sprintf(reply + strlen(reply), ", last sync: %02d:%02d - %d/%d/%d UTC", dt.hour(), dt.minute(), + dt.day(), dt.month(), dt.year()); + } } else { - sprintf(reply + strlen(reply), ", last sync: %02d:%02d - %d/%d/%d UTC", dt.hour(), dt.minute(), - dt.day(), dt.month(), dt.year()); + sprintf(reply, "off, %s", enabled ? "powered" : "unpowered"); } } else { // Normal mode - if (enabled) { + if(active) { sprintf(reply, "on, %s, %s, %d sats", - active?"active":"deactivated", + enabled?"powered":"unpowered", fix?"fix":"no fix", sats); } else { - strcpy(reply, "off"); + sprintf(reply, "off, %s", enabled ? "powered" : "unpowered"); } } } else { @@ -438,12 +441,10 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, char* command, char* re } else if (memcmp(command, "powersaving on", 14) == 0) { #if defined(NRF52_PLATFORM) _prefs->powersaving_enabled = 1; - _sensors->powersaving_enabled = 1; savePrefs(); strcpy(reply, "on - Immediate effect"); #elif defined(ESP32) && !defined(WITH_BRIDGE) _prefs->powersaving_enabled = 1; - _sensors->powersaving_enabled = 1; savePrefs(); strcpy(reply, "on - After 2 minutes"); #elif defined(WITH_BRIDGE) @@ -453,7 +454,6 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, char* command, char* re #endif } else if (memcmp(command, "powersaving off", 15) == 0) { _prefs->powersaving_enabled = 0; - _sensors->powersaving_enabled = 0; savePrefs(); strcpy(reply, "off"); } else if (memcmp(command, "powersaving", 11) == 0) { diff --git a/src/helpers/SensorManager.h b/src/helpers/SensorManager.h index 2031bbc52..89a174c22 100644 --- a/src/helpers/SensorManager.h +++ b/src/helpers/SensorManager.h @@ -13,9 +13,8 @@ class SensorManager { public: double node_lat, node_lon; // modify these, if you want to affect Advert location double node_altitude; // altitude in meters - bool powersaving_enabled; // powersaving mode - SensorManager() { node_lat = 0; node_lon = 0; node_altitude = 0; powersaving_enabled = false; } + SensorManager() { node_lat = 0; node_lon = 0; node_altitude = 0; } virtual bool begin() { return false; } virtual bool querySensors(uint8_t requester_permissions, CayenneLPP& telemetry) { return false; } virtual void loop() { } diff --git a/src/helpers/sensors/EnvironmentSensorManager.cpp b/src/helpers/sensors/EnvironmentSensorManager.cpp index 48f56d2d3..0981a8a2f 100644 --- a/src/helpers/sensors/EnvironmentSensorManager.cpp +++ b/src/helpers/sensors/EnvironmentSensorManager.cpp @@ -740,16 +740,10 @@ bool EnvironmentSensorManager::setSettingValue(const char* name, const char* val #if ENV_INCLUDE_GPS if (gps_detected && strcmp(name, "gps") == 0) { if (strcmp(value, "0") == 0) { - if (powersaving_enabled) { - _location->enablePowerSaving(false); - } - + gps_active = false; // Disabled by CLI or App stop_gps(); } else { - if (powersaving_enabled) { - _location->enablePowerSaving(true); - } - + gps_active = true; // Enabled by CLI or App start_gps(); } return true; @@ -889,10 +883,12 @@ bool EnvironmentSensorManager::gpsIsAwake(uint8_t ioPin) { void EnvironmentSensorManager::start_gps() { gps_active = true; - if (powersaving_enabled && _location->isPowerSavingEnabled()) { + if (_location->isPowerSavingEnabled()) { gps_wake = true; // gps_active is true _location->syncTime(); // Clear GPS data and force sync time _location->setNextSleep(); // Next time to off + } else { + gps_wake = true; } #ifdef RAK_WISBLOCK_GPS @@ -915,13 +911,13 @@ void EnvironmentSensorManager::start_gps() { } void EnvironmentSensorManager::stop_gps() { - if (powersaving_enabled && _location->isPowerSavingEnabled()) { - gps_wake = false; // gps_active is unchanged (true) even the GPS sleep (e.g: off) + if (_location->isPowerSavingEnabled()) { + gps_wake = false; // gps_active is unchanged (true for GPS sleep, false for GPS off) _location->stopTimeSync(); // Stop time sync _location->setNextWake(); // Next time to on } else { gps_active = false; - gps_wake = false; // When GPS is off, wake is false to be sure + gps_wake = false; } #ifdef RAK_WISBLOCK_GPS @@ -950,36 +946,35 @@ void EnvironmentSensorManager::loop() { static long next_gps_update = 0; // PowerSaving - if (powersaving_enabled) { - if (gps_detected && _location->isPowerSavingEnabled()) { - if (gps_wake && ((int32_t)(millis() - _location->getNextSleep()) >= 0 || - !_location->waitingTimeSync())) { // Time to off or GPS set - if ((int32_t)(millis() - _location->getNextSleep()) >= 0) { - POWERSAVING_DEBUG_PRINTLN("GPS wake timeout. Enter sleep"); - } - else if (!_location->waitingTimeSync()) { - POWERSAVING_DEBUG_PRINTLN("GPS set. Enter sleep early"); - } - + _location->updatePowerSavingSettings(gps_wake); // Handle change in PowerSaving mode + if (_location->isPowerSavingEnabled() && gps_detected) { + if (gps_wake) { + // GPS is awake: check whether it should sleep + if ((int32_t)(millis() - _location->getNextSleep()) >= 0) { + POWERSAVING_DEBUG_PRINTLN("GPS wake timeout. Enter sleep"); stop_gps(); - } else if (!gps_wake && ((int32_t)(millis() - _location->getNextWake()) >= 0)) { // Time to on + } else if (!_location->waitingTimeSync()) { + POWERSAVING_DEBUG_PRINTLN("GPS set. Enter sleep early"); + stop_gps(); + } + } else { + // GPS is asleep: check whether it should wake + if ((int32_t)(millis() - _location->getNextWake()) >= 0) { POWERSAVING_DEBUG_PRINTLN("GPS sleep timeout. Wakeup."); - start_gps(); - } else if (!gps_wake && _location->waitingTimeSync()) { // On for "gps sync" + } else if (_location->waitingTimeSync()) { POWERSAVING_DEBUG_PRINTLN("CLI gps sync. Wakeup"); - start_gps(); } } } - if ((!powersaving_enabled && gps_active) || (powersaving_enabled && gps_wake)) { + if ((!_location->isPowerSavingEnabled() && gps_active) || (_location->isPowerSavingEnabled() && gps_wake)) { _location->loop(); } if ((int32_t)(millis() - next_gps_update) >= 0) { - if((!powersaving_enabled && gps_active) || (powersaving_enabled && gps_wake)){ + if((!_location->isPowerSavingEnabled() && gps_active) || (_location->isPowerSavingEnabled() && gps_wake)){ #ifdef RAK_WISBLOCK_GPS if ((i2cGPSFlag || serialGPSFlag) && _location->isValid()) { node_lat = ((double)_location->getLatitude())/1000000.; @@ -999,10 +994,10 @@ void EnvironmentSensorManager::loop() { #endif // In powersaving mode, GPS is on and off. Only update data when GPS is on - if(powersaving_enabled) next_gps_update = millis() + (gps_update_interval_sec * 1000); + if(_location->isPowerSavingEnabled()) next_gps_update = millis() + (gps_update_interval_sec * 1000); } - if(!powersaving_enabled) next_gps_update = millis() + (gps_update_interval_sec * 1000); + if(!_location->isPowerSavingEnabled()) next_gps_update = millis() + (gps_update_interval_sec * 1000); } #endif #if ENV_INCLUDE_BME680_BSEC diff --git a/src/helpers/sensors/LocationProvider.h b/src/helpers/sensors/LocationProvider.h index c9204373e..05fadc44e 100644 --- a/src/helpers/sensors/LocationProvider.h +++ b/src/helpers/sensors/LocationProvider.h @@ -7,7 +7,8 @@ class LocationProvider { protected: bool _time_sync_needed = true; - bool powersaving_enabled = false; + uint8_t* powersaving_enabled = nullptr; + bool _powersaving_enabled_prev = false; // Track previous PowerSaving state unsigned long _wake_duration_secs = 86400; // Full day unsigned long _sleep_duration_secs = 0; // No off unsigned long _next_wake = 0; @@ -19,13 +20,33 @@ public: virtual bool waitingTimeSync() { return _time_sync_needed; } virtual void stopTimeSync() { _time_sync_needed = false; } - virtual void setPowerSavingProfile(unsigned long wake_duration_secs, unsigned long sleep_duration_secs) { + virtual void setPowerSavingProfile(uint8_t &enabled, unsigned long wake_duration_secs, + unsigned long sleep_duration_secs) { + powersaving_enabled = &enabled; _wake_duration_secs = wake_duration_secs; _sleep_duration_secs = sleep_duration_secs; } - virtual void enablePowerSaving(bool enabled) { powersaving_enabled = enabled; _next_wake = 0; _next_sleep = 0; } - virtual bool isPowerSavingEnabled() { return powersaving_enabled; } + virtual bool isPowerSavingEnabled() const { + return powersaving_enabled != nullptr && *powersaving_enabled != 0; + } + + virtual void updatePowerSavingSettings(bool gps_wake) { + bool powersaving_enabled = isPowerSavingEnabled(); + + // PowerSaving changed from OFF to ON + if (!_powersaving_enabled_prev && powersaving_enabled) { + if (gps_wake) { + syncTime(); // Wake when powersaving on + setNextSleep(); // On, set next sleep + } else { + setNextWake(); // Off, set next wake + } + } + + _powersaving_enabled_prev = powersaving_enabled; + } + virtual void setNextWake() { _next_wake = millis() + _sleep_duration_secs * 1000UL; } virtual unsigned long getNextWake() { return _next_wake; } virtual void setNextSleep() { _next_sleep = millis() + _wake_duration_secs * 1000UL; } diff --git a/variants/heltec_mesh_solar/target.cpp b/variants/heltec_mesh_solar/target.cpp index 28442334d..e85a62be5 100644 --- a/variants/heltec_mesh_solar/target.cpp +++ b/variants/heltec_mesh_solar/target.cpp @@ -33,7 +33,7 @@ void SolarSensorManager::start_gps() { if (!gps_active) { gps_active = true; - if (powersaving_enabled && _location->isPowerSavingEnabled()) { + if (_location->isPowerSavingEnabled()) { gps_wake = true; // gps_active is true _location->syncTime(); // Clear GPS data and force sync time _location->setNextSleep(); // Next time to off @@ -45,7 +45,7 @@ void SolarSensorManager::start_gps() { void SolarSensorManager::stop_gps() { if (gps_active) { - if (powersaving_enabled && _location->isPowerSavingEnabled()) { + if (_location->isPowerSavingEnabled()) { gps_wake = false; // gps_active is unchanged (true) even the GPS sleep (e.g: off) _location->stopTimeSync(); // Stop time sync _location->setNextWake(); // Next time to on @@ -84,35 +84,33 @@ void SolarSensorManager::loop() { static long next_gps_update = 0; // PowerSaving - if (powersaving_enabled) { - if (gps_detected && _location->isPowerSavingEnabled()) { - if (gps_wake && ((int32_t)(millis() - _location->getNextSleep()) >= 0 || - !_location->waitingTimeSync())) { // Time to off or GPS set - if ((int32_t)(millis() - _location->getNextSleep()) >= 0) { - POWERSAVING_DEBUG_PRINTLN("GPS wake timeout. Enter sleep"); - } else if (!_location->waitingTimeSync()) { - POWERSAVING_DEBUG_PRINTLN("GPS set. Enter sleep early"); - } - - stop_gps(); - } else if (!gps_wake && ((int32_t)(millis() - _location->getNextWake()) >= 0)) { // Time to on - POWERSAVING_DEBUG_PRINTLN("GPS sleep timeout. Wakeup."); - - start_gps(); - } else if (!gps_wake && _location->waitingTimeSync()) { // On for "gps sync" - POWERSAVING_DEBUG_PRINTLN("CLI gps sync. Wakeup"); - - start_gps(); + if (_location->isPowerSavingEnabled() && gps_detected) { + if (gps_wake && ((int32_t)(millis() - _location->getNextSleep()) >= 0 || + !_location->waitingTimeSync())) { // Time to off or GPS set + if ((int32_t)(millis() - _location->getNextSleep()) >= 0) { + POWERSAVING_DEBUG_PRINTLN("GPS wake timeout. Enter sleep"); + } else if (!_location->waitingTimeSync()) { + POWERSAVING_DEBUG_PRINTLN("GPS set. Enter sleep early"); } + + stop_gps(); + } else if (!gps_wake && ((int32_t)(millis() - _location->getNextWake()) >= 0)) { // Time to on + POWERSAVING_DEBUG_PRINTLN("GPS sleep timeout. Wakeup."); + + start_gps(); + } else if (!gps_wake && _location->waitingTimeSync()) { // On for "gps sync" + POWERSAVING_DEBUG_PRINTLN("CLI gps sync. Wakeup"); + + start_gps(); } } - if ((!powersaving_enabled && gps_active) || (powersaving_enabled && gps_wake)) { + if ((!_location->isPowerSavingEnabled() && gps_active) || (_location->isPowerSavingEnabled() && gps_wake)) { _location->loop(); } if ((int32_t)(millis() - next_gps_update) >= 0) { - if ((!powersaving_enabled && gps_active) || (powersaving_enabled && gps_wake)) { + if ((!_location->isPowerSavingEnabled() && gps_active) || (_location->isPowerSavingEnabled() && gps_wake)) { if (_location->isValid()) { node_lat = ((double)_location->getLatitude()) / 1000000.; node_lon = ((double)_location->getLongitude()) / 1000000.; @@ -122,10 +120,10 @@ void SolarSensorManager::loop() { } // In powersaving mode, GPS is on and off. Only update data when GPS is on - if (powersaving_enabled) next_gps_update = millis() + 1000; + if (_location->isPowerSavingEnabled()) next_gps_update = millis() + 1000; } - if (!powersaving_enabled) next_gps_update = millis() + 1000; + if (!_location->isPowerSavingEnabled()) next_gps_update = millis() + 1000; } } @@ -147,16 +145,8 @@ const char* SolarSensorManager::getSettingValue(int i) const { bool SolarSensorManager::setSettingValue(const char* name, const char* value) { if (gps_detected && strcmp(name, "gps") == 0) { if (strcmp(value, "0") == 0) { - if (powersaving_enabled) { - _location->enablePowerSaving(false); - } - stop_gps(); } else { - if (powersaving_enabled) { - _location->enablePowerSaving(true); - } - start_gps(); } return true; diff --git a/variants/heltec_tracker/target.cpp b/variants/heltec_tracker/target.cpp index 9bc5ab7cd..ab1b391ed 100644 --- a/variants/heltec_tracker/target.cpp +++ b/variants/heltec_tracker/target.cpp @@ -47,7 +47,7 @@ void HWTSensorManager::start_gps() { _location->begin(); // Claims periph_power via RefCountedDigitalPin gps_active = true; - if (powersaving_enabled && _location->isPowerSavingEnabled()) { + if (_location->isPowerSavingEnabled()) { gps_wake = true; // gps_active is true _location->syncTime(); // Clear GPS data and force sync time _location->setNextSleep(); // Next time to off @@ -59,7 +59,7 @@ void HWTSensorManager::start_gps() { void HWTSensorManager::stop_gps() { if (gps_active) { - if (powersaving_enabled && _location->isPowerSavingEnabled()) { + if (_location->isPowerSavingEnabled()) { gps_wake = false; // gps_active is unchanged (true) even the GPS sleep (e.g: off) _location->stopTimeSync(); // Stop time sync _location->setNextWake(); // Next time to on @@ -89,35 +89,33 @@ void HWTSensorManager::loop() { static long next_gps_update = 0; // PowerSaving - if (powersaving_enabled) { - if (_location->isPowerSavingEnabled()) { - if (gps_wake && ((int32_t)(millis() - _location->getNextSleep()) >= 0 || - !_location->waitingTimeSync())) { // Time to off or GPS set - if ((int32_t)(millis() - _location->getNextSleep()) >= 0) { - POWERSAVING_DEBUG_PRINTLN("GPS wake timeout. Enter sleep"); - } else if (!_location->waitingTimeSync()) { - POWERSAVING_DEBUG_PRINTLN("GPS set. Enter sleep early"); - } - - stop_gps(); - } else if (!gps_wake && ((int32_t)(millis() - _location->getNextWake()) >= 0)) { // Time to on - POWERSAVING_DEBUG_PRINTLN("GPS sleep timeout. Wakeup."); - - start_gps(); - } else if (!gps_wake && _location->waitingTimeSync()) { // On for "gps sync" - POWERSAVING_DEBUG_PRINTLN("CLI gps sync. Wakeup"); - - start_gps(); + if (_location->isPowerSavingEnabled()) { + if (gps_wake && ((int32_t)(millis() - _location->getNextSleep()) >= 0 || + !_location->waitingTimeSync())) { // Time to off or GPS set + if ((int32_t)(millis() - _location->getNextSleep()) >= 0) { + POWERSAVING_DEBUG_PRINTLN("GPS wake timeout. Enter sleep"); + } else if (!_location->waitingTimeSync()) { + POWERSAVING_DEBUG_PRINTLN("GPS set. Enter sleep early"); } + + stop_gps(); + } else if (!gps_wake && ((int32_t)(millis() - _location->getNextWake()) >= 0)) { // Time to on + POWERSAVING_DEBUG_PRINTLN("GPS sleep timeout. Wakeup."); + + start_gps(); + } else if (!gps_wake && _location->waitingTimeSync()) { // On for "gps sync" + POWERSAVING_DEBUG_PRINTLN("CLI gps sync. Wakeup"); + + start_gps(); } } - if ((!powersaving_enabled && gps_active) || (powersaving_enabled && gps_wake)) { + if ((!_location->isPowerSavingEnabled() && gps_active) || (_location->isPowerSavingEnabled() && gps_wake)) { _location->loop(); } if ((int32_t)(millis() - next_gps_update) >= 0) { - if ((!powersaving_enabled && gps_active) || (powersaving_enabled && gps_wake)) { + if ((!_location->isPowerSavingEnabled() && gps_active) || (_location->isPowerSavingEnabled() && gps_wake)) { if (_location->isValid()) { node_lat = ((double)_location->getLatitude()) / 1000000.; node_lon = ((double)_location->getLongitude()) / 1000000.; @@ -126,10 +124,10 @@ void HWTSensorManager::loop() { } // In powersaving mode, GPS is on and off. Only update data when GPS is on - if (powersaving_enabled) next_gps_update = millis() + 1000; + if (_location->isPowerSavingEnabled()) next_gps_update = millis() + 1000; } - if (!powersaving_enabled) next_gps_update = millis() + 1000; + if (!_location->isPowerSavingEnabled()) next_gps_update = millis() + 1000; } } @@ -147,16 +145,8 @@ const char* HWTSensorManager::getSettingValue(int i) const { bool HWTSensorManager::setSettingValue(const char* name, const char* value) { if (strcmp(name, "gps") == 0) { if (strcmp(value, "0") == 0) { - if (powersaving_enabled) { - _location->enablePowerSaving(false); - } - stop_gps(); } else { - if (powersaving_enabled) { - _location->enablePowerSaving(true); - } - start_gps(); } return true; diff --git a/variants/t1000-e/target.cpp b/variants/t1000-e/target.cpp index 99c9be29a..9b151bc48 100644 --- a/variants/t1000-e/target.cpp +++ b/variants/t1000-e/target.cpp @@ -82,7 +82,7 @@ mesh::LocalIdentity radio_new_identity() { void T1000SensorManager::start_gps() { gps_active = true; - if (powersaving_enabled && _nmea->isPowerSavingEnabled()) { + if (_nmea->isPowerSavingEnabled()) { gps_wake = true; // gps_active is true _nmea->syncTime(); // Clear GPS data and force sync time _nmea->setNextSleep(); // Next time to off @@ -111,7 +111,7 @@ void T1000SensorManager::start_gps() { } void T1000SensorManager::sleep_gps() { - if (powersaving_enabled && _nmea->isPowerSavingEnabled()) { + if (_nmea->isPowerSavingEnabled()) { gps_wake = false; // gps_active is unchanged (true) even the GPS sleep (e.g: off) _nmea->stopTimeSync(); // Stop time sync _nmea->setNextWake(); // Next time to on @@ -131,7 +131,7 @@ void T1000SensorManager::sleep_gps() { } void T1000SensorManager::stop_gps() { - if (powersaving_enabled && _nmea->isPowerSavingEnabled()) { + if (_nmea->isPowerSavingEnabled()) { gps_wake = false; // gps_active is unchanged (true) even the GPS sleep (e.g: off) _nmea->stopTimeSync(); // Stop time sync _nmea->setNextWake(); // Next time to on @@ -173,35 +173,33 @@ void T1000SensorManager::loop() { static long next_gps_update = 0; // PowerSaving - if (powersaving_enabled) { - if (_nmea->isPowerSavingEnabled()) { - if (gps_wake && ((int32_t)(millis() - _nmea->getNextSleep()) >= 0 || - !_nmea->waitingTimeSync())) { // Time to off or GPS set - if ((int32_t)(millis() - _nmea->getNextSleep()) >= 0) { - POWERSAVING_DEBUG_PRINTLN("GPS wake timeout. Enter sleep"); - } else if (!_nmea->waitingTimeSync()) { - POWERSAVING_DEBUG_PRINTLN("GPS set. Enter sleep early"); - } - - stop_gps(); - } else if (!gps_wake && ((int32_t)(millis() - _nmea->getNextWake()) >= 0)) { // Time to on - POWERSAVING_DEBUG_PRINTLN("GPS sleep timeout. Wakeup."); - - start_gps(); - } else if (!gps_wake && _nmea->waitingTimeSync()) { // On for "gps sync" - POWERSAVING_DEBUG_PRINTLN("CLI gps sync. Wakeup"); - - start_gps(); + if (_nmea->isPowerSavingEnabled()) { + if (gps_wake && ((int32_t)(millis() - _nmea->getNextSleep()) >= 0 || + !_nmea->waitingTimeSync())) { // Time to off or GPS set + if ((int32_t)(millis() - _nmea->getNextSleep()) >= 0) { + POWERSAVING_DEBUG_PRINTLN("GPS wake timeout. Enter sleep"); + } else if (!_nmea->waitingTimeSync()) { + POWERSAVING_DEBUG_PRINTLN("GPS set. Enter sleep early"); } + + stop_gps(); + } else if (!gps_wake && ((int32_t)(millis() - _nmea->getNextWake()) >= 0)) { // Time to on + POWERSAVING_DEBUG_PRINTLN("GPS sleep timeout. Wakeup."); + + start_gps(); + } else if (!gps_wake && _nmea->waitingTimeSync()) { // On for "gps sync" + POWERSAVING_DEBUG_PRINTLN("CLI gps sync. Wakeup"); + + start_gps(); } } - if ((!powersaving_enabled && gps_active) || (powersaving_enabled && gps_wake)) { + if ((!_nmea->isPowerSavingEnabled() && gps_active) || (_nmea->isPowerSavingEnabled() && gps_wake)) { _nmea->loop(); } if ((int32_t)(millis() - next_gps_update) >= 0) { - if ((!powersaving_enabled && gps_active) || (powersaving_enabled && gps_wake)) { + if ((!_nmea->isPowerSavingEnabled() && gps_active) || (_nmea->isPowerSavingEnabled() && gps_wake)) { if (_nmea->isValid()) { node_lat = ((double)_nmea->getLatitude()) / 1000000.; node_lon = ((double)_nmea->getLongitude()) / 1000000.; @@ -211,10 +209,10 @@ void T1000SensorManager::loop() { } // In powersaving mode, GPS is on and off. Only update data when GPS is on - if (powersaving_enabled) next_gps_update = millis() + 1000; + if (_nmea->isPowerSavingEnabled()) next_gps_update = millis() + 1000; } - if (!powersaving_enabled) next_gps_update = millis() + 1000; + if (!_nmea->isPowerSavingEnabled()) next_gps_update = millis() + 1000; } } @@ -232,16 +230,8 @@ const char* T1000SensorManager::getSettingValue(int i) const { bool T1000SensorManager::setSettingValue(const char* name, const char* value) { if (strcmp(name, "gps") == 0) { if (strcmp(value, "0") == 0) { - if (powersaving_enabled) { - _nmea->enablePowerSaving(false); - } - sleep_gps(); // sleep for faster fix ! } else { - if (powersaving_enabled) { - _nmea->enablePowerSaving(true); - } - start_gps(); } return true; From 95d63736d40a7acfbbdd322ef93899c18f5aa742 Mon Sep 17 00:00:00 2001 From: Kevin Le Date: Sat, 26 Sep 2026 19:31:22 +0700 Subject: [PATCH 2/6] Use sleep_gps for T1000e for faster GPS lock --- variants/t1000-e/target.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/variants/t1000-e/target.cpp b/variants/t1000-e/target.cpp index 9b151bc48..67f4d85a0 100644 --- a/variants/t1000-e/target.cpp +++ b/variants/t1000-e/target.cpp @@ -182,7 +182,7 @@ void T1000SensorManager::loop() { POWERSAVING_DEBUG_PRINTLN("GPS set. Enter sleep early"); } - stop_gps(); + sleep_gps(); } else if (!gps_wake && ((int32_t)(millis() - _nmea->getNextWake()) >= 0)) { // Time to on POWERSAVING_DEBUG_PRINTLN("GPS sleep timeout. Wakeup."); From 186cde1a209cf46b7f267d7aa54412ebb767fa91 Mon Sep 17 00:00:00 2001 From: Kevin Le Date: Sun, 27 Sep 2026 15:46:07 +0700 Subject: [PATCH 3/6] GPS on upon telemetry request only if GPS is active --- src/helpers/sensors/EnvironmentSensorManager.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/helpers/sensors/EnvironmentSensorManager.cpp b/src/helpers/sensors/EnvironmentSensorManager.cpp index 0981a8a2f..9fade5638 100644 --- a/src/helpers/sensors/EnvironmentSensorManager.cpp +++ b/src/helpers/sensors/EnvironmentSensorManager.cpp @@ -881,13 +881,12 @@ bool EnvironmentSensorManager::gpsIsAwake(uint8_t ioPin) { #endif void EnvironmentSensorManager::start_gps() { - gps_active = true; - if (_location->isPowerSavingEnabled()) { - gps_wake = true; // gps_active is true + gps_wake = true; // gps_active is unchanged (true for GPS sleep, false for GPS off) _location->syncTime(); // Clear GPS data and force sync time _location->setNextSleep(); // Next time to off } else { + gps_active = true; gps_wake = true; } @@ -946,8 +945,10 @@ void EnvironmentSensorManager::loop() { static long next_gps_update = 0; // PowerSaving - _location->updatePowerSavingSettings(gps_wake); // Handle change in PowerSaving mode - if (_location->isPowerSavingEnabled() && gps_detected) { + if (_location->isPowerSavingEnabled() && gps_detected && gps_active) { + // Handle change in PowerSaving mode + _location->updatePowerSavingSettings(gps_wake); + if (gps_wake) { // GPS is awake: check whether it should sleep if ((int32_t)(millis() - _location->getNextSleep()) >= 0) { From f00424bdb92388b470af9a2690ca57fc6e440a56 Mon Sep 17 00:00:00 2001 From: Kevin Le Date: Sun, 27 Sep 2026 18:27:43 +0700 Subject: [PATCH 4/6] GPS PowerSaving v2 for T1000e --- variants/t1000-e/platformio.ini | 1 + variants/t1000-e/target.cpp | 37 +++++++++++++++++++-------------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/variants/t1000-e/platformio.ini b/variants/t1000-e/platformio.ini index aa0fd97d0..42dff1aae 100644 --- a/variants/t1000-e/platformio.ini +++ b/variants/t1000-e/platformio.ini @@ -140,6 +140,7 @@ build_flags = ${t1000-e.build_flags} -D MAX_NEIGHBOURS=50 ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 +; -D POWERSAVING_DEBUG=1 build_src_filter = ${t1000-e.build_src_filter} +<../examples/simple_sensor> lib_deps = ${t1000-e.lib_deps} diff --git a/variants/t1000-e/target.cpp b/variants/t1000-e/target.cpp index 67f4d85a0..3d32fffb2 100644 --- a/variants/t1000-e/target.cpp +++ b/variants/t1000-e/target.cpp @@ -80,12 +80,13 @@ mesh::LocalIdentity radio_new_identity() { } void T1000SensorManager::start_gps() { - gps_active = true; - if (_nmea->isPowerSavingEnabled()) { - gps_wake = true; // gps_active is true + gps_wake = true; // gps_active is unchanged (true for GPS sleep, false for GPS off) _nmea->syncTime(); // Clear GPS data and force sync time _nmea->setNextSleep(); // Next time to off + } else { + gps_active = true; + gps_wake = true; } //_nmea->begin(); @@ -173,24 +174,28 @@ void T1000SensorManager::loop() { static long next_gps_update = 0; // PowerSaving - if (_nmea->isPowerSavingEnabled()) { - if (gps_wake && ((int32_t)(millis() - _nmea->getNextSleep()) >= 0 || - !_nmea->waitingTimeSync())) { // Time to off or GPS set + if (_nmea->isPowerSavingEnabled() && gps_active) { + // Handle change in PowerSaving mode + _nmea->updatePowerSavingSettings(gps_wake); + + if (gps_wake) { + // GPS is awake: check whether it should sleep if ((int32_t)(millis() - _nmea->getNextSleep()) >= 0) { POWERSAVING_DEBUG_PRINTLN("GPS wake timeout. Enter sleep"); + sleep_gps(); } else if (!_nmea->waitingTimeSync()) { POWERSAVING_DEBUG_PRINTLN("GPS set. Enter sleep early"); + sleep_gps(); + } + } else { + // GPS is asleep: check whether it should wake + if ((int32_t)(millis() - _nmea->getNextWake()) >= 0) { + POWERSAVING_DEBUG_PRINTLN("GPS sleep timeout. Wakeup."); + start_gps(); + } else if (_nmea->waitingTimeSync()) { + POWERSAVING_DEBUG_PRINTLN("CLI gps sync. Wakeup"); + start_gps(); } - - sleep_gps(); - } else if (!gps_wake && ((int32_t)(millis() - _nmea->getNextWake()) >= 0)) { // Time to on - POWERSAVING_DEBUG_PRINTLN("GPS sleep timeout. Wakeup."); - - start_gps(); - } else if (!gps_wake && _nmea->waitingTimeSync()) { // On for "gps sync" - POWERSAVING_DEBUG_PRINTLN("CLI gps sync. Wakeup"); - - start_gps(); } } From b049177b81ba65b0de87b0e336fc26294da12f04 Mon Sep 17 00:00:00 2001 From: Kevin Le Date: Sun, 27 Sep 2026 19:21:29 +0700 Subject: [PATCH 5/6] Fixed for GPS PowerSaving v2 on T1000e --- variants/t1000-e/target.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/variants/t1000-e/target.cpp b/variants/t1000-e/target.cpp index 3d32fffb2..2cfec93b7 100644 --- a/variants/t1000-e/target.cpp +++ b/variants/t1000-e/target.cpp @@ -235,8 +235,10 @@ const char* T1000SensorManager::getSettingValue(int i) const { bool T1000SensorManager::setSettingValue(const char* name, const char* value) { if (strcmp(name, "gps") == 0) { if (strcmp(value, "0") == 0) { + gps_active = false; // Disabled by CLI or App sleep_gps(); // sleep for faster fix ! } else { + gps_active = true; // Enabled by CLI or App start_gps(); } return true; From a27e78e4da1389055b6dd16ce473112d25c8a5cd Mon Sep 17 00:00:00 2001 From: Kevin Le Date: Sun, 27 Sep 2026 23:33:01 +0700 Subject: [PATCH 6/6] Added GPS PowerSaving v2 for some boards --- variants/heltec_mesh_solar/target.cpp | 39 +++++++------ variants/heltec_tracker/target.cpp | 38 +++++++----- variants/meshtracker_x1/target.cpp | 83 +++++++++++++++++++++++---- variants/meshtracker_x1/target.h | 1 + variants/t1000-e/target.cpp | 4 +- 5 files changed, 121 insertions(+), 44 deletions(-) diff --git a/variants/heltec_mesh_solar/target.cpp b/variants/heltec_mesh_solar/target.cpp index e85a62be5..aef713f30 100644 --- a/variants/heltec_mesh_solar/target.cpp +++ b/variants/heltec_mesh_solar/target.cpp @@ -31,12 +31,13 @@ mesh::LocalIdentity radio_new_identity() { void SolarSensorManager::start_gps() { if (!gps_active) { - gps_active = true; - if (_location->isPowerSavingEnabled()) { - gps_wake = true; // gps_active is true + gps_wake = true; // gps_active is true _location->syncTime(); // Clear GPS data and force sync time _location->setNextSleep(); // Next time to off + } else { + gps_active = true; + gps_wake = true; } _location->begin(); @@ -84,24 +85,28 @@ void SolarSensorManager::loop() { static long next_gps_update = 0; // PowerSaving - if (_location->isPowerSavingEnabled() && gps_detected) { - if (gps_wake && ((int32_t)(millis() - _location->getNextSleep()) >= 0 || - !_location->waitingTimeSync())) { // Time to off or GPS set + if (_location->isPowerSavingEnabled() && gps_detected && gps_active) { + // Handle change in PowerSaving mode + _location->updatePowerSavingSettings(gps_wake); + + if (gps_wake) { + // GPS is awake: check whether it should sleep if ((int32_t)(millis() - _location->getNextSleep()) >= 0) { POWERSAVING_DEBUG_PRINTLN("GPS wake timeout. Enter sleep"); + stop_gps(); } else if (!_location->waitingTimeSync()) { POWERSAVING_DEBUG_PRINTLN("GPS set. Enter sleep early"); + stop_gps(); + } + } else { + // GPS is asleep: check whether it should wake + if ((int32_t)(millis() - _location->getNextWake()) >= 0) { + POWERSAVING_DEBUG_PRINTLN("GPS sleep timeout. Wakeup."); + start_gps(); + } else if (_location->waitingTimeSync()) { + POWERSAVING_DEBUG_PRINTLN("CLI gps sync. Wakeup"); + start_gps(); } - - stop_gps(); - } else if (!gps_wake && ((int32_t)(millis() - _location->getNextWake()) >= 0)) { // Time to on - POWERSAVING_DEBUG_PRINTLN("GPS sleep timeout. Wakeup."); - - start_gps(); - } else if (!gps_wake && _location->waitingTimeSync()) { // On for "gps sync" - POWERSAVING_DEBUG_PRINTLN("CLI gps sync. Wakeup"); - - start_gps(); } } @@ -145,8 +150,10 @@ const char* SolarSensorManager::getSettingValue(int i) const { bool SolarSensorManager::setSettingValue(const char* name, const char* value) { if (gps_detected && strcmp(name, "gps") == 0) { if (strcmp(value, "0") == 0) { + gps_active = false; // Disabled by CLI or App stop_gps(); } else { + gps_active = true; // Enabled by CLI or App start_gps(); } return true; diff --git a/variants/heltec_tracker/target.cpp b/variants/heltec_tracker/target.cpp index ab1b391ed..2ae85d6d5 100644 --- a/variants/heltec_tracker/target.cpp +++ b/variants/heltec_tracker/target.cpp @@ -45,12 +45,14 @@ mesh::LocalIdentity radio_new_identity() { void HWTSensorManager::start_gps() { if (!gps_active) { _location->begin(); // Claims periph_power via RefCountedDigitalPin - gps_active = true; if (_location->isPowerSavingEnabled()) { - gps_wake = true; // gps_active is true + gps_wake = true; // gps_active is unchanged (true for GPS sleep, false for GPS off) _location->syncTime(); // Clear GPS data and force sync time _location->setNextSleep(); // Next time to off + } else { + gps_active = true; + gps_wake = true; } Serial1.println("$CFGSYS,h35155*68"); // Configure GPS for all constellations @@ -89,24 +91,28 @@ void HWTSensorManager::loop() { static long next_gps_update = 0; // PowerSaving - if (_location->isPowerSavingEnabled()) { - if (gps_wake && ((int32_t)(millis() - _location->getNextSleep()) >= 0 || - !_location->waitingTimeSync())) { // Time to off or GPS set + if (_location->isPowerSavingEnabled() && gps_active) { + // Handle change in PowerSaving mode + _location->updatePowerSavingSettings(gps_wake); + + if (gps_wake) { + // GPS is awake: check whether it should sleep if ((int32_t)(millis() - _location->getNextSleep()) >= 0) { POWERSAVING_DEBUG_PRINTLN("GPS wake timeout. Enter sleep"); + stop_gps(); } else if (!_location->waitingTimeSync()) { POWERSAVING_DEBUG_PRINTLN("GPS set. Enter sleep early"); + stop_gps(); + } + } else { + // GPS is asleep: check whether it should wake + if ((int32_t)(millis() - _location->getNextWake()) >= 0) { + POWERSAVING_DEBUG_PRINTLN("GPS sleep timeout. Wakeup."); + start_gps(); + } else if (_location->waitingTimeSync()) { + POWERSAVING_DEBUG_PRINTLN("CLI gps sync. Wakeup"); + start_gps(); } - - stop_gps(); - } else if (!gps_wake && ((int32_t)(millis() - _location->getNextWake()) >= 0)) { // Time to on - POWERSAVING_DEBUG_PRINTLN("GPS sleep timeout. Wakeup."); - - start_gps(); - } else if (!gps_wake && _location->waitingTimeSync()) { // On for "gps sync" - POWERSAVING_DEBUG_PRINTLN("CLI gps sync. Wakeup"); - - start_gps(); } } @@ -145,8 +151,10 @@ const char* HWTSensorManager::getSettingValue(int i) const { bool HWTSensorManager::setSettingValue(const char* name, const char* value) { if (strcmp(name, "gps") == 0) { if (strcmp(value, "0") == 0) { + gps_active = false; // Disabled by CLI or App stop_gps(); } else { + gps_active = true; // Enabled by CLI or App start_gps(); } return true; diff --git a/variants/meshtracker_x1/target.cpp b/variants/meshtracker_x1/target.cpp index d6d548b51..95007fa33 100644 --- a/variants/meshtracker_x1/target.cpp +++ b/variants/meshtracker_x1/target.cpp @@ -26,7 +26,15 @@ mesh::LocalIdentity radio_new_identity() { } void MeshTrackerX1SensorManager::start_gps() { - gps_active = true; + if (_nmea->isPowerSavingEnabled()) { + gps_wake = true; // gps_active is unchanged (true for GPS sleep, false for GPS off) + _nmea->syncTime(); // Clear GPS data and force sync time + _nmea->setNextSleep(); // Next time to off + } else { + gps_active = true; + gps_wake = true; + } + // this init sequence comes from seeed examples and deals with all gps pins pinMode(GPS_EN, OUTPUT); digitalWrite(GPS_EN, HIGH); @@ -47,7 +55,15 @@ void MeshTrackerX1SensorManager::start_gps() { } void MeshTrackerX1SensorManager::sleep_gps() { - gps_active = false; + if (_nmea->isPowerSavingEnabled()) { + gps_wake = false; // gps_active is unchanged (true) even the GPS sleep (e.g: off) + _nmea->stopTimeSync(); // Stop time sync + _nmea->setNextWake(); // Next time to on + } else { + gps_active = false; + gps_wake = false; // When GPS is off, wake is false to be sure + } + digitalWrite(GPS_VRTC_EN, HIGH); // keep RTC alive for faster fix on wake digitalWrite(GPS_EN, LOW); digitalWrite(GPS_RESET, LOW); @@ -56,7 +72,15 @@ void MeshTrackerX1SensorManager::sleep_gps() { } void MeshTrackerX1SensorManager::stop_gps() { - gps_active = false; + if (_nmea->isPowerSavingEnabled()) { + gps_wake = false; // gps_active is unchanged (true) even the GPS sleep (e.g: off) + _nmea->stopTimeSync(); // Stop time sync + _nmea->setNextWake(); // Next time to on + } else { + gps_active = false; + gps_wake = false; // When GPS is off, wake is false to be sure + } + digitalWrite(GPS_VRTC_EN, LOW); digitalWrite(GPS_EN, LOW); digitalWrite(GPS_RESET, LOW); @@ -95,16 +119,51 @@ bool MeshTrackerX1SensorManager::querySensors(uint8_t requester_permissions, Cay void MeshTrackerX1SensorManager::loop() { static long next_gps_update = 0; + // PowerSaving + if (_nmea->isPowerSavingEnabled() && gps_active) { + // Handle change in PowerSaving mode + _nmea->updatePowerSavingSettings(gps_wake); - _nmea->loop(); - - if (millis() > next_gps_update) { - if (gps_active && _nmea->isValid()) { - node_lat = ((double)_nmea->getLatitude())/1000000.; - node_lon = ((double)_nmea->getLongitude())/1000000.; - node_altitude = ((double)_nmea->getAltitude()) / 1000.0; + if (gps_wake) { + // GPS is awake: check whether it should sleep + if ((int32_t)(millis() - _nmea->getNextSleep()) >= 0) { + POWERSAVING_DEBUG_PRINTLN("GPS wake timeout. Enter sleep"); + sleep_gps(); + } else if (!_nmea->waitingTimeSync()) { + POWERSAVING_DEBUG_PRINTLN("GPS set. Enter sleep early"); + sleep_gps(); + } + } else { + // GPS is asleep: check whether it should wake + if ((int32_t)(millis() - _nmea->getNextWake()) >= 0) { + POWERSAVING_DEBUG_PRINTLN("GPS sleep timeout. Wakeup."); + start_gps(); + } else if (_nmea->waitingTimeSync()) { + POWERSAVING_DEBUG_PRINTLN("CLI gps sync. Wakeup"); + start_gps(); + } } - next_gps_update = millis() + 1000; + } + + if ((!_nmea->isPowerSavingEnabled() && gps_active) || (_nmea->isPowerSavingEnabled() && gps_wake)) { + _nmea->loop(); + } + + if ((int32_t)(millis() - next_gps_update) >= 0) { + if ((!_nmea->isPowerSavingEnabled() && gps_active) || (_nmea->isPowerSavingEnabled() && gps_wake)) { + if (_nmea->isValid()) { + node_lat = ((double)_nmea->getLatitude()) / 1000000.; + node_lon = ((double)_nmea->getLongitude()) / 1000000.; + MESH_DEBUG_PRINTLN("lat %f lon %f", node_lat, node_lon); + node_altitude = ((double)_nmea->getAltitude()) / 1000.0; + MESH_DEBUG_PRINTLN("lat %f lon %f alt %f", node_lat, node_lon, node_altitude); + } + + // In powersaving mode, GPS is on and off. Only update data when GPS is on + if (_nmea->isPowerSavingEnabled()) next_gps_update = millis() + 1000; + } + + if (!_nmea->isPowerSavingEnabled()) next_gps_update = millis() + 1000; } } @@ -122,8 +181,10 @@ const char* MeshTrackerX1SensorManager::getSettingValue(int i) const { bool MeshTrackerX1SensorManager::setSettingValue(const char* name, const char* value) { if (strcmp(name, "gps") == 0) { if (strcmp(value, "0") == 0) { + gps_active = false; // Disabled by CLI or App sleep_gps(); // sleep for faster fix ! } else { + gps_active = true; // Enabled by CLI or App start_gps(); } return true; diff --git a/variants/meshtracker_x1/target.h b/variants/meshtracker_x1/target.h index 9741efb6a..6138a7ee5 100644 --- a/variants/meshtracker_x1/target.h +++ b/variants/meshtracker_x1/target.h @@ -15,6 +15,7 @@ class MeshTrackerX1SensorManager: public SensorManager { bool gps_active = false; + bool gps_wake = false; // In PowerSaving, gps_active can have gps_wake true or false bool baro_ok = false; Adafruit_SPA06_003 spa06; LocationProvider * _nmea; diff --git a/variants/t1000-e/target.cpp b/variants/t1000-e/target.cpp index 2cfec93b7..2e3102398 100644 --- a/variants/t1000-e/target.cpp +++ b/variants/t1000-e/target.cpp @@ -85,8 +85,8 @@ void T1000SensorManager::start_gps() { _nmea->syncTime(); // Clear GPS data and force sync time _nmea->setNextSleep(); // Next time to off } else { - gps_active = true; - gps_wake = true; + gps_active = true; + gps_wake = true; } //_nmea->begin();