杰理 SDK 文档中心
首页
首页
  • SDK 框架库

    • JL_BLEKit 蓝牙通信核心
    • JL_AdvParse 广播包解析
    • JL_HashPair 加密配对
    • JL_OTALib 固件升级
    • JLDialUnit 彩屏仓与表盘控制
    • JLBmpConvertKit 位图转换
    • JLPackageResKit 资源包处理
    • JLLogHelper 日志工具
  • 核心功能模块

    • 音乐与媒体控制
    • 音效调节与均衡器
    • 设备发现、连接与设置
    • Auracast 广播接收与发射
    • 文件浏览、闹钟、FM 与灯光控制
    • ANC、按键设置与查找设备
    • AI 翻译与自定义命令
  • 应用架构与工程支撑

    • 杰理之家 App 架构与导航
    • 数据存储与缓存
    • Swift 工具与扩展层
    • JLAudioUnitKit 示例工程
    • SDKTestHelper 测试工具
  • 开发文档与资源

    • 文档中心与 JL_OTALib API 说明
    • 自定义蓝牙接入方式
    • 调试技巧与问题排查
    • 版本历史与社区支持

JL_OTALib 固件升级

JL_OTALib 是杰理科技(JieLi)面向 iOS/macOS 平台的蓝牙设备固件升级(OTA)库,封装了从固件文件解析、OTA 能力查询、数据分片传输、断线回连到升级结果回调的完整升级流程。开发者只需通过 JL_OTAManager 单例与几个命令方法即可为耳机、音箱、手表等杰理蓝牙设备实现稳定可靠的固件升级能力。

Purpose and Scope

本页面向 iOS/macOS 开发者,完整说明 JL_OTALib 框架(JL_OTALib.xcframework)在固件升级场景中的职责、架构、核心 API、升级状态机与典型接入方式。内容包括:

  • 框架组成与公开头文件(JL_OTAManager.h、jl_ufw.h、JLOTAFile.h、JLOtaReConnectOption.h、JLOtaCustom.h)的定位;
  • JL_OTAManager 单例对象模型、JL_OTAManagerDelegate 回调协议与全部枚举定义;
  • 从连接、查询特性、发起升级、回连续传、进度回调到完成的端到端升级流程;
  • 全部 JL_OTAResult 错误码、配置项与 API 参考。

不在本页范围:底层 BLE 扫描/连接/认证与 RCSP 数据通道由 JL_BLEKit 负责(详见 JL_BLEKit 相关页面);固件文件的生成与签名属于杰理上位机工具链,本页只涉及文件数据的解析与传输。JL_OTALib 为二进制 XCFramework 分发,本页所有代码示例均摘自其公开头文件。

Overview

库的本质:把"升级协议"封装成对象

JL_OTALib 并不是一个 UI 库,而是一个协议状态机库。它把杰理设备 OTA 升级所涉及的 RCSP 命令交互(查询特性、下发升级指令、数据分片、应答与重传、回连续传、重启设备)全部封装在 JL_OTAManager 内部,对外暴露的是一组"命令"方法与一个"进度/结果"回调。开发者不需要关心底层包格式与分片窗口,只需要:

  1. BLE 连接成功后,把 UUID、设备名等喂给 JL_OTAManager;
  2. 调用 cmdTargetFeature 查询设备 OTA 能力;
  3. 传入固件数据(.ufw/.dfu 文件内容)调用 cmdOTAData 或 cmdUpgrade 发起升级;
  4. 在 delegate 回调中接收状态与进度,处理"需要回连""低电压""TWS 未连接"等事件。

关键设计概念

概念说明
单备份 / 双备份(JL_Partition)双备份设备升级失败可自动回滚;单备份设备升级过程需先进入 Boot 模式并回连才能继续传输
回连(JL_OTAReconnectType)单备份升级时设备会断开并切换广播,SDK 支持按 UUID 或 MAC 地址自动重连
BootLoader(JL_BootLoader)部分设备需要先下载 BootLoader 才能进入升级态
资源升级(JLOtaSourcesExtendMode)支持仅升级固件、仅升级资源(UI 音效等)或普通升级三种扩展模式
强制升级(JL_OtaStatus / JL_OtaHeadset)耳机单备份等场景下,相同版本或特殊设备需要"强制"标志才能升级
复用空间 OTA(isSupportReuseSpaceOTA)设备是否支持复用存储空间进行 OTA,影响升级数据大小与策略

