杰理 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_AdvParse 广播包解析

JL_AdvParse 是杰理(Jieli)iOS 蓝牙 SDK 中用于解析 BLE 广播包的独立 XCFramework,负责将 CoreBluetooth 扫描到的原始广播字典(advertData)解析为结构化结果,并识别设备类型(音箱、TWS 耳机、充电仓、声卡、手表等),同时提供 OTA 升级回连场景下从广播包中提取蓝牙地址的辅助能力。

Purpose and Scope

本页面完整介绍 JL_AdvParse.xcframework 的公共 API 契约、类型体系、设备子模块划分与解析架构,覆盖:

  • 框架的交付形态(XCFramework、支持平台、依赖关系)
  • JL_AdvType / JL_DeviceType 两种设备类型枚举及其设计差异
  • JLAdvParse 入口类的全部公开方法(广播解析、RSSI 扩展、OTA 回连辅助)
  • 8 个设备类型子模块(JLDevicesAdv、JLTwsAdv、JLSoundBoxAdv、JLSoundCardAdv、JLChargingBoxAdv、JLEarphoneAdv、JLWatchAdv、JLOtaAdv)的职责划分
  • 解析流程、失败模式、线程安全与扩展方式

边界说明:本页面只覆盖广播包解析这一能力。JLAdvParse 框架内部的解析算法以编译后二进制形式交付,本仓库仅含头文件,因此本文档基于公开头文件契约展开,内部实现细节在源码中不可见时会明确标注。与此相邻但不在本页面范围内的能力包括:蓝牙连接管理(JL_BLE)、设备管理(JL_Manager)与 OTA 升级(JL_OT)等,请参见对应目录的独立页面。

概述

在 BLE 设备接入流程中,App 通过 CBCentralManager 扫描到设备后会拿到一个广播字典(包含 kCBAdvDataManufacturerData、kCBAdvDataLocalName 等键值)。不同品类的杰理设备(AI 音箱、TWS 耳机、充电仓、声卡、手表、传统设备)在广播包中编码的厂商数据格式各不相同,如果由每个业务 App 自行解析,会产生大量重复且易错的代码。

JLAdvParse 的设计意图正是把广播包解析从业务层抽离为单一职责的公共组件:

  1. 统一入口:App 只需调用 +bluetoothAdvParse:AdvData: 或 +bluetoothAdvData:RSSI:,传入 CoreBluetooth 的广播字典,即可拿到结构化结果;
  2. 类型分发:框架内部根据厂商数据判定设备类型,并分发到对应的子模块(JLTwsAdv、JLSoundBoxAdv 等)做品类定制化解析;
  3. OTA 回连支持:OTA 升级过程中设备会短暂断连,App 需要依据广播包中 JLOTA 标识的厂商数据里的蓝牙地址完成回连,框架为此提供 otaBleMacAddressFromCBAdvDataManufacturerData: 等专门方法;
  4. 无状态设计:所有 API 均为类方法,无实例状态,天然适合在扫描回调中高频调用。

架构

flowchart TD
    subgraph sg_App["App 层 (CoreBluetooth)"]
        CB["CBCentralManager<br/>扫描得到的 advertData 字典"]
    end

    subgraph sg_Framework["JL_AdvParse.xcframework"]
        Entry["JLAdvParse 入口<br/>bluetoothAdvParse:AdvData:<br/>bluetoothAdvData:RSSI:"]
        subgraph sg_Modules["设备类型子模块"]
            DevAdv["JLDevicesAdv"]
            TwsAdv["JLTwsAdv"]
            SoundBox["JLSoundBoxAdv"]
            SoundCard["JLSoundCardAdv"]
            ChargingBox["JLChargingBoxAdv"]
            Earphone["JLEarphoneAdv"]
            Watch["JLWatchAdv"]
            Ota["JLOtaAdv"]
        end
        Result["NSDictionary<br/>结构化解析结果"]
        TypeEnum["JL_AdvType / JL_DeviceType<br/>设备类型枚举"]
        OtaHelper["OTA 回连辅助<br/>otaBleMacAddress 系列方法"]
    end

    subgraph sg_Dep["外部依赖"]
        Log["JLLogHelper"]
        CBKit["Foundation / CoreBluetooth"]
    end

    CB -->|"广播字典"| Entry
    Entry --> DevAdv
    Entry --> TwsAdv
    Entry --> SoundBox
    Entry --> SoundCard
    Entry --> ChargingBox
    Entry --> Earphone
    Entry --> Watch
    Entry --> Ota
    Entry --> Result
    Entry --> TypeEnum
    Entry --> OtaHelper
    Entry -.->|"日志"| Log
    Entry -.-> CBKit

