杰理 SDK 文档中心
首页
首页
  • 概述与快速开始

    • 仓库概览
    • 运行环境与 SDK 集成
    • 工程结构与目录导航
  • 核心 SDK 架构

    • SDK 库体系与模块划分
    • 蓝牙连接与 RCSP 协议
    • 广播包解析与设备认证
    • 日志助手与调试支持
  • 设备功能模块

    • OTA 固件升级
    • 表盘管理与自定义表盘
    • 图像转换工具
    • 资源打包
    • 音频编解码
    • 健康与运动数据同步
    • 消息通知与实用设备功能
  • 宜动健康示例应用

    • 应用架构与页面导航
    • 健康界面与数据可视化
    • 设备连接与数据同步
    • 登录注册与用户中心
    • AI 云服务与语音交互
    • 本地数据库与持久化
    • 多语言国际化
  • 测试与调试

    • SDKTestHelper 功能测试工具
    • 音频编解码示例工程
    • 调试技巧与问题排查
  • 文档与资源

    • 在线文档与版本历史
    • 第三方框架与依赖管理

蓝牙连接与 RCSP 协议

本文档深入解析 iOS-JL_Health 项目中杰理(Jieli)BLE 芯片生态的核心通信链路:蓝牙连接管理与 RCSP(杰理私有命令协议)。内容涵盖协议包结构、数据编解码、连接生命周期、命令分发中心以及功能管理器的协作机制,全部基于 JL_BLEKit.framework 公开头文件中的真实声明。

Purpose and Scope

本页面向需要理解或扩展 App 与杰理设备(耳机、音箱、穿戴设备)通信链路的开发者,说明:

  • RCSP 协议包(JL_PKG)的二进制结构、生成与解析规则;
  • JL_Assist 蓝牙连接助手如何完成扫描过滤、服务/特征发现、设备认证与数据收发;
  • JL_ManagerM 命令中心如何按 OpCode 分发命令,并挂载各功能管理器;
  • JL_BLEAction 提供的广播过滤、配对、OTA 回连与数据通知能力;
  • 与 RCSP 相关的配置项(服务号、特征 UUID、MTU、认证密钥等)。

不覆盖的内容(属于兄弟页面):具体业务功能管理器(如 JL_FileManager 文件管理、JL_OTAManager 固件升级、JL_TwsManager 双耳、JL_AlarmClockManager 闹钟等)的内部实现;外围设备扫描与界面层逻辑;AI 语音助手(AIKIT)相关能力。这些模块仅在本页提及其挂载关系,供读者按图索骥。

Overview

iOS-JL_Health 通过 CoreBluetooth 与杰理芯片设备通信。杰理私有协议 RCSP(参考代码中的 JL_RCSP 类)承载了绝大多数设备控制命令:音量、EQ、ANC、音乐控制、文件传输、OTA 等,全部功能管理器最终都通过统一的 RCSP 命令包与设备交互。

整个链路可抽象为三层:

  1. BLE 传输层:JL_Assist 负责 CoreBluetooth 生命周期(状态回调、特征发现、MTU 协商、分包发送),把 RCSP 数据包写入 RCSP 写特征,并从读特征(Notify)接收设备回包;
  2. 协议编解码层:JL_RCSP 把上层命令模型(JL_PKG)编码为字节流,或把设备回包解码回 JL_PKG;
  3. 命令分发层:JL_ManagerM 维护命令序号 mCmdSN、接收 inputPKG: 入包,按 OpCode 分发给对应功能管理器,并通过 NSNotification(如 kJL_RCSP_RECEIVE / kJL_RCSP_SEND)广播给业务层。

RCSP 之所以采用"1 字节 OpCode + 参数区"的紧凑设计,是因为 BLE 单包 MTU 通常只有 20~244 字节,协议必须尽可能精简;同时通过 pkgIsCommand 标志位区分命令与数据,通过 pkgNeedResponse 标志位控制是否需要设备应答,保证长数据(如文件传输)能够可靠分包传输。

Architecture

