diff --git a/examples/simple_repeater/MyMesh.h b/examples/simple_repeater/MyMesh.h index dc89325861c..df2ff974fa9 100644 --- a/examples/simple_repeater/MyMesh.h +++ b/examples/simple_repeater/MyMesh.h @@ -160,6 +160,11 @@ class MyMesh : public mesh::Mesh, public CommonCLICallbacks { #if ENV_INCLUDE_GPS == 1 void applyGpsPrefs() { sensors.setSettingValue("gps", _prefs.gps_enabled?"1":"0"); + if (_prefs.gps_sleep_interval > 0) { + char interval_str[11]; // 4 294 967 295 (10 digits + null) + sprintf(interval_str, "%u", _prefs.gps_sleep_interval); + sensors.setSettingValue("gps_sleep_interval", interval_str); + } } #endif diff --git a/src/helpers/CommonCLI.cpp b/src/helpers/CommonCLI.cpp index 04199e24d1d..3c495545aa1 100644 --- a/src/helpers/CommonCLI.cpp +++ b/src/helpers/CommonCLI.cpp @@ -102,7 +102,8 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) { // Legacy file.read((uint8_t *)&_prefs->flood_max_advert, sizeof(_prefs->flood_max_advert)); // 292 file.read((uint8_t *)&_prefs->radio_fem_rxgain, sizeof(_prefs->radio_fem_rxgain)); // 293 file.read((uint8_t *)&_prefs->cad_enabled, sizeof(_prefs->cad_enabled)); // 294 - // next: 295 + file.read((uint8_t *)&_prefs->gps_sleep_interval, sizeof(_prefs->gps_sleep_interval)); // 295 + // next: 299 // sanitise bad pref values _prefs->rx_delay_base = constrain(_prefs->rx_delay_base, 0, 20.0f); @@ -360,6 +361,15 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, char* command, char* re } else { strcpy(reply, "gps toggle not found"); } + } else if (memcmp(command, "gps sleep", 9) == 0) { + if (strlen(command) == 9) { + sprintf(reply, "%u", _prefs->gps_sleep_interval); + } else if (strlen(command) > 9) { + _sensors->setSettingValue("gps_sleep_interval", command + 10); + _prefs->gps_sleep_interval = _atoi(command + 10); + savePrefs(); + strcpy(reply, "ok"); + } } else if (memcmp(command, "gps sync", 8) == 0) { LocationProvider * l = _sensors->getLocationProvider(); if (l != NULL) { @@ -420,15 +430,18 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, char* command, char* re } else if (memcmp(command, "gps", 3) == 0) { LocationProvider * l = _sensors->getLocationProvider(); if (l != NULL) { - bool enabled = l->isEnabled(); // is EN pin on ? + bool enabled = _prefs->gps_enabled; 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); + if (active) { + sprintf(reply, "on, active, %s, %d sats", + fix?"fix":"no fix", + sats); + } else { + strcpy(reply, "on, deactivated"); + } } else { strcpy(reply, "off"); } diff --git a/src/helpers/CommonCLI.h b/src/helpers/CommonCLI.h index 2759b0c4f0e..b69a3f51f02 100644 --- a/src/helpers/CommonCLI.h +++ b/src/helpers/CommonCLI.h @@ -61,6 +61,7 @@ class NodePrefs : public ConfigSerializer { // Gps settings uint8_t gps_enabled = 0; uint32_t gps_interval = 0; // in seconds + uint32_t gps_sleep_interval = 0; // in seconds uint8_t advert_loc_policy = 0; uint32_t discovery_mod_timestamp = 0; float adc_multiplier = 0; @@ -159,6 +160,7 @@ class NodePrefs : public ConfigSerializer { def("en", _parent->gps_enabled); // boolean def("int", _parent->gps_interval); // interval in seconds def("adv_loc", _parent->advert_loc_policy); + def("sleep", _parent->gps_sleep_interval); } public: GPSPrefs(NodePrefs* parent) : _parent(parent) { } diff --git a/src/helpers/sensors/EnvironmentSensorManager.cpp b/src/helpers/sensors/EnvironmentSensorManager.cpp index 0dc892c3a52..88a32b960a1 100644 --- a/src/helpers/sensors/EnvironmentSensorManager.cpp +++ b/src/helpers/sensors/EnvironmentSensorManager.cpp @@ -2,6 +2,11 @@ #include +// number of seconds to wait with the valid GPS fix before the GPS is powered down +#define GPS_WAIT_SECONDS_WITH_VALID_FIX 10 +// how long to wait for the GPS fix before giving up +#define GPS_TIMEOUT_SECONDS 600 + #if ENV_PIN_SDA && ENV_PIN_SCL #define TELEM_WIRE &Wire1 // Use Wire1 as the I2C bus for Environment Sensors #else @@ -731,8 +736,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) { + gps_enabled = false; stop_gps(); } else { + gps_enabled = true; start_gps(); } return true; @@ -742,6 +749,11 @@ bool EnvironmentSensorManager::setSettingValue(const char* name, const char* val gps_update_interval_sec = interval_seconds > 0 ? interval_seconds : 1; return true; } + if (strcmp(name, "gps_sleep_interval") == 0) { + gps_sleep_interval_sec = atoi(value); + next_gps_wakeup = 0; + return true; + } #endif return false; // not supported } @@ -927,30 +939,54 @@ void EnvironmentSensorManager::stop_gps() { void EnvironmentSensorManager::loop() { #if ENV_INCLUDE_GPS + static bool valid_fix = false; + static unsigned long valid_fix_time = 0; static unsigned long next_gps_update = 0; + if (gps_active) { _location->loop(); } - if ((long)(millis() - next_gps_update) > 0) { + if (gps_enabled && gps_sleep_interval_sec > 0 && (long)(millis() - next_gps_wakeup) > 0) { + if (gps_active) { + if ((valid_fix && (long)(millis() - valid_fix_time) >= GPS_WAIT_SECONDS_WITH_VALID_FIX * 1000) || \ + (long)(millis() - next_gps_wakeup) > GPS_TIMEOUT_SECONDS * 1000) { + next_gps_wakeup = millis() + (gps_sleep_interval_sec * 1000); + stop_gps(); + } else { + if (_location->isValid()) { + if (!valid_fix) { + valid_fix_time = millis(); + valid_fix = true; + } + } else { + valid_fix = false; + } + } + } else { + start_gps(); + valid_fix = false; + } + } + if ((long)(millis() - next_gps_update) > 0) { if(gps_active){ - #ifdef RAK_WISBLOCK_GPS - if ((i2cGPSFlag || serialGPSFlag) && _location->isValid()) { - node_lat = ((double)_location->getLatitude())/1000000.; - node_lon = ((double)_location->getLongitude())/1000000.; - MESH_DEBUG_PRINTLN("lat %f lon %f", node_lat, node_lon); - node_altitude = ((double)_location->getAltitude()) / 1000.0; - MESH_DEBUG_PRINTLN("lat %f lon %f alt %f", node_lat, node_lon, node_altitude); - } - #else - if (_location->isValid()) { - node_lat = ((double)_location->getLatitude())/1000000.; - node_lon = ((double)_location->getLongitude())/1000000.; - MESH_DEBUG_PRINTLN("lat %f lon %f", node_lat, node_lon); - node_altitude = ((double)_location->getAltitude()) / 1000.0; - MESH_DEBUG_PRINTLN("lat %f lon %f alt %f", node_lat, node_lon, node_altitude); - } - #endif + #ifdef RAK_WISBLOCK_GPS + if ((i2cGPSFlag || serialGPSFlag) && _location->isValid()) { + node_lat = ((double)_location->getLatitude())/1000000.; + node_lon = ((double)_location->getLongitude())/1000000.; + MESH_DEBUG_PRINTLN("lat %f lon %f", node_lat, node_lon); + node_altitude = ((double)_location->getAltitude()) / 1000.0; + MESH_DEBUG_PRINTLN("lat %f lon %f alt %f", node_lat, node_lon, node_altitude); + } + #else + if (_location->isValid()) { + node_lat = ((double)_location->getLatitude())/1000000.; + node_lon = ((double)_location->getLongitude())/1000000.; + MESH_DEBUG_PRINTLN("lat %f lon %f", node_lat, node_lon); + node_altitude = ((double)_location->getAltitude()) / 1000.0; + MESH_DEBUG_PRINTLN("lat %f lon %f alt %f", node_lat, node_lon, node_altitude); + } + #endif } next_gps_update = millis() + (gps_update_interval_sec * 1000); } diff --git a/src/helpers/sensors/EnvironmentSensorManager.h b/src/helpers/sensors/EnvironmentSensorManager.h index 17706cbc492..537e7273ade 100644 --- a/src/helpers/sensors/EnvironmentSensorManager.h +++ b/src/helpers/sensors/EnvironmentSensorManager.h @@ -22,8 +22,11 @@ class EnvironmentSensorManager : public SensorManager { bool gps_detected = false; bool gps_active = false; uint32_t gps_update_interval_sec = 1; + uint32_t gps_sleep_interval_sec = 0; #if ENV_INCLUDE_GPS + bool gps_enabled = false; + unsigned long next_gps_wakeup = 0; LocationProvider* _location; void start_gps(); void stop_gps(); diff --git a/src/helpers/sensors/MicroNMEALocationProvider.h b/src/helpers/sensors/MicroNMEALocationProvider.h index 37ef5762c48..087041b3b84 100644 --- a/src/helpers/sensors/MicroNMEALocationProvider.h +++ b/src/helpers/sensors/MicroNMEALocationProvider.h @@ -113,6 +113,7 @@ public : } void begin() override { + nmea.clear(); _begin_calls++; claim(); if (_pin_en != -1) {