杰理 SDK 文档中心
首页
首页
  • 项目概览

    • 项目概述与功能特性
    • 工程结构与运行环境
  • 快速开始

    • SDK 集成步骤
    • 连接方式选择指南
  • 核心 SDK 架构

    • SDK 框架组成
    • JL_OTAManager 升级管理 API
    • 设备认证与广播解析
  • 蓝牙连接与设备发现

    • 设备扫描与广播发现
    • 原生 CoreBluetooth 连接
    • JL_BLEKit SDK 连接
    • JL_Assist 自定义连接
    • GATT Over BR/EDR 经典蓝牙升级
  • OTA 升级工作流

    • 标准升级流程
    • 自动化测试与批量升级
    • 广播音箱升级
    • 升级文件管理
  • 示例工程

    • 完整示例应用
    • 迷你示例工程
    • 第三方依赖与工具
  • 开发支持与版本发布

    • 文档中心与 API 说明
    • SDK 版本与构建产物
    • 调试技巧与日志辅助

广播音箱升级

本文档介绍 iOS-JL_OTA 中「广播音箱升级」能力的完整实现:通过 BLE 扫描、连接、配对(RCSP 协议)并串行调度多台音箱执行固件 OTA 升级的端到端工作流,涵盖 BroadcastBleManager、BroadcastThread、DeviceManager 三个核心模块及其协作机制。

Purpose and Scope

本页面聚焦于 code/JL_OTA/JL_OTA/BroadcastSpeakers/BroadcastBle/ 目录下的广播音箱批量升级子系统,说明其如何:

  • 基于 CoreBluetooth 扫描/连接多台音箱,并经由杰理 SDK(JL_Assist)建立 RCSP 命令通道;
  • 以单线程队列的方式对多台设备串行执行 OTA 固件升级(同一时刻仅一台设备在升级);
  • 通过设备注册表(DeviceManager)维护外围设备与 SDK 管理器的映射;
  • 通过通知(kBDM_BLE_*)与代理协议(OtaUpdatePtl)向 UI 层上报状态与进度。

与之相关的单设备 OTA 流程、SDK 命令解析(JL_RunSDK、SDKBleHelper)以及普通 BLE 管理(JLBleManager)属于其他目录页面的范畴,本页仅在必要时引用,不展开叙述。

Overview

广播音箱升级(Broadcast Speaker Upgrade)是 JL_OTA 演示工程中面向「一拖多」场景的升级方案。与单设备 OTA 不同,广播场景的核心诉求是:在保持蓝牙广播连接的前提下,对多台同型号音箱批量烧录同一份固件。

系统由三个单例(singleton)协作完成:

模块文件职责
BroadcastBleManagerBroadcastBleManager.m蓝牙扫描、连接、断开、JL_Assist 会话管理、状态通知广播
BroadcastThreadBroadcastThread.mOTA 任务队列与串行调度(maxVerify 并发闸门)
DeviceManagerDeviceManager.m设备注册表:维护 CBPeripheral ↔ JL_EntityM/JLDeviceInfo 映射

关键设计决策:

  1. 并发闸门(maxVerify):BroadcastThread 通过 maxVerify 计数器保证任意时刻只有一台设备在执行升级,避免多路 RCSP 命令交错导致音箱侧协议状态机错乱。
  2. 按 UUID 隔离 Assist 会话:BroadcastBleManager 以 cbp.identifier.UUIDString 为 key 保存独立的 JL_Assist 实例,使多设备的命令通道互不干扰。
  3. 独立串行队列:OTA 数据发送运行在 dispatch_queue_create("ota_thread", NULL) 队列上,与主线程解耦,保证大数据包发送不阻塞 UI。

Architecture

flowchart TD
    subgraph sg_UI["UI 层 (ViewController)"]
        VC["FittingView / 升级界面"]
    end

    subgraph sg_Broadcast["广播升级子系统 BroadcastSpeakers"]
        BBM["BroadcastBleManager<br/>(单例: 扫描/连接/Assist)"]
        BT["BroadcastThread<br/>(单例: OTA 调度队列)"]
        DM["DeviceManager<br/>(单例: 设备注册表)"]
        BBM -->|"kBDM_BLE_* 通知"| VC
        BT -->|"OtaUpdatePtl 代理回调"| VC
        VC -->|"startOta: 提交任务"| BT
        BT -->|"checkoutWith: 查询设备"| DM
        BT -->|"读取 assistDicts 会话"| BBM
        DM -->|"addDevicesWithSDKEntity:"| BBM
    end

    subgraph sg_BLE["BLE 物理层"]
        CB["CBCentralManager / CBPeripheral"]
    end

    subgraph sg_SDK["杰理 SDK"]
        JA["JL_Assist (每设备独立实例)"]
        JLE["JLBleEntity"]
    end

    BBM -->|"CoreBluetooth 代理"| CB
    BBM -->|"makeAssist: 创建会话"| JA
    BBM --> JA
    DM --> JLE
    CB -.->|"广播发现"| BBM

架构说明

  • 入口:UI 层(如 FittingView 相关控制器)向 BroadcastThread 提交一组 BroadcastOtaInfo(包含 cbp 外围设备与 updatePath 固件路径)。
  • 调度:BroadcastThread 首件立即执行、其余入队,next 在每件完成后推进队列。
  • 通道:升级命令经由 BroadcastBleManager 中按 UUID 缓存的 JL_Assist 实例下发到 AE00 服务 / AE01 写通道 / AE02 读通道。
  • 反馈:进度与结果通过 OtaUpdatePtl 代理(otaResultIsBegin:、otaResult:Status:Progress:)回传 UI。

核心模块实现

BroadcastBleManager —— BLE 会话与通知中枢

BroadcastBleManager 同时实现 CBCentralManagerDelegate 与 CBPeripheralDelegate,是广播升级的蓝牙底座。其对外状态全部以 NSNotification 形式发布,UI 层据此驱动界面:

NSString *kBDM_BLE_FOUND        = @"BDM_BLE_FOUND";            //发现设备
NSString *kBDM_BLE_PAIRED       = @"BDM_BLE_PAIRED";           //BLE已配对
NSString *kBDM_BLE_CONNECTED    = @"BDM_BLE_CONNECTED";        //BLE已连接
NSString *kBDM_BLE_DISCONNECTED = @"BDM_BLE_DISCONNECTED";     //BLE断开连接

NSString *BLE_SERVICE = @"AE00"; //服务号
NSString *BLE_RCSP_W  = @"AE01"; //命令"写"通道
NSString *BLE_RCSP_R  = @"AE02"; //命令"读"通道

Source: BroadcastBleManager.m

设计意图:AE00/AE01/AE02 是杰理 RCSP 协议的标准服务/特征 UUID。BroadcastBleManager 不直接依赖具体外设型号,而是把「服务号 + 读写特征」配置为常量,任何遵循该协议的音箱都能接入,这保证了广播批量升级的通用性。

会话创建(makeAssist:) 是连接成功后的关键步骤——为每个外设按 UUID 分配独立的 JL_Assist:

-(void)makeAssist:(CBPeripheral *)cbp{
    JL_Assist *assist = _assistDicts[cbp.identifier.UUIDString];
    if (assist){
        _mAssist = assist;
    }else{
        /*--- JLSDK ADD ---*/
        assist = [[JL_Assist alloc] init];
        [_assistDicts setValue:assist forKey:cbp.identifier.UUIDString];

        _mAssist = assist;
        _mAssist.mNeedPaired = [ToolsHelper isSupportPair];             //是否需要握手配对
        _mAssist.mPairKey    = nil;             //配对秘钥(或者自定义配对码pairData)
        _mAssist.mService    = BLE_SERVICE; //服务号
        _mAssist.mRcsp_W     = BLE_RCSP_W;  //特征「写」
        _mAssist.mRcsp_R     = BLE_RCSP_R;  //特征「读」
    }
}