框架分发形态

JL_OTALib.xcframework 包含三个平台切片(来自仓库文件结构):ios-arm64(真机)、ios-arm64_x86_64-simulator(模拟器)、macos-arm64_x86_64(Mac Catalyst/桌面),可在同一工程内同时支持 iOS 与 macOS 目标。框架对外头文件共 5 个,主头文件统一导出:

#import <JL_OTALib/JL_OTAManager.h>
#import <JL_OTALib/jl_ufw.h>
#import <JL_OTALib/JLOTAFile.h>
#import <JL_OTALib/JLOtaReConnectOption.h>
#import <JL_OTALib/JLOtaCustom.h>

Source: JL_OTALib.h

其中 JL_OTAManager.h 是升级核心(本文档重点),jl_ufw.h/JLOTAFile.h 负责解析杰理固件文件格式(JL_UFW 头/分区信息),JLOtaReConnectOption.h 提供回连参数,JLOtaCustom.h 提供自定义升级策略扩展。

Architecture

flowchart TD
    subgraph sg_App["应用层(开发者代码)"]
        AppUI["业务 App / 升级界面"]
    end

    subgraph sg_OTALib["JL_OTALib.framework"]
        Manager["JL_OTAManager(单例状态机)"]
        Delegate["JL_OTAManagerDelegate 回调协议"]
        FileParser["JLOTAFile / jl_ufw 固件解析"]
        Reconnect["JLOtaReConnectOption 回连参数"]
        Custom["JLOtaCustom 自定义升级策略"]
    end

    subgraph sg_BLE["底层依赖(外部)"]
        BLEKit["JL_BLEKit(BLE 连接 / RCSP 通道)"]
        LogHelper["JLLogHelper(日志)"]
    end

    Device["杰理蓝牙设备(耳机 / 音箱 / 手表)"]

    AppUI -->|"调用命令方法"| Manager
    AppUI -->|"实现并设置"| Delegate
    Manager -->|"进度 / 状态回调"| Delegate
    Manager --> FileParser
    Manager --> Reconnect
    Manager -.->|"可配置扩展"| Custom
    Manager -->|"RCSP 数据收发"| BLEKit
    BLEKit -->|"BLE GATT 读写 / 广播回连"| Device
    LogHelper -.->|"日志输出"| Manager

架构说明:JL_OTAManager 是唯一入口与状态机载体,开发者通过单例与之交互;数据通路经由 JL_BLEKit 提供的 RCSP 通道与设备通信;升级结果与进度通过 delegate 异步回抛。JLOTAFile/jl_ufw 在升级前把固件文件解析为 SDK 可用的数据格式;JLOtaReConnectOption 供单备份回连场景定制连接参数;JLOtaCustom 是面向特殊设备的扩展钩子。

核心枚举:升级结果与设备能力

JL_OTAResult(UInt16)——升级状态/结果码

这是整个库最重要的枚举,贯穿 delegate 回调 otaUpgradeResult:Progress: 与各命令的 Result 回调。定义于 JL_OTAManager.h L15-L80:

