mirror of
https://github.com/mikecarper/MeshCore.git
synced 2026-09-26 09:28:11 +00:00
refactor: use companion CLI for hardware settings
This commit is contained in:
@@ -261,10 +261,11 @@ WiFi card. Every ESP32 WiFi Companion with WebConfig exposes the standalone
|
||||
families through its USB text terminal. Full Companion exposes the same
|
||||
role-specific terminal on TCP port 5002. Credential writes reply before
|
||||
restarting the WiFi station, so a TCP client should expect to reconnect at the
|
||||
new address; USB password input is masked. Binary
|
||||
Companion clients can use command bytes
|
||||
`0x7C` and `0x7D` over USB, BLE, or TCP port 5000 without the terminal-start
|
||||
token. WiFi-only Companions accept all three modes. Full Companion rejects
|
||||
new address; USB password input is masked. Binary Companion clients can use
|
||||
USB, BLE, or TCP port 5000 without the terminal-start token: send command
|
||||
`0x42` (`CMD_RUN_CLI_COMMAND`) followed by the same CLI text, such as
|
||||
`get wifi.powersave` or `set wifi.powersave min`. 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. On an ESP32 Full
|
||||
Companion whose primary mesh radio is ESP-NOW, `max` is also unavailable: a
|
||||
|
||||
+27
-55
@@ -237,10 +237,6 @@ catalog; bytes `0x2C`-`0x31` are parked and `0x35` is unused.
|
||||
| `0x42` | `CMD_RUN_CLI_COMMAND` | Run a local CLI command (protocol v14+). |
|
||||
| `0x4A` | `CMD_EXEC_LOCAL_OTA_CONTROL` | Run one bounded local TempRadio or OTA command on a Full Companion. |
|
||||
| `0x4B` | `CMD_BLE_MOTA_SOURCE` | Query, start, or stop an nRF52 Full Companion's Bluetooth-backed LoRa mOTA source. |
|
||||
| `0x78` / `0x79` | `CMD_GET_RADIO_FEM_RXGAIN` / `CMD_SET_RADIO_FEM_RXGAIN` | Fork extension: read or set FEM receive gain. |
|
||||
| `0x7A` / `0x7B` | `CMD_GET_RADIO_RXGAIN` / `CMD_SET_RADIO_RXGAIN` | Fork extension: read or set the radio chip's boosted receive-gain mode. |
|
||||
| `0x7C` / `0x7D` | `CMD_GET_WIFI_POWER_SAVE` / `CMD_SET_WIFI_POWER_SAVE` | Fork extension: read or set ESP32 Companion WiFi modem sleep. |
|
||||
| `0x7E` / `0x7F` | `CMD_GET_BLUETOOTH_NAME` / `CMD_SET_BLUETOOTH_NAME` | Fork extension: read or set the independent Bluetooth device name. |
|
||||
|
||||
The sections below detail the most common frames. Refer to the source named
|
||||
above for command bodies that are not expanded here.
|
||||
@@ -252,39 +248,29 @@ text. This is separate from sending a remote on-air CLI command with
|
||||
one byte and must not contain an embedded NUL. An unknown command is returned
|
||||
as the normal CLI reply text `Unknown command`, not as an error frame.
|
||||
|
||||
The fork-specific hardware-setting commands occupy the host-to-device range
|
||||
`0x78`-`0x7F`, the highest currently unused block below the push-frame bit.
|
||||
Command IDs must stay below `0x80`; IDs with bit 7 set identify asynchronous
|
||||
device-to-host push frames. These commands do not change any existing frame
|
||||
layout. Clients should probe the command they need and treat
|
||||
`ERR_CODE_UNSUPPORTED_CMD` as feature absence.
|
||||
|
||||
Firmware from this fork predating the upstream `0x42` allocation used
|
||||
`0x42`-`0x49` for these eight settings. This firmware accepts those values as
|
||||
deprecated aliases so existing clients continue to work. A one-byte `0x42`
|
||||
frame is the legacy FEM-gain GET; `0x42` followed by text is the official
|
||||
`CMD_RUN_CLI_COMMAND`. New clients should use `0x78`-`0x7F` (or send the
|
||||
equivalent text through `0x42`) because future upstream commands may reuse the
|
||||
remaining legacy IDs.
|
||||
deprecated inbound aliases so existing clients continue to work. A one-byte
|
||||
`0x42` frame is the legacy FEM-gain GET; `0x42` followed by text is the official
|
||||
`CMD_RUN_CLI_COMMAND`. New clients should use `CMD_RUN_CLI_COMMAND` for all of
|
||||
these settings, rather than allocating additional command bytes. For example,
|
||||
send `0x42` followed by `get radio.rxgain` or `set radio.rxgain on`. The reply is
|
||||
`RESP_CODE_CLI_REPLY` followed by the normal CLI reply text.
|
||||
|
||||
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
|
||||
unframed text such as `set radio.rxgain off` still requires the USB terminal
|
||||
start token; the same text may instead be carried as a framed `0x42` command
|
||||
over USB, BLE, or TCP.
|
||||
The equivalent framed CLI commands are:
|
||||
|
||||
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 the effective mode byte.
|
||||
`CMD_SET_WIFI_POWER_SAVE` is followed by that mode byte and replies with
|
||||
`RESP_CODE_OK` after saving it:
|
||||
| Setting | Commands |
|
||||
|---|---|
|
||||
| Radio receive gain | `get radio.rxgain`; `set radio.rxgain on|off` |
|
||||
| FEM receive gain | `get radio.fem.rxgain`; `set radio.fem.rxgain on|off` |
|
||||
| WiFi power save | `get wifi.powersave`; `set wifi.powersave none|min|max` |
|
||||
| Bluetooth name | `get bluetooth.name`; `set bluetooth.name <name|default>` |
|
||||
|
||||
The framed form works over the normal binary USB, BLE, or TCP transport and
|
||||
does not need the USB terminal-start token. Unsupported settings return the
|
||||
same explanatory text as the local CLI.
|
||||
|
||||
WiFi power-save modes are:
|
||||
|
||||
| Value | Mode |
|
||||
|---:|---|
|
||||
@@ -292,29 +278,15 @@ has no body and replies with `RESP_CODE_OK` followed by the effective mode byte.
|
||||
| `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. On an ESP32 Full Companion whose primary mesh
|
||||
radio is ESP-NOW, SET also returns `ERR_CODE_BAD_STATE` for `max` (value `2`): maximum
|
||||
modem sleep can make the station miss ESP-NOW broadcasts, which the access point
|
||||
cannot buffer. If an older image already saved `max`, GET reports `min` (value
|
||||
`0`) and the running policy uses `min`. A storage failure also returns
|
||||
`ERR_CODE_BAD_STATE`. If an otherwise permitted 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.
|
||||
Full Companion rejects WiFi mode `none` because simultaneous BLE transport
|
||||
requires modem sleep. A Full Companion using ESP-NOW as its primary mesh radio
|
||||
also rejects `max`, because maximum modem sleep can miss broadcasts that the
|
||||
access point cannot buffer. If an older image saved `max`, the effective mode
|
||||
is capped to and reported as `min`. Device `powersaving` remains independent.
|
||||
|
||||
The Bluetooth-name pair is available on Companion builds regardless of the
|
||||
currently selected transport, so a host can configure a BLE-capable image over
|
||||
USB or TCP before rebooting into it. `CMD_GET_BLUETOOTH_NAME` has no body and
|
||||
replies with `RESP_CODE_OK`, a one-byte mode (`0` for the default name, `1` for
|
||||
a custom name), then the effective UTF-8 device name without a terminator.
|
||||
`CMD_SET_BLUETOOTH_NAME` is followed by zero to 31 UTF-8 bytes. A non-empty
|
||||
body stores that exact complete Bluetooth name; a zero-length body clears the
|
||||
override and restores `MeshCore-<advert name>`. A successful SET replies with
|
||||
`RESP_CODE_OK`, and the new label takes effect after reboot. Embedded NULs,
|
||||
control characters, malformed UTF-8, or oversized values return
|
||||
`ERR_CODE_ILLEGAL_ARG`; a storage failure returns `ERR_CODE_BAD_STATE`.
|
||||
The Bluetooth name can be configured over USB or TCP before rebooting into BLE.
|
||||
An empty/default selection restores `MeshCore-<advert name>`; a custom name is
|
||||
limited to 31 valid UTF-8 bytes and takes effect after reboot.
|
||||
|
||||
### Bluetooth LoRa mOTA source
|
||||
|
||||
|
||||
@@ -123,21 +123,10 @@ static const uint32_t COMMAND_RADIO_APPLY_TIMEOUT_MS = 5000UL;
|
||||
#define CMD_SEND_RAW_PACKET 65
|
||||
#define CMD_RUN_CLI_COMMAND 66 // v14+
|
||||
|
||||
// Fork-specific host-to-device commands use the highest currently unused
|
||||
// block below 0x80. Bit 7 is reserved by the transport for device-to-host
|
||||
// push frames, so command IDs must remain in the low half of the byte range.
|
||||
#define CMD_GET_RADIO_FEM_RXGAIN 0x78
|
||||
#define CMD_SET_RADIO_FEM_RXGAIN 0x79
|
||||
#define CMD_GET_RADIO_RXGAIN 0x7A
|
||||
#define CMD_SET_RADIO_RXGAIN 0x7B
|
||||
#define CMD_GET_WIFI_POWER_SAVE 0x7C
|
||||
#define CMD_SET_WIFI_POWER_SAVE 0x7D
|
||||
#define CMD_GET_BLUETOOTH_NAME 0x7E
|
||||
#define CMD_SET_BLUETOOTH_NAME 0x7F
|
||||
|
||||
// Compatibility aliases used by this fork before upstream assigned 0x42 to
|
||||
// CMD_RUN_CLI_COMMAND. A one-byte 0x42 frame remains distinguishable from the
|
||||
// official command, whose frame always includes CLI text.
|
||||
// official command, whose frame always includes CLI text. New clients should
|
||||
// use CMD_RUN_CLI_COMMAND rather than allocating more one-byte command IDs.
|
||||
#define LEGACY_CMD_GET_RADIO_FEM_RXGAIN 0x42
|
||||
#define LEGACY_CMD_SET_RADIO_FEM_RXGAIN 0x43
|
||||
#define LEGACY_CMD_GET_RADIO_RXGAIN 0x44
|
||||
@@ -4113,8 +4102,7 @@ void MyMesh::handleCmdFrame(size_t len) {
|
||||
} else {
|
||||
writeErrFrame(ERR_CODE_ILLEGAL_ARG);
|
||||
}
|
||||
} else if (cmd_frame[0] == CMD_GET_RADIO_FEM_RXGAIN
|
||||
|| cmd_frame[0] == LEGACY_CMD_GET_RADIO_FEM_RXGAIN) {
|
||||
} else if (cmd_frame[0] == LEGACY_CMD_GET_RADIO_FEM_RXGAIN) {
|
||||
if (len != 1) {
|
||||
writeErrFrame(ERR_CODE_ILLEGAL_ARG);
|
||||
} else if (!board.canControlLoRaFemLna()) {
|
||||
@@ -4125,8 +4113,7 @@ void MyMesh::handleCmdFrame(size_t len) {
|
||||
memcpy(&out_frame[1], &value, 1);
|
||||
_serial->writeFrame(out_frame, 2);
|
||||
}
|
||||
} else if (cmd_frame[0] == CMD_SET_RADIO_FEM_RXGAIN
|
||||
|| cmd_frame[0] == LEGACY_CMD_SET_RADIO_FEM_RXGAIN) {
|
||||
} else if (cmd_frame[0] == LEGACY_CMD_SET_RADIO_FEM_RXGAIN) {
|
||||
uint8_t value = len >= 2 ? cmd_frame[1] : 0;
|
||||
if (len != 2) {
|
||||
writeErrFrame(ERR_CODE_ILLEGAL_ARG);
|
||||
@@ -4141,8 +4128,7 @@ void MyMesh::handleCmdFrame(size_t len) {
|
||||
} else {
|
||||
writeErrFrame(ERR_CODE_ILLEGAL_ARG);
|
||||
}
|
||||
} else if (cmd_frame[0] == CMD_GET_RADIO_RXGAIN
|
||||
|| cmd_frame[0] == LEGACY_CMD_GET_RADIO_RXGAIN) {
|
||||
} else if (cmd_frame[0] == LEGACY_CMD_GET_RADIO_RXGAIN) {
|
||||
if (len != 1) {
|
||||
writeErrFrame(ERR_CODE_ILLEGAL_ARG);
|
||||
} else if (!radio_driver.supportsRxBoostedGainMode()) {
|
||||
@@ -4152,8 +4138,7 @@ void MyMesh::handleCmdFrame(size_t len) {
|
||||
out_frame[1] = _prefs.rx_boosted_gain ? 1 : 0;
|
||||
_serial->writeFrame(out_frame, 2);
|
||||
}
|
||||
} else if (cmd_frame[0] == CMD_SET_RADIO_RXGAIN
|
||||
|| cmd_frame[0] == LEGACY_CMD_SET_RADIO_RXGAIN) {
|
||||
} else if (cmd_frame[0] == LEGACY_CMD_SET_RADIO_RXGAIN) {
|
||||
uint8_t value = len >= 2 ? cmd_frame[1] : 0;
|
||||
if (len != 2 || value > 1) {
|
||||
writeErrFrame(ERR_CODE_ILLEGAL_ARG);
|
||||
@@ -4164,8 +4149,7 @@ void MyMesh::handleCmdFrame(size_t len) {
|
||||
} else {
|
||||
writeOKFrame();
|
||||
}
|
||||
} else if (cmd_frame[0] == CMD_GET_WIFI_POWER_SAVE
|
||||
|| cmd_frame[0] == LEGACY_CMD_GET_WIFI_POWER_SAVE) {
|
||||
} else if (cmd_frame[0] == LEGACY_CMD_GET_WIFI_POWER_SAVE) {
|
||||
if (len != 1) {
|
||||
writeErrFrame(ERR_CODE_ILLEGAL_ARG);
|
||||
} else {
|
||||
@@ -4177,8 +4161,7 @@ void MyMesh::handleCmdFrame(size_t len) {
|
||||
writeErrFrame(ERR_CODE_UNSUPPORTED_CMD);
|
||||
#endif
|
||||
}
|
||||
} else if (cmd_frame[0] == CMD_SET_WIFI_POWER_SAVE
|
||||
|| cmd_frame[0] == LEGACY_CMD_SET_WIFI_POWER_SAVE) {
|
||||
} else if (cmd_frame[0] == LEGACY_CMD_SET_WIFI_POWER_SAVE) {
|
||||
if (len != 2) {
|
||||
writeErrFrame(ERR_CODE_ILLEGAL_ARG);
|
||||
} else {
|
||||
@@ -4199,8 +4182,7 @@ void MyMesh::handleCmdFrame(size_t len) {
|
||||
writeErrFrame(ERR_CODE_UNSUPPORTED_CMD);
|
||||
#endif
|
||||
}
|
||||
} else if (cmd_frame[0] == CMD_GET_BLUETOOTH_NAME
|
||||
|| cmd_frame[0] == LEGACY_CMD_GET_BLUETOOTH_NAME) {
|
||||
} else if (cmd_frame[0] == LEGACY_CMD_GET_BLUETOOTH_NAME) {
|
||||
if (len != 1) {
|
||||
writeErrFrame(ERR_CODE_ILLEGAL_ARG);
|
||||
} else {
|
||||
@@ -4213,8 +4195,7 @@ void MyMesh::handleCmdFrame(size_t len) {
|
||||
BLE_NAME_PREFIX, _prefs.node_name);
|
||||
_serial->writeFrame(out_frame, 2 + strlen(effective_name));
|
||||
}
|
||||
} else if (cmd_frame[0] == CMD_SET_BLUETOOTH_NAME
|
||||
|| cmd_frame[0] == LEGACY_CMD_SET_BLUETOOTH_NAME) {
|
||||
} else if (cmd_frame[0] == LEGACY_CMD_SET_BLUETOOTH_NAME) {
|
||||
const size_t name_len = len - 1;
|
||||
if (name_len > mesh::companion::BLUETOOTH_NAME_MAX_BYTES
|
||||
|| memchr(&cmd_frame[1], 0, name_len) != NULL) {
|
||||
|
||||
Reference in New Issue
Block a user