Source: BroadcastBleManager.m

设计意图:mNeedPaired 由 [ToolsHelper isSupportPair] 决定,意味着「是否需要握手配对」是可配置的产品行为;mPairKey = nil 表示使用 SDK 默认配对逻辑,若需要自定义 16 字节配对码,可参考注释中 pairkey 数组改为传入 pairData。_assistDicts 缓存保证同一外设重连后复用既有会话,避免重复初始化。

扫描控制:startScanBLE 在 CBManagerStatePoweredOn 时才真正发起 scanForPeripheralsWithServices:nil,否则延迟 0.5 秒重试,处理了蓝牙未就绪的时序问题;stopScanBLE 立即停止扫描。

BroadcastThread —— OTA 串行调度器

BroadcastThread 是升级编排的核心,负责把一批设备排队、逐台执行,并把进度回调给所有注册的代理(delegates)。

队列初始化与并发闸门:

- (instancetype)init
{
    self = [super init];
    if (self) {
        _reconnectDict = [NSMutableDictionary new];
        self.senderThread = dispatch_queue_create("ota_thread", NULL);
        self.verifyList = [NSMutableArray new];
    }
    return self;
}

-(void)startOta:(NSArray <BroadcastOtaInfo*>*)items{
    self.verifyList = [NSMutableArray new];
    self.maxVerify = 1;
    for (BroadcastOtaInfo *objc in items) {
        if(self.maxVerify>1){
            [self.verifyList addObject:objc];
        }else{
            [self threadRun:objc];
        }
    }
}

-(void)next{
    self.maxVerify--;
    if(self.verifyList.count>0){
        BroadcastOtaInfo *objc = self.verifyList[0];
        [self threadRun:objc];
        [self.verifyList removeObject:objc];
    }
}

Source: BroadcastThread.m

设计意图:maxVerify 是典型的令牌计数闸门——startOta: 时置为 1,第一台设备直接进入 threadRun:(其中 maxVerify++ 变为 2),其余设备全部入队;每完成一台调用 next 递减令牌并取出队首执行。这样既实现了「首件立即执行」的体验优化,又严格保证 threadRun: 的并发度不超过 1。

单机升级执行(threadRun:):

-(void)threadRun:(BroadcastOtaInfo *)info{
    self.maxVerify++;
    JLDeviceInfo *device = [[DeviceManager share] checkoutWith:info.cbp];
    JL_Assist *assist = [[BroadcastBleManager sharedInstance] assistDicts][info.cbp.identifier.UUIDString];

    for (id<OtaUpdatePtl>item in self.delegates) {
        dispatch_async(dispatch_get_main_queue(), ^{
            if([item respondsToSelector:@selector(otaResultIsBegin:)]){
                [item otaResultIsBegin:info.cbp];
            }
        });
    }

    if(info){
        NSData *data = [NSData dataWithContentsOfFile:info.updatePath];
        if(assist == nil){
            for (id<OtaUpdatePtl>objc in self.delegates) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    if([objc respondsToSelector:@selector(otaResult:Status:Progress:)]){
                        [objc otaResult:info.cbp Status:JL_OTAResultFailTWSDisconnect Progress:0.0];
                    }
                });
            }
        }
        // ... 后续通过 assist 下发固件数据并上报进度
    }
}

Source: BroadcastThread.m

设计意图:threadRun: 首先从 DeviceManager 取出设备信息、从 BroadcastBleManager 取出对应 Assist 会话,然后立刻通过 otaResultIsBegin: 通知 UI「该设备升级开始」。若会话缺失(例如设备已断开导致 assistDicts 中无对应项),则直接以 JL_OTAResultFailTWSDisconnect 失败状态回调——这是一个防御性检查,避免对无通道的设备盲目发数据。所有 UI 回调都被 dispatch_async 到主队列,保证线程安全。

DeviceManager —— 设备注册表

DeviceManager 维护 JLDeviceInfo 数组,提供设备增删查操作:

-(void)addDevicesWithSDKEntity:(JL_EntityM *)entity{
    JLBleEntity *entityBasic = [[JLBleEntity alloc] init];
    entityBasic.mRSSI = entity.mRSSI;
    entityBasic.mPeripheral = entity.mPeripheral;
    entityBasic.bleMacAddress = entity.mBleAddr;
    entityBasic.mType = entity.mType;
    [self addDevicesEntity:entityBasic WithManager:entity.mCmdManager];
}

-(JLDeviceInfo * _Nullable)checkoutWith:(CBPeripheral *)peripheral{
    for (JLDeviceInfo *info in self.devices) {
        JLBleEntity *item = info.entity;
        if ([item.mPeripheral.identifier.UUIDString isEqualToString:peripheral.identifier.UUIDString]){
            return info;
        }
    }
    return nil;
}

Source: DeviceManager.m 与 DeviceManager.m

设计意图:addDevicesWithSDKEntity: 是 SDK 发现回调与本地注册表之间的适配器,将 SDK 的 JL_EntityM(含 mCmdManager 命令管理器)扁平化为 JLBleEntity + JL_ManagerM 组合;checkoutWith: 以 CBPeripheral.identifier.UUIDString 作为稳定主键(区别于 MAC 地址可能变化的情况)。JLDeviceInfo 还暴露了 cmdGetSystemInfo 等命令方法,供后续扩展读取设备系统信息。

核心工作流

端到端升级时序

sequenceDiagram
    participant UI as UI 层 (FittingView)
    participant BBM as BroadcastBleManager
    participant DM as DeviceManager
    participant BT as BroadcastThread
    participant SDK as JL_Assist / SDK
    participant DEV as 音箱 (CBPeripheral)

    UI->>BBM: startScanBLE
    BBM->>DEV: scanForPeripheralsWithServices
    DEV-->>BBM: 广播发现 (didDiscover)
    BBM-->>UI: 通知 kBDM_BLE_FOUND
    UI->>BBM: 发起连接
    BBM->>DEV: connectPeripheral
    DEV-->>BBM: didConnect
    BBM->>BBM: makeAssist: 按 UUID 创建 JL_Assist
    BBM-->>UI: 通知 kBDM_BLE_CONNECTED / kBDM_BLE_PAIRED
    BBM->>DM: addDevicesWithSDKEntity (注册设备)
    UI->>BT: startOta: [BroadcastOtaInfo...]
    BT->>BT: 首件 threadRun, 其余入 verifyList (maxVerify=1)
    BT->>DM: checkoutWith: cbp 查设备
    BT->>BBM: 读取 assistDicts[UUID] 会话
    BT-->>UI: otaResultIsBegin: 升级开始
    BT->>SDK: 经 mRcsp_W 下发固件数据 (updatePath)
    SDK->>DEV: RCSP 写通道 AE01
    DEV-->>SDK: 进度/结果 (读通道 AE02)
    SDK-->>BT: OTA 进度与状态回调
    BT-->>UI: otaResult:Status:Progress
    BT->>BT: next (maxVerify--, 弹出队首)
    Note over BT: 循环执行下一台设备

关键流程说明

  1. 发现与连接:BroadcastBleManager 扫描到设备后以 kBDM_BLE_FOUND 通知 UI;UI 选择目标设备发起连接。
  2. 会话建立:连接成功后在 makeAssist: 中按 UUID 创建/复用 JL_Assist,配置 AE00/AE01/AE02 服务特征,并按 ToolsHelper 开关决定是否握手配对。
  3. 设备注册:SDK 发现回调通过 DeviceManager addDevicesWithSDKEntity: 把 JL_EntityM 转为 JLDeviceInfo 入库。
  4. 批量入队:UI 组装 BroadcastOtaInfo 数组(每项含 cbp 与 updatePath)调用 startOta:;首件立即执行,其余进入 verifyList。
  5. 串行升级:threadRun: 逐台读取固件、经 Assist 下发;每台完成后 next 推进队列,直至全部完成。
  6. 结果反馈:任何一步失败(如 Assist 会话缺失)都会以 JL_OTAResultFailTWSDisconnect 回调,UI 可据此展示失败原因并继续下一台。