flowchart TD
    subgraph sg_App["App 业务层 (JL_Health)"]
        UI["业务界面 / 控制器"]
        OBS["NSNotification 观察者<br/>(kJL_RCSP_RECEIVE / SEND)"]
    end

    subgraph sg_Cmd["命令分发层"]
        MGR["JL_ManagerM 命令中心"]
        DELEGATE["JL_ManagerMDelegate<br/>onManagerSendPackage:"]
        FM["功能管理器集合<br/>JL_FileManager / JL_OTAManager /<br/>JL_TwsManager / JL_CallManager / ..."]
    end

    subgraph sg_Proto["协议编解码层"]
        RCSP["JL_RCSP"]
        PKG["JL_PKG 数据模型"]
    end

    subgraph sg_BLE["BLE 传输层 (CoreBluetooth)"]
        ASSIST["JL_Assist 连接助手"]
        CENTRAL["CBCentralManager / CBPeripheral"]
        ACTION["JL_BLEAction<br/>广播过滤 / 配对 / OTA回连"]
    end

    subgraph sg_Dev["设备端"]
        DEV["杰理芯片设备"]
    end

    UI -->|"发送命令"| MGR
    MGR -->|"xmCommandCode: 构建 JL_PKG"| PKG
    MGR --> DELEGATE
    DELEGATE -->|"包回调"| ASSIST
    PKG -->|"rcspMakePackage: 编码"| RCSP
    RCSP -->|"NSData 字节流"| ASSIST
    ASSIST -->|"写入 mRcspWrite 特征"| CENTRAL
    CENTRAL -->|"BLE GATT 写入"| DEV
    DEV -->|"Notify 回包"| CENTRAL
    CENTRAL -->|"didUpdateValueForCharacteristic"| ASSIST
    ASSIST -->|"assistUpdateValueForCharacteristic:"| MGR
    MGR -->|"inputPKG: + rcspAnalysisData:"| RCSP
    RCSP -->|"解码为 JL_PKG"| MGR
    MGR -->|"按 OpCode 分发"| FM
    FM --> OBS
    OBS --> UI
    ACTION --> CENTRAL

架构说明:

  • JL_ManagerM 是整个命令体系的中枢:它持有 JL_RCSP 的编解码能力、唯一命令序号 mCmdSN、以及所有功能管理器实例。业务层通过 xmCommandCode: 系列方法下发命令,通过 inputPKG: 接收设备回包;
  • JL_Assist 是 CoreBluetooth 与上层之间的"适配器":App 只需在系统代理回调里调用 assistUpdateState:、assistDiscoverCharacteristicsForService:Peripheral: 等转发方法,即可获得特征发现、认证配对与数据收发的完整处理;
  • JL_RCSP 无状态、只做编解码(工具类),保证协议逻辑单一、可独立测试;
  • JL_BLEAction 以单例形式提供设备过滤、握手配对与 OTA 回连等"连接前"能力,与 JL_Assist 的"连接中/连接后"能力互补。

(架构依据:JL_RCSP.h、JL_Assist.h、JL_ManagerM.h、JL_BLEAction.h)

RCSP 协议包结构(JL_PKG)

RCSP 的命令载荷模型是 JL_PKG,其字段定义精确到比特位:

@interface JL_PKG : NSObject
@property(assign,nonatomic) uint16_t pkgIsCommand;       //1Bit
@property(assign,nonatomic) uint16_t pkgNeedResponse;    //1Bit
@property(assign,nonatomic) uint16_t pkgUnused;          //6Bits
@property(assign,nonatomic) uint16_t pkgOpCode;          //8Bits
@property(assign,nonatomic) uint16_t pkgLength;          //参数长度(本身不计)
@property(strong,nonatomic) NSData   *pkgData;           //参数数据
@end

Source: JL_RCSP.h

头字段语义

字段位宽含义
pkgIsCommand1 bit1 = 命令包(需要按 OpCode 处理),0 = 数据包
pkgNeedResponse1 bit是否需要设备回复(仅命令包有意义,与 xmCommandCode:needResponse: 参数对应)
pkgUnused6 bits保留位,供协议扩展
pkgOpCode8 bits操作码,对应 JL_OpCode.h 中的命令枚举,如 0x01 系统、0x05 设备信息、0x1A 文件等
pkgLength—参数区长度(不包含头部自身)
pkgData—参数区原始字节

这个"1+1+6+8"的头部设计意图是:把 OpCode 固定为单字节,使最常见的控制命令(音量、EQ、播放/暂停)恰好落在 1~2 个 BLE 包内,降低 MTU 压力;6 位保留位则为后续协议版本预留了扩展空间而无需改变包头总长。

JL_RCSP:协议编解码核心

JL_RCSP 是一个纯工具类,提供 6 个静态方法完成"模型 ⇄ 字节流 ⇄ 参数数组"的完整转换:

方法方向说明
rcspMakePackage:模型 → 字节流把 JL_PKG 编码为待发送的 NSData(XM 数据包)
rcspAnalysisData:字节流 → 模型把接收到的原始数据解析为 JL_PKG
rcspMakeParams:参数数组 → 字节流把 NSData 元素数组拼装为参数区数据
rcspAnalysisParams:JL_PKG → 参数数组把 pkgData 参数区拆分为数组
rcspInfoArrFromData:信息数据 → 数组分解 JL_PKG 中的信息数据(LTV 结构)
rcspInfoFromData2ByteSize:LTV 数据 → 数组拆分 L 长度为 2 字节的 LTV 数据
/**
 解析JL数据包
 @param data 把数据转成JL_PKG模型。
 @return JL_PKG数据模型
 */
+(JL_PKG*)rcspAnalysisData:(NSData*)data;

/**
 生成XM数据包
 @param pkg 把JL_PKG模型转成data。
 @return 数据
 */
+(NSData*)rcspMakePackage:(JL_PKG*)pkg;

/**
 分析JL_PKG参数
 @param pkg 把JL_PKG的xmData参数部分解析成一列数组。
 @return 参数数组
 */
+(NSArray*)rcspAnalysisParams:(JL_PKG*)pkg;

/**
 生成JL_PKG参数
 @param array 把参数数组变成data(注意:数组元素必须是NSData类型)。
 @return 数据
 */
+(NSData*)rcspMakeParams:(NSArray*)array;

Source: JL_RCSP.h

设计要点

  • 参数区采用数组模型:rcspMakeParams: 严格要求数组元素是 NSData,这使每个参数块可以独立构造(例如先拼操作数、再拼 TLV 子块),避免多层字节拼接的指针错误;
  • LTV 双模式:rcspInfoArrFromData:(单字节长度)与 rcspInfoFromData2ByteSize:(双字节长度)并存,前者用于短参数(如设备信息字段),后者用于文件/大数据块场景(如固件升级、歌词传输),兼顾紧凑性与长度上限;
  • 无状态设计:编解码不依赖连接上下文,便于单元测试与在非 BLE 通道(如串口调试)复用。

核心数据流:命令发送与回包接收

sequenceDiagram
    participant UI as 业务层
    participant MGR as JL_ManagerM
    participant RCSP as JL_RCSP
    participant AS as JL_Assist
    participant CB as CoreBluetooth
    participant DEV as 设备

    UI->>MGR: xmCommandCode:needResponse:sendData:
    activate MGR
    MGR->>MGR: 生成命令序号 mCmdSN 并构建 JL_PKG
    MGR->>RCSP: rcspMakePackage:(JL_PKG)
    RCSP-->>MGR: NSData 字节流
    MGR-->>UI: onManagerSendPackage:(JL_PKG) 代理回调
    MGR->>AS: assistDidWriteData:(NSData)
    activate AS
    AS->>CB: 写入 mRcspWrite 特征(按 MTU 分包)
    CB->>DEV: GATT Write
    deactivate AS
    deactivate MGR

    DEV-->>CB: Notify 回包
    CB-->>AS: didUpdateValueForCharacteristic:
    AS->>MGR: assistUpdateValueForCharacteristic:(CBCharacteristic)
    activate MGR
    MGR->>RCSP: rcspAnalysisData:(value)
    RCSP-->>MGR: JL_PKG(含 OpCode 与参数)
    MGR->>MGR: inputPKG: 按 OpCode 路由到功能管理器
    MGR-->>UI: 发送 kJL_RCSP_RECEIVE 通知(字典含 UUID/对象)
    deactivate MGR

步骤解读:

  1. 业务层调用 JL_ManagerM 的命令方法(如 xmCommandCode:needResponse:sendData:),管理器自增 mCmdSN 并构造 JL_PKG;
  2. JL_RCSP 将模型编码为字节流;管理器通过 JL_ManagerMDelegate 的 onManagerSendPackage: 把包交给外部(即 JL_Assist 的写通道),同时广播 kJL_RCSP_SEND 通知供日志/调试使用;
  3. JL_Assist 把数据按 MTU 分包写入 RCSP 写特征(mRcspWrite),设备执行命令;
  4. 设备通过 Notify 回包,CoreBluetooth 回调 didUpdateValueForCharacteristic:,App 转发给 JL_Assist 的 assistUpdateValueForCharacteristic:,再进入 JL_ManagerM inputPKG:;
  5. 管理器用 rcspAnalysisData: 还原 JL_PKG,按 pkgOpCode 路由到对应功能管理器,最终以 NSDictionary 通知(含 kJL_MANAGER_KEY_UUID 与 kJL_MANAGER_KEY_OBJECT)形式抛给业务层。

