Обновление прошивки устройства
Device OTA обновляет основную прошивку поддерживаемого устройства AIBuds. Это отдельный процесс от Camera OTA, который обновляет модуль камеры.
Приложение передаёт совместимый локальный пакет прошивки после собственной проверки обновления, загрузки, проверки целостности и совместимости с моделью устройства. SDK передаёт и устанавливает пакет, сообщает о запуске, передаёт прогресс от 0.0 до 1.0 и возвращает итог вместе со средней скоростью. startHandler подтверждает только запуск задачи OTA; окончательный результат берите из completionHandler.
Device OTA delivery path
Validate the product input first, then let the SDK start, transfer, and complete the main-firmware update.
Предварительные условия
- Устройство подключено и соответствует
DeviceOtaAPI. - Определяйте поддерживаемый протокол по
otaProtocolCapability, а не по имени файла прошивки. - Для FitCloud Pro или Jieli установите и зарегистрируйте соответствующий плагин OTA до подключения устройства.
- Заряд устройства не ниже
otaBatteryLimitпроцентов. filePathуказывает на правильный и полный пакет прошивки для данного устройства.- До завершения оставляйте приложение активным и поддерживайте стабильное подключение.
Реализация с помощью AI
Реализуйте этот сценарий с AI
Используйте официальный навык «Обновление прошивки AIBuds» и адаптируйте сценарий к приложению.
Прочитайте и выполните инструкции https://docs-aibuds.github.io/ru/skills/update-aibuds-firmware. Используйте этот навык, чтобы реализовать «Обновление прошивки AIBuds» в данном iOS-проекте и проверить результат.Справочник API
Фреймворк
AIBuds.xcframework
Импорт
- Swift
- Objective-C
import AIBuds
import AIBudsFoundation#import <AIBuds/AIBuds-Swift.h>
#import <AIBuds/AIBuds.h>Протокол
- Swift
- Objective-C
/// 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?
)
}/// The protocol for device OTA upgrade API.
@protocol AIBudsDeviceOtaAPI <AIBudsDeviceAPI>
/// The OTA protocol capability reported by the device.
/// Defaults to `AIBudsOtaProtocolCapabilityAbmate` when the device does not report it.
@property(nonatomic, readonly) AIBudsOtaProtocolCapability otaProtocolCapability;
/// OTA battery limit, 0...100, unit: percent.
@property(nonatomic, readonly) NSInteger otaBatteryLimit;
/// Start OTA upgrade from a local firmware path.
///
/// - Parameters:
/// - filePath: The readable local firmware file path.
/// - startHandler: Called when the OTA start attempt completes.
/// - success: `YES` if the OTA task started; otherwise `NO`.
/// - error: Failure information, or `nil` if the task started.
/// - progressHandler: Called when OTA progress changes.
/// - progress: Progress in the range `0.0...1.0`.
/// - completionHandler: Called when the OTA operation finishes.
/// - success: `YES` if the upgrade succeeded; otherwise `NO`.
/// - avgSpeed: Average transfer speed in kB/s.
/// - error: Failure information, or `nil` if the upgrade succeeded.
- (void)startOtaWithFilePath:(NSString *_Nonnull)filePath
startHandler:(AIBudsOtaStartCompletionHandler _Nullable)startHandler
progressHandler:(AIBudsOtaProgressHandler _Nullable)progressHandler
completionHandler:(AIBudsOtaCompletionHandler _Nullable)completionHandler;
/// Start OTA upgrade with an explicit transfer protocol configuration.
///
/// - Parameters:
/// - filePath: The readable local firmware file path.
/// - configuration: The OTA protocol configuration required by the device.
/// - startHandler: Called when the OTA start attempt completes.
/// - success: `YES` if the OTA task started; otherwise `NO`.
/// - error: Failure information, or `nil` if the task started.
/// - progressHandler: Called when OTA progress changes.
/// - progress: Progress in the range `0.0...1.0`.
/// - completionHandler: Called when the OTA operation finishes.
/// - success: `YES` if the upgrade succeeded; otherwise `NO`.
/// - avgSpeed: Average transfer speed in kB/s.
/// - error: Failure information, or `nil` if the upgrade succeeded.
- (void)startOtaWithFilePath:(NSString *_Nonnull)filePath
configuration:(AIBudsOtaConfiguration *_Nonnull)configuration
startHandler:(AIBudsOtaStartCompletionHandler _Nullable)startHandler
progressHandler:(AIBudsOtaProgressHandler _Nullable)progressHandler
completionHandler:(AIBudsOtaCompletionHandler _Nullable)completionHandler;
@endСм. otaProtocolCapability, otaBatteryLimit и перегрузки startOta в справочнике API.
Возможности устройства
После готовности устройства прочитайте otaProtocolCapability и ограничьте набор доступных протоколов.
| Swift | Objective-C | Исходное значение | Поддерживаемый протокол |
|---|---|---|---|
.none | AIBudsOtaProtocolCapabilityNone | -1 | Поддержка OTA не заявлена. |
.abmate | AIBudsOtaProtocolCapabilityAbmate | 0 | ABMate. Также используется по умолчанию, если возможность не заявлена. |
.fitcloudPro | AIBudsOtaProtocolCapabilityFitcloudPro | 1 | FitCloud Pro. Требуется плагин FitCloud Pro. |
.abmateAndFitcloudPro | AIBudsOtaProtocolCapabilityAbmateAndFitcloudPro | 2 | ABMate и FitCloud Pro; показывайте только зарегистрированные варианты. |
.jieli | AIBudsOtaProtocolCapabilityJieli | 3 | Однобанковый OTA Jieli. Требуется плагин Jieli. |
Конфигурация OTA
OtaConfiguration задаёт протокол BLE OTA для перегрузки с конфигурацией. Свойство otaProtocol по умолчанию равно .abmate.
| Swift | Objective-C | Исходное значение | Назначение |
|---|---|---|---|
.abmate | AIBudsOtaProtocolKindAbmate | 0 | Протокол OTA ABMate. |
.fitcloudPro | AIBudsOtaProtocolKindFitcloudPro | 1 | Протокол OTA FitCloud Pro. |
.jieli | AIBudsOtaProtocolKindJieli | 2 | Протокол однобанкового OTA Jieli. |
Не выбирайте протокол на основании предположений о файле прошивки. Используйте протокол, заданный подключённым устройством и интеграцией продукта.
Дополнительные плагины OTA
FitCloud Pro и Jieli поставляются как отдельные subspec CocoaPods. Зарегистрируйте плагины до подключения устройства, чтобы SDK мог обнаружить нужные характеристики BLE и подписаться на них. AIBudsSDK/AllInOne устанавливает и регистрирует оба автоматически.
pod 'AIBudsSDK/FitCloudProOTA'
pod 'AIBudsSDK/JieliOTA'import AIBuds
import AIBudsFitCloudProOTA
import AIBudsJieliOTA
AIBudsSDK.registerOtaPlugin(FitCloudProOtaSDK.otaPlugin)
AIBudsSDK.registerOtaPlugin(JieliOtaSDK.otaPlugin)При модульной интеграции регистрируйте только реализации, входящие в продукт. Повторная регистрация того же OtaProtocolKind заменяет предыдущий плагин. Проверяйте доступность через AIBudsSDK.otaPlugin(for:), а для отмены регистрации используйте AIBudsSDK.removeOtaPlugin(for:).
Возвращаемое значение
Ни одна перегрузка не возвращает значение напрямую. startHandler сообщает о запуске задачи OTA, progressHandler — нормализованный прогресс, а completionHandler — окончательный результат и среднюю скорость передачи.
Примеры использования
- Swift
- Objective-C
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"))
})id<AIBudsDeviceOtaAPI> device = (id<AIBudsDeviceOtaAPI>)self.device;
if (![device conformsToProtocol:@protocol(AIBudsDeviceOtaAPI)])
return;
[device startOtaWithFilePath:firmwareURL.path
startHandler:^(BOOL success, NSError *_Nullable error) {
if (!success)
NSLog(@"OTA failed to start: %@", error.localizedDescription);
}
progressHandler:^(CGFloat progress) {
NSLog(@"OTA: %.0f%%", progress * 100);
}
completionHandler:^(BOOL success, CGFloat averageSpeed, NSError *_Nullable error) {
if (success) {
NSLog(@"OTA completed at %.2f kB/s", averageSpeed);
} else {
NSLog(@"OTA failed: %@", error.localizedDescription);
}
}];Явный выбор протокола OTA
Используйте перегрузку с конфигурацией только тогда, когда интеграция продукта точно определяет требуемый устройством протокол OTA.
- Swift
- Objective-C
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"))
}
)AIBudsOtaConfiguration *configuration = [[AIBudsOtaConfiguration alloc] init];
configuration.otaProtocol = AIBudsOtaProtocolKindFitcloudPro;
[device startOtaWithFilePath:firmwareURL.path
configuration:configuration
startHandler:^(BOOL success, NSError *_Nullable error) {
if (!success)
NSLog(@"OTA failed to start: %@", error.localizedDescription);
}
progressHandler:^(CGFloat progress) {
NSLog(@"OTA: %.0f%%", progress * 100);
}
completionHandler:^(BOOL success, CGFloat averageSpeed, NSError *_Nullable error) {
if (success) {
NSLog(@"OTA completed at %.2f kB/s", averageSpeed);
} else {
NSLog(@"OTA failed: %@", error.localizedDescription);
}
}];Обработка ошибок
Для ошибок OTA используются AIBudsSDK.OtaErrorDomain и SdkOtaErrorCode.
| Коды | Типичная причина |
|---|---|
unknown | SDK не может точнее классифицировать ошибку. |
otaTaskAlreadyRunning | Другая задача OTA уже выполняется. |
otaTaskCreateFailedDueToFileNotFound | Локальный путь к прошивке не существует. |
otaTaskStartFailedDueToFileReadError, otaTaskStartFailedDueToFileHandleCreateError | Пакет не удаётся открыть или прочитать. |
otaTaskStartFailedDueToInvalidFileHashData | Некорректные хеш-данные прошивки. |
otaTaskStartFailedDueToGetOtaInfoError | Не удалось получить обязательные метаданные OTA. |
otaTaskStartFailedDueToInvalidOffsetAddress, otaTaskStartFailedDueToInvalidBlockSize | Некорректные метаданные передачи. |
otaTaskStartFailedDueToNotAllowUpdate | Текущее состояние устройства не допускает обновление. |
otaTaskSendDataFailedDueToFileHandleIsNil, otaTaskSendDataFailedDueToSeekFileHandleFailed, otaTaskSendDataFailedDueToReadFileDataFailed, otaTaskSendDataFailedDueToOtaInfoIsNil | SDK не может продолжить чтение или отправку данных прошивки. |
otaTaskFailedDueToDeviceReportKeyMismatch, otaTaskFailedDueToDeviceReportCrcError, otaTaskFailedDueToDeviceReportSeqError, otaTaskFailedDueToDeviceReportDataLengthError | Устройство отклоняет данные или сообщает о нарушении целостности либо последовательности. |
otaTaskFailedDueToDeviceDisconnect, otaTaskFailedDueToTimeout | Устройство отключилось или истекло время ожидания операции. |
Отличайте ошибку startHandler от сбоя после начала передачи. Не повторяйте автоматически обновление с непроверенным пакетом: сначала заново проверьте модель устройства, версию прошивки, целостность пакета, заряд, выбор протокола и подключение.
Рекомендации
- До вызова SDK завершите поиск и загрузку обновления, проверку подписи или целостности и совместимости с моделью устройства.
- Проверяйте
otaBatteryLimitнепосредственно перед запуском, а не только при показе экрана обновления. - Не допускайте одновременного запуска OTA, Camera OTA, импорта медиафайлов и других длительных операций.
- Направляйте обновления UI в главную очередь, поскольку обратные вызовы могут поступать в другой очереди.
- Считайте
startHandlerтолько подтверждением запуска; не сообщайте об успехе обновления до успешногоcompletionHandler. - До окончательного завершения оставляйте приложение активным и подключение стабильным, затем после переподключения проверьте сообщаемую версию прошивки.
Примечания
- Прогресс нормализован в диапазоне
0.0...1.0; ограничивайте отображаемое значение, не изменяя результат SDK. avgSpeedв кБ/с передаётся только итоговым обработчиком завершения.- По умолчанию
OtaConfiguration.otaProtocolравно.abmate; выбирайте.fitcloudProили.jieli, только если их поддерживаютotaProtocolCapabilityи установленный плагин. - SDK не предоставляет метод отмены OTA. Кнопка Cancel в Demo лишь сбрасывает локальное состояние интерфейса и не отменяет операцию SDK.