架构说明:

  • 入口层 JLAdvParse:对外暴露的全部能力集中在 JLAdvParse.h 中,包括两个解析入口和两个 OTA 辅助方法。所有方法均为 + 类方法,调用方无需持有实例。
  • 设备类型子模块:伞头文件 JL_AdvParse.h 依次导入 JLDevicesAdv、JLTwsAdv、JLSoundBoxAdv、JLSoundCardAdv、JLChargingBoxAdv、JLEarphoneAdv、JLWatchAdv、JLOtaAdv 八个头文件,每个子模块对应一类设备的广播数据模型,是"按品类扩展"的天然扩展点。
  • 结果形态:解析结果统一以 NSDictionary 返回,便于与既有 KVC/字典桥接代码集成;设备类型通过枚举常量表达,避免魔法数字。
  • 依赖:框架依赖 JLLogHelper(日志组件,见 JLAdvParse.h 的 import 语句)与 Foundation 框架;广播字典的键名遵循 CoreBluetooth 的 kCBAdvData* 约定。

交付形态:仓库中 JL_AdvParse.xcframework 包含 ios-arm64(真机)、ios-arm64_x86_64-simulator(模拟器)与 macos-arm64_x86_64(macOS)三个平台切片,头文件位于各切片的 Headers/ 目录下;主版本号通过 JL_AdvParseVersionNumber / JL_AdvParseVersionString 导出。

核心类型体系

JL_AdvType 广播类型枚举

JL_AdvType 定义在 JLAdvParse.h 第 14-22 行,是一个 UInt8 基础类型的枚举,描述广播包层面可识别的设备品类:

typedef NS_ENUM(UInt8,JL_AdvType) {
    JL_AdvTypeSoundBox              = 0,     //音箱类型
    JL_AdvTypeChargingBin           = 1,     //充电仓类型
    JL_AdvTypeTWS                   = 2,     //TWS耳机类型
    JL_AdvTypeHeadset               = 3,     //普通耳机类型
    JL_AdvTypeSoundCard             = 4,     //声卡类型
    JL_AdvTypeWatch                 = 5,     //手表类型
    JL_AdvTypeTradition             = 6,     //传统设备类型
};

Source: JLAdvParse.h

该枚举取值紧凑(0-6),适合作为解析结果的类型标签写入字典。注意它不含 Dongle 类型——Dongle 只在设备级枚举 JL_DeviceType 中出现。

JL_DeviceType 设备类型枚举

JL_DeviceType 定义在 JLAdvParse.h 第 25-34 行,基础类型为 NSInteger,语义上表示设备整体类型:

typedef NS_ENUM(NSInteger,JL_DeviceType) {
    JL_DeviceTypeSoundBox           = 0,     //AI音箱类型
    JL_DeviceTypeChargingBin        = 1,     //充电仓类型
    JL_DeviceTypeTWS                = 2,     //TWS耳机类型
    JL_DeviceTypeHeadset            = 3,     //普通耳机类型
    JL_DeviceTypeSoundCard          = 4,     //声卡类型
    JL_DeviceTypeWatch              = 5,     //手表类型
    JL_DeviceTypeDongle             = 6,     //Dongle
    JL_DeviceTypeTradition          = -1,    //传统设备类型
};

Source: JLAdvParse.h

两种枚举的设计差异(WHY)

维度JL_AdvTypeJL_DeviceType
基础类型UInt8(1 字节)NSInteger(平台字长)
品类覆盖7 种(0-6),无 Dongle8 种(-1、0-6),含 Dongle
传统设备取值6(正数,可纳入位段/序列化)-1(哨兵值,表示"无法归类")
设计意图广播包解析阶段的紧凑类型标签设备管理阶段的完整类型判定

