Files
HaloKeymind/docs/ota_wizard.md

211 lines
11 KiB
Markdown

<!-- meshcore-hosted-doc-link:start -->
<p class="meshcore-hosted-doc-link"><a href="https://mikecarper.github.io/MeshCore/ota_wizard/">View this page on MeshCore Docs</a>.</p>
<!-- meshcore-hosted-doc-link:end -->
# Guided LoRa updates
Run one Python command to update a directly reachable Repeater or Room Server.
The wizard identifies the board, chooses compatible firmware, prepares the
transfer, installs it, checks the result, and restores the original radio,
RX power-saving, and OTA settings. On supported nRF52 boards it also checks
for a newer compatible signed bootloader and includes that update in the plan.
## Connect a source radio
Use either connection:
| Computer connection | Source radio | Destination |
| --- | --- | --- |
| Raspberry Pi → USB | ESP32 Repeater with OTA and `ota.peer` support | Repeater or Room Server |
| Computer or Pi → USB | Full Companion with USB OTA source and direct admin support | Repeater or Room Server |
A **Station G2 Repeater connected to a Pi** can manage and serve an update to
an **Ikoka Stick Repeater** through that single USB connection. It does not
need a second local radio or the phone app. Install a source firmware build
containing `ota.peer` first; older Repeater firmware cannot manage the remote
node through USB. Check with `ota.peer status` in its USB console.
The Full Companion source also needs a current build containing the wizard's
version 2 direct admin support. An older Full Companion may serve OTA files but cannot
provide this guarded admin connection; the wizard will ask for a source
firmware upgrade instead of proceeding with that connection.
Check `get ota.direct` from its USB console for `v=2`. Update replies use a
separate mailbox; the wizard does not consume ordinary queued messages or change
saved contact routes. Some Full Companion boards borrow queue space for OTA and
retain up to 128 unread messages during an update. If more are waiting, sync them
with an app first; the wizard refuses to discard them to make room.
The source and destination must already use the same main-channel settings
and hear each other directly. The destination needs working LoRa OTA support
and its admin password. A stock nRF52 bootloader may need a matching local
installation before it can accept remote updates.
The wizard sends discovery, admin commands, and OTA traffic directly with no
relay hops. An older destination may put its first login reply in a flood
envelope; the wizard accepts it only if it arrives with zero hops, establishes
a direct return route, then requires a fresh direct identity check.
Close other apps using the USB port before starting.
## Start
From the MeshCore checkout, run:
```bash
python3 tools/lora_ota/ota_wizard.py
```
On Windows, use `py` in place of `python3`. No command-line options are needed.
The menu provides these actions:
1. **Update a nearby radio** — the default.
2. **Check radios / save a preparation request** — inspect without installing.
3. **Prepare an update bundle on this computer** — no radios needed.
4. **Recover an interrupted update** — restore saved settings.
5. **Settings** — change transfer, bootloader, connection, or build preferences.
6. **Exit**.
The first live connection installs USB and verification dependencies in a
private Python environment if needed. On Raspberry Pi OS, install
`python3-venv` if Python reports that it is missing.
Preparing a signed input file can also install signature-verification support
on first use, without installing the USB software.
For an update, the wizard selects the USB radio and destination automatically
when there is only one of each. Otherwise, choose from the displayed lists.
Enter the destination admin password once, choose firmware, then review the
plan and press Enter to start. Password entry is hidden and passwords are
never saved. After an action, the menu is shown again.
## Choose firmware from GitHub releases
The firmware menu offers:
- **Latest compatible GitHub release (recommended):** downloads the published
stable file for the detected board and role.
- **Choose another GitHub release:** lists compatible releases, including
clearly labelled previews, so you can choose a version.
- **Local firmware file or prepared bundle:** accepts an application DFU ZIP,
BIN, HEX, full mOTA, or a bundle prepared on another computer.
- **Build custom Full firmware from source:** offered on a computer with the
firmware build tools and Bash. It is not offered by default on a Pi.
You do not need to copy release URLs or manually download published files.
The wizard checks the board and role, searches release files for an exact
running base when preparing a differential update, and checks for a compatible
signed bootloader on supported nRF52 destinations. Firmware that is already
installed or older is left in place.
The final plan shows the package sizes, firmware version, and any bootloader
or trusted update signer being installed. After reboot, the wizard checks the
running firmware hash and version, or the bootloader identity and version,
before reporting success.
## Differential or full updates
**Automatic** is the default transfer setting. It uses a differential package
when a compatible builder and the **exact running firmware** are available
and the package is smaller. A file with the same version label but a different
body hash is not a usable base. Published bases are found through GitHub
releases; a local base can be selected when the running image was custom.
Unsigned full `.mota` files can also supply the new image for a differential
update. Signed packages retain their signatures; prepared bundles retain their
chosen transfer format.
On a computer, the differential builder can be prepared automatically with a
compatible Rust toolchain. On a Pi without a builder, a full update is made by
Python without compiling. The destination must support full updates, such as
an Ikoka Stick with working QSPI storage.
To force a full application transfer, open **Settings**, choose **Full** for
the transfer method, then start the update. Settings also lets you turn the
bootloader check off for an application-only update, choose a USB port or
source type, or set a builder path, custom source folder/version, or cache folder.
An internal-flash nRF52 destination that requires differential installation
cannot use the full fallback. Use the computer-to-Pi workflow below.
## Prepare on a computer, send from a Pi
All steps use the same menu; no command-line options are needed.
1. On the Pi, choose **Check radios / save a preparation request**. Connect to
the source and select the destination as prompted. Copy the JSON file
shown after **Preparation request:** to the computer. It contains public
board information and the exact running hash, without the password.
2. On the computer, choose **Prepare an update bundle on this computer**.
Select the saved request or enter its file path. Choose firmware from
GitHub releases, or select a local custom image. The wizard searches for
the exact base and offers a local base file if needed. Accept the proposed
output filename or choose another one.
3. Copy the resulting `.ota.zip` file to the Pi. Choose **Update a nearby
radio**, then **Local firmware file or prepared bundle**, and select that
ZIP.
The preparation step does not open a radio. When the builder and input files
are already present, local preparation also works without network access.
For a full bundle on a destination that supports it, choose **Full** in
**Settings** before preparation; this needs neither a differential compiler
nor USB dependencies.
The live destination is checked again before installation. A changed base
hash or a different board stops a differential update.
## If the connection is interrupted
Keep the same source radio connected and run the wizard again. Choose
**Recover an interrupted update**, then select the saved session by its
public-key prefix and progress state. The wizard checks the complete source
and destination keys before restoring settings. A normal update also restores an unfinished
session for the selected destination before proceeding.
Keep the recovery record until restoration is complete. A lost install reply
is followed by a running-image check; the wizard does not blindly repeat an
install command. A cancelled download is cleared only when its package ID
matches this update. Automatic installation is restored only after installation
or receive-slot clearance is confirmed; an uncertain result leaves it off and
keeps the recovery record.
Temporary radio windows use the existing main-channel
settings. Existing temporary schedules block an update before settings are
changed, including on older firmware.
The window covers both bootloader and firmware transfers, including reboot
and setup time. Status checks normally run every ten seconds.
The cache is normally `~/.cache/meshcore/ota` on Linux,
`~/Library/Caches/MeshCore/ota` on macOS, or `%LOCALAPPDATA%\MeshCore\ota` on
Windows. It contains firmware, public preparation records, selected board
keys, and restoration settings. Trusted signer keys added for an update remain
installed on the destination.
<details markdown="1">
<summary>Optional command-line use for automation</summary>
Interactive users can use the menus for every step. Existing command-line
options remain available for scripts:
| Option | Purpose |
| --- | --- |
| `--check` | Inspect without downloading or installing firmware |
| `--port /dev/ttyUSB0` | Choose a port; Windows example: `--port COM5` |
| `--mode repeater` or `--mode companion` | Select the source type |
| `--target PUBLIC_KEY` | Choose the full destination key; direct discovery is still required |
| `--firmware FILE` | Use a local firmware image or prepared bundle |
| `--base FILE` | Supply the exact running image for differential preparation |
| `--full` | Force a full transfer where supported |
| `--build` | Build custom Full firmware from source |
| `--no-bootloader` | Update application firmware only |
| `--prepare-only --request DEVICE.json --firmware FILE --output update.ota.zip` | Prepare without radios |
| `--recover --target PUBLIC_KEY` | Restore settings and exit |
| `--yes` | Accept the displayed plan; credentials and required choices must still be supplied |
For unattended use, provide `MESHCORE_ADMIN_PASSWORD` in the process environment
and pass the port, source type, and target key. The password is excluded from
preferences, recovery records, and the custom build environment.
</details>
For individual commands and a manual board example, see
[Station G2 to Ikoka Stick](ota_station_g2_to_ikoka_stick.md). For routed updates
and explicit multi-node setup, use the [scripted LoRa OTA guide](lora_ota_automation.md).