Skip to main content

Device Firmware Update

Device OTA updates the main firmware running on a supported AIBuds device. It is separate from Camera OTA, which updates the device's camera module.

The host app supplies a compatible local firmware package after completing its own update check, download, integrity verification, and device-model validation. The SDK transfers and installs that package, reports startup success, streams progress from 0.0 to 1.0, and returns the final upgrade result with the average transfer speed. Treat startHandler only as confirmation that the OTA task started; use completionHandler as the authoritative final result.

Animated workflow

Device OTA delivery path

Validate the product input first, then let the SDK start, transfer, and complete the main-firmware update.

Host app

Validate Package

Verify integrity, firmware compatibility, and the readable local path.

Host app

Check Battery

Compare the current device battery with otaBatteryLimit immediately before starting.

Host app

Select Protocol

Use the default overload or the product-required OTA protocol configuration.

SDK

Start OTA Task

Submit the local package and distinguish start acceptance from final success.

SDK + device

Transfer & Install

Keep the connection stable while normalized progress advances from 0.0 to 1.0.

progress · 0.0...1.0
Authoritative result

Final Completion

Use success, average transfer speed, and error from the completion handler.

A successful start callback is not a successful firmware update; wait for final completion.

Prerequisites

  • The device is connected and conforms to DeviceOtaAPI.
  • Use otaProtocolCapability to determine the supported protocol; do not infer it from the firmware filename.
  • For FitCloud Pro or Jieli, install and register the matching OTA plugin before connecting the device.
  • Device battery is at least otaBatteryLimit percent.
  • filePath points to the correct, complete firmware package for this device.
  • Keep the app active and connection stable until completion.

Implement with AI Assistance

Build with AI

Implement this workflow with AI

Use the official Update AIBuds Firmware skill to adapt this workflow to your app.

Read and follow https://docs-aibuds.github.io/skills/update-aibuds-firmware. Use it to implement Update AIBuds Firmware in this iOS project and verify the result.
View official skill

API Reference

Framework

AIBuds.xcframework

Import

Swift
import AIBuds
import AIBudsFoundation

Protocol

Swift
/// The protocol for device OTA upgrade API.
protocol DeviceOtaAPI: DeviceAPI {
    /// The OTA protocol capability reported by the device.
    /// Defaults to `.abmate` when the device does not report this capability.
    var otaProtocolCapability: OtaProtocolCapability { get }

    /// OTA battery limit, 0...100, unit: percent.
    var otaBatteryLimit: Int { get }

    /// Start OTA upgrade.
    /// - Parameters:
    ///   - filePath: Upgrade file path.
    ///   - startHandler: Upgrade start callback.
    ///     - success: Whether the OTA task started successfully.
    ///     - error: Failure information, or `nil` if the task started.
    ///   - progressHandler: Upgrade progress callback.
    ///     - progress: Progress value in the range `0.0...1.0`.
    ///   - completionHandler: Final upgrade completion callback.
    ///     - success: Whether the upgrade succeeded.
    ///     - avgSpeed: Average transfer speed in kB/s.
    ///     - error: Failure information, or `nil` if the upgrade succeeded.
    func startOta(
        withFilePath filePath: String,
        startHandler: AIBudsOtaStartCompletionHandler?,
        progressHandler: AIBudsOtaProgressHandler?,
        completionHandler: AIBudsOtaCompletionHandler?
    )

    /// Start OTA upgrade with an explicit transfer protocol configuration.
    /// - Parameters:
    ///   - filePath: Upgrade file path.
    ///   - configuration: OTA protocol configuration.
    ///   - startHandler: Upgrade start callback.
    ///     - success: Whether the OTA task started successfully.
    ///     - error: Failure information, or `nil` if the task started.
    ///   - progressHandler: Upgrade progress callback.
    ///     - progress: Progress value in the range `0.0...1.0`.
    ///   - completionHandler: Final upgrade completion callback.
    ///     - success: Whether the upgrade succeeded.
    ///     - avgSpeed: Average transfer speed in kB/s.
    ///     - error: Failure information, or `nil` if the upgrade succeeded.
    func startOta(
        withFilePath filePath: String,
        configuration: OtaConfiguration,
        startHandler: AIBudsOtaStartCompletionHandler?,
        progressHandler: AIBudsOtaProgressHandler?,
        completionHandler: AIBudsOtaCompletionHandler?
    )
}

See otaProtocolCapability, otaBatteryLimit, and the startOta overloads in the API Reference.

Device Capability

Read otaProtocolCapability after the device is ready and use it to constrain protocol selection.

SwiftObjective-CRaw valueSupported protocol
.noneAIBudsOtaProtocolCapabilityNone-1No reported OTA support.
.abmateAIBudsOtaProtocolCapabilityAbmate0ABMate. This is also the fallback when the capability is not reported.
.fitcloudProAIBudsOtaProtocolCapabilityFitcloudPro1FitCloud Pro. Requires the FitCloud Pro plugin.
.abmateAndFitcloudProAIBudsOtaProtocolCapabilityAbmateAndFitcloudPro2ABMate and FitCloud Pro; present only the registered choices.
.jieliAIBudsOtaProtocolCapabilityJieli3Jieli single-bank OTA. Requires the Jieli plugin.

OTA Configuration

OtaConfiguration selects the BLE OTA protocol used by the configured overload. Its otaProtocol property defaults to .abmate.

SwiftObjective-CRaw valueMeaning
.abmateAIBudsOtaProtocolKindAbmate0ABMate OTA protocol.
.fitcloudProAIBudsOtaProtocolKindFitcloudPro1FitCloud Pro OTA protocol.
.jieliAIBudsOtaProtocolKindJieli2Jieli single-bank OTA protocol.

