Expose Companion WiFi and radio power controls
This commit is contained in:
1 parent
7a4da3ccfb
commit
e4c8ae5a0b
27 files changed
+1840
-1349
No files matched your search
+12
-2
@@ -332,7 +332,9 @@ You can flash the merged firmware using either the web flasher or the command li
|
||||
- `WITH_SNMP=1` - Enable SNMP agent (optional, see [MQTT_SNMP.md](MQTT_SNMP.md))
|
||||
- `MQTT_DEBUG=1` - Enable debug logging (optional)
|
||||
- `MQTT_WIFI_TX_POWER` - WiFi TX power level (default: `WIFI_POWER_11dBm`)
|
||||
- ~~`MQTT_WIFI_POWER_SAVE_DEFAULT`~~ - Removed; all builds now default to `none` (no power save)
|
||||
- `DEFAULT_WIFI_POWER_SAVE_MODE` - Fresh-install WiFi modem-sleep default:
|
||||
`0` = `min`, `1` = `none`, `2` = `max`. The Cascade profile sets `0`;
|
||||
target-default builds use `1`.
|
||||
|
||||
#### Compile-time fresh-install defaults (`src/helpers/MQTTDefaults.h`)
|
||||
|
||||
@@ -344,6 +346,7 @@ Optional PlatformIO `build_flags` override defaults written when `/mqtt_prefs` i
|
||||
| `MQTT_DEFAULT_IATA` | (empty) | e.g. `'"YYZ"'` |
|
||||
| `MQTT_DEFAULT_TIMEZONE` | (empty) | e.g. `'"America/Toronto"'` |
|
||||
| `MQTT_DEFAULT_TIMEZONE_OFFSET` | `0` | Fallback hours when TZ string is empty |
|
||||
| `DEFAULT_WIFI_POWER_SAVE_MODE` | `1` (`none`); Cascade profile: `0` (`min`) | Fresh MQTT and standalone WebConfig WiFi setting; saved settings take precedence |
|
||||
|
||||
Example community build:
|
||||
|
||||
@@ -377,7 +380,8 @@ The MQTT bridge comes with the following defaults for fresh installs (unless ove
|
||||
- **Per-slot packet filters**: `all` (every payload type is uploaded)
|
||||
- **WiFi SSID**: (blank - must be configured)
|
||||
- **WiFi Password**: (blank - optional for open networks)
|
||||
- **WiFi Power Save**: `none` (no power save)
|
||||
- **WiFi Power Save**: `min` for Cascade-profile builds; otherwise `none`
|
||||
(a saved setting takes precedence)
|
||||
- **Timezone**: (blank - uses UTC until configured, unless `MQTT_DEFAULT_TIMEZONE` is set at build time)
|
||||
- **Timezone Offset**: 0 (fallback, no offset, unless `MQTT_DEFAULT_TIMEZONE_OFFSET` is set)
|
||||
- **Repeat (forwarding)**: On (set `repeat off` for receive-only observers)
|
||||
@@ -613,6 +617,12 @@ These settings apply across all MQTT slots:
|
||||
- `min` - Minimum power saving (balanced performance and power)
|
||||
- `max` - Maximum power saving (lowest power consumption, may affect performance)
|
||||
|
||||
On an ESP32 MQTT Companion, the Companion-owned `mesh-wifi` setting is the
|
||||
canonical WiFi power-save value. It is exposed in Companion WebConfig and the
|
||||
binary Companion protocol. Full Companion also exposes it on the USB terminal
|
||||
and TCP port 5002, but rejects `none` because its BLE transport requires modem
|
||||
sleep. Changing Companion device `powersaving` does not overwrite this value.
|
||||
|
||||
### Timezone Commands
|
||||
|
||||
#### Get Commands
|
||||
|
||||
@@ -934,7 +934,7 @@ prompt_for_radio_build_settings() {
|
||||
prompt_for_firmware_profile_settings() {
|
||||
local -a options=(
|
||||
"Keep target defaults"
|
||||
"Cascade: path.hash.mode=2 / loop.detect=minimal / cad=on / rxdelay=2 / agc.reset.interval=8 / advert.interval=0 / flood.advert.interval=83 / multi.acks=1 / companion.manual.add=1 / companion.autoadd=0"
|
||||
"Cascade: power saving + RXPS on / WiFi power save=min / path.hash.mode=2 / loop.detect=minimal / cad=on / rxdelay=2 / agc.reset.interval=8 / advert.interval=0 / flood.advert.interval=83 / multi.acks=1 / companion.manual.add=1 / companion.autoadd=0"
|
||||
)
|
||||
|
||||
clear_firmware_profile_overrides
|
||||
@@ -2419,7 +2419,7 @@ apply_radio_overrides() {
|
||||
apply_firmware_profile_overrides() {
|
||||
case "${FIRMWARE_PROFILE_OVERRIDE,,}" in
|
||||
cascade)
|
||||
export PLATFORMIO_BUILD_FLAGS="${PLATFORMIO_BUILD_FLAGS} -DCASCADE_PROFILE=1 -DDEFAULT_PATH_HASH_MODE=2 -DDEFAULT_LOOP_DETECT=1 -DDEFAULT_CAD_ENABLED=1 -DDEFAULT_RX_DELAY_BASE=2.0f -DDEFAULT_AGC_RESET_INTERVAL_SECONDS=8 -DDEFAULT_ADVERT_INTERVAL_MINUTES=0 -DDEFAULT_FLOOD_ADVERT_INTERVAL_HOURS=83 -DDEFAULT_MULTI_ACKS=1 -DDEFAULT_MANUAL_ADD_CONTACTS=1 -DDEFAULT_AUTOADD_CONFIG=0 -DDEFAULT_POWERSAVING_ENABLED=1 -DDEFAULT_RXPS_ENABLED=1 -DDEFAULT_RXPS_LEVEL=8 -DDEFAULT_RXPS_PREAMBLE=16 -DRXPS_FIXED_ENABLED=1 -DRXPS_FIXED_LEVEL=8 -DRXPS_FIXED_PREAMBLE=16"
|
||||
export PLATFORMIO_BUILD_FLAGS="${PLATFORMIO_BUILD_FLAGS} -DCASCADE_PROFILE=1 -DDEFAULT_PATH_HASH_MODE=2 -DDEFAULT_LOOP_DETECT=1 -DDEFAULT_CAD_ENABLED=1 -DDEFAULT_RX_DELAY_BASE=2.0f -DDEFAULT_AGC_RESET_INTERVAL_SECONDS=8 -DDEFAULT_ADVERT_INTERVAL_MINUTES=0 -DDEFAULT_FLOOD_ADVERT_INTERVAL_HOURS=83 -DDEFAULT_MULTI_ACKS=1 -DDEFAULT_MANUAL_ADD_CONTACTS=1 -DDEFAULT_AUTOADD_CONFIG=0 -DDEFAULT_POWERSAVING_ENABLED=1 -DDEFAULT_RXPS_ENABLED=1 -DDEFAULT_RXPS_LEVEL=8 -DDEFAULT_RXPS_PREAMBLE=16 -DRXPS_FIXED_ENABLED=1 -DRXPS_FIXED_LEVEL=8 -DRXPS_FIXED_PREAMBLE=16 -DDEFAULT_WIFI_POWER_SAVE_MODE=0"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
+34
-13
@@ -77,6 +77,8 @@ Fresh MQTT observer settings are:
|
||||
- slot 1 set to `analyzer-us`;
|
||||
- slot 2 set to `analyzer-eu`;
|
||||
- slots 3 through 6 disabled;
|
||||
- WiFi modem power saving set to `min` in the Cascade profile and `none` in
|
||||
target-default builds;
|
||||
- WiFi SSID and IATA code empty.
|
||||
|
||||
Up to six broker configurations can be saved. The number that can be active at
|
||||
@@ -196,8 +198,17 @@ the station IP.
|
||||
|
||||
If the configured network remains unavailable for two minutes, the companion
|
||||
opens its setup AP so the credentials can be repaired. It continues retrying
|
||||
the saved network. WiFi modem sleep is forced off on WiFi companions because
|
||||
modem-sleep pauses can interfere with timely LoRa radio servicing.
|
||||
the saved network. WiFi modem sleep has its own persisted `wifi.powersave`
|
||||
setting and is independent of the Companion device `powersaving` setting. The
|
||||
WiFi card in Companion WebConfig exposes `none`, `min`, and `max`. Fresh
|
||||
Cascade-profile builds select `min`; target-default builds select `none`.
|
||||
A saved setting takes precedence after an upgrade.
|
||||
|
||||
WiFi-only Companions can use all three modes. A Full Companion also runs BLE,
|
||||
so ESP32 WiFi/Bluetooth coexistence requires at least minimum modem sleep. It
|
||||
reports `min` when an old or target-default `none` value is found and rejects a
|
||||
new `none` selection while Bluetooth is compiled in. Device power saving can
|
||||
therefore be turned on or off without changing the selected WiFi modem policy.
|
||||
|
||||
WiFi companions do not have the repeater/room-server admin CLI password model,
|
||||
so their LAN WebConfig page is intentionally unauthenticated. Use them only on
|
||||
@@ -207,14 +218,16 @@ The WebConfig **Advanced** card exposes device power saving on WiFi Companion,
|
||||
repeater, and room-server builds. It also exposes RX power saving on radio chips
|
||||
that support receive duty cycling. RXPS can select continuous receive, levels
|
||||
1-10, automatic or explicit 16/32-symbol preambles, or manual receive/sleep
|
||||
windows. Both settings are persisted across reboots.
|
||||
windows. The WebConfig **WiFi** card exposes WiFi modem power saving. All three
|
||||
settings are persisted across reboots.
|
||||
|
||||
The two settings are independent. A WiFi Companion keeps its transports
|
||||
The three settings are independent. A WiFi Companion keeps its transports
|
||||
available while device power saving reduces CPU and GPS idle power. An
|
||||
infrastructure node can sleep when device power saving is enabled, so its WiFi
|
||||
services may be temporarily unavailable. RXPS only duty-cycles the LoRa
|
||||
receiver. Fresh Cascade-profile builds default to device power saving on and
|
||||
RXPS on at level 8 with a 16-symbol preamble.
|
||||
receiver. Fresh Cascade-profile builds default to device power saving on,
|
||||
RXPS on at level 8 with a 16-symbol preamble, and WiFi modem power saving at
|
||||
`min` on every build that includes ESP32 WiFi.
|
||||
|
||||
When `ENABLE_OTA` is included, a WiFi companion also listens on:
|
||||
|
||||
@@ -223,8 +236,8 @@ When `ENABLE_OTA` is included, a WiFi companion also listens on:
|
||||
|
||||
These ports do not replace the companion protocol on TCP 5000.
|
||||
On a `companion_radio_full` build, port 5002 additionally accepts bounded
|
||||
`tempradio` and `normalradio` commands, while LoRa staging and installation on
|
||||
the Companion itself are disabled.
|
||||
`tempradio`, `normalradio`, and `get/set wifi.powersave` commands, while LoRa
|
||||
staging and installation on the Companion itself are disabled.
|
||||
|
||||
FULL ESP32 builds share the port 5001 folder seeder. It starts whenever that
|
||||
role has a usable WiFi station or setup access point and stops when WiFi stops.
|
||||
@@ -395,10 +408,16 @@ set wifi.powersave min
|
||||
set wifi.powersave max
|
||||
```
|
||||
|
||||
The default is `none`, which gives the most predictable MQTT and radio
|
||||
performance at the highest power use. `min` and `max` reduce power but may add
|
||||
latency or reduce reliability on busy nodes. WiFi companions always disable
|
||||
modem sleep regardless of this observer setting.
|
||||
Fresh Cascade-profile builds default to `min`; target-default builds use
|
||||
`none`, which gives the most predictable MQTT and radio performance at the
|
||||
highest power use. `min` and `max` reduce power but may add latency or reduce
|
||||
reliability on busy nodes. A saved operator setting takes precedence on an
|
||||
upgrade. ESP32 WiFi Companions expose the same values in their WebConfig WiFi
|
||||
card. Full Companion also accepts the text commands from its USB terminal and
|
||||
TCP port 5002. The normal binary Companion protocol can read or write the
|
||||
setting over USB, BLE, or TCP port 5000 without entering terminal mode. Full
|
||||
Companion rejects `none` because its simultaneous BLE transport requires WiFi
|
||||
modem sleep.
|
||||
|
||||
MQTT observer targets normally limit ESP32 WiFi transmit power to 11 dBm unless
|
||||
the board configuration overrides `MQTT_WIFI_TX_POWER`. This setting affects
|
||||
@@ -408,7 +427,9 @@ WiFi only, not LoRa transmit power.
|
||||
|
||||
`get wifi.status`, `get wifi.ssid`, `get wifi.powersave`, and `get wifi.cli`
|
||||
are available on MQTT observers and on FULL non-MQTT repeater/room-server
|
||||
builds with WebConfig.
|
||||
builds with WebConfig. ESP32 WiFi Companions expose `wifi.powersave` through
|
||||
their role-specific interfaces described above; they do not expose the full
|
||||
infrastructure WiFi CLI family.
|
||||
MQTT commands such as `get mqtt.status` and `set mqtt1.preset ...` still require
|
||||
an MQTT observer target. Unknown settings return `Error: unknown setting:
|
||||
<name>`. Older portable builds can instead report `Unsupported in this
|
||||
|
||||
@@ -113,7 +113,9 @@ does not exist on that target:
|
||||
- WebConfig and the `wifi.ssid`, `wifi.status`, `wifi.powersave`, and `wifi.cli` command
|
||||
family require an ESP32 WebConfig build. FULL standalone repeater and
|
||||
room-server builds support the corresponding WiFi setters and status
|
||||
commands.
|
||||
commands. ESP32 WiFi Companion exposes `wifi.powersave` in its WebConfig
|
||||
form and binary protocol; Full Companion also exposes the text getter and
|
||||
setter on its USB terminal and TCP port 5002.
|
||||
- MQTT commands require an MQTT observer target.
|
||||
- `discover.scopes` requires an MQTT observer with compiled neighbor support;
|
||||
it does not independently require PSRAM or the FULL parser.
|
||||
|
||||
+11
-1
@@ -201,7 +201,9 @@ SSID, LAN IP, and RSSI. When the shared OTA seeder is running, the reply appends
|
||||
`OTA TCP 5001: listening` or `OTA TCP 5001: client connected`. WiFi being off
|
||||
is normal while WebConfig is inactive; run `start webconfig` when a temporary
|
||||
connection is wanted. `get wifi.powersave` reports the saved standalone setting
|
||||
as `none`, `min`, or `max`; the default is `none`.
|
||||
as `none`, `min`, or `max`. Fresh Cascade-profile builds default to `min`;
|
||||
target-default builds use `none`. A saved setting takes precedence after an
|
||||
upgrade.
|
||||
|
||||
The WiFi `set` commands work on MQTT observers and on FULL standalone
|
||||
ESP32 repeater/room-server builds. On a standalone build, changing the SSID or
|
||||
@@ -211,6 +213,14 @@ Power-save changes are applied immediately when WiFi is running and otherwise
|
||||
take effect on the next connection. `get wifi.pwd` is intentionally unavailable
|
||||
so the standalone password is never returned by the CLI.
|
||||
|
||||
ESP32 WiFi Companion WebConfig exposes the same `wifi.powersave` values in its
|
||||
WiFi card. Full Companion also accepts `get/set wifi.powersave` from its USB
|
||||
terminal and TCP port 5002. Binary Companion clients can use command bytes
|
||||
`0x46` and `0x47` over USB, BLE, or TCP port 5000 without the terminal-start
|
||||
token. WiFi-only Companions accept all three modes; Full Companion rejects
|
||||
`none` because its simultaneous BLE transport requires modem sleep. Companion
|
||||
device `powersaving` and LoRa `radio.rxps` remain independent.
|
||||
|
||||
The browser portal is not compiled into the two 4 MB
|
||||
`LilyGo_TLora_V2_1_1_6_*_observer_mqtt` targets because it does not fit while
|
||||
retaining the two app slots required for LoRa OTA. Their normal CLI settings
|
||||
|
||||
@@ -219,10 +219,47 @@ catalog; bytes `0x2C`-`0x31` are parked and `0x35` is unused.
|
||||
| `0x3F` / `0x40` | `CMD_SET_DEFAULT_FLOOD_SCOPE` / `CMD_GET_DEFAULT_FLOOD_SCOPE` | Write or read the default flood scope. |
|
||||
| `0x41` | `CMD_SEND_RAW_PACKET` | Queue a fully encoded raw mesh packet. |
|
||||
| `0x42` / `0x43` | `CMD_GET_RADIO_FEM_RXGAIN` / `CMD_SET_RADIO_FEM_RXGAIN` | Read or set FEM receive gain. |
|
||||
| `0x44` / `0x45` | `CMD_GET_RADIO_RXGAIN` / `CMD_SET_RADIO_RXGAIN` | Read or set the radio chip's boosted receive-gain mode. |
|
||||
| `0x46` / `0x47` | `CMD_GET_WIFI_POWER_SAVE` / `CMD_SET_WIFI_POWER_SAVE` | Read or set ESP32 Companion WiFi modem sleep. |
|
||||
|
||||
The sections below detail the most common frames. Refer to the source named
|
||||
above for command bodies that are not expanded here.
|
||||
|
||||
The additive hardware-setting commands `0x42`-`0x47` do not change any existing
|
||||
version-13 frame layout. Clients should probe the command they need and treat
|
||||
`ERR_CODE_UNSUPPORTED_CMD` as feature absence.
|
||||
|
||||
Both gain-command pairs can be used over the normal binary Companion
|
||||
connection; USB does not need to enter terminal mode. Inside the transport's
|
||||
normal Companion frame, send a GET command as its single command byte. Send a
|
||||
SET command followed by one byte (`0` for off, `1` for on). A GET reply is
|
||||
`RESP_CODE_OK` followed by the saved state; a successful SET reply is
|
||||
`RESP_CODE_OK`. Invalid states return `ERR_CODE_ILLEGAL_ARG`. A temporarily
|
||||
busy radio returns `ERR_CODE_BAD_STATE`; unsupported boosted gain returns
|
||||
`ERR_CODE_UNSUPPORTED_CMD`. The FEM pair also returns
|
||||
`ERR_CODE_UNSUPPORTED_CMD` when the board cannot control its external LNA. Raw
|
||||
text such as `set radio.rxgain off` still requires the USB terminal start token.
|
||||
|
||||
The WiFi power-save pair is available on ESP32 WiFi Companion builds over the
|
||||
normal binary USB, BLE, or TCP port 5000 transport. `CMD_GET_WIFI_POWER_SAVE`
|
||||
has no body and replies with `RESP_CODE_OK` followed by one mode byte.
|
||||
`CMD_SET_WIFI_POWER_SAVE` is followed by that mode byte and replies with
|
||||
`RESP_CODE_OK` after saving it:
|
||||
|
||||
| Value | Mode |
|
||||
|---:|---|
|
||||
| `0` | `min` - minimum modem sleep |
|
||||
| `1` | `none` - no modem sleep |
|
||||
| `2` | `max` - maximum modem sleep |
|
||||
|
||||
An out-of-range value returns `ERR_CODE_ILLEGAL_ARG`. A non-WiFi Companion
|
||||
returns `ERR_CODE_UNSUPPORTED_CMD`. Full Companion has Bluetooth enabled and
|
||||
therefore returns `ERR_CODE_BAD_STATE` for `none`, because ESP32 WiFi/Bluetooth
|
||||
coexistence requires modem sleep. A storage failure also returns
|
||||
`ERR_CODE_BAD_STATE`. If an already-saved mode cannot be applied to the active
|
||||
WiFi driver, SET still returns `RESP_CODE_OK` and the mode is applied on the
|
||||
next connection. Device `powersaving` does not overwrite this setting.
|
||||
|
||||
### 1. App Start
|
||||
|
||||
**Purpose**: Initialize communication with the device. Must be sent first after connection.
|
||||
|
||||
@@ -54,6 +54,9 @@ runtime, so the Companion bulk-build commands omit the redundant legacy
|
||||
boost** switch. From the USB terminal, use:
|
||||
|
||||
```text
|
||||
get radio.rxgain
|
||||
set radio.rxgain off
|
||||
set radio.rxgain on
|
||||
get radio.fem.rxgain
|
||||
set radio.fem.rxgain off
|
||||
set radio.fem.rxgain on
|
||||
@@ -62,8 +65,10 @@ set radio.fem.txgain off
|
||||
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.
|
||||
`radio.rxgain` controls the radio chip's boosted receive-gain mode; the FEM
|
||||
commands control the external receive and transmit paths. 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:
|
||||
@@ -74,6 +79,23 @@ powersaving on
|
||||
powersaving off
|
||||
```
|
||||
|
||||
On ESP32, WiFi modem power saving is a third independent setting. Select it in
|
||||
the WebConfig **WiFi** card, or use the Full Companion USB terminal or TCP port
|
||||
5002:
|
||||
|
||||
```text
|
||||
get wifi.powersave
|
||||
set wifi.powersave min
|
||||
set wifi.powersave max
|
||||
```
|
||||
|
||||
The normal binary Companion connection can also read or write this setting over
|
||||
USB, BLE, or TCP port 5000 without entering terminal mode. The saved values are
|
||||
`0` for `min`, `1` for `none`, and `2` for `max`; see the
|
||||
[Companion protocol](./companion_protocol.md#commands). Full Companion rejects
|
||||
`none` because simultaneous WiFi and BLE require modem sleep. Fresh Cascade
|
||||
builds select `min`, and an existing saved selection takes precedence.
|
||||
|
||||
On radios with RX duty-cycle support, WebConfig and the USB terminal also
|
||||
expose the persisted RXPS setting:
|
||||
|
||||
@@ -98,11 +120,12 @@ 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. While a native-USB host is enumerated, the platform sleep attempt
|
||||
is held off so USB CDC remains responsive; detaching the host releases that
|
||||
guard. CPU, radio-modem, and GPS power-saving settings remain active, and USB
|
||||
power from a charger alone does not create a Companion session. The selected
|
||||
state is retained after reboot.
|
||||
requires it. Changing device power saving does not overwrite the saved WiFi
|
||||
power-save mode. While a native-USB host is enumerated, the platform sleep
|
||||
attempt is held off so USB CDC remains responsive; detaching the host releases
|
||||
that guard. CPU, radio-modem, and GPS power-saving settings remain active, and
|
||||
USB power from a charger alone does not create a Companion session. The
|
||||
selected state is retained after reboot.
|
||||
|
||||
On the LilyGo T-Beam 1W Full Companion, press the physical `BOOT` button once
|
||||
to turn the ESP32 WiFi radio and all WiFi services off or on. The screen confirms
|
||||
@@ -139,7 +162,7 @@ itself.
|
||||
| ESP32 | TCP 5000 | Binary Companion over WiFi |
|
||||
| ESP32 | HTTP 80 | Companion WebConfig and first-boot WiFi setup |
|
||||
| ESP32 | TCP 5001 | Host `.mota` folder from `motatool serve --tcp` |
|
||||
| ESP32 | TCP 5002 | Local `ota`, `tempradio`, and `normalradio` console |
|
||||
| ESP32 | TCP 5002 | Local `ota`, `tempradio`, `normalradio`, and `wifi.powersave` console |
|
||||
| nRF52 | USB mOTA mode | Host `.mota` folder from `motatool serve --serial` |
|
||||
|
||||
Delivery-required replies are returned only to the interface which supplied the
|
||||
@@ -194,7 +217,8 @@ The terminal supports Companion chat commands, including `channels`,
|
||||
`channel <name-or-slot> <message>`, remote administration with
|
||||
`login <admin-password>` and `cmd <remote-command>`, and routed
|
||||
`trace [recipient-name-or-prefix]`, plus local `ota`, `tempradio`, and
|
||||
`normalradio` controls. For example:
|
||||
`normalradio` controls. ESP32 builds also provide local
|
||||
`get/set wifi.powersave`. For example:
|
||||
|
||||
```text
|
||||
channels
|
||||
|
||||
@@ -85,16 +85,42 @@ set af {air-time-factor}
|
||||
Sets the transmit air-time-factor. Deprecated - use `set dutycycle` instead.
|
||||
|
||||
```
|
||||
powersaving
|
||||
powersaving {on|off}
|
||||
set powersaving {on|off}
|
||||
```
|
||||
Shows or changes Companion device power saving. On ESP32 this controls CPU and
|
||||
GPS idle behavior; it does not change LoRa RXPS or WiFi modem sleep.
|
||||
|
||||
```
|
||||
get radio.rxps
|
||||
set radio.rxps {off|on|level 1-10 [preamble 16|32]|rx_us sleep_us}
|
||||
```
|
||||
Shows or changes LoRa receive duty cycling on supported radios. Fresh Cascade
|
||||
builds select level 8 with a 16-symbol preamble.
|
||||
|
||||
```
|
||||
get wifi.powersave
|
||||
set wifi.powersave {none|min|max}
|
||||
```
|
||||
Shows or changes the persisted WiFi modem-sleep policy on ESP32 WiFi Companion
|
||||
builds. Full Companion requires at least `min` while BLE is present and rejects
|
||||
`none`. The WebConfig WiFi card and the normal binary Companion protocol expose
|
||||
the same setting; binary clients do not need the terminal-start token.
|
||||
|
||||
```
|
||||
get radio.rxgain
|
||||
set radio.rxgain {on|off}
|
||||
get radio.fem.rxgain
|
||||
set radio.fem.rxgain {on|off}
|
||||
get radio.fem.txgain
|
||||
set radio.fem.txgain {on|off}
|
||||
```
|
||||
Shows or changes the external FEM receive-path LNA or transmit-path gain on
|
||||
`radio.rxgain` changes the radio chip's boosted receive-gain mode. The FEM
|
||||
settings control the external receive-path LNA or transmit-path gain on
|
||||
supported boards. Changes are applied immediately and saved across reboots;
|
||||
changing RX gain also recalibrates the radio noise floor. These settings are
|
||||
separate from the SX126x `radio.rxgain` setting. Boards without the respective
|
||||
control report it as unsupported.
|
||||
changing either receive-gain path also recalibrates the radio noise floor.
|
||||
Boards without the respective control report it as unsupported.
|
||||
|
||||
|
||||
```
|
||||
|
||||
@@ -1,10 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined(ESP32) && defined(WIFI_SSID)
|
||||
|
||||
enum class CompanionWiFiPowerSaveResult : uint8_t {
|
||||
Applied,
|
||||
SavedForNextConnection,
|
||||
InvalidMode,
|
||||
BluetoothConflict,
|
||||
StorageError,
|
||||
};
|
||||
|
||||
// The requested state is persisted immediately. Network services transition
|
||||
// from the main loop so a button callback never tears down an active server.
|
||||
bool toggleCompanionWiFi();
|
||||
bool isCompanionWiFiEnabled();
|
||||
|
||||
// Companion WiFi power save is stored in the shared mesh-wifi NVS namespace.
|
||||
// The returned mode is always the effective mode: WiFi+BLE builds map a stale
|
||||
// or default "none" value to "min" because modem sleep is required for radio
|
||||
// coexistence.
|
||||
uint8_t getCompanionWiFiPowerSave();
|
||||
const char* getCompanionWiFiPowerSaveName();
|
||||
const char* companionWiFiPowerSaveName(uint8_t mode);
|
||||
CompanionWiFiPowerSaveResult setCompanionWiFiPowerSave(uint8_t mode);
|
||||
void reloadCompanionWiFiPowerSave();
|
||||
bool applyCompanionWiFiPowerSave();
|
||||
|
||||
#endif
|
||||
@@ -6,6 +6,11 @@
|
||||
#include "helpers/radiolib/RXPowerSaving.h"
|
||||
#include "helpers/radiolib/RxBoostedGainDefaults.h"
|
||||
|
||||
#if defined(ESP32) && defined(WIFI_SSID)
|
||||
#include "CompanionWiFi.h"
|
||||
#include <helpers/WiFiPowerSave.h>
|
||||
#endif
|
||||
|
||||
#if defined(ESP32_PLATFORM)
|
||||
#include <helpers/ESP32TrueRandom.h>
|
||||
#endif
|
||||
@@ -90,7 +95,7 @@ static const uint32_t COMMAND_RADIO_APPLY_TIMEOUT_MS = 5000UL;
|
||||
#define CMD_SET_CUSTOM_VAR 41
|
||||
#define CMD_GET_ADVERT_PATH 42
|
||||
#define CMD_GET_TUNING_PARAMS 43
|
||||
// NOTE: CMD range 44..49 parked, potentially for WiFi operations
|
||||
// NOTE: decimal command IDs 44..49 (0x2C..0x31) remain parked
|
||||
#define CMD_SEND_BINARY_REQ 50
|
||||
#define CMD_FACTORY_RESET 51
|
||||
#define CMD_SEND_PATH_DISCOVERY_REQ 52
|
||||
@@ -108,6 +113,10 @@ static const uint32_t COMMAND_RADIO_APPLY_TIMEOUT_MS = 5000UL;
|
||||
#define CMD_SEND_RAW_PACKET 65
|
||||
#define CMD_GET_RADIO_FEM_RXGAIN 66
|
||||
#define CMD_SET_RADIO_FEM_RXGAIN 67
|
||||
#define CMD_GET_RADIO_RXGAIN 68
|
||||
#define CMD_SET_RADIO_RXGAIN 69
|
||||
#define CMD_GET_WIFI_POWER_SAVE 70
|
||||
#define CMD_SET_WIFI_POWER_SAVE 71
|
||||
|
||||
#if defined(RADIO_FEM_RXGAIN) && (RADIO_FEM_RXGAIN == 0)
|
||||
static constexpr uint8_t DEFAULT_FEM_RX_GAIN = 0;
|
||||
@@ -1513,6 +1522,9 @@ void MyMesh::begin(bool has_display, bool radio_available) {
|
||||
applyMQTTDefaults(&_mqtt_prefs);
|
||||
_mqtt_configured = CompanionMqttSetupPortal::loadStoredConfig(_mqtt_prefs);
|
||||
if (!_mqtt_configured) applyMQTTDefaults(&_mqtt_prefs);
|
||||
// Companion WiFi owns the connection and its mesh-wifi NVS setting is
|
||||
// canonical. Keep MQTT reconnects from restoring a stale MQTT-pref value.
|
||||
_mqtt_prefs.wifi_power_save = getCompanionWiFiPowerSave();
|
||||
|
||||
MQTTNodeInfo node_info;
|
||||
node_info.node_name = _prefs.node_name;
|
||||
@@ -1711,6 +1723,21 @@ bool MyMesh::handleFullOtaCommand(const char* command, char* reply,
|
||||
if (!command || !reply || reply_size == 0) return false;
|
||||
while (*command == ' ') command++;
|
||||
|
||||
#if defined(ESP32) && defined(WIFI_SSID)
|
||||
if (strcmp(command, "get wifi.powersave") == 0) {
|
||||
formatWiFiPowerSaving(reply, reply_size);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (strcmp(command, "set wifi.powersave") == 0
|
||||
|| strncmp(command, "set wifi.powersave ", 19) == 0) {
|
||||
const char* value = command + 18;
|
||||
while (*value == ' ') value++;
|
||||
applyAndSaveWiFiPowerSaving(value, reply, reply_size);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (strcmp(command, "tempradio") == 0) {
|
||||
if (_temp_radio_set_at) {
|
||||
snprintf(reply, reply_size, "TempRadio pending: %.3f,%.2f,%u,%u",
|
||||
@@ -1938,8 +1965,13 @@ void MyMesh::getNodeSnapshot(WebConfigServer::NodeSnapshot& s) {
|
||||
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_POWER_SAVING;
|
||||
| WebConfigServer::CAP_RX_DELAY | WebConfigServer::CAP_POWER_SAVING;
|
||||
#if defined(ESP32) && defined(WIFI_SSID)
|
||||
s.capabilities |= WebConfigServer::CAP_WIFI_POWER_SAVE;
|
||||
#endif
|
||||
if (radio_driver.supportsRxBoostedGainMode()) {
|
||||
s.capabilities |= WebConfigServer::CAP_RX_GAIN;
|
||||
}
|
||||
if (board.canControlLoRaFemLna()) {
|
||||
s.capabilities |= WebConfigServer::CAP_FEM_RX_GAIN;
|
||||
}
|
||||
@@ -2010,6 +2042,13 @@ void MyMesh::onConfigBatchStart() {
|
||||
}
|
||||
|
||||
void MyMesh::onConfigBatchEnd() {
|
||||
#if defined(ESP32) && defined(WIFI_SSID)
|
||||
// The WebConfig WiFi form writes the canonical mesh-wifi namespace itself.
|
||||
// Reload it here so the Companion runtime and MQTT reconnect policy cannot
|
||||
// retain a stale modem-sleep mode.
|
||||
reloadCompanionWiFiPowerSave();
|
||||
syncWiFiPowerSaving();
|
||||
#endif
|
||||
#ifdef WITH_MQTT_BRIDGE
|
||||
if (_wc_mqtt_dirty) {
|
||||
CompanionMqttSetupPortal::saveStoredConfig(_mqtt_prefs);
|
||||
@@ -2018,6 +2057,9 @@ void MyMesh::onConfigBatchEnd() {
|
||||
MQTTPrefs verified;
|
||||
_mqtt_configured = CompanionMqttSetupPortal::loadStoredConfig(verified);
|
||||
if (_mqtt_configured) _mqtt_prefs = verified;
|
||||
// The standalone Companion setting remains canonical even if MQTT config
|
||||
// verification reloaded an older copy of this field.
|
||||
_mqtt_prefs.wifi_power_save = getCompanionWiFiPowerSave();
|
||||
}
|
||||
#endif
|
||||
_wc_mqtt_dirty = false;
|
||||
@@ -2025,6 +2067,12 @@ void MyMesh::onConfigBatchEnd() {
|
||||
|
||||
void MyMesh::execCommand(char* cmd, char* reply) {
|
||||
reply[0] = 0;
|
||||
#if defined(ESP32) && defined(WIFI_SSID)
|
||||
if (cmd && strcmp(cmd, "get wifi.powersave") == 0) {
|
||||
formatWiFiPowerSaving(reply, 160);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (!cmd || strncmp(cmd, "set ", 4) != 0) {
|
||||
strcpy(reply, "Error: unsupported command");
|
||||
return;
|
||||
@@ -2113,12 +2161,18 @@ void MyMesh::execCommand(char* cmd, char* reply) {
|
||||
strcpy(reply, "Error: must be on or off");
|
||||
} else {
|
||||
if (strcmp(key, "radio.rxgain") == 0) {
|
||||
_prefs.rx_boosted_gain = enabled;
|
||||
if (_radio_available) radio_driver.setRxBoostedGainMode(enabled);
|
||||
if (!radio_driver.supportsRxBoostedGainMode()) {
|
||||
strcpy(reply, "Error: RX boosted gain unsupported");
|
||||
return;
|
||||
}
|
||||
if (!applyAndSaveRxBoostedGain(enabled)) {
|
||||
strcpy(reply, "Error: radio busy; retry");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
_prefs.client_repeat = enabled;
|
||||
savePrefs();
|
||||
}
|
||||
savePrefs();
|
||||
strcpy(reply, "OK");
|
||||
}
|
||||
return;
|
||||
@@ -2131,6 +2185,12 @@ void MyMesh::execCommand(char* cmd, char* reply) {
|
||||
applyAndSavePowerSaving(value, reply);
|
||||
return;
|
||||
}
|
||||
#if defined(ESP32) && defined(WIFI_SSID)
|
||||
if (strcmp(key, "wifi.powersave") == 0) {
|
||||
applyAndSaveWiFiPowerSaving(value, reply, 160);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (strcmp(key, "radio.fem.rxgain") == 0) {
|
||||
bool enabled;
|
||||
if (!wcParseBool(value, enabled)) {
|
||||
@@ -3357,6 +3417,50 @@ void MyMesh::handleCmdFrame(size_t len) {
|
||||
} else {
|
||||
writeErrFrame(ERR_CODE_ILLEGAL_ARG);
|
||||
}
|
||||
} else if (cmd_frame[0] == CMD_GET_RADIO_RXGAIN) {
|
||||
if (!radio_driver.supportsRxBoostedGainMode()) {
|
||||
writeErrFrame(ERR_CODE_UNSUPPORTED_CMD);
|
||||
} else {
|
||||
out_frame[0] = RESP_CODE_OK;
|
||||
out_frame[1] = _prefs.rx_boosted_gain ? 1 : 0;
|
||||
_serial->writeFrame(out_frame, 2);
|
||||
}
|
||||
} else if (cmd_frame[0] == CMD_SET_RADIO_RXGAIN && len >= 2) {
|
||||
uint8_t value = cmd_frame[1];
|
||||
if (value > 1) {
|
||||
writeErrFrame(ERR_CODE_ILLEGAL_ARG);
|
||||
} else if (!radio_driver.supportsRxBoostedGainMode()) {
|
||||
writeErrFrame(ERR_CODE_UNSUPPORTED_CMD);
|
||||
} else if (!applyAndSaveRxBoostedGain(value != 0)) {
|
||||
writeErrFrame(ERR_CODE_BAD_STATE);
|
||||
} else {
|
||||
writeOKFrame();
|
||||
}
|
||||
} else if (cmd_frame[0] == CMD_GET_WIFI_POWER_SAVE) {
|
||||
#if defined(ESP32) && defined(WIFI_SSID)
|
||||
out_frame[0] = RESP_CODE_OK;
|
||||
out_frame[1] = getCompanionWiFiPowerSave();
|
||||
_serial->writeFrame(out_frame, 2);
|
||||
#else
|
||||
writeErrFrame(ERR_CODE_UNSUPPORTED_CMD);
|
||||
#endif
|
||||
} else if (cmd_frame[0] == CMD_SET_WIFI_POWER_SAVE && len >= 2) {
|
||||
#if defined(ESP32) && defined(WIFI_SSID)
|
||||
const uint8_t value = cmd_frame[1];
|
||||
if (value > mesh::wifi::kPowerSaveMax) {
|
||||
writeErrFrame(ERR_CODE_ILLEGAL_ARG);
|
||||
} else {
|
||||
char reply[160];
|
||||
if (applyAndSaveWiFiPowerSaving(
|
||||
companionWiFiPowerSaveName(value), reply, sizeof(reply))) {
|
||||
writeOKFrame();
|
||||
} else {
|
||||
writeErrFrame(ERR_CODE_BAD_STATE);
|
||||
}
|
||||
}
|
||||
#else
|
||||
writeErrFrame(ERR_CODE_UNSUPPORTED_CMD);
|
||||
#endif
|
||||
} else if (cmd_frame[0] == CMD_GET_ADVERT_PATH && len >= PUB_KEY_SIZE+2) {
|
||||
// FUTURE use: uint8_t reserved = cmd_frame[1];
|
||||
uint8_t *pub_key = &cmd_frame[2];
|
||||
@@ -3579,6 +3683,17 @@ bool MyMesh::applyAndSaveFemTxGain(bool enabled) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MyMesh::applyAndSaveRxBoostedGain(bool enabled) {
|
||||
if (!radio_driver.supportsRxBoostedGainMode()
|
||||
|| (_radio_available && !radio_driver.setRxBoostedGainMode(enabled))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_prefs.rx_boosted_gain = enabled ? 1 : 0;
|
||||
savePrefs();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MyMesh::applyAndSavePowerSaving(const char* value, char* reply) {
|
||||
bool enabled;
|
||||
if (strcmp(value, "on") == 0) {
|
||||
@@ -3597,6 +3712,66 @@ bool MyMesh::applyAndSavePowerSaving(const char* value, char* reply) {
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(ESP32) && defined(WIFI_SSID)
|
||||
void MyMesh::syncWiFiPowerSaving() {
|
||||
const uint8_t mode = getCompanionWiFiPowerSave();
|
||||
#ifdef WITH_MQTT_BRIDGE
|
||||
_mqtt_prefs.wifi_power_save = mode;
|
||||
#endif
|
||||
#ifdef WITH_WEBCONFIG
|
||||
if (_webconfig) _webconfig->reloadStandaloneWiFi();
|
||||
#endif
|
||||
}
|
||||
|
||||
void MyMesh::formatWiFiPowerSaving(char* reply, size_t reply_size) const {
|
||||
if (!reply || reply_size == 0) return;
|
||||
snprintf(reply, reply_size, "> %s", getCompanionWiFiPowerSaveName());
|
||||
}
|
||||
|
||||
bool MyMesh::applyAndSaveWiFiPowerSaving(const char* value, char* reply,
|
||||
size_t reply_size) {
|
||||
if (!reply || reply_size == 0) return false;
|
||||
uint8_t mode = mesh::wifi::kDefaultPowerSave;
|
||||
if (value && strcmp(value, "min") == 0) {
|
||||
mode = mesh::wifi::kPowerSaveMin;
|
||||
} else if (value && strcmp(value, "none") == 0) {
|
||||
mode = mesh::wifi::kPowerSaveNone;
|
||||
} else if (value && strcmp(value, "max") == 0) {
|
||||
mode = mesh::wifi::kPowerSaveMax;
|
||||
} else {
|
||||
snprintf(reply, reply_size,
|
||||
"Error: power save must be none, min, or max");
|
||||
return false;
|
||||
}
|
||||
|
||||
const CompanionWiFiPowerSaveResult result =
|
||||
setCompanionWiFiPowerSave(mode);
|
||||
if (result == CompanionWiFiPowerSaveResult::BluetoothConflict) {
|
||||
snprintf(reply, reply_size,
|
||||
"Error: power save none is unavailable while Bluetooth is active");
|
||||
return false;
|
||||
}
|
||||
if (result == CompanionWiFiPowerSaveResult::InvalidMode) {
|
||||
snprintf(reply, reply_size,
|
||||
"Error: power save must be none, min, or max");
|
||||
return false;
|
||||
}
|
||||
if (result == CompanionWiFiPowerSaveResult::StorageError) {
|
||||
snprintf(reply, reply_size, "Error: failed to save WiFi power save");
|
||||
return false;
|
||||
}
|
||||
|
||||
syncWiFiPowerSaving();
|
||||
if (result == CompanionWiFiPowerSaveResult::Applied) {
|
||||
snprintf(reply, reply_size, "OK - WiFi power save set to %s", value);
|
||||
} else {
|
||||
snprintf(reply, reply_size,
|
||||
"OK - saved; WiFi power save applies on next connection");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool MyMesh::applyAndSaveRxPowerSaving(const char* value, char* reply) {
|
||||
if (!radio_driver.supportsRxPowerSaving()) {
|
||||
strcpy(reply, "Error: RX power saving unsupported");
|
||||
@@ -4505,6 +4680,19 @@ void MyMesh::handleTerminalCommand(char* command) {
|
||||
(unsigned long)_prefs.rx_ps_rx_us,
|
||||
(unsigned long)_prefs.rx_ps_sleep_us);
|
||||
}
|
||||
#if defined(ESP32) && defined(WIFI_SSID)
|
||||
} else if (strcmp(command, "get wifi.powersave") == 0) {
|
||||
char reply[160];
|
||||
formatWiFiPowerSaving(reply, sizeof(reply));
|
||||
Serial.printf(" %s\r\n", reply);
|
||||
#endif
|
||||
} else if (strcmp(command, "get radio.rxgain") == 0) {
|
||||
if (!radio_driver.supportsRxBoostedGainMode()) {
|
||||
Serial.print(" ERROR: RX boosted gain is unsupported on this radio\r\n");
|
||||
} else {
|
||||
Serial.printf(" radio.rxgain %s\r\n",
|
||||
_prefs.rx_boosted_gain ? "on" : "off");
|
||||
}
|
||||
} 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");
|
||||
@@ -4529,6 +4717,30 @@ void MyMesh::handleTerminalCommand(char* command) {
|
||||
char reply[160];
|
||||
applyAndSaveRxPowerSaving(config + 11, reply);
|
||||
Serial.printf(" %s\r\n", reply);
|
||||
#if defined(ESP32) && defined(WIFI_SSID)
|
||||
} else if (strncmp(config, "wifi.powersave", 14) == 0
|
||||
&& (config[14] == 0 || config[14] == ' '
|
||||
|| config[14] == '\t')) {
|
||||
const char* value = config + 14;
|
||||
while (*value == ' ' || *value == '\t') value++;
|
||||
char reply[160];
|
||||
applyAndSaveWiFiPowerSaving(value, reply, sizeof(reply));
|
||||
Serial.printf(" %s\r\n", reply);
|
||||
#endif
|
||||
} else if (strncmp(config, "radio.rxgain", 12) == 0
|
||||
&& (config[12] == 0 || config[12] == ' '
|
||||
|| config[12] == '\t')) {
|
||||
const char* value = config + 12;
|
||||
while (*value == ' ' || *value == '\t') value++;
|
||||
if (strcmp(value, "on") != 0 && strcmp(value, "off") != 0) {
|
||||
Serial.print(" ERROR: use set radio.rxgain <on|off>\r\n");
|
||||
} else if (!radio_driver.supportsRxBoostedGainMode()) {
|
||||
Serial.print(" ERROR: RX boosted gain is unsupported on this radio\r\n");
|
||||
} else if (!applyAndSaveRxBoostedGain(strcmp(value, "on") == 0)) {
|
||||
Serial.print(" ERROR: radio busy; retry\r\n");
|
||||
} else {
|
||||
Serial.printf(" OK - radio.rxgain %s\r\n", value);
|
||||
}
|
||||
} else if (strncmp(config, "af ", 3) == 0) {
|
||||
_prefs.airtime_factor = constrain((float)atof(config + 3), 0.0f, 9.0f);
|
||||
savePrefs();
|
||||
@@ -4591,8 +4803,14 @@ void MyMesh::handleTerminalCommand(char* command) {
|
||||
Serial.print("Commands:\r\n");
|
||||
Serial.print(" set {name|lat|lon|freq|tx|af} {value}\r\n");
|
||||
Serial.print(" powersaving [on|off]\r\n");
|
||||
#if defined(ESP32) && defined(WIFI_SSID)
|
||||
Serial.print(" get wifi.powersave\r\n");
|
||||
Serial.print(" set wifi.powersave <none|min|max>\r\n");
|
||||
#endif
|
||||
Serial.print(" get radio.rxps\r\n");
|
||||
Serial.print(" set radio.rxps <off|on|level 1-10 [preamble 16|32]|rx_us sleep_us>\r\n");
|
||||
Serial.print(" get radio.rxgain\r\n");
|
||||
Serial.print(" set radio.rxgain <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");
|
||||
|
||||
@@ -284,8 +284,15 @@ private:
|
||||
void checkSerialInterface();
|
||||
bool applyAndSaveFemRxGain(bool enabled);
|
||||
bool applyAndSaveFemTxGain(bool enabled);
|
||||
bool applyAndSaveRxBoostedGain(bool enabled);
|
||||
bool applyAndSavePowerSaving(const char* value, char* reply);
|
||||
bool applyAndSaveRxPowerSaving(const char* value, char* reply);
|
||||
#if defined(ESP32) && defined(WIFI_SSID)
|
||||
bool applyAndSaveWiFiPowerSaving(const char* value, char* reply,
|
||||
size_t reply_size);
|
||||
void formatWiFiPowerSaving(char* reply, size_t reply_size) const;
|
||||
void syncWiFiPowerSaving();
|
||||
#endif
|
||||
#ifdef ENABLE_USB_INTERFACE
|
||||
ContactInfo* getTerminalRecipient();
|
||||
void printTerminalPath(const ContactInfo& recipient);
|
||||
|
||||
@@ -52,6 +52,9 @@ MultiSerialInterface interface_manager;
|
||||
#include <helpers/esp32/SerialWifiInterface.h>
|
||||
#include <helpers/WiFiSetupPortal.h>
|
||||
#include <helpers/WiFiReconnectPolicy.h>
|
||||
#include <helpers/WiFiPowerSave.h>
|
||||
#include <Preferences.h>
|
||||
#include <esp_wifi.h>
|
||||
SerialWifiInterface wifi_interface;
|
||||
#ifndef WIFI_PWD
|
||||
#define WIFI_PWD ""
|
||||
@@ -188,15 +191,6 @@ static bool applyCompanionPowerSaving(bool enabled) {
|
||||
}
|
||||
#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;
|
||||
@@ -473,6 +467,88 @@ void halt() {
|
||||
static bool companion_wifi_active = false;
|
||||
static bool companion_wifi_disable_in_progress = false;
|
||||
static bool companion_wifi_services_stopped = false;
|
||||
static bool companion_wifi_power_save_loaded = false;
|
||||
static uint8_t companion_wifi_power_save = mesh::wifi::kDefaultPowerSave;
|
||||
|
||||
static bool companionWiFiBluetoothActive() {
|
||||
#if defined(BLE_PIN_CODE)
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
const char* companionWiFiPowerSaveName(uint8_t mode) {
|
||||
if (mode == mesh::wifi::kPowerSaveMin) return "min";
|
||||
if (mode == mesh::wifi::kPowerSaveMax) return "max";
|
||||
return "none";
|
||||
}
|
||||
|
||||
static wifi_ps_type_t companionWiFiPowerSaveType(uint8_t mode) {
|
||||
if (mode == mesh::wifi::kPowerSaveNone) return WIFI_PS_NONE;
|
||||
if (mode == mesh::wifi::kPowerSaveMax) return WIFI_PS_MAX_MODEM;
|
||||
return WIFI_PS_MIN_MODEM;
|
||||
}
|
||||
|
||||
void reloadCompanionWiFiPowerSave() {
|
||||
uint8_t configured = mesh::wifi::kDefaultPowerSave;
|
||||
Preferences nvs;
|
||||
if (nvs.begin("mesh-wifi", true)) {
|
||||
configured = nvs.getUChar("powersave", mesh::wifi::kDefaultPowerSave);
|
||||
nvs.end();
|
||||
}
|
||||
companion_wifi_power_save = mesh::wifi::effectivePowerSave(
|
||||
configured, companionWiFiBluetoothActive());
|
||||
companion_wifi_power_save_loaded = true;
|
||||
applyCompanionWiFiPowerSave();
|
||||
}
|
||||
|
||||
uint8_t getCompanionWiFiPowerSave() {
|
||||
if (!companion_wifi_power_save_loaded) reloadCompanionWiFiPowerSave();
|
||||
return companion_wifi_power_save;
|
||||
}
|
||||
|
||||
const char* getCompanionWiFiPowerSaveName() {
|
||||
return companionWiFiPowerSaveName(getCompanionWiFiPowerSave());
|
||||
}
|
||||
|
||||
bool applyCompanionWiFiPowerSave() {
|
||||
if (!companion_wifi_power_save_loaded) {
|
||||
reloadCompanionWiFiPowerSave();
|
||||
return true;
|
||||
}
|
||||
if (WiFi.getMode() == WIFI_OFF) return true;
|
||||
return esp_wifi_set_ps(
|
||||
companionWiFiPowerSaveType(companion_wifi_power_save)) == ESP_OK;
|
||||
}
|
||||
|
||||
CompanionWiFiPowerSaveResult setCompanionWiFiPowerSave(uint8_t mode) {
|
||||
if (mode > mesh::wifi::kPowerSaveMax) {
|
||||
return CompanionWiFiPowerSaveResult::InvalidMode;
|
||||
}
|
||||
if (mesh::wifi::effectivePowerSave(mode, companionWiFiBluetoothActive())
|
||||
!= mode) {
|
||||
return CompanionWiFiPowerSaveResult::BluetoothConflict;
|
||||
}
|
||||
|
||||
Preferences nvs;
|
||||
if (!nvs.begin("mesh-wifi", false)) {
|
||||
return CompanionWiFiPowerSaveResult::StorageError;
|
||||
}
|
||||
const bool saved =
|
||||
nvs.putUChar("powersave", mode) == sizeof(uint8_t);
|
||||
nvs.end();
|
||||
if (!saved) return CompanionWiFiPowerSaveResult::StorageError;
|
||||
|
||||
companion_wifi_power_save = mode;
|
||||
companion_wifi_power_save_loaded = true;
|
||||
if (WiFi.getMode() == WIFI_OFF) {
|
||||
return CompanionWiFiPowerSaveResult::SavedForNextConnection;
|
||||
}
|
||||
return applyCompanionWiFiPowerSave()
|
||||
? CompanionWiFiPowerSaveResult::Applied
|
||||
: CompanionWiFiPowerSaveResult::SavedForNextConnection;
|
||||
}
|
||||
|
||||
static void loadCompanionWiFiCredentials() {
|
||||
companion_wifi_has_credentials = WiFiSetupPortal::loadStoredCredentials(
|
||||
@@ -571,8 +647,9 @@ void halt() {
|
||||
|
||||
/* WIFI OTA CONSOLE - a tiny text CLI for OTA over WiFi. Connect with e.g. `nc <ip> 5002` and type
|
||||
`ota status` / `ota ls` / `ota announce` / ... - one client at a time, on a DEDICATED port separate from
|
||||
the companion (5000) and the seeder (5001). Full companions also accept `tempradio ...` and
|
||||
`normalradio` here so a host can run an end-to-end mOTA source without occupying the binary port. */
|
||||
the companion (5000) and the seeder (5001). Full companions also accept `tempradio ...`,
|
||||
`normalradio`, and WiFi power-save commands here so a host can manage the source without
|
||||
occupying the binary port. */
|
||||
#if defined(ESP32) && defined(WIFI_SSID) && defined(ENABLE_OTA)
|
||||
#include <helpers/ota/OtaCli.h> // mesh::ota::handle_ota_command(line, reply, board)
|
||||
#include <helpers/esp32/WiFiOtaSeeder.h>
|
||||
@@ -603,6 +680,7 @@ void halt() {
|
||||
ota_console_client.print("OTA console - type `ota ...`");
|
||||
#if defined(COMPANION_RADIO_FULL)
|
||||
ota_console_client.print(" or `tempradio freq,bw,sf,cr,minutes`");
|
||||
ota_console_client.print("; `get/set wifi.powersave`");
|
||||
#endif
|
||||
ota_console_client.print("\r\n> "); }
|
||||
return;
|
||||
@@ -615,7 +693,7 @@ void halt() {
|
||||
char reply[160]; reply[0] = 0;
|
||||
#if defined(COMPANION_RADIO_FULL)
|
||||
if (!the_mesh.handleFullOtaCommand(ota_console_line, reply, sizeof(reply)))
|
||||
strcpy(reply, "supported: ota ... | tempradio ... | normalradio");
|
||||
strcpy(reply, "supported: ota ... | tempradio ... | normalradio | get/set wifi.powersave");
|
||||
#else
|
||||
if (!mesh::ota::handle_ota_command(ota_console_line, reply, board))
|
||||
strcpy(reply, "only `ota ...` commands are supported on this console");
|
||||
@@ -663,11 +741,7 @@ void halt() {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(BLE_PIN_CODE)
|
||||
WiFi.setSleep(true);
|
||||
#else
|
||||
WiFi.setSleep(false);
|
||||
#endif
|
||||
applyCompanionWiFiPowerSave();
|
||||
wifi_interface.begin(TCP_PORT);
|
||||
wifi_interface.enable();
|
||||
#ifdef ENABLE_OTA
|
||||
@@ -952,7 +1026,8 @@ void setup() {
|
||||
#endif
|
||||
// keep frames intact and pace the contact stream when the host is slow
|
||||
usb_serial_interface.enableFlowControl(true);
|
||||
#if defined(ESP32) && defined(ARDUINO_USB_MODE) && ARDUINO_USB_MODE == 1
|
||||
#if defined(ESP32) && defined(ARDUINO_USB_MODE) && ARDUINO_USB_MODE == 1 \
|
||||
&& defined(ARDUINO_USB_CDC_ON_BOOT) && ARDUINO_USB_CDC_ON_BOOT
|
||||
// a 256 byte TX buffer overflows during a contact sync, and write() blocks
|
||||
// up to tx_timeout_ms per call against a stalled host (same reasoning as
|
||||
// the kiss_modem tuning)
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "MQTTPrefs.h"
|
||||
#include "MQTTPacketFilter.h"
|
||||
#include "MQTTPresets.h"
|
||||
#include "WiFiPowerSave.h"
|
||||
|
||||
// Compile-time defaults for fresh /mqtt_prefs (override via platformio build_flags).
|
||||
// Example:
|
||||
@@ -14,6 +15,7 @@
|
||||
// -D MQTT_DEFAULT_IATA='"YYZ"'
|
||||
// -D MQTT_DEFAULT_TIMEZONE='"America/Toronto"'
|
||||
// -D MQTT_DEFAULT_TIMEZONE_OFFSET=-5
|
||||
// -D DEFAULT_WIFI_POWER_SAVE_MODE=0 // min; 1=none, 2=max
|
||||
|
||||
#ifndef MQTT_DEFAULT_SLOT1_PRESET
|
||||
#define MQTT_DEFAULT_SLOT1_PRESET "analyzer-us"
|
||||
@@ -69,7 +71,7 @@ static inline void applyMQTTDefaults(MQTTPrefs* prefs) {
|
||||
prefs->mqtt_tx_enabled = 2;
|
||||
prefs->mqtt_rx_enabled = 1;
|
||||
prefs->mqtt_status_interval = 300000;
|
||||
prefs->wifi_power_save = 1;
|
||||
prefs->wifi_power_save = mesh::wifi::kDefaultPowerSave;
|
||||
|
||||
mqttDefaultSlotPreset(prefs->mqtt_slot_preset[0], sizeof(prefs->mqtt_slot_preset[0]),
|
||||
MQTT_DEFAULT_SLOT1_PRESET);
|
||||
|
||||
@@ -2,16 +2,32 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// Stored WiFi power-save values are 0=min, 1=none, and 2=max. Build profiles
|
||||
// may override the fresh-install default without changing the persisted wire /
|
||||
// file representation. Existing saved settings always take precedence.
|
||||
#ifndef DEFAULT_WIFI_POWER_SAVE_MODE
|
||||
#define DEFAULT_WIFI_POWER_SAVE_MODE 1
|
||||
#endif
|
||||
|
||||
#if DEFAULT_WIFI_POWER_SAVE_MODE < 0 || DEFAULT_WIFI_POWER_SAVE_MODE > 2
|
||||
#error "DEFAULT_WIFI_POWER_SAVE_MODE must be 0 (min), 1 (none), or 2 (max)"
|
||||
#endif
|
||||
|
||||
namespace mesh {
|
||||
namespace wifi {
|
||||
|
||||
// MeshCore stores WiFi power save as: 0=min, 1=none, 2=max. ESP32 WiFi and
|
||||
// Bluetooth coexistence requires modem sleep, so "none" must fall back to the
|
||||
// minimum sleep policy whenever Bluetooth is active.
|
||||
static constexpr uint8_t kPowerSaveMin = 0;
|
||||
static constexpr uint8_t kPowerSaveNone = 1;
|
||||
static constexpr uint8_t kPowerSaveMax = 2;
|
||||
static constexpr uint8_t kDefaultPowerSave = DEFAULT_WIFI_POWER_SAVE_MODE;
|
||||
|
||||
// ESP32 WiFi and Bluetooth coexistence requires modem sleep, so "none" must
|
||||
// fall back to the minimum sleep policy whenever Bluetooth is active.
|
||||
inline uint8_t effectivePowerSave(uint8_t configured,
|
||||
bool bluetooth_active) {
|
||||
if (configured > 2) configured = 1;
|
||||
return bluetooth_active && configured == 1 ? 0 : configured;
|
||||
if (configured > kPowerSaveMax) configured = kDefaultPowerSave;
|
||||
return bluetooth_active && configured == kPowerSaveNone
|
||||
? kPowerSaveMin : configured;
|
||||
}
|
||||
|
||||
} // namespace wifi
|
||||
|
||||
@@ -49,6 +49,7 @@ public:
|
||||
* Radio interface.
|
||||
*/
|
||||
virtual bool setRxBoostedGainMode(bool) { return false; }
|
||||
virtual bool supportsRxBoostedGainMode() const { return false; }
|
||||
virtual bool getRxBoostedGainMode() const { return false; }
|
||||
|
||||
// ESP-NOW has no LoRa RX power-saving watchdog or noise-floor calibration.
|
||||
|
||||
+1263
-1264
File diff suppressed because it is too large.
Load diff
@@ -205,7 +205,8 @@ WebConfigServer::WebConfigServer(Callbacks* callbacks, void* mqtt_prefs, bool ow
|
||||
if (obs) {
|
||||
strncpy(_wifi_ssid, obs->wifi_ssid, sizeof(_wifi_ssid) - 1);
|
||||
strncpy(_wifi_password, obs->wifi_password, sizeof(_wifi_password) - 1);
|
||||
_wifi_power_save = obs->wifi_power_save <= 2 ? obs->wifi_power_save : 1;
|
||||
_wifi_power_save = obs->wifi_power_save <= mesh::wifi::kPowerSaveMax
|
||||
? obs->wifi_power_save : mesh::wifi::kDefaultPowerSave;
|
||||
// Companion builds keep their canonical connection credentials in the
|
||||
// shared mesh-wifi namespace. A fresh MQTT configuration can therefore
|
||||
// have an empty MQTTPrefs WiFi field even while the companion is already
|
||||
@@ -270,7 +271,8 @@ bool WebConfigServer::loadStandaloneWiFi(char* ssid, size_t ssid_len,
|
||||
if (!nvs.begin("mesh-wifi", true)) return false;
|
||||
String stored_ssid = nvs.getString("ssid", "");
|
||||
String stored_password = nvs.getString("password", "");
|
||||
uint8_t stored_ps = nvs.getUChar("powersave", 1);
|
||||
uint8_t stored_ps = nvs.getUChar(
|
||||
"powersave", mesh::wifi::kDefaultPowerSave);
|
||||
nvs.end();
|
||||
if (stored_ssid.length() >= ssid_len
|
||||
|| stored_password.length() >= password_len) {
|
||||
@@ -288,7 +290,8 @@ bool WebConfigServer::saveStandaloneWiFi(const char* ssid, const char* password,
|
||||
uint8_t power_save) {
|
||||
power_save = effectiveWiFiPowerSave(power_save);
|
||||
if (!ssid || !ssid[0] || strlen(ssid) >= 32
|
||||
|| (password && strlen(password) >= 64) || power_save > 2) {
|
||||
|| (password && strlen(password) >= 64)
|
||||
|| power_save > mesh::wifi::kPowerSaveMax) {
|
||||
return false;
|
||||
}
|
||||
Preferences nvs;
|
||||
@@ -347,7 +350,7 @@ bool WebConfigServer::setStandaloneWiFiPassword(const char* value, char* reply,
|
||||
bool WebConfigServer::setStandaloneWiFiPowerSave(const char* value, char* reply,
|
||||
size_t reply_len) {
|
||||
if (!reply || reply_len == 0) return false;
|
||||
uint8_t power_save = 1;
|
||||
uint8_t power_save = mesh::wifi::kDefaultPowerSave;
|
||||
if (!mesh::cli::parseStandaloneWiFiPowerSave(value, power_save)) {
|
||||
snprintf(reply, reply_len, "Error: power save must be none, min, or max");
|
||||
return false;
|
||||
@@ -374,9 +377,9 @@ bool WebConfigServer::setStandaloneWiFiPowerSave(const char* value, char* reply,
|
||||
esp_err_t apply_result = ESP_OK;
|
||||
if (WiFi.getMode() != WIFI_OFF) {
|
||||
const wifi_ps_type_t ps_mode =
|
||||
power_save == 1 ? WIFI_PS_NONE
|
||||
: power_save == 2 ? WIFI_PS_MAX_MODEM
|
||||
: WIFI_PS_MIN_MODEM;
|
||||
power_save == mesh::wifi::kPowerSaveNone ? WIFI_PS_NONE
|
||||
: power_save == mesh::wifi::kPowerSaveMax ? WIFI_PS_MAX_MODEM
|
||||
: WIFI_PS_MIN_MODEM;
|
||||
apply_result = esp_wifi_set_ps(ps_mode);
|
||||
}
|
||||
if (apply_result == ESP_OK) {
|
||||
@@ -419,7 +422,7 @@ bool WebConfigServer::formatWiFiSSID(char* reply, size_t reply_len) {
|
||||
|
||||
char ssid[32] = "";
|
||||
char password[64] = "";
|
||||
uint8_t power_save = 1;
|
||||
uint8_t power_save = mesh::wifi::kDefaultPowerSave;
|
||||
bool configured = loadStandaloneWiFi(
|
||||
ssid, sizeof(ssid), password, sizeof(password), &power_save);
|
||||
if (_active && _active->_wifi_ssid[0]) {
|
||||
@@ -435,7 +438,7 @@ bool WebConfigServer::formatWiFiSSID(char* reply, size_t reply_len) {
|
||||
bool WebConfigServer::formatWiFiPowerSave(char* reply, size_t reply_len) {
|
||||
if (!reply || reply_len == 0) return false;
|
||||
|
||||
uint8_t power_save = 1;
|
||||
uint8_t power_save = mesh::wifi::kDefaultPowerSave;
|
||||
if (_active) {
|
||||
power_save = _active->_wifi_power_save;
|
||||
} else {
|
||||
@@ -446,9 +449,9 @@ bool WebConfigServer::formatWiFiPowerSave(char* reply, size_t reply_len) {
|
||||
}
|
||||
|
||||
const char* name = "none";
|
||||
if (power_save == 0) {
|
||||
if (power_save == mesh::wifi::kPowerSaveMin) {
|
||||
name = "min";
|
||||
} else if (power_save == 2) {
|
||||
} else if (power_save == mesh::wifi::kPowerSaveMax) {
|
||||
name = "max";
|
||||
}
|
||||
snprintf(reply, reply_len, "> %s", name);
|
||||
@@ -477,7 +480,7 @@ bool WebConfigServer::formatWiFiStatus(char* reply, size_t reply_len) {
|
||||
|
||||
char ssid[32] = "";
|
||||
char password[64] = "";
|
||||
uint8_t power_save = 1;
|
||||
uint8_t power_save = mesh::wifi::kDefaultPowerSave;
|
||||
bool configured = loadStandaloneWiFi(
|
||||
ssid, sizeof(ssid), password, sizeof(password), &power_save);
|
||||
WebConfigServer* active = _active;
|
||||
@@ -678,9 +681,10 @@ bool WebConfigServer::startAutoMode(char reply[]) {
|
||||
_wifi_reconnect_tracker.noteDisconnected(millis());
|
||||
WiFi.begin(_wifi_ssid, _wifi_password);
|
||||
_wifi_power_save = effectiveWiFiPowerSave(_wifi_power_save);
|
||||
wifi_ps_type_t ps_mode = _wifi_power_save == 1 ? WIFI_PS_NONE
|
||||
: _wifi_power_save == 2 ? WIFI_PS_MAX_MODEM
|
||||
: WIFI_PS_MIN_MODEM;
|
||||
wifi_ps_type_t ps_mode =
|
||||
_wifi_power_save == mesh::wifi::kPowerSaveNone ? WIFI_PS_NONE
|
||||
: _wifi_power_save == mesh::wifi::kPowerSaveMax ? WIFI_PS_MAX_MODEM
|
||||
: WIFI_PS_MIN_MODEM;
|
||||
esp_wifi_set_ps(ps_mode);
|
||||
_mode = MODE_CONNECTING;
|
||||
_connect_deadline = millis() + 15000;
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/semphr.h>
|
||||
#include <helpers/WebConfigBatch.h>
|
||||
#include <helpers/WiFiPowerSave.h>
|
||||
#include <helpers/WiFiReconnectPolicy.h>
|
||||
|
||||
class AsyncWebServer;
|
||||
@@ -229,7 +230,7 @@ private:
|
||||
uint32_t _connect_deadline = 0;
|
||||
char _wifi_ssid[32] = {0};
|
||||
char _wifi_password[64] = {0};
|
||||
uint8_t _wifi_power_save = 1;
|
||||
uint8_t _wifi_power_save = mesh::wifi::kDefaultPowerSave;
|
||||
bool _cli_enabled = true;
|
||||
// A `password` command has succeeded this session. Lets the CLI satisfy the
|
||||
// initial-setup invariant across separate submissions; the form batch always
|
||||
|
||||
@@ -55,6 +55,7 @@ protected:
|
||||
return ((CustomLLCC68 *)_radio)->setRxBoostedGainMode(en) == RADIOLIB_ERR_NONE;
|
||||
}
|
||||
public:
|
||||
bool supportsRxBoostedGainMode() const override { return true; }
|
||||
bool getRxBoostedGainMode() const override {
|
||||
return ((CustomLLCC68 *)_radio)->getRxBoostedGainMode();
|
||||
}
|
||||
|
||||
@@ -134,6 +134,7 @@ protected:
|
||||
return ((CustomLR1110 *)_radio)->setRxBoostedGainMode(en) == RADIOLIB_ERR_NONE;
|
||||
}
|
||||
public:
|
||||
bool supportsRxBoostedGainMode() const override { return true; }
|
||||
bool getRxBoostedGainMode() const override {
|
||||
return ((CustomLR1110 *)_radio)->getRxBoostedGainMode();
|
||||
}
|
||||
|
||||
@@ -178,6 +178,7 @@ public:
|
||||
|
||||
void doResetAGC() override { }
|
||||
|
||||
bool supportsRxBoostedGainMode() const override { return true; }
|
||||
bool getRxBoostedGainMode() const override {
|
||||
return ((CustomLR2021 *)_radio)->getRxBoostedGainMode();
|
||||
}
|
||||
|
||||
@@ -160,6 +160,7 @@ protected:
|
||||
return ((CustomSX1262 *)_radio)->setRxBoostedGainMode(en) == RADIOLIB_ERR_NONE;
|
||||
}
|
||||
public:
|
||||
bool supportsRxBoostedGainMode() const override { return true; }
|
||||
bool getRxBoostedGainMode() const override {
|
||||
return ((CustomSX1262 *)_radio)->getRxBoostedGainMode();
|
||||
}
|
||||
|
||||
@@ -57,6 +57,7 @@ protected:
|
||||
return ((CustomSX1268 *)_radio)->setRxBoostedGainMode(en) == RADIOLIB_ERR_NONE;
|
||||
}
|
||||
public:
|
||||
bool supportsRxBoostedGainMode() const override { return true; }
|
||||
bool getRxBoostedGainMode() const override {
|
||||
return ((CustomSX1268 *)_radio)->getRxBoostedGainMode();
|
||||
}
|
||||
|
||||
@@ -210,6 +210,7 @@ public:
|
||||
float packetScore(float snr, int packet_len) override { return packetScoreInt(snr, 10, packet_len); } // assume sf=10
|
||||
|
||||
bool setRxBoostedGainMode(bool enabled);
|
||||
virtual bool supportsRxBoostedGainMode() const { return false; }
|
||||
virtual bool getRxBoostedGainMode() const { return false; }
|
||||
|
||||
virtual bool configSideDetectors(const uint8_t sideDetSFs[], uint8_t num, float bw) { return false; }
|
||||
|
||||
@@ -81,6 +81,7 @@ public:
|
||||
uint32_t getPacketsSent() const { return n_sent; }
|
||||
void resetStats() { n_recv = n_sent = n_recv_errors = 0; }
|
||||
bool setRxBoostedGainMode(bool /*enabled*/) { return false; }
|
||||
bool supportsRxBoostedGainMode() const { return false; }
|
||||
bool getRxBoostedGainMode() const { return false; }
|
||||
uint32_t getRxPsWatchdogSoftCount() const { return 0; }
|
||||
uint32_t getRxPsWatchdogHardCount() const { return 0; }
|
||||
|
||||
@@ -442,12 +442,22 @@ TEST(CLICommandUtils, ValidatesStandaloneWiFiValues) {
|
||||
}
|
||||
|
||||
TEST(CLICommandUtils, EnforcesWiFiSleepForBluetoothCoexistence) {
|
||||
EXPECT_EQ(0, mesh::wifi::effectivePowerSave(0, true));
|
||||
EXPECT_EQ(0, mesh::wifi::effectivePowerSave(1, true));
|
||||
EXPECT_EQ(2, mesh::wifi::effectivePowerSave(2, true));
|
||||
EXPECT_EQ(1, mesh::wifi::effectivePowerSave(1, false));
|
||||
EXPECT_EQ(0, mesh::wifi::effectivePowerSave(99, true));
|
||||
EXPECT_EQ(1, mesh::wifi::effectivePowerSave(99, false));
|
||||
EXPECT_EQ(mesh::wifi::kPowerSaveMin,
|
||||
mesh::wifi::effectivePowerSave(mesh::wifi::kPowerSaveMin, true));
|
||||
EXPECT_EQ(mesh::wifi::kPowerSaveMin,
|
||||
mesh::wifi::effectivePowerSave(mesh::wifi::kPowerSaveNone, true));
|
||||
EXPECT_EQ(mesh::wifi::kPowerSaveMax,
|
||||
mesh::wifi::effectivePowerSave(mesh::wifi::kPowerSaveMax, true));
|
||||
EXPECT_EQ(mesh::wifi::kPowerSaveNone,
|
||||
mesh::wifi::effectivePowerSave(mesh::wifi::kPowerSaveNone, false));
|
||||
EXPECT_EQ(mesh::wifi::kPowerSaveMin,
|
||||
mesh::wifi::effectivePowerSave(99, true));
|
||||
EXPECT_EQ(mesh::wifi::kPowerSaveNone,
|
||||
mesh::wifi::effectivePowerSave(99, false));
|
||||
}
|
||||
|
||||
TEST(CLICommandUtils, DefaultsWiFiPowerSaveToNoneWithoutProfileOverride) {
|
||||
EXPECT_EQ(mesh::wifi::kPowerSaveNone, mesh::wifi::kDefaultPowerSave);
|
||||
}
|
||||
|
||||
TEST(CLICommandUtils, MatchesDiscoverNeighborsWithoutPrefixCollisions) {
|
||||
|
||||
+1
-1
@@ -494,7 +494,7 @@ body.tab-cli{padding-bottom:0}
|
||||
</div></div>
|
||||
<div class="f"><label>Password</label><input type="password" data-k="wifi.pwd" autocomplete="off"></div>
|
||||
<div class="f" data-cap="1024"><label>Power save</label>
|
||||
<select data-k="wifi.powersave"><option value="min">Minimum</option><option value="none">None (default; lowest latency)</option><option value="max">Maximum (battery)</option></select></div>
|
||||
<select data-k="wifi.powersave"><option value="min">Minimum</option><option value="none">None (lowest latency)</option><option value="max">Maximum (battery)</option></select></div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h2>Maintenance</h2>
|
||||
|
||||
Reference in new issue
Block a user