枚举值值含义
JL_OTAResultSuccess0x00OTA 升级成功
JL_OTAResultFail0x01OTA 升级失败(通用)
JL_OTAResultDataIsNull0x02升级数据为空
JL_OTAResultCommandFail0x03OTA 指令失败
JL_OTAResultSeekFail0x04OTA 标示偏移查找失败
JL_OTAResultInfoFail0x05固件信息错误
JL_OTAResultLowPower0x06设备电压低,拒绝升级
JL_OTAResultEnterFail0x07未能进入 OTA 升级模式
JL_OTAResultUpgrading0x08OTA 升级中
JL_OTAResultReconnect0x09需要重连设备(UUID 方式)
JL_OTAResultReboot0x0a需要设备重启
JL_OTAResultPreparing0x0bOTA 准备中
JL_OTAResultPrepared0x0fOTA 准备完成
JL_OTAResultStatusIsUpdating0x10设备已在升级中
JL_OTAResultFailedConnectMore0x11多台设备连接,需手动断开另一台
JL_OTAResultFailSameSN0xe0升级数据校验失败,SN 多次重复
JL_OTAResultCancel0xe1升级已取消
JL_OTAResultFailVerification0xf1升级数据校验失败
JL_OTAResultFailCompletely0xf2升级完全失败
JL_OTAResultFailKey0xf3加密 Key 不对
JL_OTAResultFailErrorFile0xf4升级文件出错
JL_OTAResultFailUboot0xf5uboot 不匹配
JL_OTAResultFailLenght0xf6升级过程长度出错
JL_OTAResultFailFlash0xf7升级过程 flash 读写失败
JL_OTAResultFailCmdTimeout0xf8升级过程指令超时
JL_OTAResultFailSameVersion0xf9固件相同版本
JL_OTAResultFailTWSDisconnect0xfaTWS 耳机未连接
JL_OTAResultFailNotInBin0xfb耳机未在充电仓
JL_OTAResultReconnectWithMacAddr0xfc需要重连设备(MAC 方式)
JL_OTAResultDisconnect0xfdOTA 设备断开
JL_OTAResultReconnectUpdateSource0xfe需要重连设备(更新资源)
JL_OTAResultUnknown0xff未知错误

设计意图:错误码覆盖了协议层错误(0x01~0x07)、流程状态(0x08~0x11)与数据/设备侧错误(0xe0~0xfe)三组。其中 0x09/0xfc/0xfe 三个"需重连"码是单备份升级回连机制的关键信号,开发者收到后应停止传输、等待 SDK 内部或自行按 UUID/MAC 重连。

设备能力与升级模式枚举

typedef NS_ENUM(UInt8, JL_OTAReconnectType) {
    JL_OTAReconnectTypeUUID = 0x00,    // OTA升级回连使用uuid
    JL_OTAReconnectTypeMACAddr = 0x01, // OTA升级回连使用mac地址
};

typedef NS_ENUM(UInt8, JL_OtaStatus) {
    JL_OtaStatusNormal = 0, // 正常升级
    JL_OtaStatusForce = 1,  // 强制升级
};

typedef NS_ENUM(UInt8, JLOtaSourcesExtendMode) {
    JLSourcesExtendModeDisable = 0,        // 不启用
    JLSourcesExtendModeNormal = 1,         // 启用普通资源升级模式
    JLSourcesExtendModeSourceOnly = 2,     // 启用只升级资源的模式
    JLSourcesExtendModeFirmwareOnly = 3,   // 启用只升级固件程序的模式
};

typedef NS_ENUM(UInt8, JL_BootLoader) {
    JL_BootLoaderNO = 0,  // 不需要下载Bootloader
    JL_BootLoaderYES = 1, // 需要下载BootLoader
};

typedef NS_ENUM(UInt8, JL_Partition) {
    JL_PartitionSingle = 0, // 固件单备份
    JL_PartitionDouble = 1, // 固件双备份
};

Source: JL_OTAManager.h

其中 JL_OtaWatch 与 otaWatch 属性已被 __attribute__((deprecated)) 标记废弃,统一改用 JLOtaSourcesExtendMode(otaSourceMode)表达资源升级模式——这反映了库的演进方向:把"手表资源升级"这一单一场景抽象为通用的"固件/资源分离升级"能力。

回调 Block 类型

typedef void (^JL_OTA_RT)(JL_OTAResult result, float progress);
typedef void (^JL_OTA_RESULT)(uint8_t status, uint8_t sn, NSData *__nullable data);

Source: JL_OTAManager.h

  • JL_OTA_RT:升级进度回调,progress 为 0.0~1.0 浮点进度;
  • JL_OTA_RESULT:命令应答回调(主要给取消升级等命令使用),携带命令序号 sn 与原始应答 data。

JL_OTAManager 对象模型

单例获取

/// 获取 OTA 升级对象
+ (JL_OTAManager *)getOTAManager;

/// 不建议使用自行初始化
/// 推荐获取 getOTAManager
- (instancetype)init __attribute__((deprecated("Please use getOTAManager instead.")));

