Skip to content

Over-the-air (OTA) firmware update over W5500 Ethernet, MQTT-triggered #27

Description

@TalkingJupiter

Context

Firmware is flashed over USB today (platformio.ini sets upload_port per controller). With
controllers mounted in racks, physical access for reflashing doesn't scale, and #26 unifies the
image so every device runs the same binary — making a fleet-wide OTA path both feasible and
necessary. The MQTT contract already anticipates this: enabled:false is documented as "remote
off, e.g. OTA," and #19 tracks quieting a device during an update.

Problem

  • No remote update mechanism exists — every firmware change requires USB access to each ESP32.
  • Transport is wired W5500 Ethernet, not WiFi, so the standard mDNS-based ArduinoOTA /
    espota flow does not apply. OTA must work over the Ethernet client.
  • The two controllers form an A/B failover pair; updating the active one must not blind the rack.

Proposal

Pull-based HTTP OTA using the Arduino Update.h API over the existing W5500 EthernetClient.
The host (Radxa) serves the firmware binary; an MQTT command tells a target device to fetch and
apply it, then reboot. This reuses the broker + provisioning channel we already have rather than
introducing a new push protocol.

Decisions needed

  1. Trigger & command topic — e.g. repacss/devices/<mac>/ota carrying firmware URL + version
    • expected checksum. Per-device vs rack-wide vs broadcast.
  2. Binary source — Radxa HTTP endpoint serving the .bin; where versions live and how a
    device knows its current vs available version.
  3. Integrity & safety — checksum/signature verification before Update.end(); refuse on
    mismatch. Consider signed images given the control-channel spoofing concern raised in Prod network design: isolate rack telemetry segment + broker bootstrap (DHCP) #24.
  4. Failover coordination — update standby first, verify healthy, then active; or set the
    target enabled:false (Firmware: accept enabled:false to support remote disable #19) so its peer takes over before it reboots. Never update both at once.
  5. Rollback — behavior on failed boot after flash (bad image, power loss mid-write). ESP32
    rollback / OTA-data partition strategy.
  6. Partition scheme — confirm the build uses a dual-app OTA partition table (default single-
    app layout has no OTA slot); update platformio.ini board_build.partitions if needed.
  7. Ack/status — device reports OTA progress/result (downloading → verifying → applied → booted,
    or failed+reason) back over MQTT so the host knows the outcome (relates to the Publish config_ack after applying config #13 config_ack pattern).

Considerations

Acceptance criteria

  • A device fetches and applies a new image over W5500 Ethernet, triggered by an MQTT command, and
    reboots into it.
  • Image integrity is verified before commit; a corrupt/mismatched image is rejected without bricking.
  • A failed flash rolls back to the previous working image.
  • Rolling A/B update keeps the rack reporting throughout (peer covers the device being updated).
  • OTA outcome (success/failure + reason) is reported back to the host.

Files affected

  • ESP32-Firmware/platformio.ini — OTA partition table (board_build.partitions), build/version metadata
  • ESP32-Firmware/src/TelemetrySender.cpp — MQTT command handling for the OTA topic
  • new ESP32-Firmware/src/ OTA module (fetch + Update.h apply + verify + status)
  • ESP32-Firmware/src/main.cpp — coordinate OTA with failover / enabled gating
  • docs/mqtt-contract.md — define the OTA command/status topics + payload schema
  • host side — firmware-serving endpoint + OTA trigger (provisioning service)

Relates to #19 (remote disable during OTA), #24 (control-channel auth/signing), #13 (ack pattern),
#26 (unified image).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions