OTA Update Mechanism¶
Why a State Machine¶
OTA updates are long-running, multi-step operations that can fail at any
stage. A finite state machine (FSM) makes the allowed transitions explicit,
prevents illegal state combinations, and provides a clear recovery path from
every failure mode. The current state is always observable via GetOTAStatus.
State Persistence and Power-Loss Recovery¶
When entering one of six checkpointable states (update_available,
downloading, paused, update_ready, download_failed, update_failed),
OTAStateMachine writes an OTASnapshot to a YAML checkpoint file at
DEFAULT_CHECKPOINT_FILE (/data/tolomeo/ota-service.yml). The snapshot
records the current state, installed firmware info, and pending update info.
Entering updated or update_successful instead deletes the checkpoint.
Note
If /data does not exist at runtime (development machines, CI
environments), the checkpoint falls back to
<tempdir>/tolomeo/ota-service.yml (e.g. /tmp/tolomeo/ota-service.yml
on Linux). Production edge devices are expected to have /data mounted.
At startup, the FSM enters the bootstrapping state and reads the checkpoint
file. It selects one of the six detect_* transitions to move to the correct
runtime state:
bootstrapping → updated (no pending update)
bootstrapping → update_available (update was announced)
bootstrapping → paused (download was in progress but paused)
bootstrapping → update_ready (download completed, not yet installed)
bootstrapping → download_failed (download was in progress and failed)
bootstrapping → update_failed (install was in progress and failed)
This means the service survives a power cut at any point in the update lifecycle and resumes from exactly where it left off.
Download Task Synchronisation¶
OTAPlugin does not drive the FSM directly during a download. Instead, it
registers callbacks on TaskManager via _on_download_state_change and
_on_download_error. When the download task completes, the callback fires
fsm.download_success(); on failure it fires fsm.download_fail(). This
decouples the FSM from the asyncio task scheduler.
Error Recovery¶
Every failure state has exactly one recovery path:
| State | Recovery command | Resulting state |
|---|---|---|
download_failed |
AbortOTAUpdate |
update_available |
update_failed |
AbortOTAUpdate |
update_available |
| Any state | ResetOTAState |
Returns the FSM to a clean baseline (bootstrapping → re-detect → updated), discarding any pending update |
CancelOTAUpdate applies to in-progress states (downloading, paused,
update_ready) and returns to update_available without clearing the
pending update info, allowing an immediate retry.