两个枚举并存并非冗余:广播包解析阶段,JL_AdvType 作为紧凑的 UInt8 标签,便于编码进厂商数据结构或作为字典键;而 JL_DeviceType 面向设备管理语义,用 -1 作为"传统设备"哨兵、用 6 表示 Dongle,避免与广播标签语义混淆。App 在拿到解析结果后,应依据业务场景选择对应枚举做类型判断。

JLAdvParse 入口 API 详解

JLAdvParse 是框架唯一对外暴露的入口类(JLAdvParse.h 第 38 行起),全部为类方法。

版本查询

/// 打印当前SDK的版本
+(void)sdkVersion;

Source: JLAdvParse.h

+sdkVersion 在控制台打印框架版本,用于集成排查。版本号同时以 JL_AdvParseVersionNumber(double)与 JL_AdvParseVersionString(const unsigned char[])两个符号导出(JL_AdvParse.h 第 12-15 行)。

广播包解析(基础入口)

/// 解析设备广播包内容
/// @param key 过滤码(只针对传统设备生效,默认填空即可)
/// @param advertData 蓝牙广播字典
+(NSDictionary*)bluetoothAdvParse:(NSData *_Nullable)key AdvData:(NSDictionary*_Nonnull)advertData;

Source: JLAdvParse.h

设计要点:

  • advertData 为 _Nonnull——调用方必须传入 CoreBluetooth 扫描回调(didDiscoverPeripheral)中的 advertisementData 字典,该字典包含 kCBAdvDataManufacturerData、kCBAdvDataLocalName、kCBAdvDataServiceUUIDs 等键;
  • key 为 _Nullable 过滤码,仅对传统设备(JL_AdvTypeTradition)生效。传统设备没有标准厂商 ID 头,需要靠业务方传入自定义匹配码来识别;对现代品类设备传 nil(默认填空)即可;
  • 返回 NSDictionary*:解析成功时返回包含设备类型、厂商数据等结构化信息的字典;无法识别时返回空字典(非 nil),调用方需自行判空。

广播包解析(含 RSSI)

/// 解析蓝牙广播包
/// @param advertData 蓝牙广播报字典
/// @param rssi 蓝牙信号强度
+(NSDictionary *)bluetoothAdvData:(NSDictionary *)advertData RSSI:(NSNumber *)rssi;

Source: JLAdvParse.h

该重载在基础解析之上附加 rssi(信号强度,NSNumber)。设计意图是:扫描阶段 App 往往需要"解析结果 + 信号强度"一起做连接决策(如就近选机、自动回连),一次调用同时拿到两者可减少重复扫描与状态同步成本。rssi 同样来自 didDiscoverPeripheral 回调的 RSSI 参数。

OTA 回连辅助方法

+ (NSString * _Nullable)otaBleMacAddressFromCBAdvDataManufacturerData:(NSData *)kCBAdvDataManufacturerData;

+ (Boolean)otaBleMacAddress:(NSString *)otaBleMacAddress isEqualToCBAdvDataManufacturerData:(NSData *)kCBAdvDataManufacturerData;

Source: JLAdvParse.h

这两个方法专门服务于 OTA 升级回连场景:升级过程中设备会重新上电并广播,其广播包 kCBAdvDataManufacturerData 中带有 JLOTA 标识及蓝牙地址。App 在扫描到新广播时,可以用:

  • otaBleMacAddressFromCBAdvDataManufacturerData: 从厂商数据中提取 JLOTA 标识对应的蓝牙地址字符串;提取不到时返回 nil;
  • otaBleMacAddress:isEqualToCBAdvDataManufacturerData: 判断"OTA 升级中设备的蓝牙地址"是否与当前广播包厂商数据中的地址一致,返回 Boolean(true/false),用于精确匹配回连目标。

这一对方法将"OTA 重连目标识别"这一高频易错逻辑收敛进框架,避免各业务 App 重复实现厂商数据字节解析。

设备类型子模块

伞头文件 JL_AdvParse.h 按品类导入了 8 个数据模型头文件:

头文件对应品类与枚举的映射
JLDevicesAdv.h通用设备广播数据基类/通用字段各品类共用
JLTwsAdv.hTWS 真无线耳机JL_AdvTypeTWS / JL_DeviceTypeTWS
JLSoundBoxAdv.hAI 音箱JL_AdvTypeSoundBox / JL_DeviceTypeSoundBox
JLSoundCardAdv.h声卡JL_AdvTypeSoundCard / JL_DeviceTypeSoundCard
JLChargingBoxAdv.h充电仓JL_AdvTypeChargingBin / JL_DeviceTypeChargingBin
JLEarphoneAdv.h普通耳机JL_AdvTypeHeadset / JL_DeviceTypeHeadset
JLWatchAdv.h手表JL_AdvTypeWatch / JL_DeviceTypeWatch
JLOtaAdv.hOTA 广播数据供回连辅助方法使用

这些子模块各自封装对应品类的厂商数据布局(电量、名称、左右耳状态、配对状态等字段),由 JLAdvParse 按识别出的类型分发解析。各子模块的字段级定义位于各自头文件中,本仓库以编译后二进制交付,字段明细请以 XCFramework 内对应 Headers/*.h 为准。

核心解析流程

广播解析时序

sequenceDiagram
    participant App as App (CBCentralManager)
    participant JL as JLAdvParse
    participant Sub as 设备类型子模块
    participant Dict as NSDictionary 结果

    App->>JL: bluetoothAdvParse:key AdvData:advertData
    activate JL
    JL->>JL: 读取 kCBAdvDataManufacturerData 厂商数据
    JL->>JL: 判定设备类型 (JL_AdvType 0-6)
    alt 传统设备 (JL_AdvTypeTradition)
        JL->>JL: 用 key 过滤码匹配识别
    end
    JL->>Sub: 按类型分发到对应子模块
    Sub-->>JL: 品类字段结构化结果
    JL-->>Dict: 返回解析字典
    deactivate JL

    App->>JL: bluetoothAdvData:advertData RSSI:rssi
    activate JL
    JL-->>App: 附带 RSSI 的解析字典
    deactivate JL

    App->>JL: otaBleMacAddressFromCBAdvDataManufacturerData:data
    activate JL
    JL-->>App: JLOTA 标识对应的蓝牙地址 或 nil
    deactivate JL

设备类型判定流程

flowchart TD
    Start([扫描到广播]) --> Data["advertData 字典"]
    Data --> HasMfr{"kCBAdvDataManufacturerData<br/>存在?"}
    HasMfr -->|"否"| Unknown["返回空字典<br/>无法识别类型"]
    HasMfr -->|"是"| OtaMark{"含 JLOTA 标识?"}
    OtaMark -->|"是"| Ota["提取 OTA 蓝牙地址<br/>otaBleMacAddress 系列"]
    OtaMark -->|"否"| Classify{"厂商数据判定类型"}
    Classify -->|"0"| SoundBox["SoundBox 音箱"]
    Classify -->|"1"| Charging["ChargingBin 充电仓"]
    Classify -->|"2"| Tws["TWS 耳机"]
    Classify -->|"3"| Headset["普通耳机"]
    Classify -->|"4"| SoundCard["声卡"]
    Classify -->|"5"| Watch["手表"]
    Classify -->|"6 / 无法判定"| Tradition{"传统设备?"}
    Tradition -->|"是"| KeyMatch{"key 过滤码匹配?"}
    KeyMatch -->|"匹配"| Trad["传统设备解析成功"]
    KeyMatch -->|"不匹配"| Unknown
    Tradition -->|"否"| Unknown
    SoundBox --> Done["按品类返回结构化字典"]
    Charging --> Done
    Tws --> Done
    Headset --> Done
    SoundCard --> Done
    Watch --> Done
    Trad --> Done

流程要点:

  1. 厂商数据优先:解析的核心输入是 kCBAdvDataManufacturerData,缺少该键时无法完成类型判定,返回空字典——这解释了为什么 advertData 被标记为 _Nonnull;
  2. 类型分发:框架从厂商数据字节中判定 JL_AdvType,再路由到对应子模块做字段级解析;
  3. 传统设备兜底:无法从厂商数据判定标准品类时,进入传统设备分支,依赖调用方传入的 key 过滤码完成匹配——这是 key 参数"只针对传统设备生效"的原因;
  4. OTA 特判:JLOTA 标识的厂商数据不走品类解析,而是走回连地址提取路径,保证升级场景的快速重连。

使用示例

说明:JL_AdvParse 以二进制 XCFramework 交付,本仓库未包含 Demo 调用点(对 bluetoothAdvParse / bluetoothAdvData 的 .m/.mm/.swift 引用检索无结果)。以下示例取自框架公开头文件本身的 API 声明,调用方式按头文件注释契约说明。

基础广播解析(扫描回调中)

在 CBCentralManagerDelegate 的 didDiscoverPeripheral 回调中,将系统提供的广播字典直接传入:

- (void)centralManager:(CBCentralManager *)central
 didDiscoverPeripheral:(CBPeripheral *)peripheral
     advertisementData:(NSDictionary<NSString *, id> *)advertisementData
                  RSSI:(NSNumber *)RSSI
{
    // key 仅对传统设备生效,现代品类设备传 nil 即可
    NSDictionary *advInfo = [JLAdvParse bluetoothAdvParse:nil
                                                 AdvData:advertisementData];
    // advInfo 包含设备类型等信息,nil 判断由调用方处理
    if (advInfo.count > 0) {
        // 按 JL_AdvType / JL_DeviceType 枚举值处理不同品类
    }
}

对应入口声明见 JLAdvParse.h。

携带 RSSI 的解析(连接决策场景)

// 同时获得解析结果与信号强度,用于就近选机或自动回连
NSDictionary *advData = [JLAdvParse bluetoothAdvData:advertisementData
                                                RSSI:RSSI];

对应入口声明见 JLAdvParse.h。

OTA 升级回连匹配

// 1) 从新扫描到的厂商数据中提取 JLOTA 标识的蓝牙地址
NSString *mac = [JLAdvParse otaBleMacAddressFromCBAdvDataManufacturerData:
                    advertisementData[CBAdvertisementDataManufacturerDataKey]];
// mac 可能为 nil(非 OTA 广播)

// 2) 与正在 OTA 的设备地址精确比对,决定是否发起回连
Boolean matched = [JLAdvParse otaBleMacAddress:otaDeviceMac
             isEqualToCBAdvDataManufacturerData:
                    advertisementData[CBAdvertisementDataManufacturerDataKey]];

对应声明见 JLAdvParse.h。

API 参考

+ (void)sdkVersion

打印当前框架版本到控制台。无参数、无返回值。用于集成与排障。

+ (NSDictionary *)bluetoothAdvParse:(NSData * _Nullable)key AdvData:(NSDictionary * _Nonnull)advertData

解析设备广播包内容(基础入口)。

参数:

  • key(NSData?):过滤码,仅对传统设备生效,默认传 nil;
  • advertData(NSDictionary,非空):CoreBluetooth 广播字典(advertisementData)。

返回: 结构化解析结果字典;无法识别时返回空字典(调用方需判空)。

约束:

  • advertData 违反 _Nonnull 契约(传 nil)属未定义行为,应避免。

+ (NSDictionary *)bluetoothAdvData:(NSDictionary *)advertData RSSI:(NSNumber *)rssi

解析蓝牙广播包并附加信号强度。

参数:

  • advertData(NSDictionary):蓝牙广播字典;
  • rssi(NSNumber):信号强度(来自扫描回调的 RSSI)。

返回: 附带 RSSI 信息的解析结果字典。

+ (NSString * _Nullable)otaBleMacAddressFromCBAdvDataManufacturerData:(NSData *)kCBAdvDataManufacturerData

从广播包 kCBAdvDataManufacturerData 中提取 JLOTA 标识的蓝牙地址。

参数:

  • kCBAdvDataManufacturerData(NSData):广播包厂商数据。

返回: 蓝牙地址字符串;非 OTA 广播或提取失败时返回 nil。

+ (Boolean)otaBleMacAddress:(NSString *)otaBleMacAddress isEqualToCBAdvDataManufacturerData:(NSData *)kCBAdvDataManufacturerData

判断给定蓝牙地址是否等于广播包厂商数据中的地址。

参数:

  • otaBleMacAddress(NSString):OTA 升级中设备的蓝牙地址;
  • kCBAdvDataManufacturerData(NSData):广播包厂商数据。

返回: true(匹配)/ false(不匹配或数据缺失)。

失败模式与边界情况

基于公开 API 契约,以下边界情况需要调用方特别注意:

场景表现处理建议
advertData 为 nil违反 _Nonnull 契约,行为未定义扫描回调中系统保证非空;自行构造字典时先判空
广播包无 kCBAdvDataManufacturerData 键无法判定类型,返回空字典用 advInfo.count > 0 判空后再使用结果
非杰理设备的广播类型无法识别,走传统设备兜底不传 key 时大概率返回空字典,属预期行为
传统设备未传 key 或 key 不匹配匹配失败,返回空字典按头文件注释"默认填空即可",仅传统设备场景才需传入过滤码
非 OTA 广播调用 otaBleMacAddressFrom...:返回 nil调用方必须先判空再使用返回值
otaBleMacAddress:isEqualTo...: 输入地址与厂商数据地址不一致返回 false用于精确匹配回连目标,比对失败不应直接断连现有链路
模拟器/平台切片不匹配链接失败或运行时崩溃按运行目标选择 ios-arm64(真机)、ios-arm64_x86_64-simulator(模拟器)或 macos-arm64_x86_64 切片

并发与线程安全

  • 无状态设计:JLAdvParse 全部为类方法,无实例变量、无可变共享状态,因此天然线程安全——可在 CBCentralManagerDelegate 回调线程(不一定为主线程)中直接调用,无需加锁;
  • 高频调用友好:扫描回调可能以较高频率触发,解析为纯内存字典操作,无 I/O 阻塞,可放心在回调中同步调用;
  • 调用方职责:返回的 NSDictionary 若被多个线程共享使用,仍由调用方自行保证读写互斥(与框架无关)。

性能与运维

  • 时延:广播解析是纯 CPU 内存操作,单次开销极小(微秒级),扫描回调中同步调用不会造成明显卡顿;
  • 内存:解析结果仅为小字典对象,无缓存、无长生命周期对象,不会产生内存增长问题;
  • 日志:框架依赖 JLLogHelper(见 JLAdvParse.h 第 10 行),集成时需同时引入该日志组件,否则链接失败;
  • 版本核对:通过 +sdkVersion 或导出符号 JL_AdvParseVersionNumber / JL_AdvParseVersionString 确认集成版本,避免与固件广播格式不匹配导致解析异常;
  • 分发:以 XCFramework 形式同时覆盖 iOS 真机、模拟器与 macOS,配合 Swift Package / CocoaPods 均可集成。

扩展点

  1. 品类子模块扩展:伞头文件(JL_AdvParse.h)按品类导入 JLDevicesAdv、JLTwsAdv、JLSoundBoxAdv、JLSoundCardAdv、JLChargingBoxAdv、JLEarphoneAdv、JLWatchAdv、JLOtaAdv,新品类设备接入时可在对应子模块中扩展字段解析;
  2. 过滤码机制:key 参数为传统设备提供业务侧自定义匹配入口,适配非标准广播格式时无需改动框架;
  3. 结果字典桥接:统一 NSDictionary 返回便于与 KVC、JSON 序列化、Swift 桥接无缝衔接,业务层可在此基础上二次封装为强类型模型;
  4. OTA 回连协议:JLOTA 标识与地址提取逻辑封装在框架内,固件侧若调整标识字节,仅需升级框架版本,业务代码无需变更。

相关链接

  • 框架伞头文件:JL_AdvParse.h
  • 核心解析 API:JLAdvParse.h
  • 相关页面:蓝牙连接管理(JL_BLE)、设备管理(JL_Manager)、OTA 升级(JL_OT)——详见 SDK 框架目录下对应文档
Prev
JL_BLEKit 蓝牙通信核心
Next
JL_HashPair 加密配对