(依据:JL_RCSP.h、JL_ManagerM.h、JL_BLEAction.h)

JL_Assist:BLE 连接生命周期

JL_Assist 封装了从蓝牙状态变化到数据收发全过程。它的设计原则是"薄转发":App 在 CoreBluetooth 代理方法中直接调用对应 assist 方法,内部完成状态机推进,业务层无需关心 GATT 细节。

/// Execute in a method 「- (void)centralManagerDidUpdateState:」
-(void)assistUpdateState:(CBManagerState)state;

/// Execute in a method 「- (void)peripheral:didDiscoverServices:」
-(void)assistDiscoverCharacteristicsForService:(CBService*)service
                                    Peripheral:(CBPeripheral*)peripheral;

/// Execute in a method 「- (void)peripheral:didUpdateNotificationStateForCharacteristic:error:」
-(void)assistUpdateCharacteristic:(nonnull CBCharacteristic *)characteristic
                       Peripheral:(CBPeripheral*)peripheral
                           Result:(JL_Assist_BK)result;

/// Execute in a method 「- (void)peripheral:didUpdateValueForCharacteristic:error:」
-(void)assistUpdateValueForCharacteristic:(CBCharacteristic *)characteristic;

/// Execute in a method 「- (void)peripheral:didWriteValueForCharacteristic:error:」
/// Execute in a method 「- (void)peripheral:didIsReadyForWrite:error:」
-(void)assistDidReady;

/// Execute in a method 「- (void)centralManager:didDisconnectPeripheral:error:」
-(void)assistDisconnectPeripheral:(CBPeripheral *)peripheral;

Source: JL_Assist.h

连接状态机

stateDiagram-v2
    [*] --> Idle: assistUpdateState: poweredOn
    Idle --> Discovering: 连接外设 & didDiscoverServices
    Discovering --> Authenticating: assistDiscoverCharacteristicsForService:
    Authenticating --> Ready: assistUpdateCharacteristic: Result(YES)
    Authenticating --> Failed: Result(NO)
    Failed --> Idle: assistDisconnectPeripheral:
    Ready --> DataFlow: assistUpdateValueForCharacteristic: / assistDidReady
    DataFlow --> Ready
    Ready --> Idle: 断开 / 蓝牙关闭
    Failed --> [*]
  • Discovering:assistDiscoverCharacteristicsForService:Peripheral: 内部按 mService(服务号)匹配服务,再按 mRcsp_W(写特征 UUID)与 mRcsp_R(读/Notify 特征 UUID)匹配特征并保存为 mRcspWrite / mRcspRead;
  • Authenticating:assistUpdateCharacteristic:Peripheral:Result: 在订阅 Notify 成功后触发。若 mAuthEnable == YES,则用 mAuthKey 完成设备认证握手,结果通过 JL_Assist_BK 回调(BOOL isPaired)返回;若未开启认证则直接回调成功;
  • Ready/DataFlow:assistDidReady 表示写通道就绪(处理 didWriteValue 与 didIsReadyForWrite),assistUpdateValueForCharacteristic: 负责把设备 Notify 数据上传给命令中心。

关键属性与配置

属性类型默认说明
mServiceNSString—GATT 服务 UUID(RCSP 服务号),必须配置
mRcsp_WNSString—RCSP 写特征 UUID
mRcsp_RNSString—RCSP 读/Notify 特征 UUID
mAuthKeyNSDatanil设备认证密钥(替代已废弃的 mPairKey)
mAuthEnableBOOLNO是否需要设备认证(替代已废弃的 mNeedPaired)
mLimitMtuNSInteger40在最大 MTU 基础上预留的写入余量
mMaxMtuNSInteger—最大 MTU,建议用 maximumWriteValueLengthForType: 实测刷新
mLogDataBOOLNO是否打印裸数据(调试用)
mCmdManagerJL_ManagerM—命令中心引用,数据上报的终点

Source: JL_Assist.h

设计意图:mLimitMtu 默认 40 字节余量,是因为 iOS 上报的 MTU 往往是协商上限,实际写满可能触发系统节流;预留余量并配合 assistDidReady 的流控,可显著降低 didIsReadyForWrite 排队导致的丢包概率。mDelegate(JL_AssistDelegate)若被设置,则所有待发数据都交给外部回调 assistDidWriteData: 发送,便于自定义加密或替换传输通道。

