OTA updates~
The firmware can update itself over the network ("over-the-air"). There are two independent mechanisms:
- Channel update (pull) — the device fetches a small descriptor from a remote channel, compares versions, and if they differ downloads and flashes the firmware over HTTPS.
- Image upload (push) — you send a firmware
.binstraight to the device as the body of an HTTP request.
Both write to a spare application slot and only switch over once the image is complete and valid, so a failed or interrupted update leaves the running firmware intact. The very first installation (a blank chip) is done over USB with the browser web installer, not OTA.
How it works~
The partition table reserves two application slots, app0 (ota_0) and app1
(ota_1) of 1856 KB each, plus an otadata partition that records which slot
boots. An update always writes to the slot that is not currently running.
When the image passes validation, otadata is flipped to the new slot and the
device restarts into it; if anything fails, the old slot is untouched and stays
the boot target. The restart is scheduled a moment after the HTTP response is
sent, so the client still receives the result.
Note
All HTTPS transfers verify the server certificate against the built-in certificate bundle, so the channel descriptor and the firmware binary must be served over HTTPS with a publicly trusted certificate.
Update channels~
Channels are declared in board.yaml under
ota.channels — one to three entries, each with a name and a path (the URL
of the channel's descriptor):
ota:
channels:
- name: stable
path: https://dzurikmiroslav.github.io/esp32-evse/ota/stable/esp32.json
- name: testing
path: https://dzurikmiroslav.github.io/esp32-evse/ota/testing/esp32.json
The descriptor path differs per chip family (esp32.json, esp32s2.json, …),
which is how the right build is matched to the hardware.
The selected channel is stored in NVS; if none has been chosen, the first
channel in board.yaml is the default.
Channel descriptor format~
The file each channel points at is a small JSON object with two string fields:
{
"version": "v2.2.0",
"path": "https://dzurikmiroslav.github.io/esp32-evse/ota/stable/esp32-evse.bin"
}
| Field | Meaning |
|---|---|
version |
The firmware version string offered by this channel |
path |
Absolute HTTPS URL of the firmware image to flash |
If you self-host a channel, serve a descriptor in this shape and point a
board.yaml channel path at it.
When OTA is not enough~
OTA only replaces the application image. Some releases also change things outside
the app slot — the partition table, or the board.yaml format. Those
cannot be delivered by OTA and require a full flash over USB with the
web installer, after
which the board.yaml may need to be recreated in the new format. The release
notes call this out when it applies, so check them before a major version jump.
Note
Because a full flash rewrites the LittleFS usr partition, back up your
board.yaml and any Lua scripts first (for example over
WebDAV).
See also~
- Board configuration schema →
ota— defining channels - Web installer — initial install and full reflash