GPS PowerSaving v1.1: Added support for BLE companions

This commit is contained in:
Kevin Le
2026-07-20 16:19:27 +07:00
parent 38509583fa
commit a7a4e52947
7 changed files with 85 additions and 45 deletions
+12
View File
@@ -234,6 +234,18 @@ void setup() {
#error "need to define filesystem"
#endif
#if ENV_INCLUDE_GPS == 1
// Apply PowerSaving profile for GPS
if(sensors.getLocationProvider() != NULL) {
// Enable by default
sensors.powersaving_enabled = true;
sensors.getLocationProvider()->enablePowerSaving(true);
// Set GPS on and off duration in seconds
sensors.getLocationProvider()->setPowerSavingProfile(600, 300); // Max 10 minutes, 5 minutes
}
#endif
sensors.begin();
#if ENV_INCLUDE_GPS == 1
+12
View File
@@ -87,6 +87,18 @@ void setup() {
command[0] = 0;
#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
}
#endif
sensors.begin();
the_mesh.begin(fs);
+9
View File
@@ -37,6 +37,15 @@
#define BRIDGE_DEBUG_PRINTLN(...) {}
#endif
#if POWERSAVING_DEBUG && ARDUINO
#include <Arduino.h>
#define POWERSAVING_DEBUG_PRINT(F, ...) Serial.printf("POWERSAVING: " F, ##__VA_ARGS__)
#define POWERSAVING_DEBUG_PRINTLN(F, ...) Serial.printf("POWERSAVING: " F "\n", ##__VA_ARGS__)
#else
#define POWERSAVING_DEBUG_PRINT(...) {}
#define POWERSAVING_DEBUG_PRINTLN(...) {}
#endif
namespace mesh {
#define BD_STARTUP_NORMAL 0 // getStartupReason() codes
+3 -3
View File
@@ -436,9 +436,9 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, char* command, char* re
int sats = l->satellitesCount();
bool active = !strcmp(_sensors->getSettingByKey("gps"), "1");
if (_prefs->powersaving_enabled && l->getGPSPowerSaving()) { // GPS Power Saving
if (_prefs->powersaving_enabled && l->isPowerSavingEnabled()) { // GPS Power Saving
if (enabled) {
unsigned long mins = (l->getNextGPSOff() - millis()) / 60000UL;
unsigned long mins = (l->getNextSleep() - millis()) / 60000UL;
sprintf(reply, "on (powersaving, sleep in %luh %lum), %s, %s, %d sats",
mins / 60UL,
mins % 60UL,
@@ -446,7 +446,7 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, char* command, char* re
fix ? "fix" : "no fix",
sats);
} else {
unsigned long mins = (l->getNextGPSOn() - millis()) / 60000UL;
unsigned long mins = (l->getNextWake() - millis()) / 60000UL;
sprintf(reply, "off (powersaving, wake in %luh %lum)",
mins / 60UL,
mins % 60UL);
@@ -621,12 +621,6 @@ static const SensorDef SENSOR_TABLE[] = {
static const size_t SENSOR_TABLE_SIZE = (sizeof(SENSOR_TABLE) / sizeof(SENSOR_TABLE[0])) - 1;
// ============================================================
// Power Saving GPS
// ============================================================
static unsigned long GPS_ON_DURATION_SECS = 600; // 10 minutes
static unsigned long GPS_OFF_DURATION_SECS = 86400; // 1 day
// ============================================================
// begin() — scan the I2C bus, then initialize only what was
// found. A sensor whose address does not ACK during the scan
@@ -737,13 +731,13 @@ bool EnvironmentSensorManager::setSettingValue(const char* name, const char* val
if (gps_detected && strcmp(name, "gps") == 0) {
if (strcmp(value, "0") == 0) {
if (powersaving_enabled) {
_location->setGPSPowerSaving(false);
_location->enablePowerSaving(false);
}
stop_gps();
} else {
if (powersaving_enabled) {
_location->setGPSPowerSaving(true);
_location->enablePowerSaving(true);
}
start_gps();
@@ -885,6 +879,13 @@ bool EnvironmentSensorManager::gpsIsAwake(uint8_t ioPin){
void EnvironmentSensorManager::start_gps() {
gps_active = true;
if (powersaving_enabled && _location->isPowerSavingEnabled()) {
gps_wake = true; // gps_active is true
_location->syncTime(); // Clear GPS data and force sync time
_location->setNextSleep(); // Next time to off
}
#ifdef RAK_WISBLOCK_GPS
pinMode(gpsResetPin, OUTPUT);
digitalWrite(gpsResetPin, HIGH);
@@ -897,22 +898,19 @@ void EnvironmentSensorManager::start_gps() {
#ifndef PIN_GPS_EN
MESH_DEBUG_PRINTLN("Start GPS is N/A on this board. Actual GPS state unchanged");
#endif
if (powersaving_enabled && _location->getGPSPowerSaving()) {
_location->syncTime(); // Clear GPS data and force sync time
_location->setNextGPSOff(millis() + GPS_ON_DURATION_SECS * 1000UL); // Next time to off
}
}
void EnvironmentSensorManager::stop_gps() {
gps_active = false;
if (powersaving_enabled && _location->getGPSPowerSaving()) {
if (powersaving_enabled && _location->isPowerSavingEnabled()) {
gps_wake = false; // gps_active is unchanged (true) even the GPS sleep (e.g: off)
_location->stopTimeSync(); // Stop time sync
_location->setNextGPSOn(millis() + GPS_OFF_DURATION_SECS * 1000UL); // Next time to on
_location->setNextWake(); // Next time to on
} else {
gps_active = false;
gps_wake = false; // When GPS is off, wake is false to be sure
}
#ifdef RAK_WISBLOCK_GPS
#ifdef RAK_WISBLOCK_GPS
pinMode(gpsResetPin, OUTPUT);
digitalWrite(gpsResetPin, LOW);
return;
@@ -934,37 +932,35 @@ void EnvironmentSensorManager::loop() {
// PowerSaving
if (powersaving_enabled) {
if (gps_detected && _location->getGPSPowerSaving()) {
if (gps_active && ((int32_t)(millis() - _location->getNextGPSOff()) >= 0 ||
if (gps_detected && _location->isPowerSavingEnabled()) {
if (gps_wake && ((int32_t)(millis() - _location->getNextSleep()) >= 0 ||
!_location->waitingTimeSync())) { // Time to off or GPS set
// --- TO REMOVE
if ((int32_t)(millis() - _location->getNextGPSOff()) >= 0) Serial.println("Timeout, off");
else if (!_location->waitingTimeSync()) Serial.println("GPS set, off early");
// --- TO REMOVE
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_active && ((int32_t)(millis() - _location->getNextGPSOn()) >= 0)) { // Time to on
// --- TO REMOVE
Serial.println("Timeout, on");
// --- TO REMOVE
} 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_active && _location->waitingTimeSync()) { // On for "gps sync"
// --- TO REMOVE
Serial.println("gps sync CLI, on");
// --- TO REMOVE
} else if (!gps_wake && _location->waitingTimeSync()) { // On for "gps sync"
POWERSAVING_DEBUG_PRINTLN("CLI gps sync. Wakeup");
start_gps();
}
}
}
if (gps_active) {
if ((!powersaving_enabled && gps_active) || (powersaving_enabled && gps_wake)) {
_location->loop();
}
if ((int32_t)(millis() - next_gps_update) >= 0) {
if(gps_active){
if((!powersaving_enabled && gps_active) || (powersaving_enabled && gps_wake)){
#ifdef RAK_WISBLOCK_GPS
if ((i2cGPSFlag || serialGPSFlag) && _location->isValid()) {
node_lat = ((double)_location->getLatitude())/1000000.;
@@ -21,6 +21,7 @@ protected:
bool gps_detected = false;
bool gps_active = false;
bool gps_wake = false; // In PowerSaving, gps_active can have gps_wake true or false
uint32_t gps_update_interval_sec = 1;
#if ENV_INCLUDE_GPS
+18 -8
View File
@@ -6,22 +6,32 @@
class LocationProvider {
protected:
bool _time_sync_needed = true;
bool powersaving_enabled = false;
unsigned long _next_gps_off = 0;
unsigned long _next_gps_on = 0;
unsigned long _wake_duration_secs = 86400; // Full day
unsigned long _sleep_duration_secs = 0; // No off
unsigned long _next_wake = 0;
unsigned long _next_sleep = 0;
unsigned long _last_valid_time_sync = 0;
public:
virtual void syncTime() { _time_sync_needed = true; }
virtual bool waitingTimeSync() { return _time_sync_needed; }
virtual void stopTimeSync() { _time_sync_needed = false; }
virtual void setGPSPowerSaving(bool enabled) { powersaving_enabled = enabled; _next_gps_off = 0; _next_gps_on = 0; }
virtual bool getGPSPowerSaving() { return powersaving_enabled; }
virtual void setNextGPSOff(unsigned long _millis) { _next_gps_off = _millis; }
virtual unsigned long getNextGPSOff() { return _next_gps_off; }
virtual void setNextGPSOn(unsigned long _millis) { _next_gps_on = _millis; }
virtual unsigned long getNextGPSOn() { return _next_gps_on; }
virtual void setPowerSavingProfile(unsigned long wake_duration_secs, unsigned long sleep_duration_secs) {
_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 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; }
virtual unsigned long getNextSleep() { return _next_sleep; }
virtual unsigned long getLastValidTimeSync() { return _last_valid_time_sync; }
virtual long getLatitude() = 0;
virtual long getLongitude() = 0;
virtual long getAltitude() = 0;