JL_ManagerM:命令中心与功能管理器

JL_ManagerM 是连接建立后所有命令的总入口。它对外暴露只读的设备信息(mBLE_UUID、mBLE_NAME)与命令序号(mCmdSN),并聚合了 20+ 个功能管理器,每个管理器对应一类设备能力:

@property(nonatomic,strong)JL_SmallFileManager      *mSmallFileManager;
@property(nonatomic,strong)JL_FileManager           *mFileManager;
@property(nonatomic,strong)JL_OTAManager            *mOTAManager;
@property(nonatomic,strong)JL_FlashOperateManager   *mFlashManager;
@property(nonatomic,strong)JL_CallManager           *mCallManager;
@property(nonatomic,strong)JL_AlarmClockManager     *mAlarmClockManager;
@property(nonatomic,strong)JL_TwsManager            *mTwsManager;
@property(nonatomic,strong)JL_MusicControlManager   *mMusicControlManager;
@property(nonatomic,strong)JL_SystemEQ              *mSystemEQ;
@property(nonatomic,strong)JL_SystemTime            *mSystemTime;
@property(nonatomic,strong)JL_SystemVolume          *mSystemVolume;
@property(nonatomic,strong)JL_CustomManager         *mCustomManager;
@property(nonatomic,strong)JL_BatchManger           *mBatchManger;

Source: JL_ManagerM.h

命令发送 API

/**
 发送【命令包】
 @param cmdCode 具体要发送的命令
 @param needResponse 是否需要回复
 @param sendData 具体要发送的数据
 @discussion 只有isCommand是YES时needResponse才有意义,即只有命令才需要回复
 */
-(void)xmCommandCode:(uint8_t)cmdCode
        needResponse:(BOOL)needResponse
            sendData:(NSData*)sendData;

Source: JL_ManagerM.h

管理器的其他关键方法:

  • setPropertyUpdate: — 控制设备属性是否主动上报;
  • setBleUuid: / setBleName: — 记录当前设备身份;
  • inputPKG: — 命令中心接收 JL_PKG 的入口(由 JL_Assist 上报触发),内部解析 OpCode 并路由;
  • noteEntityConnected / noteEntityDisconnected / noteEntityBleOff — 向各功能管理器广播连接/断开/蓝牙关闭事件,使管理器及时复位内部状态(如文件传输中断)。

通知约定

从 JL_ManagerM 发出的所有通知均为字典格式:

/*
 *  从JL_ManagerM发出去的通知都是字典,如下所示:
 *
 *  @{ kJL_MANAGER_KEY_UUID  :当前设备的UUID,
 *     kJL_MANAGER_KEY_OBJECT:外抛的对象 }
 */
extern NSString *kJL_MANAGER_KEY_UUID;      //KEY --> UUID
extern NSString *kJL_MANAGER_KEY_OBJECT;    //KEY --> 对象

Source: JL_ManagerM.h

统一携带 UUID 是为了支持多设备连接(如 TWS 双耳或同时连接多个外设):观察者可以通过 UUID 区分通知来自哪台设备,避免状态串扰。

JL_BLEAction:广播过滤、配对与 OTA 回连

JL_BLEAction 以单例形式提供"连接前"的辅助能力,其职责与 JL_Assist(连接后)互补:

+(id)sharedMe;

/**
 过滤其余蓝牙设备
 @param key 过滤码
 @param advertData 蓝牙广播字典
 @return NSDictionary 广播包含信息字典
 */
+(NSDictionary*)bluetoothKey_1:(NSData*)key Filter:(NSDictionary*)advertData;

/**
 蓝牙设备配对
 @param pKey 配对码
 @param bk   配对回调YES:成功 NO:失败
 */
-(void)bluetoothPairingKey:(NSData *__nullable)pKey Result:(ATC_Block)bk;
-(void)inputPairData:(NSData*)rData;
-(void)cancelPair;

