Add full Companion OTA source builds

This commit is contained in:
mikecarper committed 2026-08-10 12:39:07 -07:00
1 parent 1bceda54a6
commit 88ba5b26cb
19 files changed
+1212 -86

No files matched your search

+9
View File
@@ -175,6 +175,12 @@ A `*_companion_radio_wifi` build replaces the BLE or USB companion link with
the MeshCore companion protocol over TCP port 5000. The phone or computer must
be able to reach the device on the same LAN.
An ESP32 `*_companion_radio_full` target keeps all three Companion links at
once: USB, BLE, and TCP port 5000. It also provides a source-only LoRa mOTA
service on ports 5001 and 5002. See the
[full Companion guide](./companion_radio_full.md) for its build, terminal mode,
and complete update-source workflow.
The companion loads runtime credentials saved in NVS. A non-placeholder
compile-time `WIFI_SSID`/`WIFI_PWD` can be used as a first-boot fallback, but
saved credentials take priority. With no credentials, its WebConfig portal
@@ -196,6 +202,9 @@ When `ENABLE_OTA` is included, a WiFi companion also listens on:
- TCP 5002 for the OTA text console.
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.
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.
+212
View File
@@ -0,0 +1,212 @@
# Full Companion
`companion_radio_full` combines every Companion transport available on its
platform and acts as a host-backed LoRa mOTA source for updating other nodes.
The full Companion is deliberately not a LoRa OTA destination: it has no
firmware staging store, refuses `ota install`, and never advertises its own
firmware as an mOTA image.
| Capability | ESP32 full | nRF52 full |
| --- | --- | --- |
| USB Binary Companion | Yes | Yes |
| BLE Binary Companion | Yes | Yes |
| USB ASCII terminal | Yes | Yes |
| Host-backed LoRa mOTA source | WiFi TCP 5001 | Exclusive USB mode |
| WiFi Companion/WebConfig | Yes | No - nRF52840 has no WiFi |
| LoRa self-update | No | No |
## Build and install
The target is synthesized by `build.sh` only when matching transport recipes
exist for the exact board variant:
- ESP32 requires matching WiFi, USB, and BLE Companion environments.
- nRF52 requires matching USB and BLE Companion environments.
List the available targets:
```bash
bash build.sh list | grep companion_radio_full
```
Build by using one exact listed name:
```bash
bash build.sh build-firmware heltec_v4_r8_companion_radio_full \
--firmware-version v1.17.0
bash build.sh build-firmware RAK_4631_companion_radio_full \
--firmware-version v1.17.0
```
Artifacts are written to `out/` by default.
On 4 MB ESP32 boards, the full target uses a single 3 MB application
partition so WiFi, BLE, WebConfig, and source-only mOTA fit together. Flash
the generated `-merged.bin` when first installing this partition layout.
Boards with 8 MB or more retain dual application partitions. Heltec V2 and
TLora V2 use 100 contacts, 8 group channels, and a 16-frame offline queue in
this combined profile because of internal DRAM limits.
The nRF52 target inherits the board's ordinary USB Companion installation
format and adds BLE plus the serial mOTA source. It does not enable an SD cache
or any other board-specific storage behavior; host files are streamed as they
are requested.
## Interfaces
| Platform | Interface | Purpose |
| --- | --- | --- |
| Both | USB, 115200 baud | Binary Companion by default; terminal switch available |
| Both | BLE | Binary Companion; default pairing PIN `123456` |
| 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 |
| nRF52 | USB mOTA mode | Host `.mota` folder from `motatool serve --serial` |
Binary Companion replies are broadcast through the multi-interface manager,
so use one active Companion application at a time. On nRF52, BLE remains
available while USB is in terminal or mOTA mode.
ESP32 ports 5000, 5001, 5002, and WebConfig have no independent login layer.
Expose them only on a trusted LAN or temporary setup network. See
[WiFi setup](./WiFi.md) for credential setup and reconnect behavior.
## USB Binary and terminal modes
USB starts in Binary mode for MeshCore apps and `meshcli`:
```bash
meshcli -s /dev/ttyACM0 -b 115200 ver
```
Open the port at 115200 and send the terminal start token as an exact line:
```bash
picocom -b 115200 /dev/ttyACM0
+++MESHCORE-TERM-START
```
The terminal supports Companion chat commands plus local `ota`, `tempradio`,
and `normalradio` controls. Return to Binary mode with:
```text
+++MESHCORE-TERM-STOP
```
Closing the USB data connection also resets the port to Binary mode. A
different baud rate, including 57600, does not select ASCII mode.
## nRF52 USB mOTA mode
The nRF52 full target has a third, exclusive USB mode for the host folder.
Unmodified `motatool serve --serial` already sends `ota folder on` when it
opens the port. The Binary parser recognizes that exact idle control sequence,
stops USB Binary traffic, and attaches the serial folder source. The sequence
is not examined inside a framed Binary Companion packet.
While mOTA mode owns USB:
- mOTA manifests and blocks stream from the computer on demand.
- USB Binary and the USB text terminal are unavailable.
- BLE Binary Companion remains available.
- `motatool` sending `ota folder off`, or disconnecting the USB data session,
detaches the folder and restores Binary mode.
No manual mode token or modified `motatool` build is required.
## Serve mOTA images manually
First put the destination, required relays, controller, and source on the same
bounded TempRadio tuple. The example frequency below is not legal everywhere;
choose a legal tuple supported by every participating radio.
### ESP32 source
Use the local console to start TempRadio:
```bash
nc 192.168.1.50 5002
```
```text
tempradio 909.950,250,7,5,120
ota status
```
Then start the dedicated TCP seeder:
```bash
motatool serve --dir ./motas --tcp 192.168.1.50:5001 -v
```
### nRF52 source
Use the USB terminal briefly to schedule TempRadio, then return to Binary mode
and close the terminal:
```text
+++MESHCORE-TERM-START
tempradio 909.950,250,7,5,120
+++MESHCORE-TERM-STOP
```
Start the serial seeder on that same port:
```bash
motatool serve --dir ./motas --serial /dev/ttyACM1 --baud 115200 -v
```
`motatool` switches the port into mOTA mode automatically. Stop it with
Ctrl-C to detach the folder. Reopen the terminal and use `normalradio` if the
source should return early; otherwise the saved radio settings return when the
bounded window expires.
Both platforms intentionally refuse firmware installation commands such as:
```text
ota pull <id> flash
ota install
ota dev ...
```
## Script a complete update
The Bash and PowerShell wrappers accept a release ZIP or ready `.mota`, set up
TempRadio, run `motatool`, monitor the exact image, install it on the
destination, and restore the radio path. Use a separate Companion as the
controller.
For an ESP32 full source:
```bash
export MESHCORE_ADMIN_PASSWORD='target-admin-password'
./tools/lora_ota/lora_ota.sh ./release.zip "Roof Node" \
--controller-serial /dev/ttyACM0 \
--source-tcp 192.168.1.50:5001 \
--source-cli-tcp 192.168.1.50:5002
```
For an nRF52 full source, the script automatically detects the token-switched
terminal and uses the same source port sequentially for control and seeding:
```bash
export MESHCORE_ADMIN_PASSWORD='target-admin-password'
./tools/lora_ota/lora_ota.sh ./release.zip "Roof Node" \
--controller-serial /dev/ttyACM0 \
--source-serial /dev/ttyACM1
```
```powershell
$env:MESHCORE_ADMIN_PASSWORD = 'target-admin-password'
& .\tools\lora_ota\lora_ota.ps1 '.\release.zip' 'Roof Node' `
--controller-serial COM7 `
--source-serial COM8
```
See the [start-to-finish LoRa OTA guide](./lora_ota_automation.md) for package
selection, nRF52 in-place deltas, relays, trust checks, and recovery behavior.
+1
View File
@@ -14,6 +14,7 @@ Below are a few quick start guides.
- [MeshTower V2 microSD self-updates](./ota_meshtower_v2_sdcard.md)
- [GPS Tracking](./gps_tracking.md)
- [Companion Protocol](./companion_protocol.md)
- [Full Companion: ESP32 and nRF52](./companion_radio_full.md)
- [Packet Format](./packet_format.md)
- [QR Codes](./qr_codes.md)
+52 -14
View File
@@ -28,9 +28,10 @@ computer -- MeshCore binary API --> controller Companion -------------------+
script uses `meshcli` to send remote admin commands to the target and changes
the controller's live radio parameters during the transfer. A serial
Companion stays in its normal **Binary** USB mode at 115200 baud.
- **OTA source:** a separate OTA-enabled repeater or FULL node whose USB port
is a raw text CLI and supports `ota folder on`. `motatool` uses that same
link for its binary seeder frames after enabling the folder.
- **OTA source:** an OTA-enabled repeater/FULL node whose USB port is a raw
text CLI, an ESP32 `companion_radio_full` using WiFi ports 5001 and 5002, or
an nRF52 `companion_radio_full` whose USB port switches between Binary,
terminal control, and exclusive mOTA seeding.
- **Target:** an OTA-enabled ESP32 or nRF52 node present in the controller's
contact list. Its admin password is required.
- **Relays:** optional. They do not need to install OTA themselves, but every
@@ -41,11 +42,11 @@ One serial port cannot serve both controller roles: `meshcli` must keep
reopening the controller while `motatool` owns the source port. The script
rejects an attempt to use the same port for both.
The Companion USB ASCII switch (`+++MESHCORE-TERM-START`) is an interactive
chat terminal, not the raw repeater/FULL management CLI expected by
`motatool`. It does not make a Companion's serial port an OTA seeder. For a
WiFi seeder, use a FULL/repeater source's port 5001 plus its raw USB CLI, as
shown below.
The USB ASCII switch (`+++MESHCORE-TERM-START`) is the local control path, not
the mOTA data framing. On an nRF52 full Companion, the script uses that mode
briefly for `ota status` and TempRadio commands. It then closes the CLI and
starts `motatool`, whose existing `ota folder on` preamble switches the same
USB port into exclusive mOTA mode. BLE remains available during that mode.
## Destination requirements
@@ -120,15 +121,27 @@ Test the controller's binary API:
meshcli -s /dev/ttyACM0 -b 115200 ver
```
Test the source's raw text CLI and OTA support:
For an ordinary raw-text source, test its OTA support:
```bash
meshcli -r -s /dev/ttyACM1 -b 115200 "ota status"
```
The second command must print an `OTA | ... target:XXXXXXXX` status. The
automation repeats this preflight and stops before changing any radios if the
source is the wrong build or interface.
The command must print an `OTA | ... target:XXXXXXXX` status.
For an nRF52 full Companion, open the source port in a terminal, send
`+++MESHCORE-TERM-START`, and run `ota status`. It must report `OTA seeder`,
`install:disabled`, and target `00000000`; send `+++MESHCORE-TERM-STOP` before
closing the terminal. The automation detects and performs this token-wrapped
preflight itself, so no extra command-line option is needed.
For an ESP32 full Companion, test its separate WiFi control console instead:
```bash
printf 'ota status\r\n' | nc 192.168.1.50 5002
```
It must report `OTA seeder`, `install:disabled`, and target `00000000`.
Changing a terminal to 57600 baud does not select ASCII mode. USB Companion
builds and the normal raw management CLI use 115200 unless a particular build
@@ -280,6 +293,31 @@ while its raw USB CLI is used to start TempRadio:
--source-cli-serial /dev/ttyACM1
```
An ESP32 `companion_radio_full` uses WiFi for both dedicated source links:
```bash
./tools/lora_ota/lora_ota.sh ./release.mota "Remote Target" \
--controller-serial /dev/ttyACM0 \
--source-tcp 192.168.1.50:5001 \
--source-cli-tcp 192.168.1.50:5002
```
Port 5002 defaults automatically when it is omitted from
`--source-cli-tcp`. The source-only Companion never stages or installs the
image itself; it streams the host folder to other nodes over LoRa. See the
[full Companion guide](./companion_radio_full.md) for manual operation and
interface details.
An nRF52 `companion_radio_full` uses one USB source port sequentially. The
runner automatically wraps local control commands in the terminal tokens, and
unmodified `motatool` switches that port into mOTA mode when seeding starts:
```bash
./tools/lora_ota/lora_ota.sh ./release.mota "Remote Target" \
--controller-serial /dev/ttyACM0 \
--source-serial /dev/ttyACM1
```
If the source is already on the exact TempRadio tuple through a scheduled or
manual operation, `--source-already-temp` lets a TCP source run without a raw
CLI link. The script cannot verify, extend, or shorten that source window, so
@@ -338,8 +376,8 @@ the destination.
## What happens during a run
1. Validate the input paths and host tools, then prove the source is an
OTA-enabled raw CLI.
1. Validate the input paths and host tools, then prove the source is either an
OTA-enabled raw CLI or a source-only full Companion control interface.
2. Authenticate to the target and query its target ID, hardware, running body
hash, version, and nRF52 bootloader capabilities.
3. Select or build one compatible mOTA and verify all block hashes, Merkle
+20 -6
View File
@@ -47,8 +47,8 @@ Both paths require:
that the node can discover, download, verify, and install LoRa OTA. Intermediate repeaters do **not** need an
OTA-enabled build: current repeater firmware relays OTA packets opaquely without storing or installing them.
Portable logging, portable MQTT, and untagged builds cannot install LoRa OTA; FULL logging OTA builds can.
- An OTA-enabled MeshCore source connected to the computer by USB serial, or an ESP32 WiFi companion/FULL
ESP32 source connected over WiFi as described below.
- An OTA-enabled MeshCore source connected to the computer by USB serial, or
an ESP32 WiFi companion/FULL source connected over WiFi as described below.
- Overlapping `tempradio` windows on the source, destination, and every repeater needed between them.
LoRa OTA packets are generated, consumed, and relayed only while `tempradio` is active. Intermediate repeaters
@@ -74,12 +74,18 @@ substantial serial output.
### Choose the source radio
Use an OTA-enabled MeshCore node as the source. It receives the update folder from the computer, then
advertises it over LoRa. ESP32 USB/WiFi companions and FULL ESP32 roles include the required transport.
Use an OTA-enabled MeshCore node as the source. It receives the update folder
from the computer, then advertises it over LoRa. ESP32 USB/WiFi companions and
FULL ESP32 roles include the required transport. A
`*_companion_radio_full` target keeps only the source half of LoRa OTA: it
serves host images but cannot stage or install one for itself. ESP32 full
combines USB, BLE, and WiFi; nRF52 full combines USB and BLE because nRF52840
has no WiFi.
A small set of high-capacity classic ESP32 companions
keep their normal image and provide a separate `-full-ota-` image with 100 contacts, 8 group channels, and
a 16-frame offline queue. Install that variant's merged image over USB once before using it. Connect the
source by USB serial or, when supported, by WiFi. For USB serial, confirm that its USB CLI accepts:
source by USB serial or, when supported, by WiFi. For an ordinary raw-text USB
source, confirm that its USB CLI accepts:
```text
ota folder on
@@ -89,6 +95,12 @@ If an older build reports that `OTA_FOLDER_SERIAL` is not compiled in, install a
`-full-ota-` build first. Do **not** use a KISS modem: KISS firmware is a TNC/KISS frame interface
and does not provide the MeshCore CLI or the OTA-folder transport that `motatool serve` requires.
An nRF52 `companion_radio_full` starts in USB Binary mode. Use
`+++MESHCORE-TERM-START` for local TempRadio commands, then return with
`+++MESHCORE-TERM-STOP`. When `motatool serve --serial` opens the port, its
automatic `ota folder on` command selects exclusive mOTA mode; stopping the
tool or disconnecting resets USB to Binary. BLE remains available throughout.
For an ESP32 WiFi companion or FULL ESP32 source with active WiFi, use its dedicated OTA seeder:
```bash
@@ -96,7 +108,9 @@ motatool serve --dir ./motas --tcp <source-host>:5001 -v
```
Port `5001` is separate from the companion application port (`5000`) and the
infrastructure WebConfig/browser-OTA port (`80`). On a FULL repeater or room
HTTP configuration/browser-OTA port (`80`, depending on the role). An ESP32
`companion_radio_full` also has a local OTA/TempRadio console on port `5002`;
see the [full Companion guide](./companion_radio_full.md). On a FULL repeater or room
server, `start webconfig` can bring up the saved WiFi connection. Other FULL
roles with browser OTA support can raise `MeshCore-OTA` with `start ota` and
use `192.168.4.1:5001`. The TCP seeder auto-attaches; do not also run