Source: JL_OTAManager.h

getOTAManager 是唯一推荐的获取方式。设计意图:OTA 状态机必须与设备连接生命周期一一对应,单例保证整个 App 内只有一份升级上下文,避免多实例各自维护状态导致指令串扰。

开发者必须填写的属性

属性类型说明
mBLE_UUIDNSString *设备 UUID,开发者填入
mBLE_NAMENSString *设备名称,开发者填入
delegateid<JL_OTAManagerDelegate>交互回调代理

由设备特性查询结果填充的属性

属性类型说明
bleOnlyBOOL是否仅支持 BLE(不支持经典蓝牙)
bleAddrNSString *BLE 蓝牙地址
mCmdSNuint8_tSN 值(命令序号)
versionuint16_t设备版本号
versionFirmwareNSString *设备版本信息字符串
otaStatusJL_OtaStatus设备 OTA 状态(正常/强制)
otaHeadsetJL_OtaHeadset耳机单备份是否需要强制升级
isSupportReuseSpaceOTABOOL是否支持复用空间 OTA
isSupportExpandBOOL是否支持 OTA 拓展功能
otaSourceModeJLOtaSourcesExtendMode资源升级模式
otaPartitionJL_Partition单/双备份
bootloaderTypeJL_BootLoader是否需要下载 BootLoader
otaReconnectTypeJL_OTAReconnectType回连方式(UUID/MAC)

只读进度属性

/// OTA升级内容大小(设备通知的)
@property(assign, nonatomic, readonly) int64_t otaLength;
/// 已传输的数据大小
@property(assign, nonatomic, readonly) uint32_t otaSent;

Source: JL_OTAManager.h

otaLength/otaSent 由设备通知与 SDK 内部计数维护,可用来做 UI 进度条的自定义计算。

JL_OTAManagerDelegate 回调协议

@protocol JL_OTAManagerDelegate <NSObject>

/// 即将被发送的数据
/// @param data 数据内容
- (void)otaDataSend:(NSData *_Nonnull)data;

@optional
/// 回调设备状态信息
- (void)otaFeatureResult:(JL_OTAManager *_Nonnull)manager;
/// 回调升级状态以及进度等
- (void)otaUpgradeResult:(JL_OTAResult)result Progress:(float)progress;
/// 取消OTA升级
- (void)otaCancel;

@end

Source: JL_OTAManager.h

  • otaDataSend: 是唯一必选回调:SDK 将要发送的 RCSP 数据交还给上层,由上层(JL_BLEKit 通道)真正写入 BLE。这是把"协议生成"与"物理发送"解耦的关键设计——库本身不持有蓝牙连接。
  • otaFeatureResult::cmdTargetFeature 查询完成后触发,此时可读取设备能力属性并决定升级策略;
  • otaUpgradeResult:Progress::升级过程的主回调,携带 JL_OTAResult 与 0~1 进度;
  • otaCancel:SDK 收到取消指令后的确认回调。

核心升级流程

端到端时序

sequenceDiagram
    participant App as App 开发者
    participant M as JL_OTAManager
    participant B as JL_BLEKit 通道
    participant D as 杰理设备

    App->>M: getOTAManager + 填写 mBLE_UUID/mBLE_NAME
    App->>M: noteEntityConnected(BLE 已连接并认证完成)
    App->>M: cmdTargetFeature(第一步,查询OTA能力)
    M->>B: 发送 RCSP 特性查询命令
    B->>D: GATT 写入
    D-->>B: 特性应答
    B-->>M: cmdOtaDataReceive: 数据
    M-->>App: otaFeatureResult(属性已填充)

    alt 设备需挂载外置 Flash
        App->>M: cmdSystemFunction(查询系统状态)
    end

    App->>M: cmdOTAData:固件数据 Result:^(result, progress)
    M->>D: 升级指令 + 数据分片
    alt 双备份或无需回连
        loop 传输中
            M->>D: 固件数据包
            D-->>M: 应答 / 进度
            M-->>App: otaUpgradeResult(Upgrading, progress)
        end
    else 单备份需回连
        D-->>M: JL_OTAResultReconnect / ReconnectWithMacAddr
        M-->>App: 通知需回连
        M->>B: 断开并按 UUID/MAC 回连设备
        B-->>M: 回连成功
        M->>D: cmdOtaDataIIResult 继续传输(或 cmdUpgrade 内部处理)
        loop 传输中
            M->>D: 固件数据包
            D-->>M: 应答 / 进度
            M-->>App: otaUpgradeResult(progress)
        end
    end

    D-->>M: 传输完成,设备重启
    M-->>App: otaUpgradeResult(JL_OTAResultSuccess, 1.0)