使用示例

提交一批设备的 OTA 升级

UI 层批量发起升级的入口调用(摘自 BroadcastThread 对外接口的实际使用方式):

// 组装升级任务数组:每项包含目标外设与固件路径
NSArray<BroadcastOtaInfo *> *items = [self buildOtaItems]; // items[i].cbp / items[i].updatePath
[[BroadcastThread share] startOta:items];

说明:BroadcastOtaInfo 携带 cbp(CBPeripheral)与 updatePath(固件文件路径),threadRun: 内部通过 [NSData dataWithContentsOfFile:info.updatePath] 读取固件。见 BroadcastThread.m。

注册 UI 代理接收进度

BroadcastThread 通过 delegates(实现 OtaUpdatePtl 协议)广播升级事件,UI 在收到 otaResultIsBegin: 时切换为升级中界面,在 otaResult:Status:Progress: 中更新进度条:

for (id<OtaUpdatePtl>item in self.delegates) {
    dispatch_async(dispatch_get_main_queue(), ^{
        if([item respondsToSelector:@selector(otaResultIsBegin:)]){
            [item otaResultIsBegin:info.cbp];       // 通知 UI:该设备升级开始
        }
    });
}

Source: BroadcastThread.m

监听蓝牙状态通知

UI 监听 BroadcastBleManager 发布的通知,驱动扫描/连接界面:

// 通知常量由 BroadcastBleManager.m 定义
NSString *kBDM_BLE_FOUND        = @"BDM_BLE_FOUND";        //发现设备
NSString *kBDM_BLE_PAIRED       = @"BDM_BLE_PAIRED";       //BLE已配对
NSString *kBDM_BLE_CONNECTED    = @"BDM_BLE_CONNECTED";    //BLE已连接
NSString *kBDM_BLE_DISCONNECTED = @"BDM_BLE_DISCONNECTED"; //BLE断开连接

Source: BroadcastBleManager.m

设备注册(SDK 发现回调适配)

-(void)addDevicesWithSDKEntity:(JL_EntityM *)entity{
    JLBleEntity *entityBasic = [[JLBleEntity alloc] init];
    entityBasic.mRSSI = entity.mRSSI;
    entityBasic.mPeripheral = entity.mPeripheral;
    entityBasic.bleMacAddress = entity.mBleAddr;
    entityBasic.mType = entity.mType;
    [self addDevicesEntity:entityBasic WithManager:entity.mCmdManager];
}

Source: DeviceManager.m

配置选项

广播升级子系统的可调配置集中在 BroadcastBleManager 的常量与 JL_Assist 属性上:

配置项类型默认值说明
BLE_SERVICENSString@"AE00"RCSP 服务号(UUID 前缀)
BLE_RCSP_WNSString@"AE01"命令「写」特征
BLE_RCSP_RNSString@"AE02"命令「读」特征
assist.mNeedPairedBOOL[ToolsHelper isSupportPair]是否需要握手配对,由工具类开关决定
assist.mPairKeyNSDatanil配对秘钥;nil 走 SDK 默认配对,可传 16 字节自定义配对码
maxVerifyNSInteger1(启动时)并发闸门,恒为 1 保证串行升级
senderThreaddispatch_queue_t"ota_thread"OTA 数据发送专用串行队列

API 参考

BroadcastBleManager

方法/属性签名要点说明
sharedInstance+ (instancetype)sharedInstance全局单例,dispatch_once 保证只初始化一次
init- (instancetype)init初始化 CBCentralManager(delegate 为 self)、assistDicts、blePeripheralArr、connectDict
makeAssist:- (void)makeAssist:(CBPeripheral *)cbp按外设 UUID 创建或复用 JL_Assist 会话,配置服务/特征与配对参数
startScanBLE- (void)startScanBLE蓝牙就绪后开始扫描(scanForPeripheralsWithServices:nil),未就绪则延迟 0.5s 重试
stopScanBLE- (void)stopScanBLE停止扫描
assistDictsNSMutableDictionary以 UUIDString 为 key 的 JL_Assist 会话表,供 BroadcastThread 读取

