fix(power): stop GPS duty-cycling from starving !gps fix and fighting manual toggles

Two races between the new GPS duty-cycle scheduler and code that changes
GPS state independently of it:

- gpsDutyCycleLoop() capped every "GPS on" phase at a fixed 60s and would
  stop_gps() as soon as a fix went valid, with no awareness of an
  in-flight "!gps fix" bot request -- so a fix's own up-to-300s acquire
  window (and its 10s averaging phase) could get cut short by the
  scheduler shutting GPS off mid-request. MyMesh::isGpsFixPending() now
  feeds into UITask's existing "is anything live using GPS right now"
  hold, alongside trail/live-share/locator/nearby.

- setSettingValue("gps", ...) (Settings toggle, bot !gps on/off, CLI)
  starts/stops GPS directly without resetting the scheduler's own phase
  timer, so a manual toggle could land on a stale, already-expired
  deadline left over from before -- immediately re-stopping GPS a tick
  after turning it on. The phase timer now resets on every external
  change, so the next duty-cycle tick re-arms fresh.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
MarekZegare4
2026-08-12 22:08:13 +02:00
co-authored by Claude Sonnet 5
parent 22b05ada52
commit c045df1da5
3 changed files with 14 additions and 1 deletions
@@ -718,6 +718,13 @@ bool EnvironmentSensorManager::setSettingValue(const char* name, const char* val
} else {
stop_gps();
}
// This bypasses gpsDutyCycleLoop()'s own start_gps()/stop_gps() calls, so
// its phase timer would otherwise still be counting down (or already
// expired) from before this external change -- reset it so the next
// duty-cycle tick re-arms a fresh phase instead of judging gps_active
// against a stale deadline (e.g. stopping GPS again a tick after this
// just started it).
_gps_duty_phase_until = 0;
return true;
}
if (strcmp(name, "gps_interval") == 0) {