升级流程状态机(逐步走查)

  1. 连接与登记:BLE 连接成功后(JL_BLEKit 侧认证完成),开发者调用 noteEntityConnected 告知 SDK,并确保 mBLE_UUID/mBLE_NAME 已填写。设备断开时调用 noteEntityDisconnected,SDK 据此复位内部传输状态。

  2. 查询特性(必须第一步):调用 cmdTargetFeature 查询设备 OTA 能力。SDK 根据应答填充 otaPartition、bootloaderType、otaReconnectType、otaSourceMode 等属性,随后触发 otaFeatureResult:。设计意图:不同设备(单/双备份、是否需要 BootLoader、回连方式)升级路径差异很大,必须先拿到能力再决定策略,否则可能出现"双备份设备被当作单备份处理"等错误。

  3. (可选)查询系统功能:cmdSystemFunction 仅在设备需要挂载外置 Flash 才能升级时执行。

  4. 发起升级:将固件文件(由 JLOTAFile/jl_ufw 解析后的数据)通过 cmdOTAData:Result: 传入。SDK 内部进入"准备→传输"状态,JL_OTAResultPreparing→JL_OTAResultPrepared→JL_OTAResultUpgrading 依次上报。

  5. 回连分支(单备份特有):单备份设备升级时,设备会断开进入 Boot 广播。SDK 通过 JL_OTAResultReconnect(UUID 方式)或 JL_OTAResultReconnectWithMacAddr(MAC 方式)通知上层;开发者可用 cmdOtaIsRelinking 查询是否正在回连。回连成功后可调用 cmdOtaDataIIResult: 再次发起升级(针对已断开的传输上下文),或直接使用 cmdUpgrade:Option:Result: 让 SDK 内部完成回连与续传(此接口免去外层回连策略,但要求使用 Result 回调而非 delegate 回调)。

  6. 进度与完成:传输期间 otaUpgradeResult:Progress: 持续回调进度;完成后设备重启,SDK 回调 JL_OTAResultSuccess。若需要,可调用 cmdRebootDevice/cmdRebootForceDevice 主动重启设备。

  7. 中断与清理:cmdOTACancelResult: 取消升级(SDK 回调 otaCancel 确认);升级会话结束后调用 resetOTAManager 复位状态机,准备下一次升级。

数据接收入口

设备端(经 JL_BLEKit 通道)返回的任何 RCSP 数据都必须喂给 SDK:

/// Receive data from rcsp
/// 设备端过来的数据
/// - Parameter data: data
- (void)cmdOtaDataReceive:(NSData *)data;

Source: JL_OTAManager.h

这是"数据回灌"入口,与 otaDataSend: 形成闭环:SDK 生成数据 → 上层发送 → 设备应答 → 上层回灌给 SDK。若此入口漏接,升级将永远停留在等待应答状态并最终超时。

使用示例

以下示例均摘自 JL_OTAManager.h 公开接口,展示标准接入模式(Objective-C)。

示例 1:获取单例并配置升级上下文

连接设备后,填充设备标识、设置代理并告知 SDK 连接已就绪:

// 获取 OTA 升级对象
JL_OTAManager *manager = [JL_OTAManager getOTAManager];

/// 设备UUID(需要开发者填入)
manager.mBLE_UUID = deviceUUID;
/// 设备名称(需要开发者填入)
manager.mBLE_NAME = deviceName;
/// 设备交互回调代理
manager.delegate = self;

// 当BLE连接上时告知SDK
[manager noteEntityConnected];
// 当BLE断开时告知SDK
[manager noteEntityDisconnected];

Source: JL_OTAManager.h

示例 2:连接后第一步——查询 OTA 能力

