PowerSaving GPS version 1 for repeaters

This commit is contained in:
Kevin Le committed 2026-07-16 18:48:39 +07:00
1 parent 46c729b2e9
commit 16fbf33582
6 files changed
+120 -15

No files matched your search

+7
View File
@@ -162,6 +162,13 @@ 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
+36 -9
View File
@@ -368,7 +368,12 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, char* command, char* re
if (_sensors->setSettingValue("gps", "1")) {
_prefs->gps_enabled = 1;
savePrefs();
strcpy(reply, "ok");
if (_prefs->powersaving_enabled) { // Power Saving
strcpy(reply, "on (powersaving)");
} else { // Normal mode
strcpy(reply, "ok");
}
} else {
strcpy(reply, "gps toggle not found");
}
@@ -384,7 +389,7 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, char* command, char* re
LocationProvider * l = _sensors->getLocationProvider();
if (l != NULL) {
l->syncTime();
strcpy(reply, "ok");
strcpy(reply, "scheduled");
} else {
strcpy(reply, "gps provider not found");
}
@@ -430,13 +435,35 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, char* command, char* re
bool fix = l->isValid(); // has fix ?
int sats = l->satellitesCount();
bool active = !strcmp(_sensors->getSettingByKey("gps"), "1");
if (enabled) {
sprintf(reply, "on, %s, %s, %d sats",
active?"active":"deactivated",
fix?"fix":"no fix",
sats);
} else {
strcpy(reply, "off");
if (_prefs->powersaving_enabled && l->getGPSPowerSaving()) { // GPS Power Saving
if (enabled) {
sprintf(reply, "on (powersaving, sleep in %lum), %s, %s, %d sats",
(l->getNextGPSOff() - millis()) / 60000UL,
active?"active":"deactivated",
fix?"fix":"no fix",
sats);
} else {
sprintf(reply, "off (powersaving, wake in %lum)", (l->getNextGPSOn() - millis()) / 60000UL);
}
// "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 { // Normal mode
if (enabled) {
sprintf(reply, "on, %s, %s, %d sats",
active?"active":"deactivated",
fix?"fix":"no fix",
sats);
} else {
strcpy(reply, "off");
}
}
} else {
strcpy(reply, "Can't find GPS");
+2 -1
View File
@@ -13,8 +13,9 @@ 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; }
SensorManager() { node_lat = 0; node_lon = 0; node_altitude = 0; powersaving_enabled = false; }
virtual bool begin() { return false; }
virtual bool querySensors(uint8_t requester_permissions, CayenneLPP& telemetry) { return false; }
virtual void loop() { }
@@ -621,6 +621,12 @@ 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
@@ -730,8 +736,16 @@ 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->setGPSPowerSaving(false);
}
stop_gps();
} else {
if (powersaving_enabled) {
_location->setGPSPowerSaving(true);
}
start_gps();
}
return true;
@@ -883,11 +897,22 @@ 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;
#ifdef RAK_WISBLOCK_GPS
if (powersaving_enabled && _location->getGPSPowerSaving()) {
_location->stopTimeSync(); // Stop time sync
_location->setNextGPSOn(millis() + GPS_OFF_DURATION_SECS * 1000UL); // Next time to on
}
#ifdef RAK_WISBLOCK_GPS
pinMode(gpsResetPin, OUTPUT);
digitalWrite(gpsResetPin, LOW);
return;
@@ -906,11 +931,39 @@ void EnvironmentSensorManager::loop() {
#if ENV_INCLUDE_GPS
static long next_gps_update = 0;
// PowerSaving
if (powersaving_enabled) {
if (gps_detected && _location->getGPSPowerSaving()) {
if (gps_active && ((int32_t)(millis() - _location->getNextGPSOff()) >= 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
stop_gps();
} else if (!gps_active && ((int32_t)(millis() - _location->getNextGPSOn()) >= 0)) { // Time to on
// --- TO REMOVE
Serial.println("Timeout, on");
// --- TO REMOVE
start_gps();
} else if (!gps_active && _location->waitingTimeSync()) { // On for "gps sync"
// --- TO REMOVE
Serial.println("gps sync CLI, on");
// --- TO REMOVE
start_gps();
}
}
}
if (gps_active) {
_location->loop();
}
if (millis() > next_gps_update) {
if ((int32_t)(millis() - next_gps_update) >= 0) {
if(gps_active){
#ifdef RAK_WISBLOCK_GPS
if ((i2cGPSFlag || serialGPSFlag) && _location->isValid()) {
@@ -929,8 +982,12 @@ void EnvironmentSensorManager::loop() {
MESH_DEBUG_PRINTLN("lat %f lon %f alt %f", node_lat, node_lon, node_altitude);
}
#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);
}
next_gps_update = millis() + (gps_update_interval_sec * 1000);
if(!powersaving_enabled) next_gps_update = millis() + (gps_update_interval_sec * 1000);
}
#endif
#if ENV_INCLUDE_BME680_BSEC
+12
View File
@@ -6,10 +6,22 @@
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 _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 unsigned long setNextGPSOff(unsigned long _millis) { _next_gps_off = _millis; }
virtual unsigned long getNextGPSOff() { return _next_gps_off; }
virtual unsigned long setNextGPSOn(unsigned long _millis) { _next_gps_on = _millis; }
virtual unsigned long getNextGPSOn() { return _next_gps_on; }
virtual unsigned long getLastValidTimeSync() { return _last_valid_time_sync; }
virtual long getLatitude() = 0;
virtual long getLongitude() = 0;
virtual long getAltitude() = 0;
@@ -120,7 +120,7 @@ public :
return alt;
}
long satellitesCount() override { return nmea.getNumSatellites(); }
bool isValid() override { return nmea.isValid(); }
bool isValid() override { return nmea.isValid() && nmea.getYear() < 2030; } // TODO: Pending better validation
long getTimestamp() override {
DateTime dt(nmea.getYear(), nmea.getMonth(),nmea.getDay(),nmea.getHour(),nmea.getMinute(),nmea.getSecond());
@@ -154,9 +154,10 @@ public :
_clock->setCurrentTime(getTimestamp());
_time_sync_needed = false;
_last_time_sync = millis();
_last_valid_time_sync = _clock->getCurrentTime();
}
}
if (isValid()) {
if (isValid() && satellitesCount() >= 5) {
time_valid ++;
}
}