通知(NSNotificationCenter 广播):

通知名含义
kBDM_BLE_FOUND发现新设备(BDM_BLE_FOUND)
kBDM_BLE_PAIREDBLE 已完成配对握手(BDM_BLE_PAIRED)
kBDM_BLE_CONNECTEDBLE 已连接(BDM_BLE_CONNECTED)
kBDM_BLE_DISCONNECTEDBLE 断开连接(BDM_BLE_DISCONNECTED)

BroadcastThread

方法签名要点说明
share+ (instancetype)share全局单例
startOta:- (void)startOta:(NSArray<BroadcastOtaInfo *> *)items批量提交升级任务:重置队列与 maxVerify=1,首件立即执行,其余入队
next- (void)next递减 maxVerify,弹出队首任务继续执行;无任务时保持空闲
threadRun:- (void)threadRun:(BroadcastOtaInfo *)info单台设备升级执行体:查设备、取 Assist、读固件、回调开始/进度/结果
delegatesNSArray<id<OtaUpdatePtl>>升级事件代理列表,UI 注册后接收回调

代理协议 OtaUpdatePtl 回调(均在主队列派发):

  • otaResultIsBegin:(CBPeripheral *)cbp:某设备升级开始。
  • otaResult:(CBPeripheral *)cbp Status:(JL_OTAResult)status Progress:(float)progress:升级状态与进度,status 取值含 JL_OTAResultFailTWSDisconnect(会话缺失/断开导致的失败)等 SDK 枚举。

DeviceManager / JLDeviceInfo

方法签名要点说明
share+ (instancetype)share全局单例,持有 devices 数组
addDevicesWithSDKEntity:- (void)addDevicesWithSDKEntity:(JL_EntityM *)entitySDK 发现回调适配:JL_EntityM → JLBleEntity 并入库
addDevicesEntity:WithManager:- (void)addDevicesEntity:(JLBleEntity *)entity WithManager:(JL_ManagerM *)manager按 UUID 去重后新增 JLDeviceInfo
removeDevicesBy:- (void)removeDevicesBy:(CBPeripheral *)cbp按外设移除注册项
checkoutWith:- (JLDeviceInfo * _Nullable)checkoutWith:(CBPeripheral *)peripheral按 UUID 查询设备,未找到返回 nil
JLDeviceInfo.test- (void)test示例命令:cmdGetSystemInfo:JL_FunctionCodeCOMMON SelectionBit:0x4000 读取系统信息

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

失败模式

  1. Assist 会话缺失(升级前检查):threadRun: 中 assist 为 nil 时直接回调 JL_OTAResultFailTWSDisconnect,不发送任何数据。触发条件通常是设备在入队后、执行前断开,或 makeAssist: 尚未完成。
  2. 固件文件读取失败:[NSData dataWithContentsOfFile:info.updatePath] 返回空数据时后续升级自然失败;调用方需保证 updatePath 指向有效文件。
  3. 蓝牙未就绪扫描:startScanBLE 在 CBManagerStatePoweredOn 之前调用会延迟 0.5s 重试一次,但仍可能在系统蓝牙关闭时扫描无果——UI 应结合系统蓝牙状态提示用户。

边界情况

  • 重复注册:addDevicesEntity:WithManager: 以 identifier.UUIDString 去重,同一外设不会重复入库;但若同一设备重新广播,SDK 可能生成新 CBPeripheral 对象,UUID 保持不变时仍可命中缓存。
  • 断开后的队列:next 不感知设备连接状态,队列会继续推进到下一台;失败设备的状态通过代理回调告知 UI,由 UI 决定是否重试。
  • 空任务数组:startOta: 传入空数组时仅重置队列与闸门,不执行任何升级,行为安全。