/// 查询设备OTA信息
/// 所有情况下都需要执行,而且是在连上后(认证完成)第一步执行
[manager cmdTargetFeature];

/// 查询设备系统状态
/// 当设备需要挂载外置flash才能正常升级时需要执行,其他情况则无需执行
[manager cmdSystemFunction];

Source: JL_OTAManager.h

查询完成后在 otaFeatureResult: 回调中读取 otaPartition、bootloaderType、otaReconnectType 等属性,即可判断走普通升级还是回连升级。

示例 3:发起升级(标准方式)

/// 开始OTA升级
/// @param data 升级数据
/// @param result 升级结果
[manager cmdOTAData:otaData Result:^(JL_OTAResult result, float progress) {
    // 处理升级结果与进度
    dispatch_async(dispatch_get_main_queue(), ^{
        if (result == JL_OTAResultUpgrading) {
            progressView.progress = progress;
        } else if (result == JL_OTAResultSuccess) {
            // 升级成功
        } else if (result == JL_OTAResultLowPower) {
            // 提示用户充电
        }
    });
}];

Source: JL_OTAManager.h

示例 4:一键升级(内部回连,单备份推荐)

/// OTA升级III
/// 单备份升级特有!!!
/// 此接口免去了公版 OTA 的外边回连策略,内部实现回连
/// ⚠️使用此方法时不可使用 delegate 的回调信息,要使用 Result 的回调信息
/// @param data OTA数据
/// @param option 回连选项
/// @param result 回复
[manager cmdUpgrade:otaData
              Option:reconnectOption
              Result:^(JL_OTAResult result, float progress) {
    // 唯一的进度/结果来源
}];

Source: JL_OTAManager.h

注意:cmdUpgrade:Option:Result: 与 delegate 回调互斥(头文件明确标注"不可使用 delegate 的回调信息"),因为内部回连会重新走连接流程,delegate 状态与 Result 回调可能不一致。选其一即可。

示例 5:取消与复位

// OTA升级取消
[manager cmdOTACancelResult:^(uint8_t status, uint8_t sn, NSData *data) {
    // 取消应答
}];

// 重置OTA manager(升级会话结束后清理状态)
[manager resetOTAManager];

Source: JL_OTAManager.h

配置选项

以下为 JL_OTAManager 提供的行为配置(默认值以头文件注释为准):

配置项方法/属性类型默认值说明
最大丢包次数maxLostCount:int10传输层丢包重传上限,超过则判定升级失败
指令超时时间cmdTimeOut:int5(秒)单条 RCSP 命令等待应答的超时时间
回连方式otaReconnectTypeJL_OTAReconnectType由 cmdTargetFeature 查询结果决定UUID 或 MAC 地址回连
资源升级模式otaSourceModeJLOtaSourcesExtendModeJLSourcesExtendModeDisable普通/仅资源/仅固件升级
单双备份otaPartitionJL_Partition由设备查询决定影响是否需要回连续传
BootLoaderbootloaderTypeJL_BootLoader由设备查询决定是否先下载 BootLoader
耳机强制升级otaHeadsetJL_OtaHeadsetJL_OtaHeadsetNO耳机单备份场景强制升级开关
仅 BLEbleOnlyBOOLNO设备是否仅支持 BLE
发送日志logSendData:BOOLNO打印 OTA 发送的数据内容(调试用)
回连开关setOTARelink:BOOL—已废弃,禁止外部使用(状态机内部管理)

Source: JL_OTAManager.h

API 参考

+ (JL_OTAManager *)getOTAManager

获取 OTA 升级单例对象。推荐唯一获取方式;init 已废弃。

Returns:JL_OTAManager * 全局单例。

- (void)noteEntityConnected / - (void)noteEntityDisconnected

告知 SDK 设备 BLE 连接/断开事件。必须在连接建立与断开时准确调用,是状态机对设备生命周期感知的输入。

- (void)cmdOtaDataReceive:(NSData *)data

接收设备端回灌的 RCSP 数据。必须将 JL_BLEKit 通道收到的所有数据透传至此方法,否则 SDK 无法解析应答。

参数:data —— 设备返回的原始数据包。

- (void)cmdTargetFeature

