Fix Companion device power saving
This commit is contained in:
1 parent
9161dfd7d5
commit
933697f65c
16 files changed
+1959
-1821
No files matched your search
@@ -96,7 +96,7 @@ fix, no WiFi connection, an inactive bridge, or an nRF52 bootloader without
|
||||
| System | [`get/set system.watchdog`](cli_commands.md#enable-or-disable-the-nrf52-system-watchdog) | nRF52 | Yes | Yes | Yes |
|
||||
| System | [`get public.key`](cli_commands.md#view-this-nodes-public-key) | All text CLI roles | Yes | Yes | Yes |
|
||||
| System | [`get role`](cli_commands.md#view-this-nodes-configured-role) | All text CLI roles | Yes | Yes | Yes |
|
||||
| System | [`powersaving`; `powersaving on/off`](cli_commands.md#view-or-change-this-nodes-power-saving-flag-repeater-only) | Supported repeater board | Feature | Feature | Feature |
|
||||
| System | [`powersaving`; `powersaving on/off`](cli_commands.md#view-or-change-this-nodes-power-saving-flag) | Supported repeater board | Feature | Feature | Feature |
|
||||
| System | [`get/set reboot.interval`](#reboot-interval) | Full parser | Yes | Yes | Yes |
|
||||
| Clock sync | [`get/set clock.sync.*`; `clock.sync.mesh now`](cli_commands.md#estimate-and-correct-infrastructure-node-time-after-startup) | Repeater, sensor, and room server; `clock.sync.internet` needs MQTT repeater | Yes | Yes | Yes |
|
||||
| Routing | [`get/set repeat`](cli_commands.md#view-or-change-this-nodes-repeat-flag) | Forwarding-capable role | Yes | Yes | Yes |
|
||||
@@ -253,7 +253,7 @@ fix, no WiFi connection, an inactive bridge, or an nRF52 bootloader without
|
||||
| System | [`get/set system.watchdog`](cli_commands.md#enable-or-disable-the-nrf52-system-watchdog) | nRF52 only | No | No | No | No | No | No | No |
|
||||
| System | [`get public.key`](cli_commands.md#view-this-nodes-public-key) | Full parser | Yes | Yes | Yes | No | No | Yes | Yes |
|
||||
| System | [`get role`](cli_commands.md#view-this-nodes-configured-role) | All text CLI roles | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
|
||||
| System | [`powersaving`; `powersaving on/off`](cli_commands.md#view-or-change-this-nodes-power-saving-flag-repeater-only) | Supported repeater board | Feature | Feature | Feature | No | No | Feature | Feature |
|
||||
| System | [`powersaving`; `powersaving on/off`](cli_commands.md#view-or-change-this-nodes-power-saving-flag) | Supported repeater board | Feature | Feature | Feature | No | No | Feature | Feature |
|
||||
| System | [`get/set reboot.interval`](#reboot-interval) | Full parser | Yes | Yes | Yes | No | No | Yes | Yes |
|
||||
| Clock sync | [`get/set clock.sync.*`; `clock.sync.mesh now`](cli_commands.md#estimate-and-correct-infrastructure-node-time-after-startup) | Repeater, sensor, and room server; `clock.sync.internet` needs MQTT repeater | Yes | Yes | Yes | No | Yes | Yes | Yes |
|
||||
| Routing | [`get/set repeat`](cli_commands.md#view-or-change-this-nodes-repeat-flag) | Forwarding-capable role | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
|
||||
|
||||
@@ -1076,7 +1076,7 @@ get clock.sync.status
|
||||
|
||||
---
|
||||
|
||||
#### View or change this node's power saving flag (Repeater Only)
|
||||
#### View or change this node's power saving flag
|
||||
**Usage:**
|
||||
- `powersaving`
|
||||
- `powersaving on`
|
||||
@@ -1088,7 +1088,9 @@ get clock.sync.status
|
||||
|
||||
**Default:** `off`
|
||||
|
||||
**Note:** When enabled, device enters sleep mode between radio transmissions. Enabling is refused from the local serial console or while an active USB serial data connection is detected; USB power alone does not block power saving.
|
||||
**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`).
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -65,6 +65,21 @@ set radio.fem.txgain on
|
||||
The selected states are applied immediately and retained after reboot. FEM TX
|
||||
gain is reported as unsupported on boards without software-selectable PA gain.
|
||||
|
||||
Device power saving is separate from LoRa RXPS. It can be changed in WebConfig
|
||||
with the **Device power saving** switch or from the USB terminal:
|
||||
|
||||
```text
|
||||
powersaving
|
||||
powersaving on
|
||||
powersaving off
|
||||
```
|
||||
|
||||
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
|
||||
states; WiFi modem sleep stays enabled when BLE is present because coexistence
|
||||
requires it. The selected state is retained after reboot.
|
||||
|
||||
Artifacts are written to `out/` by default.
|
||||
|
||||
On 4 MB ESP32 boards, the full target uses a single 3 MB application
|
||||
|
||||
@@ -333,6 +333,10 @@ void DataStore::loadPrefsInt(const char *filename, CompanionNodePrefs& _prefs, d
|
||||
file.read((uint8_t *)&_prefs.rx_ps_sleep_us, sizeof(_prefs.rx_ps_sleep_us)); // 131
|
||||
file.read((uint8_t *)&_prefs.rx_ps_level, sizeof(_prefs.rx_ps_level)); // 135
|
||||
file.read((uint8_t *)&_prefs.rx_ps_preamble, sizeof(_prefs.rx_ps_preamble)); // 136
|
||||
if (file.available() >= (int)sizeof(_prefs.powersaving_enabled)) {
|
||||
file.read((uint8_t *)&_prefs.powersaving_enabled,
|
||||
sizeof(_prefs.powersaving_enabled)); // 137
|
||||
}
|
||||
}
|
||||
|
||||
file.close();
|
||||
@@ -395,6 +399,8 @@ bool DataStore::savePrefs(const CompanionNodePrefs& _prefs, double node_lat, dou
|
||||
sizeof(_prefs.rx_ps_level)) == sizeof(_prefs.rx_ps_level); // 135
|
||||
success = success && file.write((uint8_t *)&_prefs.rx_ps_preamble,
|
||||
sizeof(_prefs.rx_ps_preamble)) == sizeof(_prefs.rx_ps_preamble); // 136
|
||||
success = success && file.write((uint8_t *)&_prefs.powersaving_enabled,
|
||||
sizeof(_prefs.powersaving_enabled)) == sizeof(_prefs.powersaving_enabled); // 137
|
||||
|
||||
#if defined(NRF52_PLATFORM)
|
||||
success = file.commit(success);
|
||||
|
||||
@@ -1355,6 +1355,7 @@ 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;
|
||||
recalcRxPowerSavingFromLevel(_prefs.rx_ps_level, _prefs.sf, _prefs.bw,
|
||||
_prefs.rx_ps_preamble, &_prefs.rx_ps_rx_us,
|
||||
&_prefs.rx_ps_sleep_us);
|
||||
@@ -1437,6 +1438,7 @@ void MyMesh::begin(bool has_display) {
|
||||
_prefs.radio_fem_rxgain = constrain(_prefs.radio_fem_rxgain, 0, 1);
|
||||
_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.rx_ps_level = constrain(_prefs.rx_ps_level, 0, 10);
|
||||
if (_prefs.rx_ps_preamble != 16 && _prefs.rx_ps_preamble != 32) {
|
||||
_prefs.rx_ps_preamble = 0;
|
||||
@@ -1883,9 +1885,11 @@ void MyMesh::getNodeSnapshot(WebConfigServer::NodeSnapshot& s) {
|
||||
s.rx_ps_preamble = _prefs.rx_ps_preamble;
|
||||
s.rx_ps_rx_us = _prefs.rx_ps_rx_us;
|
||||
s.rx_ps_sleep_us = _prefs.rx_ps_sleep_us;
|
||||
s.power_saving = _prefs.powersaving_enabled;
|
||||
s.repeat = _prefs.client_repeat != 0;
|
||||
s.capabilities = WebConfigServer::CAP_LOCATION | WebConfigServer::CAP_AIRTIME
|
||||
| WebConfigServer::CAP_RX_DELAY | WebConfigServer::CAP_RX_GAIN;
|
||||
| WebConfigServer::CAP_RX_DELAY | WebConfigServer::CAP_RX_GAIN
|
||||
| WebConfigServer::CAP_POWER_SAVING;
|
||||
if (board.canControlLoRaFemLna()) {
|
||||
s.capabilities |= WebConfigServer::CAP_FEM_RX_GAIN;
|
||||
}
|
||||
@@ -2069,6 +2073,10 @@ void MyMesh::execCommand(char* cmd, char* reply) {
|
||||
applyAndSaveRxPowerSaving(value, reply);
|
||||
return;
|
||||
}
|
||||
if (strcmp(key, "powersaving") == 0) {
|
||||
applyAndSavePowerSaving(value, reply);
|
||||
return;
|
||||
}
|
||||
if (strcmp(key, "radio.fem.rxgain") == 0) {
|
||||
bool enabled;
|
||||
if (!wcParseBool(value, enabled)) {
|
||||
@@ -3507,6 +3515,24 @@ bool MyMesh::applyAndSaveFemTxGain(bool enabled) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MyMesh::applyAndSavePowerSaving(const char* value, char* reply) {
|
||||
bool enabled;
|
||||
if (strcmp(value, "on") == 0) {
|
||||
enabled = true;
|
||||
} else if (strcmp(value, "off") == 0) {
|
||||
enabled = false;
|
||||
} else {
|
||||
strcpy(reply, "Error: use powersaving on or powersaving off");
|
||||
return false;
|
||||
}
|
||||
|
||||
_prefs.powersaving_enabled = enabled ? 1 : 0;
|
||||
sensors.setPowerSavingEnabled(enabled);
|
||||
savePrefs();
|
||||
snprintf(reply, 160, "OK - powersaving %s", enabled ? "on" : "off");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MyMesh::applyAndSaveRxPowerSaving(const char* value, char* reply) {
|
||||
if (!radio_driver.supportsRxPowerSaving()) {
|
||||
strcpy(reply, "Error: RX power saving unsupported");
|
||||
@@ -4395,6 +4421,14 @@ void MyMesh::handleTerminalCommand(char* command) {
|
||||
}
|
||||
} else if (strncmp(command, "import ", 7) == 0) {
|
||||
importTerminalCard(command + 7);
|
||||
} else if (strcmp(command, "powersaving") == 0
|
||||
|| strcmp(command, "get powersaving") == 0) {
|
||||
Serial.printf(" powersaving %s\r\n",
|
||||
_prefs.powersaving_enabled ? "on" : "off");
|
||||
} else if (strncmp(command, "powersaving ", 12) == 0) {
|
||||
char reply[160];
|
||||
applyAndSavePowerSaving(command + 12, reply);
|
||||
Serial.printf(" %s\r\n", reply);
|
||||
} else if (strcmp(command, "get radio.fem.rxgain") == 0) {
|
||||
if (!board.canControlLoRaFemLna()) {
|
||||
Serial.print(" ERROR: FEM RX gain control is unsupported on this board\r\n");
|
||||
@@ -4411,7 +4445,11 @@ void MyMesh::handleTerminalCommand(char* command) {
|
||||
}
|
||||
} else if (strncmp(command, "set ", 4) == 0) {
|
||||
const char* config = command + 4;
|
||||
if (strncmp(config, "af ", 3) == 0) {
|
||||
if (strncmp(config, "powersaving ", 12) == 0) {
|
||||
char reply[160];
|
||||
applyAndSavePowerSaving(config + 12, reply);
|
||||
Serial.printf(" %s\r\n", reply);
|
||||
} else if (strncmp(config, "af ", 3) == 0) {
|
||||
_prefs.airtime_factor = constrain((float)atof(config + 3), 0.0f, 9.0f);
|
||||
savePrefs();
|
||||
Serial.print(" OK\r\n");
|
||||
@@ -4472,6 +4510,7 @@ void MyMesh::handleTerminalCommand(char* command) {
|
||||
} else if (strcmp(command, "help") == 0) {
|
||||
Serial.print("Commands:\r\n");
|
||||
Serial.print(" set {name|lat|lon|freq|tx|af} {value}\r\n");
|
||||
Serial.print(" powersaving [on|off]\r\n");
|
||||
Serial.print(" get radio.fem.rxgain\r\n");
|
||||
Serial.print(" set radio.fem.rxgain <on|off>\r\n");
|
||||
Serial.print(" get radio.fem.txgain\r\n");
|
||||
|
||||
@@ -278,6 +278,7 @@ private:
|
||||
void checkSerialInterface();
|
||||
bool applyAndSaveFemRxGain(bool enabled);
|
||||
bool applyAndSaveFemTxGain(bool enabled);
|
||||
bool applyAndSavePowerSaving(const char* value, char* reply);
|
||||
bool applyAndSaveRxPowerSaving(const char* value, char* reply);
|
||||
#ifdef ENABLE_USB_INTERFACE
|
||||
ContactInfo* getTerminalRecipient();
|
||||
|
||||
@@ -44,6 +44,7 @@ struct CompanionNodePrefs { // persisted to file
|
||||
uint32_t rx_ps_sleep_us; // sleep window in microseconds
|
||||
uint8_t rx_ps_level; // 0=manual timings, 1..10=level-derived
|
||||
uint8_t rx_ps_preamble; // 0=auto from SF, otherwise 16 or 32
|
||||
uint8_t powersaving_enabled; // device CPU/GPS idle power saving
|
||||
|
||||
// Keep the upstream repeat API while retaining the existing binary prefs
|
||||
// layout used by this branch.
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include "MyMesh.h"
|
||||
|
||||
#ifdef ESP32_PLATFORM
|
||||
#include "esp_pm.h"
|
||||
#include "esp_bt.h"
|
||||
#endif
|
||||
|
||||
@@ -122,6 +121,74 @@ MyMesh the_mesh(radio_driver, fast_rng, rtc_clock, tables, store
|
||||
|
||||
/* END GLOBAL OBJECTS */
|
||||
|
||||
#ifdef ESP32_PLATFORM
|
||||
static int8_t applied_power_saving = -1;
|
||||
static int8_t attempted_power_saving = -1;
|
||||
static unsigned long power_saving_retry_at = 0;
|
||||
|
||||
static uint32_t companionNominalCpuMhz() {
|
||||
#ifdef ESP32_CPU_FREQ
|
||||
return ESP32_CPU_FREQ;
|
||||
#else
|
||||
return F_CPU / 1000000UL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool applyCompanionPowerSaving(bool enabled) {
|
||||
const uint32_t nominal_mhz = companionNominalCpuMhz();
|
||||
const uint32_t target_mhz = enabled && nominal_mhz > 80 ? 80 : nominal_mhz;
|
||||
if (!setCpuFrequencyMhz(target_mhz)) {
|
||||
Serial.printf("Device power saving failed: CPU %lu MHz is unsupported\r\n",
|
||||
(unsigned long)target_mhz);
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(BLE_PIN_CODE) && !CONFIG_IDF_TARGET_ESP32C6
|
||||
esp_err_t bt_result = enabled ? esp_bt_sleep_enable()
|
||||
: esp_bt_sleep_disable();
|
||||
if (bt_result != ESP_OK) {
|
||||
Serial.printf("Bluetooth sleep %s failed: %s\r\n",
|
||||
enabled ? "enable" : "disable",
|
||||
esp_err_to_name(bt_result));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WIFI_SSID
|
||||
#if defined(BLE_PIN_CODE)
|
||||
// WiFi modem sleep is required for WiFi/BLE coexistence in Full Companion.
|
||||
WiFi.setSleep(true);
|
||||
#else
|
||||
WiFi.setSleep(enabled);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
Serial.printf("Device power saving %s: CPU %lu MHz\r\n",
|
||||
enabled ? "on" : "off", (unsigned long)target_mhz);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void serviceCompanionPowerSaving(bool force = false) {
|
||||
const int8_t requested = the_mesh.getNodePrefs()->powersaving_enabled ? 1 : 0;
|
||||
if (!force && applied_power_saving == requested) return;
|
||||
|
||||
const unsigned long now = millis();
|
||||
if (!force && attempted_power_saving == requested
|
||||
&& power_saving_retry_at != 0
|
||||
&& (int32_t)(now - power_saving_retry_at) < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
attempted_power_saving = requested;
|
||||
if (applyCompanionPowerSaving(requested != 0)) {
|
||||
applied_power_saving = requested;
|
||||
power_saving_retry_at = 0;
|
||||
} else {
|
||||
power_saving_retry_at = now + 5000;
|
||||
if (power_saving_retry_at == 0) power_saving_retry_at = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(ENABLE_USB_INTERFACE)
|
||||
static char usb_terminal_line[MAX_TRANS_UNIT * 2 + 32];
|
||||
static size_t usb_terminal_line_len = 0;
|
||||
@@ -664,12 +731,12 @@ void setup() {
|
||||
the_mesh.startInterface(interface_manager);
|
||||
sensors.begin();
|
||||
|
||||
#if ENV_INCLUDE_GPS == 1 && defined(BLE_PIN_CODE)
|
||||
// BLE companions keep GPS duty cycling enabled by default: at most 10
|
||||
// minutes awake, followed by 5 minutes asleep.
|
||||
#if ENV_INCLUDE_GPS == 1
|
||||
// Device power saving applies a 10-minute awake, 5-minute sleep GPS cycle.
|
||||
if (sensors.getLocationProvider() != NULL) {
|
||||
sensors.getLocationProvider()->setPowerSavingProfile(600, 300);
|
||||
sensors.setPowerSavingEnabled(true);
|
||||
sensors.setPowerSavingEnabled(
|
||||
the_mesh.getNodePrefs()->powersaving_enabled != 0);
|
||||
}
|
||||
#endif
|
||||
#if ENV_INCLUDE_GPS == 1
|
||||
@@ -683,34 +750,7 @@ void setup() {
|
||||
board.onBootComplete();
|
||||
|
||||
#ifdef ESP32_PLATFORM
|
||||
#if !CONFIG_IDF_TARGET_ESP32C6
|
||||
// Enable BLE sleep
|
||||
esp_err_t errBLESleep = esp_bt_sleep_enable();
|
||||
if (errBLESleep == ESP_OK) {
|
||||
Serial.println("Bluetooth sleep enabled successfully");
|
||||
} else {
|
||||
Serial.printf("Bluetooth sleep enable failed: %s\n", esp_err_to_name(errBLESleep));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32C3
|
||||
esp_pm_config_esp32c3_t pm_config;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
esp_pm_config_esp32s3_t pm_config;
|
||||
#elif CONFIG_IDF_TARGET_ESP32
|
||||
esp_pm_config_esp32_t pm_config;
|
||||
#elif CONFIG_IDF_TARGET_ESP32C6
|
||||
esp_pm_config_t pm_config;
|
||||
#endif
|
||||
|
||||
// Configure Power Management
|
||||
pm_config = { .max_freq_mhz = 80, .min_freq_mhz = 40, .light_sleep_enable = true };
|
||||
esp_err_t errPM = esp_pm_configure(&pm_config);
|
||||
if (errPM == ESP_OK) {
|
||||
Serial.println("Power Management configured successfully");
|
||||
} else {
|
||||
Serial.printf("Power Management failed to configure: %d\r\n", errPM);
|
||||
}
|
||||
serviceCompanionPowerSaving(true);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -744,9 +784,14 @@ void loop() {
|
||||
external_watchdog.loop();
|
||||
#endif
|
||||
|
||||
#ifdef ESP32_PLATFORM
|
||||
serviceCompanionPowerSaving();
|
||||
#endif
|
||||
|
||||
// USB power alone (for example, a wall charger) must not disable power
|
||||
// saving. Stay awake only while a computer has an active USB data session.
|
||||
bool can_sleep = !the_mesh.hasPendingWork();
|
||||
bool can_sleep = the_mesh.getNodePrefs()->powersaving_enabled
|
||||
&& !the_mesh.hasPendingWork();
|
||||
#if defined(NRF52_PLATFORM)
|
||||
can_sleep = can_sleep && !board.isUsbHostConnected();
|
||||
#endif
|
||||
|
||||
@@ -104,6 +104,7 @@ def default_config(setup_mode):
|
||||
"rxdelay": 0.0, "txdelay": 0.5, "cad": False, "rxgain": True,
|
||||
"rxps_enabled": True, "rxps_level": 5, "rxps_preamble": 16,
|
||||
"rxps_rx_us": 20936, "rxps_sleep_us": 13425,
|
||||
"powersaving": False,
|
||||
"repeat": True, "flood_max": 64, "flood_max_advert": 8,
|
||||
"flood_max_unscoped": 8, "loop_detect": "moderate",
|
||||
"name": "MockNode", "lat": 39.7392, "lon": -104.9903,
|
||||
@@ -196,8 +197,8 @@ class State:
|
||||
"uptime_s": int(time.time() - self.start),
|
||||
"runtime_slots": 6, "max_slots": 6, "active_slots": self.active_slots,
|
||||
# Every ordinary repeater feature except an external FEM, plus
|
||||
# radio RX power saving (bit 12).
|
||||
"capabilities": 0x17FF,
|
||||
# radio RX power saving (bit 12) and device power saving (bit 13).
|
||||
"capabilities": 0x37FF,
|
||||
"max_cmds": CLI_MAX_CMDS,
|
||||
}
|
||||
|
||||
@@ -207,6 +208,7 @@ class State:
|
||||
# to produce realistic per-field OK / Error replies for the UI chips).
|
||||
# ---------------------------------------------------------------------------
|
||||
BOOL_KEYS = {"cad": ("radio", "cad"), "radio.rxgain": ("radio", "rxgain"),
|
||||
"powersaving": ("radio", "powersaving"),
|
||||
"repeat": ("radio", "repeat"), "mqtt.status": ("mqtt", "status"),
|
||||
"mqtt.packets": ("mqtt", "packets"), "mqtt.raw": ("mqtt", "raw"),
|
||||
"mqtt.rx": ("mqtt", "rx"), "snmp": ("mqtt", "snmp"),
|
||||
|
||||
@@ -19,7 +19,8 @@
|
||||
static const char* const WC_ALLOWED_SET_KEYS[] = {
|
||||
// NodePrefs (radio / node)
|
||||
"name", "lat", "lon", "radio", "tx", "af", "rxdelay", "txdelay",
|
||||
"cad", "radio.rxgain", "radio.fem.rxgain", "radio.rxps", "repeat",
|
||||
"cad", "radio.rxgain", "radio.fem.rxgain", "radio.rxps", "powersaving",
|
||||
"repeat",
|
||||
"advert.interval", "flood.advert.interval",
|
||||
"flood.max", "flood.max.advert", "flood.max.unscoped", "loop.detect",
|
||||
// MQTTPrefs (WiFi / MQTT / misc observer)
|
||||
|
||||
+1782
-1778
File diff suppressed because it is too large.
Load diff
@@ -1438,6 +1438,7 @@ void WebConfigServer::handleConfigGet(AsyncWebServerRequest* req) {
|
||||
radio["rxps_preamble"] = node.rx_ps_preamble;
|
||||
radio["rxps_rx_us"] = node.rx_ps_rx_us;
|
||||
radio["rxps_sleep_us"] = node.rx_ps_sleep_us;
|
||||
radio["powersaving"] = (bool)node.power_saving;
|
||||
radio["repeat"] = (bool)node.repeat;
|
||||
radio["flood_max"] = node.flood_max;
|
||||
radio["flood_max_advert"] = node.flood_max_advert;
|
||||
|
||||
@@ -59,6 +59,7 @@ public:
|
||||
CAP_WIFI_POWER_SAVE = 1UL << 10,
|
||||
CAP_FEM_RX_GAIN = 1UL << 11,
|
||||
CAP_RX_POWER_SAVING = 1UL << 12,
|
||||
CAP_POWER_SAVING = 1UL << 13,
|
||||
CAP_DELAYS = CAP_RX_DELAY | CAP_TX_DELAY,
|
||||
};
|
||||
|
||||
@@ -86,6 +87,7 @@ public:
|
||||
uint8_t rx_ps_preamble;
|
||||
uint32_t rx_ps_rx_us;
|
||||
uint32_t rx_ps_sleep_us;
|
||||
uint8_t power_saving;
|
||||
uint8_t repeat;
|
||||
uint16_t advert_interval;
|
||||
uint8_t flood_advert_interval;
|
||||
|
||||
@@ -50,6 +50,21 @@ public:
|
||||
const std::string& text() const { return _text; }
|
||||
};
|
||||
|
||||
TEST(CompanionNodePrefs, DevicePowerSavingIsIndependentFromRxps) {
|
||||
CompanionNodePrefs prefs = {};
|
||||
prefs.rx_powersaving_enabled = 1;
|
||||
prefs.powersaving_enabled = 0;
|
||||
|
||||
EXPECT_EQ(1, prefs.rx_powersaving_enabled);
|
||||
EXPECT_EQ(0, prefs.powersaving_enabled);
|
||||
|
||||
prefs.powersaving_enabled = 1;
|
||||
prefs.rx_powersaving_enabled = 0;
|
||||
|
||||
EXPECT_EQ(0, prefs.rx_powersaving_enabled);
|
||||
EXPECT_EQ(1, prefs.powersaving_enabled);
|
||||
}
|
||||
|
||||
#if 0
|
||||
// Re-enable test once we can SET fem_ values in companion
|
||||
TEST(CompanionNodePrefs, RxGainSettingsRoundTripIndependently) {
|
||||
|
||||
@@ -10,6 +10,7 @@ TEST(WebConfigKeys, AllowsKnownScalarKeys) {
|
||||
EXPECT_TRUE(wcIsAllowedSetKey("name"));
|
||||
EXPECT_TRUE(wcIsAllowedSetKey("radio"));
|
||||
EXPECT_TRUE(wcIsAllowedSetKey("radio.rxps"));
|
||||
EXPECT_TRUE(wcIsAllowedSetKey("powersaving"));
|
||||
EXPECT_TRUE(wcIsAllowedSetKey("repeat"));
|
||||
EXPECT_TRUE(wcIsAllowedSetKey("wifi.ssid"));
|
||||
EXPECT_TRUE(wcIsAllowedSetKey("mqtt.iata"));
|
||||
|
||||
@@ -387,6 +387,8 @@ body.tab-cli{padding-bottom:0}
|
||||
<span class="tgl"><input type="checkbox" data-k="radio.rxgain"><u></u></span></div>
|
||||
<div class="sw" data-cap="2048"><span><b>FEM RX boost</b><i>External front-end-module LNA</i></span>
|
||||
<span class="tgl"><input type="checkbox" data-k="radio.fem.rxgain"><u></u></span></div>
|
||||
<div class="sw" data-cap="8192"><span><b>Device power saving</b><i>Reduce CPU and GPS idle power; USB, BLE, and WiFi stay available</i></span>
|
||||
<span class="tgl"><input type="checkbox" data-k="powersaving"><u></u></span></div>
|
||||
<div data-cap="4096" id="rxps-wrap">
|
||||
<div class="sw"><span><b>RX power saving</b><i>Duty-cycle the LoRa receiver; off keeps continuous receive</i></span>
|
||||
<span class="tgl"><input type="checkbox" data-rxps="enabled"><u></u></span></div>
|
||||
@@ -738,6 +740,7 @@ function cfgVal(k){ // map a `set` key to its current value string, from st.cfg
|
||||
case"cad":return r.cad?"on":"off";case"radio.rxgain":return r.rxgain?"on":"off";
|
||||
case"radio.fem.rxgain":return r.fem_rxgain?"on":"off";
|
||||
case"radio.rxps":return rxpsCfgValue(r);
|
||||
case"powersaving":return r.powersaving?"on":"off";
|
||||
case"repeat":return r.repeat?"on":"off";
|
||||
case"flood.max":return String(r.flood_max);
|
||||
case"flood.max.advert":return String(r.flood_max_advert);
|
||||
|
||||
Reference in new issue
Block a user