并发与线程安全

  • 串行执行保证:maxVerify 令牌闸门确保 threadRun: 并发度 ≤ 1,避免多台音箱的 RCSP 命令在蓝牙链路上交错。
  • 独立会话隔离:每台设备持有独立的 JL_Assist(assistDicts[UUID]),命令序号(SN)互不干扰。
  • UI 回调线程:所有 OtaUpdatePtl 回调均 dispatch_async 到主队列,UI 无需额外加锁。
  • 发送队列:固件数据发送运行在专用串行队列 "ota_thread" 上,与主线程解耦;但该队列与 CoreBluetooth 代理回调(queue:nil 即主队列)之间的同步依赖 SDK 内部机制,扩展时不宜在代理回调中直接阻塞等待升级完成。

性能与运维注意事项

  • 数据发送吞吐:固件下发走 AE01 写通道,实际速率受 BLE MTU 与 JL_Assist 分片策略约束;串行设计使单设备吞吐最大化,但总时长随设备数量线性增长,批量场景需在 UI 上展示「第 N 台 / 共 M 台」。
  • 内存占用:threadRun: 一次性 dataWithContentsOfFile: 读入整个固件,大固件(数 MB)会瞬时占用较多内存;广播场景若同时缓存多份固件需注意内存水位。
  • 扫描功耗:startScanBLE 使用 scanForPeripheralsWithServices:nil 全量扫描,持续扫描耗电较高,建议在连接目标设备后立即 stopScanBLE。
  • 重连缓存:BroadcastBleManager 维护 lastUUID、lastBleMacAddressList、connectDict 等重连辅助数据,说明系统支持断线重连的运维预期;具体重连策略由 CBCentralManagerDelegate 回调驱动。

扩展点

  1. OtaUpdatePtl 代理协议:UI 层实现该协议即可接入升级进度,无需改动调度逻辑;多代理注册可同时驱动多个界面(如列表页 + 详情页)。
  2. 自定义配对码:在 makeAssist: 中将 mPairKey 设为自定义 16 字节 pairData(代码中有注释示例),可适配需要固定配对码的产线/渠道设备。
  3. ToolsHelper isSupportPair:作为「是否需要握手配对」的全局开关,修改该工具方法即可在不改升级流程的情况下切换新旧协议设备。
  4. DeviceManager 设备注册:JLDeviceInfo 的 test 方法展示了基于 cmdGetSystemInfo 扩展设备信息查询的范式,可在升级前做型号/固件版本校验。
  5. maxVerify 闸门语义:当前恒为 1 实现严格串行;若未来协议支持并发通道,可将 maxVerify 提升为可配置值以支持「N 台并行」。

测试与验证建议

仓库内该目录未提供独立单元测试文件,验证主要依赖真机联调:

  • 单台冒烟:连接一台音箱,提交单元素数组,验证 otaResultIsBegin: → 进度递增 → 成功回调的完整链路。
  • 批量串行验证:连接 2~3 台设备,观察 threadRun: 是否严格逐台执行(可通过 maxVerify 日志或设备端日志确认无并发)。
  • 断线注入:升级中途断开设备,验证 assist 缺失分支回调 JL_OTAResultFailTWSDisconnect 且队列继续推进。
  • 配对开关:切换 ToolsHelper isSupportPair,验证 kBDM_BLE_PAIRED 通知在两种模式下均能正确触发。

Related Links

  • 广播音箱 BLE 管理器源码(扫描/连接/会话:BroadcastBleManager.m)
  • 广播音箱 OTA 调度器源码(队列与串行升级:BroadcastThread.m)
  • 设备注册表源码(DeviceManager.m / JLDeviceInfo)
  • 相关能力页:单设备 OTA 流程(SDKBleManager/JL_RunSDK.m、SDKBleHelper.m)、通用 BLE 管理(BleManager/JLBleManager.m)、SDK 命令协助(BleManager/JLBleEntity.m)
Prev
自动化测试与批量升级
Next
升级文件管理