查询设备 OTA 能力信息。连接认证完成后第一步必须执行;完成后触发 otaFeatureResult:。

- (void)cmdSystemFunction

查询设备系统状态。仅当设备需挂载外置 Flash 才能升级时执行。

- (void)cmdOTAData:(NSData *)data Result:(JL_OTA_RT __nullable)result

发起标准 OTA 升级。

参数:

  • data:升级数据(固件文件解析后的内容);
  • result:升级结果/进度回调 (JL_OTAResult, float progress),可为 nil(此时依赖 delegate)。

- (void)cmdOtaDataIIResult:(JL_OTA_RT __nullable)result

OTA 升级 II,单备份升级特有。用于回连成功后再次发起升级,续传此前中断的升级上下文。

- (void)cmdUpgrade:(NSData *)data Option:(JLOtaReConnectOption *__nullable)option Result:(JL_OTA_RT __nonnull)result

OTA 升级 III,单备份升级特有。SDK 内部实现回连,免去外层回连策略。

参数:

  • data:OTA 数据;
  • option:回连选项(JLOtaReConnectOption),可为 nil;
  • result:结果回调(非空,且此时不应使用 delegate 回调)。

- (void)cmdOTACancelResult:(JL_OTA_RESULT __nullable)result

取消 OTA 升级,通过 JL_OTA_RESULT 回调返回命令应答(status/sn/data)。

- (void)cmdRebootDevice / - (void)cmdRebootForceDevice

请求设备重启 / 强制重启(升级完成后清理设备状态时使用)。

- (BOOL)cmdOtaIsRelinking

查询单备份升级当前是否正处于回连阶段。Returns:BOOL,正在回连返回 YES。

- (void)resetOTAManager

重置 OTA 管理器内部状态,升级会话结束后调用,为下一次升级做准备。

+ (NSString *)logSDKVersion

打印/获取 OTA SDK 版本号。Returns:版本字符串。

- (void)maxLostCount:(int)count / - (void)cmdTimeOut:(int)timeOut

配置传输可靠性参数:最大丢包次数(默认 10)与命令超时秒数(默认 5)。弱信号环境可适当调大丢包上限,避免误判失败。

失败模式、边界情况与并发

升级失败分类与处置建议

依据 JL_OTAResult 枚举(JL_OTAManager.h L15-L80),可将失败归纳为四类:

类别错误码处置建议
用户/环境问题LowPower(0x06)、FailTWSDisconnect(0xfa)、FailNotInBin(0xfb)、FailedConnectMore(0x11)提示用户充电、连接 TWS 副耳、放入充电仓、断开多余设备后重试
数据/固件问题DataIsNull(0x02)、InfoFail(0x05)、FailSameSN(0xe0)、FailVerification(0xf1)、FailKey(0xf3)、FailErrorFile(0xf4)、FailUboot(0xf5)、FailSameVersion(0xf9)校验固件文件与设备型号/加密 Key/版本是否匹配,重新获取固件
传输/设备故障SeekFail(0x04)、FailLenght(0xf6)、FailFlash(0xf7)、FailCmdTimeout(0xf8)、Disconnect(0xfd)、Fail(0x01)检查信号强度与距离,适当调大 maxLostCount/cmdTimeOut,重试升级
流程状态信号Reconnect(0x09)、ReconnectWithMacAddr(0xfc)、ReconnectUpdateSource(0xfe)、Reboot(0x0a)、Preparing(0x0b)、Prepared(0x0f)、Upgrading(0x08)、StatusIsUpdating(0x10)这些不是错误,是状态机推进信号,按流程处理(回连、等待、续传)即可

回连机制的边界情况

  • 回连是单备份升级的必经之路:设备进入 Boot 模式后会断开原连接,此时若上层未及时处理 JL_OTAResultReconnect/JL_OTAResultReconnectWithMacAddr,SDK 会停留在等待回连状态,直至 cmdTimeOut 超时。cmdOtaIsRelinking 可用于 UI 层显示"正在回连"。
  • UUID 与 MAC 回连的差异:UUID 方式(0x09)适用于 iOS 端连接过的设备(CoreBluetooth 缓存的 UUID);MAC 方式(0xfc)适用于需要按蓝牙 MAC 精确回连的场景(如多设备环境)。
  • cmdUpgrade:Option:Result: 与 delegate 互斥:使用内部回连接口时,delegate 的 otaUpgradeResult: 不再可靠,必须全部依赖 Result 回调,否则会出现双重处理或漏处理。

