68 lines
1.6 KiB
Markdown
68 lines
1.6 KiB
Markdown
# OTA protocol
|
|
|
|
The updater uses a JSON manifest rather than Git operations on-device.
|
|
|
|
## Manifest schema 1
|
|
|
|
```json
|
|
{
|
|
"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
|
|
|
|
1. Wait for the long update interval to become due.
|
|
2. Wait for configured inactivity and no busy lock.
|
|
3. Connect Wi-Fi if needed.
|
|
4. Fetch the manifest.
|
|
5. Hash local target files.
|
|
6. Download only changed files into `/.update`.
|
|
7. Verify every SHA-256.
|
|
8. Create `/update_pending.json` with `commit_complete=false`.
|
|
9. Rename current files to `.bak`.
|
|
10. Rename staged files into their final locations.
|
|
11. Mark `commit_complete=true`.
|
|
12. Reboot.
|
|
13. New launcher/app performs setup.
|
|
14. App calls `ctx["system"].ready()`.
|
|
15. 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` / `public`
|
|
- `auto`
|
|
- `basic`
|
|
- `bearer`
|
|
- `token`
|
|
- `header` (arbitrary header + optional prefix)
|
|
|
|
HTTPS is required unless `UPDATE_ALLOW_HTTP=true` is explicitly set.
|