Source: JL_BLEAction.h

  • 广播过滤:bluetoothKey_1:Filter: 用厂商过滤码匹配 kCBAdvDataManufacturerData,返回广播中包含的设备信息字典。这是扫描列表过滤"非杰理设备"的标准入口,配合 JL_Assist 的 mRcspPeripheral 完成连接;
  • 配对/认证前置:bluetoothPairingKey:Result: 发起握手配对(对应设备端的配对码挑战),数据流经 inputPairData: 注入、cancelPair 取消——该流程现已逐步被 JL_Assist 的 mAuthKey/mAuthEnable 认证取代(源码中 mPairKey/mNeedPaired 已标记 deprecated);
  • OTA 回连:固件升级后设备可能更换广播身份,otaBleMacAddressFromCBAdvDataManufacturerData: 可从广播中提取 'JLOTA' 标识的蓝牙地址,otaBleMacAddress:isEqualToCBAdvDataManufacturerData: 判断当前设备是否为升级目标,用于升级中断线后的自动重连;
  • 数据通知:kJL_RCSP_RECEIVE(接收)与 kJL_RCSP_SEND(发送)是全局裸数据通知,日志系统与抓包工具依赖它们实现协议可视化。
/**
 *  BLE数据通知
 */
extern NSString *kJL_RCSP_RECEIVE;      //Rcsp数据【接收】
extern NSString *kJL_RCSP_SEND;         //Rcsp数据【发送】

Source: JL_BLEAction.h

与 RCSP 相关的扩展属性

  • TWS / LeAudio 地址:JLTwsAdv 中的 rcspUseLeAudioAddress 标志指示 RCSP 命令是否使用 LE Audio 地址,供双耳/LE Audio 场景下区分命令寻址方式(见 JLTwsAdv.h);
  • Flash 系统类型:JL_FlashSystemType_RCSP = 1 表示设备 Flash 采用 RCSP 文件系统(区别于 FATFS),文件管理器的读写路径据此选择(见 JLModel_Flash.h)。

Usage Examples

1. 在 CoreBluetooth 代理中桥接 JL_Assist(连接建立)

以下模式展示了 App 如何把系统蓝牙回调"转发"给 JL_Assist,由后者完成服务/特征发现与认证。这是所有接入方必须遵循的桥接样板:

// 在 CBCentralManagerDelegate / CBPeripheralDelegate 回调中:
- (void)centralManagerDidUpdateState:(CBManagerState)state {
    [assist assistUpdateState:state];                       // 蓝牙开关状态同步
}

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error {
    for (CBService *service in peripheral.services) {
        [peripheral discoverCharacteristics:nil forService:service];
    }
}

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error {
    // JL_Assist 按 mService/mRcsp_W/mRcsp_R 匹配并缓存特征
    [assist assistDiscoverCharacteristicsForService:service Peripheral:peripheral];
}

- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
    // 订阅 Notify 完成后触发认证握手,isPaired 为 YES 表示可开始收发命令
    [assist assistUpdateCharacteristic:characteristic
                            Peripheral:peripheral
                                Result:^(BOOL isPaired) {
        if (isPaired) { /* 连接就绪,可以发命令 */ }
    }];
}

- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
    [assist assistUpdateValueForCharacteristic:characteristic];   // 设备回包 → 命令中心
}

Source: JL_Assist.h

2. RCSP 数据包编解码(协议层独立使用)

JL_RCSP 的编解码方法不依赖连接,可用于抓包分析、单元测试或自定义通道:

// 接收方向:设备回包 NSData → JL_PKG 模型
JL_PKG *pkg = [JL_RCSP rcspAnalysisData:receivedData];
uint16_t opCode = pkg.pkgOpCode;                 // 取命令码
NSArray *params = [JL_RCSP rcspAnalysisParams:pkg]; // 参数拆分为数组

// 发送方向:构造 JL_PKG → 编码为字节流
JL_PKG *outPkg = [[JL_PKG alloc] init];
outPkg.pkgIsCommand = 1;                          // 命令包
outPkg.pkgNeedResponse = 1;                       // 需要设备回复
outPkg.pkgOpCode = 0x01;                          // 以 0x01 系统命令为例
outPkg.pkgData = [JL_RCSP rcspMakeParams:@[data1, data2]]; // 参数区
NSData *frame = [JL_RCSP rcspMakePackage:outPkg]; // 得到可发送的 XM 数据包

Sources: JL_RCSP.h、JL_RCSP.h

3. 扫描列表过滤与 OTA 回连

// 过滤:只保留广播中携带杰理过滤码的设备
NSDictionary *info = [JL_BLEAction bluetoothKey_1:filterKey
                                           Filter:advertisementData];
if (info) { /* 该设备是杰理设备,展示/自动连接 */ }

// OTA 回连:升级后从广播包取回设备蓝牙地址
NSString *mac = [JL_BLEAction otaBleMacAddressFromCBAdvDataManufacturerData:advManufacturerData];
BOOL isTarget = [JL_BLEAction otaBleMacAddress:mac
              isEqualToCBAdvDataManufacturerData:advManufacturerData];