并发与多设备

  • 单例约束:JL_OTAManager 为单例,同一时刻只维护一份升级上下文。若 App 同时连接多台杰理设备,只允许对其中一台执行升级;JL_OTAResultFailedConnectMore(0x11)正是设备侧检测到多连接时给出的保护信号——必须手动断开另一台设备后才能继续。
  • 数据回灌串行性:cmdOtaDataReceive: 应在蓝牙接收回调的串行队列上按序调用,避免多线程并发回灌导致分片乱序。发送侧 otaDataSend: 也应保持串行写特征。
  • 主线程 UI 更新:delegate 与 Block 回调可能不在主线程触发,示例代码中使用 dispatch_async(dispatch_get_main_queue(), ...) 更新进度条是推荐做法。

传输可靠性

  • 丢包重传由 SDK 内部管理,maxLostCount:(默认 10)控制最大连续丢包次数;cmdTimeOut:(默认 5 秒)控制单命令等待超时。两者共同构成"超时即失败"的保护网,防止升级过程无限挂起。
  • 设备电量不足(LowPower)时升级会被设备侧直接拒绝——这是保护性设计:OTA 写 Flash 期间断电会导致设备变砖,宁可拒绝也不要冒险。

性能与运维注意事项

  • 升级耗时的决定因素:固件大小、BLE MTU/分片窗口、丢包重传。otaLength(设备通知的升级内容大小)与 otaSent(已传输字节数)可计算实时吞吐,便于展示 ETA。
  • 日志:logSendData: 可打印 SDK 发送的每一条数据,是排查"设备不应答/指令错误"的首选工具;logSDKVersion 可在反馈问题时附带 SDK 版本号。
  • 升级期间的行为约束:升级过程中应避免主动断开 BLE、切换后台过度频繁或触发系统级蓝牙重置;设备侧正在写 Flash 时强杀 App 不会损坏设备(双备份可回滚),但单备份设备可能进入 Boot 待升级状态,需要重新走回连升级。
  • 分发形态:XCFramework 已包含 ios-arm64 / ios-arm64_x86_64-simulator / macos-arm64_x86_64 三个切片,无需按目标平台拆分引用;注意真机调试时选择 ios-arm64 切片,模拟器调试时选择 ios-arm64_x86_64-simulator。

扩展点

  1. JL_OTAManagerDelegate 协议:通过实现 otaFeatureResult:、otaUpgradeResult:Progress:、otaCancel 自定义升级流程的 UI 与业务编排,而无需改动库内部逻辑。
  2. JLOtaReConnectOption:为 cmdUpgrade:Option:Result: 提供回连参数(UUID/名称/地址等),可针对特殊设备定制回连行为。
  3. JLOtaCustom:面向特殊设备的自定义升级策略入口(公开头文件之一),适合对标准升级流程不满足的定制项目。
  4. jl_ufw / JLOTAFile:固件文件解析层,负责从 .ufw/.dfu 文件提取升级数据与校验信息;如需对接自有文件格式,可在此层之外先转换为 SDK 期望的数据后直接调用 cmdOTAData:。
  5. JLOtaSourcesExtendMode:资源/固件分离升级模式(SourceOnly/FirmwareOnly),适合需要单独推送 UI 资源或语音资源的场景,无需走完整固件升级流程。

Related Links

  • JL_OTALib.h(框架主头文件)
  • JL_OTAManager.h(OTA 管理核心 API)
  • 框架其他公开头文件:jl_ufw.h、JLOTAFile.h、JLOtaReConnectOption.h、JLOtaCustom.h(同目录)
  • 底层蓝牙连接与 RCSP 数据通道:见 JL_BLEKit 相关页面
  • 演示工程接入示例:见 code/JieLi_Home_Demo 与 code/SDKTestHelper
Prev
JL_HashPair 加密配对
Next
JLDialUnit 彩屏仓与表盘控制