Enable Companion power saving by default

This commit is contained in:
mikecarper committed 2026-08-16 21:06:23 -07:00
1 parent a514b2a6d5
commit 80ea7976e2
6 files changed
+63 -3

No files matched your search

+2 -2
View File
@@ -1086,11 +1086,11 @@ get clock.sync.status
- `on`: enable power saving
- `off`: disable power saving
**Default:** `off`
**Default:** `off` for infrastructure roles; `on` for Companion firmware
**Note:** Infrastructure firmware enters sleep between radio transmissions. It refuses to enable power saving from the local serial console or while an active USB serial data connection is detected; USB power alone does not block power saving.
Full Companion firmware accepts the command from its local USB terminal and exposes the same setting in WebConfig. On ESP32, it lowers the CPU clock to 80 MHz, enables idle yielding, and enables the configured GPS duty cycle. USB, BLE, and WiFi remain available. `powersaving off` restores the board's normal CPU clock and disables the GPS duty cycle. This device setting is separate from LoRa RXPS (`radio.rxps`) and WiFi modem power save (`wifi.powersave`).
Companion firmware defaults this setting to `on`. Full Companion accepts the command from its local USB terminal and exposes the same setting in WebConfig. On ESP32, it lowers the CPU clock to 80 MHz, enables idle yielding, and enables the configured GPS duty cycle. USB, BLE, and WiFi remain available. `powersaving off` restores the board's normal CPU clock and disables the GPS duty cycle. This device setting is separate from LoRa RXPS (`radio.rxps`) and WiFi modem power save (`wifi.powersave`).
---
+5
View File
@@ -74,6 +74,11 @@ powersaving on
powersaving off
```
Companion firmware defaults device power saving to on. Version 1.17.1.2 also
turns it on once when upgrading an older Companion preference file, including
one written by the short-lived default-off regression. After that one-time
migration, an explicit `powersaving off` selection remains persistent.
On ESP32, enabling it lowers the CPU clock to 80 MHz, enables idle yielding,
and enables the configured GPS duty cycle. Disabling it restores the normal CPU
clock and keeps GPS awake. Full Companion transports remain available in both
+7
View File
@@ -339,6 +339,10 @@ void DataStore::loadPrefsInt(const char *filename, CompanionNodePrefs& _prefs, d
if (file.available() >= (int)sizeof(_prefs.wifi_enabled)) {
file.read((uint8_t *)&_prefs.wifi_enabled,
sizeof(_prefs.wifi_enabled)); // 138
if (file.available() >= (int)sizeof(_prefs.powersaving_policy_version)) {
file.read((uint8_t *)&_prefs.powersaving_policy_version,
sizeof(_prefs.powersaving_policy_version)); // 139
}
}
}
}
@@ -407,6 +411,9 @@ bool DataStore::savePrefs(const CompanionNodePrefs& _prefs, double node_lat, dou
sizeof(_prefs.powersaving_enabled)) == sizeof(_prefs.powersaving_enabled); // 137
success = success && file.write((uint8_t *)&_prefs.wifi_enabled,
sizeof(_prefs.wifi_enabled)) == sizeof(_prefs.wifi_enabled); // 138
success = success && file.write((uint8_t *)&_prefs.powersaving_policy_version,
sizeof(_prefs.powersaving_policy_version))
== sizeof(_prefs.powersaving_policy_version); // 139
#if defined(NRF52_PLATFORM)
success = file.commit(success);
+15 -1
View File
@@ -1356,7 +1356,8 @@ MyMesh::MyMesh(mesh::Radio &radio, mesh::RNG &rng, mesh::RTCClock &rtc, SimpleMe
_prefs.rx_ps_preamble = RXPS_FIXED_PREAMBLE;
_prefs.rx_ps_rx_us = RX_POWERSAVING_DEFAULT_RX_US;
_prefs.rx_ps_sleep_us = RX_POWERSAVING_DEFAULT_SLEEP_US;
_prefs.powersaving_enabled = 0;
_prefs.powersaving_enabled = 1;
_prefs.powersaving_policy_version = 0;
_prefs.wifi_enabled = 1;
recalcRxPowerSavingFromLevel(_prefs.rx_ps_level, _prefs.sf, _prefs.bw,
_prefs.rx_ps_preamble, &_prefs.rx_ps_rx_us,
@@ -1420,6 +1421,13 @@ void MyMesh::begin(bool has_display, bool radio_available) {
// load persisted prefs
_store->loadPrefs(_prefs, sensors.node_lat, sensors.node_lon);
// v1.17.1.2 repairs the Companion default-off regression for both fresh
// installs and devices that already persisted the regressed value. The
// appended policy marker makes this a one-time migration, so a later
// explicit `powersaving off` choice remains persistent.
const bool power_saving_default_migrated =
migrateCompanionPowerSavingDefault(_prefs);
// sanitise bad pref values
_prefs.rx_delay_base = constrain(_prefs.rx_delay_base, 0, 20.0f);
_prefs.airtime_factor = constrain(_prefs.airtime_factor, 0, 9.0f);
@@ -1443,6 +1451,9 @@ void MyMesh::begin(bool has_display, bool radio_available) {
_prefs.radio_fem_txgain = constrain(_prefs.radio_fem_txgain, 0, 1);
_prefs.rx_powersaving_enabled = constrain(_prefs.rx_powersaving_enabled, 0, 1);
_prefs.powersaving_enabled = constrain(_prefs.powersaving_enabled, 0, 1);
_prefs.powersaving_policy_version = constrain(
_prefs.powersaving_policy_version, 0,
COMPANION_POWERSAVING_POLICY_VERSION);
_prefs.wifi_enabled = constrain(_prefs.wifi_enabled, 0, 1);
_prefs.rx_ps_level = constrain(_prefs.rx_ps_level, 0, 10);
if (_prefs.rx_ps_preamble != 16 && _prefs.rx_ps_preamble != 32) {
@@ -1452,6 +1463,9 @@ void MyMesh::begin(bool has_display, bool radio_available) {
recalcRxPowerSavingFromLevel(_prefs.rx_ps_level, _prefs.sf, _prefs.bw,
_prefs.rx_ps_preamble, &_prefs.rx_ps_rx_us,
&_prefs.rx_ps_sleep_us);
if (power_saving_default_migrated) {
_store->savePrefs(_prefs, sensors.node_lat, sensors.node_lon);
}
#ifdef BLE_PIN_CODE // 123456 by default
if (_prefs.ble_pin == 0) {
+17
View File
@@ -9,6 +9,12 @@
#define ADVERT_LOC_NONE 0
#define ADVERT_LOC_SHARE 1
// Increment when a release must migrate the persisted Companion device-power
// policy. Version 1 corrects the short-lived default-off regression: old
// preference files are upgraded to power saving on exactly once, after which
// an explicit user choice remains persistent.
#define COMPANION_POWERSAVING_POLICY_VERSION 1
struct CompanionNodePrefs { // persisted to file
float airtime_factor;
char node_name[32];
@@ -46,9 +52,20 @@ struct CompanionNodePrefs { // persisted to file
uint8_t rx_ps_preamble; // 0=auto from SF, otherwise 16 or 32
uint8_t powersaving_enabled; // device CPU/GPS idle power saving
uint8_t wifi_enabled; // Companion WiFi radio and services
uint8_t powersaving_policy_version; // one-time default migration marker
// Keep the upstream repeat API while retaining the existing binary prefs
// layout used by this branch.
bool isRepeatEn() const { return client_repeat != 0; }
void setRepeatEn(bool enabled) { client_repeat = enabled ? 1 : 0; }
};
inline bool migrateCompanionPowerSavingDefault(CompanionNodePrefs& prefs) {
if (prefs.powersaving_policy_version == COMPANION_POWERSAVING_POLICY_VERSION) {
return false;
}
prefs.powersaving_enabled = 1;
prefs.powersaving_policy_version = COMPANION_POWERSAVING_POLICY_VERSION;
return true;
}
@@ -80,6 +80,23 @@ TEST(CompanionNodePrefs, WiFiStateIsIndependentFromPowerSaving) {
EXPECT_EQ(1, prefs.powersaving_enabled);
}
TEST(CompanionNodePrefs, MigratesRegressedPowerSavingDefaultOnce) {
CompanionNodePrefs prefs = {};
prefs.powersaving_enabled = 0;
prefs.powersaving_policy_version = 0;
EXPECT_TRUE(migrateCompanionPowerSavingDefault(prefs));
EXPECT_EQ(1, prefs.powersaving_enabled);
EXPECT_EQ(COMPANION_POWERSAVING_POLICY_VERSION,
prefs.powersaving_policy_version);
// Once migrated, an explicit user choice to turn power saving off remains
// untouched on later boots.
prefs.powersaving_enabled = 0;
EXPECT_FALSE(migrateCompanionPowerSavingDefault(prefs));
EXPECT_EQ(0, prefs.powersaving_enabled);
}
#if 0
// Re-enable test once we can SET fem_ values in companion
TEST(CompanionNodePrefs, RxGainSettingsRoundTripIndependently) {