flutter_ota 1.0.0
flutter_ota: ^1.0.0 copied to clipboard
Ship firmware without a cable — OTA updates for ESP32-class BLE devices (ESP-IDF/Arduino). MQTT and Wi-Fi HTTP/HTTPS support are planned.
Changelog #
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased] #
1.0.0 - 2026-07-31 #
Added #
- Optional
saveOtaLogsparameter onupdateFirmware(defaulttrue) to capture the current OTA run’s log lines in memory for host-app debug UIs. Oversized / firmware-payload dumps are never stored — status, handshake, progress, and error lines only. - Exported session-log helpers:
otaSessionLogs,otaSessionLogText,clearOtaSessionLogs, andotaLogCaptureEnabled. - Example app: Save OTA logs toggle, View OTA Logs screen with
copy/clear, and route
/ota_logs. validateFirmwareImage/isSupportedFirmwareImage— pre-check that a path, URL, or filename is.binor.imgbefore starting OTA.validateFirmwareSource— for URLs, downloads then validates the payload (rejects HTML; checks.bin/.imgwhen a filename is known). Assets and file picker still validate the path/name up front.- Shared
downloadAndValidateFirmware/validateFirmwarePayloadreplace the URL-only Google Drive HTML helper. UnsupportedFirmwareImageExceptionwhen the image type is not supported.- File picker restricted to
.bin/.img(FileType.custom). - GitHub Actions CI workflow that runs
dart format,flutter analyze, andflutter test(package + example) on pushes and pull requests. - Optional, composable firmware integrity via
FirmwareIntegrityConfig/IntegrityFeature:shaBeforeTransfer— Flutter SHA-256 of the loaded binary vs a server-provided digest before any BLE write.shaAfterFlash— expected digest sent to the device after the image (ESP-IDF PostSHA:SET_HASH/0x07+ 32 bytes, thenDONE; Arduino:0xF9flags +0xFA+ 32 bytes after the last segment); success only after post-flash verification (Arduino0x0F/ ESP-IDF status5; mismatch Arduino0x0E/ ESP-IDF status6).
- Features combine freely so firmware may support SHA-start only, SHA-end only, both, or neither. Default remains no integrity (unchanged wire format).
- Typed integrity exceptions:
FirmwareIntegrityException,FirmwareHashMismatchException,DeviceHashMismatchException. Pre-transfer and device post-flash mismatches both emitfailedValueonpercentageStreamand then rethrow so callers can catch by type. - Unit tests for config validation, pre-transfer SHA, and protocol integrity paths.
- Typed exception hierarchy for OTA failures —
OtaException(base),EmptyFirmwareException, andFirmwareDownloadException(which carries the HTTPstatusCode) — so callers can handle errors by type instead of matching on raw strings. - Validation that rejects an empty downloaded firmware body (HTTP 200 with 0 bytes) before chunking.
- Early-fail guard that aborts the update when the firmware is empty, before any BLE handshake or writes are sent, so the device is never left mid-update with nothing to flash.
dispose()method onOtaPackagefor resource management; the package also disposes itself when an update reaches a terminal state.- Optional
mtuSizeparameter onupdateFirmwareto control the chunk (packet) size used during transfer, honoured by both the ESP-IDF and Arduino paths. maxMtuSize(512) andarduinoHeaderSize(2) constants, plus up-front, protocol-aware validation ofmtuSize: it must be between 1 and 512 for ESP-IDF, or 1 and 510 for Arduino (which prepends a 2-byte packet header). Out-of-range values throwOtaExceptionbefore any BLE writes, instead of failing mid-transfer with a GATT error.- Structured
logger-based logging, replacingprintstatements. - README section on aligning
BluetoothDevice.requestMtu()with themtuSizepassed toupdateFirmware, including per-protocol wire-size notes for ESP-IDF and Arduino.
Fixed #
- ESP-IDF transfer progress no longer reaches
100before the device ACKs FINISH (status5). Mid-transfer progress is capped at99; terminal100is emitted only after a successful device acknowledgement. The example app also treats success asfirmwareUpdateafter ACK, not progress alone. - URL firmware downloads that return HTML (e.g. a Google Drive
/viewshare page) are rejected with a clear error instead of being hashed as firmware. FirmwareDownloadExceptionandEmptyFirmwareExceptionare rethrown after emittingfailedValue, so UIs can show the real failure reason (not only a generic “OTA failed” toast).OtaClient.run()now rejects concurrent calls withOtaException(same re-entrancy guard asEsp32OtaPackage.updateFirmware), so custom transport/protocol users cannot interleave writes on a shared transport.DeviceHashMismatchExceptionis now thrown (and rethrown byOtaClientafterfailedValue) when the device reports a post-flash SHA-256 mismatch (Arduino0x0E/ ESP-IDF status6), matching pre-transferFirmwareHashMismatchExceptionhandling. Previously the exception was only constructed for logging on the Arduino path, and the ESP-IDF path returnedfalsewith no typed error.- Arduino updates now use the caller-supplied
mtuSize. Previously it was ignored in favour of the device-negotiated MTU and hardcoded values (200,400), so the requested chunk size never reached the device. - Arduino OTA progress for firmware with more than 255 segments: progress now uses the full 16-bit segment index from device notifications instead of the low byte only, which previously caused progress to wrap above ~4 MB.
- Arduino notification handler no longer throws
RangeErroron empty or short device notifications;0x0F(complete) and0xF2(install start) messages are handled safely using only the opcode byte. - Short or invalid Arduino
0xF1segment requests (truncated payload or out-of-range segment index) now fail the OTA update instead of being silently ignored, which could leave the transfer stuck without a terminalfailedValue. - Unknown Arduino opcodes no longer decode
value[1]/value[2]as a segment index or emit misleading progress. - ESP-IDF control-characteristic reads are guarded against empty responses
before indexing
value[0].
Changed #
- Refactored the OTA API to use the
UpdateTypeandFirmwareTypeenums in place of integer codes. - Firmware loaders now throw the typed exceptions above instead of plain
Strings, and rethrow existingOtaExceptions without re-wrapping them. - Generalised the failure log message from "BLE error" to "OTA update aborted" to reflect that it now also covers validation failures.
- Removed the unused
mtuSizeparameter from internal Arduino raw file-picker loading; Arduino chunking still happens inArduinoOtaProtocolduring transfer. - ESP-IDF transfer loop now validates that each pre-chunked payload is ≤
mtuSizebefore writing, catching internal chunk/handshake mismatches early.
Removed #
- The unused
serviceand UUID parameters fromupdateFirmware. - Unused helper methods (
getFirmware,uint8ListToIntList) fromEsp32OtaPackage. - The hardcoded
mtufield (400) onEsp32OtaPackage;sendPartnow takes the chunk size as a parameter sourced frommtuSize.