Source: JL_BLEAction.h

Configuration Options

JL_Assist 是 RCSP 链路的主要配置点,配置必须发生在 assistUpdateState: 与特征发现之前:

选项类型默认值说明
mServiceNSString无RCSP GATT 服务号,特征发现时匹配
mRcsp_WNSString无RCSP 写特征 UUID
mRcsp_RNSString无RCSP 读/Notify 特征 UUID
mAuthEnableBOOLNO是否启用设备认证握手
mAuthKeyNSDatanil设备认证密钥(替代已废弃的 mPairKey)
mLimitMtuNSInteger40写入 MTU 余量,防止写满触发流控
mMaxMtuNSInteger0最大 MTU,建议实测刷新
mLogDataBOOLNO是否打印收发裸数据
mDelegateid<JL_AssistDelegate>nil设置后数据改由外部回调发送
mBleNameNSString无设备名字(日志/展示用)

Source: JL_Assist.h

API Reference

JL_RCSP(协议编解码工具类)

方法参数返回值说明
+ rcspAnalysisData:NSData *dataJL_PKG *原始数据解析为包模型
+ rcspMakePackage:JL_PKG *pkgNSData *包模型编码为字节流
+ rcspAnalysisParams:JL_PKG *pkgNSArray *拆分参数区为数组
+ rcspMakeParams:NSArray *arrayNSData *参数数组拼装为数据(元素必须是 NSData)
+ rcspInfoArrFromData:NSData *dataNSArray *分解 LTV 信息(L 为 1 字节)
+ rcspInfoFromData2ByteSize:NSData *dataNSArray *拆分 L 为 2 字节的 LTV 数据

JL_Assist(BLE 连接助手)

  • - assistUpdateState:(CBManagerState)state — 在 centralManagerDidUpdateState: 中调用,同步蓝牙开关状态;
  • - assistDiscoverCharacteristicsForService:Peripheral: — 在 didDiscoverCharacteristicsForService: 中调用,匹配并缓存 mRcspWrite/mRcspRead;
  • - assistUpdateCharacteristic:Peripheral:Result: — 订阅 Notify 后触发认证;回调 JL_Assist_BK(BOOL isPaired)(YES 配对成功 / NO 失败);
  • - assistUpdateValueForCharacteristic: — 设备 Notify 数据上报入口,内部交给 mCmdManager;
  • - assistDidReady — 写通道就绪信号(didWriteValueForCharacteristic: / didIsReadyForWrite: 中调用);
  • - assistDisconnectPeripheral: — 断开事件处理,复位连接状态。

JL_ManagerM(命令中心)

  • - xmCommandCode:(uint8_t)cmdCode needResponse:(BOOL)needResponse sendData:(NSData*)sendData — 发送命令包;needResponse 仅在命令包场景有效;
  • - inputPKG:(JL_PKG*)pkg — 接收设备回包并路由;
  • - noteEntityConnected / noteEntityDisconnected / noteEntityBleOff — 连接事件广播;
  • - setPropertyUpdate:(BOOL)isUpdate、- setBleUuid:/- setBleName: — 状态设置;
  • 代理 JL_ManagerMDelegate - onManagerSendPackage:(JL_PKG*)pkg — 命令包外发回调。

JL_BLEAction(单例辅助)

  • + sharedMe — 获取单例;
  • + bluetoothKey_1:Filter: — 过滤码匹配广播,返回设备信息字典;
  • - bluetoothPairingKey:Result: / - inputPairData: / - cancelPair — 握手配对流程;
  • + otaBleMacAddressFromCBAdvDataManufacturerData: — 提取 OTA 蓝牙地址;
  • + otaBleMacAddress:isEqualToCBAdvDataManufacturerData: — 判断是否为 OTA 目标设备。

Failure Modes, Edge Cases & Concurrency

连接阶段失败

场景现象处理路径
蓝牙未开启/关闭centralManagerDidUpdateState: 非 poweredOnassistUpdateState: 同步状态;JL_ManagerM 收到 noteEntityBleOff 后各管理器复位
特征发现失败服务/特征 UUID 与 mService/mRcsp_W/mRcsp_R 不匹配不会缓存 mRcspWrite/mRcspRead,后续写数据失败;需核对设备端固件配置
认证失败JL_Assist_BK 回调 NO认证握手未通过,禁止进入数据收发;需检查 mAuthKey 与设备端密钥一致
连接断开didDisconnectPeripheral:assistDisconnectPeripheral: 复位;noteEntityDisconnected 通知各管理器清理进行中的传输(如文件/OTA)

