Magnifica_S-Pro/README.md

3.2 KiB

ESP32-C3 Universal MicroPython Launcher

A fault-tolerant launcher intended for the Magnifica ESP32-C3 project, but kept generic enough to reuse elsewhere.

Core behavior

  • /.env on the device holds all secrets and per-device options.
  • Wi-Fi, BLE and UART are independent startup options.
  • One Git repository can hold both the launcher and main application.
  • The ESP32 does not need Git. It downloads a tiny JSON manifest and only changed raw files.
  • /launcher.py, /app/main.py, and other manifest-listed files can update in one staged transaction.
  • SHA-256 is verified before any file is committed.
  • .bak rollback files plus a stable boot.py protect against interrupted or broken OTA.
  • Secrets are never updated and are never in the manifest.

Energy / update behavior

There is no 5-second repository polling loop.

Defaults are:

  • remote manifest check: once every 24 hours
  • boot delay before a possible check: 3 minutes
  • minimum inactivity before OTA may begin: 5 minutes
  • if busy when due: reconsider locally after 15 minutes
  • network failure: wait 1 hour before another remote attempt
  • BLE disabled by default
  • Wi-Fi power saving enabled best-effort

If Wi-Fi exists only for OTA, set WIFI_KEEP_CONNECTED=false. If the app itself needs Wi-Fi for remote control, leave it true.

Repository layout

repo/
├─ README.md
├─ .gitignore
├─ .env.example
├─ firmware/
│  ├─ boot.py                 # stable recovery stub; install manually
│  ├─ launcher.py             # OTA-updatable launcher
│  ├─ manifest.json           # generated SHA-256 manifest
│  └─ app/
│     ├─ __init__.py
│     └─ main.py              # actual Magnifica logic
├─ tools/
│  └─ build_manifest.py
└─ docs/
   ├─ DIGITAL_PROBE.md
   ├─ SETUP.md
   └─ OTA_PROTOCOL.md

On the ESP32:

/
├─ boot.py
├─ launcher.py
├─ .env
├─ update_state.json          # generated automatically
└─ app/
   ├─ __init__.py
   └─ main.py

Safe inactivity-aware updates

The application receives ctx["activity"].

Call this whenever a real interaction or machine-state change occurs:

ctx["activity"].touch()

Bracket anything that must never be interrupted by OTA:

ctx["activity"].begin()
try:
    await brew_or_move_mechanism()
finally:
    ctx["activity"].end()

OTA can start only after the long check interval is due and the device has been idle for UPDATE_MIN_IDLE_SECONDS and no busy lock is active.

Gitea example

UPDATE_PROVIDER=gitea
UPDATE_REPO_URL=https://git.example.com/user/repo
UPDATE_BRANCH=main
UPDATE_AUTH_MODE=auto
UPDATE_TOKEN=your_token

A public Gitea repo uses:

UPDATE_AUTH_MODE=none

Other platforms

Built-in URL/auth handling exists for Gitea/Forgejo/Codeberg, GitLab, GitHub and Bitbucket. For unusual self-hosted layouts, use UPDATE_MANIFEST_URL or UPDATE_RAW_BASE_URL and optionally a custom auth header.

See docs/SETUP.md and docs/OTA_PROTOCOL.md.

Development probe

The first Magnifica S development tool is an input-only digital probe for front-panel signal discovery. See docs/DIGITAL_PROBE.md; do not connect an unknown machine wire directly to an ESP32 GPIO.