Do not select a protocol by guessing from the firmware file. Use the protocol required by the connected device and product integration.

Optional OTA Plugins

FitCloud Pro and Jieli are separate CocoaPods subspecs. Register their plugins before connecting a device so the SDK can discover and subscribe to the required BLE characteristics. AIBudsSDK/AllInOne installs and registers both automatically.

Ruby
pod 'AIBudsSDK/FitCloudProOTA'
pod 'AIBudsSDK/JieliOTA'
Swift
import AIBuds
import AIBudsFitCloudProOTA
import AIBudsJieliOTA

AIBudsSDK.registerOtaPlugin(FitCloudProOtaSDK.otaPlugin)
AIBudsSDK.registerOtaPlugin(JieliOtaSDK.otaPlugin)

For modular integration, register only the implementations your product ships. A later registration for the same OtaProtocolKind replaces the previous plugin. Use AIBudsSDK.otaPlugin(for:) to test availability or AIBudsSDK.removeOtaPlugin(for:) to unregister one.

Return Value

Neither overload returns a value directly. startHandler reports whether the OTA task started, progressHandler reports normalized progress, and completionHandler provides the authoritative final result and average transfer speed.

Usage Examples

Swift
guard let device = device as? DeviceOtaAPI else { return }
guard deviceBatteryPercent >= device.otaBatteryLimit else {
    print("Charge the device before updating")
    return
}

device.startOta(
    withFilePath: firmwareURL.path,
    startHandler: { success, error in
        if !success { print(error?.localizedDescription ?? "OTA failed to start") }
    },
    progressHandler: { progress in
        print("OTA: \(Int(progress * 100))%")
    },
    completionHandler: { success, averageSpeed, error in
        print(
            success
                ? "OTA completed at \(averageSpeed) kB/s"
                : (error?.localizedDescription ?? "OTA failed"))
    })

Use an Explicit OTA Protocol

Use the configured overload only when your product integration knows which OTA protocol the connected device requires.

Swift
let configuration = OtaConfiguration()
configuration.otaProtocol = .fitcloudPro

device.startOta(
    withFilePath: firmwareURL.path,
    configuration: configuration,
    startHandler: { success, error in
        if !success {
            print(error?.localizedDescription ?? "OTA failed to start")
        }
    },
    progressHandler: { progress in
        print("OTA: \(Int(progress * 100))%")
    },
    completionHandler: { success, averageSpeed, error in
        print(
            success
                ? "OTA completed at \(averageSpeed) kB/s"
                : (error?.localizedDescription ?? "OTA failed"))
    }
)

Error Handling

OTA errors use AIBudsSDK.OtaErrorDomain and SdkOtaErrorCode.

CodesTypical condition
unknownThe SDK cannot classify the error more narrowly.
otaTaskAlreadyRunningAnother OTA task is already active.
otaTaskCreateFailedDueToFileNotFoundThe local firmware path does not exist.
otaTaskStartFailedDueToFileReadError, otaTaskStartFailedDueToFileHandleCreateErrorThe package cannot be opened or read.
otaTaskStartFailedDueToInvalidFileHashDataFirmware hash data is invalid.
otaTaskStartFailedDueToGetOtaInfoErrorRequired OTA metadata cannot be obtained.
otaTaskStartFailedDueToInvalidOffsetAddress, otaTaskStartFailedDueToInvalidBlockSizeTransfer metadata is invalid.
otaTaskStartFailedDueToNotAllowUpdateThe device does not allow the update in its current state.
otaTaskSendDataFailedDueToFileHandleIsNil, otaTaskSendDataFailedDueToSeekFileHandleFailed, otaTaskSendDataFailedDueToReadFileDataFailed, otaTaskSendDataFailedDueToOtaInfoIsNilThe SDK cannot continue reading or sending firmware data.
otaTaskFailedDueToDeviceReportKeyMismatch, otaTaskFailedDueToDeviceReportCrcError, otaTaskFailedDueToDeviceReportSeqError, otaTaskFailedDueToDeviceReportDataLengthErrorThe device rejects transferred data or reports an integrity/sequence problem.
otaTaskFailedDueToDeviceDisconnect, otaTaskFailedDueToTimeoutThe device disconnects or the operation times out.

Distinguish startHandler failure from a failure after transfer begins. Do not retry automatically with an unverified package; revalidate device model, firmware version, package integrity, battery, protocol selection, and connection first.

Best Practices

  1. Complete update discovery, download, signature or integrity verification, and device-model compatibility checks before calling the SDK.
  2. Check otaBatteryLimit immediately before starting, not only when presenting the update UI.
  3. Prevent concurrent OTA, Camera OTA, Media File Import, or other long-running device operations.
  4. Dispatch UI updates to the main queue because callbacks may arrive on another queue.
  5. Treat startHandler as task-start confirmation only; do not report upgrade success until completionHandler succeeds.
  6. Keep the app active and the device connection stable through final completion, then verify the reported firmware version after reconnecting.

Notes

  • Progress is normalized to 0.0...1.0; clamp UI presentation defensively without changing the SDK result.
  • avgSpeed is reported in kB/s only by the final completion handler.
  • OtaConfiguration.otaProtocol defaults to .abmate; select .fitcloudPro or .jieli only when otaProtocolCapability and an installed plugin support it.
  • The SDK does not expose an OTA cancellation method. The Demo's Cancel button resets its local UI state and must not be documented as cancelling the SDK operation.