Skip to content

OTAmpy v4.8.0

Choose a tag to compare

@simonl65 simonl65 released this 11 Sep 21:52
· 23 commits to main since this release
Immutable release. Only release title and notes can be modified.

OTAmpy 4.8.0 — 2026-09-11

Major (breaking changes)

  • None.

Minor (functionality added in a backward compatible manner)

  • Shared-UART (channel-mux) mode, end to end. A project whose own code needs the same physical UART as OTAmpy can wrap it in otampy.mux.SerialMux on the device and have the host CLI speak the matching framing, so one radio link carries OTAmpy traffic alongside the application's own stream. New wire contract below URST (docs/protocol.md §1.3, PROTOCOL_VERSION unchanged), a host otampy.channel.ChannelCodec/ChannelSerial codec, a --mux/--no-mux CLI flag and mux config key, and an otampy init --mux scaffold. Opt-in; existing direct-mode devices and CLIs are unaffected.
  • Boot-time recovery window — recover a device stranded before ota.poll(), over the radio, no USB. boot.py now listens briefly on every boot for UPDATE_REQUEST or ROLLBACK, widening to an ~8 s window after a boot that never reached poll() or still carries an unconfirmed candidate. New device settings OTA_BOOT_RECOVERY_LISTEN_MS/OTA_BOOT_MARK_FILE; new host retry loops via otampy upd --recover and otampy rollback --recover with a configurable recovery-wait. Honors OTA_REQUIRE_AUTH when set. Optional OTA(...).boot(heartbeat=wdt.feed) lets a custom boot.py feed a watchdog across both blocking stretches. PROTOCOL_VERSION unchanged.
  • A committed OTA update is now on trial until it is confirmed. boot.py tracks unconfirmed candidates in a retain-previous journal and auto-restores the previous generation if the device reboots within OTA_TRIAL_BOOTS (default 3) boots without being confirmed. New channel-0 commands CONFIRM/UPDATE_STATE; new CLI commands otampy confirm and otampy state; otampy upd now auto-confirms after a healthy PING. PROTOCOL_VERSION unchanged.
  • otampy rollback reverts a confirmed (or trialling) update over the radio, restoring the one retained previous generation via a new ROLLBACK channel-0 command. Refuses safely when nothing is retained or a commit is mid-flight.
  • Boot-time UPDATE_COMMIT is now all-or-nothing and retains the previous generation, via a new commit journal (OTA_JOURNAL_FILE) and restore.repair() run on every boot. UPDATE_START discards the previously retained generation, keeping at most one prior generation on device.
  • otampy cp can now copy device-to-host. A device:<path>[:<host target>] argument downloads a single file from the device, reusing the existing CAT command rather than adding new device-side protocol.

Patch (backward compatible bug fixes)

  • otampy upd --all-files no longer uploads __pycache__ artifacts or *.example.* template files, which were never meant to be flashed to the device.
  • Session-scoped settings (ports/log-level/config/device-dir/mux) no longer silently revert under automation that forks a fresh subprocess per command. A new OTAMPY_SESSION_ID env var lets such callers opt into a fixed session identifier instead of relying on process ancestry, which changed on every invocation with no persistent parent shell.
  • Every successful otampy upd no longer reports failure due to the post-commit health check racing the new recovery window. Post-commit and rollback health checks now use their own post-commit-ready-timeout (default 30) instead of sharing the shorter update-ready-timeout.
  • The shipped boot.py/main.py example scaffold is direct mode again, fixing a regression where it wired SerialMux unconditionally and silently broke plain (non-mux) host CLI commands.