1.6 KiB
1.6 KiB
OTA protocol
The updater uses a JSON manifest rather than Git operations on-device.
Manifest schema 1
{
"schema": 1,
"release": "1.2.3",
"files": [
{
"source": "firmware/launcher.py",
"target": "/launcher.py",
"sha256": "..."
},
{
"source": "firmware/app/main.py",
"target": "/app/main.py",
"sha256": "..."
}
]
}
A file is downloaded only when its local SHA-256 differs.
Transaction
- Wait for the long update interval to become due.
- Wait for configured inactivity and no busy lock.
- Connect Wi-Fi if needed.
- Fetch the manifest.
- Hash local target files.
- Download only changed files into
/.update. - Verify every SHA-256.
- Create
/update_pending.jsonwithcommit_complete=false. - Rename current files to
.bak. - Rename staged files into their final locations.
- Mark
commit_complete=true. - Reboot.
- New launcher/app performs setup.
- App calls
ctx["system"].ready(). - Backups and pending marker are removed.
A power loss during commit leaves commit_complete=false; stable boot.py restores the backups before normal startup.
If a completed update cannot import/start, boot.py restores the backups.
Why boot.py is intentionally stable
The recovery component should not replace itself in the same transaction it is responsible for recovering. Update /boot.py manually and rarely.
Authentication
Credentials exist only in /.env.
Supported modes:
none/publicautobasicbearertokenheader(arbitrary header + optional prefix)
HTTPS is required unless UPDATE_ALLOW_HTTP=true is explicitly set.