数据收发边界与并发

  • MTU 分包与流控:写入超过 mMaxMtu - mLimitMtu 的数据必须分包。assistDidReady(对应 didIsReadyForWrite:)是 iOS 的写队列流控信号——大量连续写入时,必须等待该回调再发下一包,否则触发系统级节流甚至丢包。mLimitMtu 默认 40 正是为这条边界预留的缓冲;
  • 命令序号竞态:mCmdSN 由 JL_ManagerM 统一自增,保证同一时刻发出的命令序号唯一,设备端依赖它做请求-应答匹配。多线程调用命令接口时,序号生成必须在管理器内部串行,业务层不应自行拼装序号;
  • 多设备通知区分:所有通知字典携带 kJL_MANAGER_KEY_UUID,观察者必须按 UUID 过滤,避免 TWS/多设备场景下的状态串扰;
  • 命令/数据包歧义:pkgIsCommand 区分命令与数据;长文件传输由 pkgLength 与分包序号还原,rcspInfoFromData2ByteSize:(2 字节长度)专用于大块 LTV 数据,避免 1 字节长度溢出(最大 255 的限制)。

协议兼容性注意

  • mPairKey/mNeedPaired 已标记 deprecated,新代码应使用 mAuthKey/mAuthEnable;
  • rcspUseLeAudioAddress(见 JLTwsAdv.h)影响 RCSP 命令的寻址方式,LE Audio 设备与经典 BLE 设备的命令构造不能混用;
  • Flash 系统类型 JL_FlashSystemType_RCSP(见 JLModel_Flash.h)决定文件读写协议分支,升级固件改变文件系统后必须同步刷新该字段。

Performance & Operational Notes

  • 日志:JL_Assist.mLogData 开启后打印裸数据;kJL_RCSP_RECEIVE / kJL_RCSP_SEND 通知可挂接协议抓包工具,用于线上问题定位,但高频通知有性能开销,正式包建议关闭或采样;
  • MTU 优化:mMaxMtu 初始化值不一定准确,源码注释明确建议在连接后通过 [peripheral maximumWriteValueLengthForType:CBCharacteristicWriteWithoutResponse] 实测刷新(见 JL_Assist.h),更大的 MTU 能显著减少文件传输的包数;
  • 热路径:音频流控(音乐控制、音量)与系统属性上报(setPropertyUpdate:)是高频路径,功能管理器通过属性下发而非逐条查询,减少空中往返;
  • OTA 中断恢复:升级断线后使用 JL_BLEAction 的广播地址匹配能力自动回连目标设备,避免用户手动重连错设备。

Extension Points

  1. 自定义传输通道:实现 JL_AssistDelegate 的 assistDidWriteData:,可接管数据发送(如加密、转发到其他外设),JL_Assist 内部不再处理发送;
  2. 新功能管理器:JL_ManagerM 已挂载 20+ 管理器,新增设备能力时可在 JL_ManagerM.h 增加属性、并在 inputPKG: 的分发逻辑中扩展 OpCode 路由,复用统一的 xmCommandCode: 发送链路;
  3. 协议扩展位:pkgUnused(6 bits)为协议保留,扩展命令码需与设备端固件同步升级,注意与 JL_OpCode.h 的现有枚举不冲突;
  4. 扫描策略定制:bluetoothKey_1:Filter: 返回的广播信息字典可扩展为扫描列表的展示数据源,自定义过滤逻辑只需在调用前处理 advertisementData。

Related Links

  • JL_RCSP.h — 协议编解码与 JL_PKG 模型
  • JL_Assist.h — BLE 连接助手与认证配置
  • JL_ManagerM.h — 命令中心与功能管理器集合
  • JL_BLEAction.h — 广播过滤、配对与 OTA 回连
  • JL_OpCode.h — 命令码定义(经 JL_BLEKit.h 引入)
  • JLTwsAdv.h — RCSP 与 LeAudio 地址
  • JLModel_Flash.h — Flash 系统类型(FATFS/RCSP)
  • 相关兄弟页面:各功能管理器(文件管理、OTA 升级、TWS、闹钟等)的内部机制请参见对应目录页。
Prev
SDK 库体系与模块划分
Next
广播包解析与设备认证