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

    • 项目简介与核心能力
    • 快速开始
    • 工程结构与依赖库
  • 核心功能

    • RCSP OTA 升级流程
    • BLE 升级通道
    • SPP 升级通道
    • 自动回连机制
  • 蓝牙通信架构

    • 蓝牙抽象层与基础组件
    • BLE 模块实现
    • SPP 模块实现
    • 蓝牙管理与 OTA 管理器
  • 示例应用

    • 应用入口与启动流程
    • 主界面与设备连接交互
    • 关于、日志与辅助页面
  • 调试与运维

    • 日志系统与调试技巧
    • 问题排查与技术支持
  • 开发者指南

    • SDK 版本历史
    • 集成与二次开发指南

RCSP OTA 升级流程

本页面完整记录 Jieli 杰理 HarmonyOS OTA SDK 中基于 RCSP(Real-time Command/Service Protocol)协议的固件升级流程,涵盖从蓝牙连接、RCSP 初始化、升级命令交互、断线重连到升级完成回调的端到端机制。

Purpose and Scope

本页面聚焦于 RCSP OTA 升级流程 这一核心能力,说明以下内容:

  • BluetoothOTAManager 如何组织蓝牙事件与 RCSP/OTA 模块之间的桥接;
  • OTAWrapper 如何封装 jl-ota(JL_OTA)、jl-rcsp(JL_RCSP)与 jl-auth(JLAuth)三个 SDK 库并驱动升级;
  • RCSP 初始化、设备信息获取、强制升级判断、升级启动、进度回调、断线回连(内部回连与自定义回连)的完整流程;
  • 蓝牙层(BLE/SPP)数据收发如何与 RCSP 协议栈对接。

与本页面相邻但不在本页展开的主题:蓝牙扫描/连接的底层实现请参阅 "蓝牙连接管理" 相关页面;升级包文件解析与校验属于 "OTA 升级文件处理" 页面;认证流程属于 "JL Auth 认证" 页面。

Overview

RCSP 是杰理(Jieli)设备的实时命令/服务协议,承载 OTA 升级、设备信息查询、认证等指令。在 HarmonyOS 应用中,RCSP OTA 升级流程由三层协作完成:

  1. 蓝牙通信层(BluetoothManager、BleImpl、SppImpl):负责扫描、连接、收发原始数据;
  2. 协议适配层(BluetoothOTAManager):把蓝牙事件(扫描到设备、连接状态变化、特征值通知)翻译成 OTA 层能理解的回调,同时把 OTA 层要发送的数据通过 BLE/SPP 通道发出去;
  3. OTA 协议层(OTAWrapper + JL_OTA.RcspOTAManager):真正执行 RCSP 升级指令序列(获取目标信息、下发固件、校验、重启、回连、上报进度)。

整个流程的关键设计意图是:SDK 内部只管 RCSP 协议逻辑,而把"如何扫描、如何连接、如何收发字节"全部抽象成 OTAWrapperOption 回调,由上层(BluetoothOTAManager)按实际的蓝牙类型(BLE 或 SPP)实现。这样协议层与传输层完全解耦,同一套 RCSP 升级逻辑可以同时跑在 BLE 和 EDR/SPP 两种物理链路上。

Architecture

下图展示了 RCSP OTA 升级流程的组件架构与数据流向:

flowchart TD
    subgraph sg_App["应用层"]
        App["业务页面 / 调用方"]
        bluetoothOTAManager["bluetoothOTAManager 单例"]
    end

    subgraph sg_Adapter["协议适配层"]
        BTOManager["BluetoothOTAManager"]
        OTAWrapper["OTAWrapper"]
    end

    subgraph sg_SDK["RCSP SDK 库"]
        RcspOTAManager["JL_OTA.RcspOTAManager"]
        RcspImpl["JL_RCSP.RcspImpl"]
        Auth["JLAuth.Auth"]
        CallbackMgr["JL_RCSP.RcspCallbackManager"]
    end

    subgraph sg_BT["蓝牙通信层"]
        BluetoothManager["bluetoothInstance"]
        BleImpl["BleImpl (BLE)"]
        SppImpl["SppImpl (SPP/EDR)"]
    end

    App -->|"startOTA()"| bluetoothOTAManager
    bluetoothOTAManager -->|"构造 OTAWrapperOption"| BTOManager
    BTOManager -->|"startOTA / 回调转发"| OTAWrapper
    OTAWrapper -->|"new RcspOTAManager(rcspImpl)"| RcspOTAManager
    OTAWrapper -->|"getRCSPImpl / RcspImpl"| RcspImpl
    OTAWrapper -->|"认证 / 设备信息"| Auth
    OTAWrapper -->|"统一分发 RCSP 回调"| CallbackMgr
    RcspOTAManager -->|"sendData / 断开 / 连接"| OTAWrapper
    OTAWrapper -->|"otaWrapperOption 回调"| BTOManager
    BTOManager -->|"bleImpl.sendData / sppImpl.sendData"| BluetoothManager
    BluetoothManager --> BleImpl
    BluetoothManager --> SppImpl
    BleImpl -->|"NOTIFY 特征值数据"| BTOManager
    SppImpl -->|"SOCKET UUID 数据"| BTOManager

各组件职责说明:

组件职责关键证据
BluetoothOTAManager单例入口,注册蓝牙事件回调,实现 OTAWrapperOption(扫描/连接/断开/发送数据),转发升级回调BluetoothOTAManager.ets
OTAWrapper协议封装层,按 deviceId 管理 RcspOTAManager/RcspImpl/Auth 实例,把 SDK 回调桥接给上层OtaWrapper.ets
JL_OTA.RcspOTAManagerRCSP 升级状态机核心,驱动升级指令序列由 OTAWrapper.startOTA() 创建
JL_RCSP.RcspImpl单设备 RCSP 协议实例,负责指令编解码与设备信息维护_RcspImplMap 按 deviceId 管理
BleImpl / SppImpl物理传输:BLE 特征值读写 / SPP socket 读写BluetoothOTAManager.ets

设计上采用按 deviceId 分片的实例管理:OTAWrapper 内部用 _RcspOTAManagerMap、_RcspImplMap、_AuthMap 等 Map 分别缓存每个设备的协议对象,从而支持多设备并发升级,且每个设备的回调互不干扰。lib_rcsp/Index.ets 统一对外导出 JL_OTA、JL_RCSP、JLAuth 三个库,应用只需 import 一个入口即可访问全部 SDK 能力:

import * as JL_OTA from "jl-ota";
import * as JL_RCSP from "jl-rcsp"
import * as JLAuth from "jl-auth"

export {
  JL_OTA,
  JL_RCSP,
  JLAuth,
}

Source: lib_rcsp/Index.ets

核心实现详解

RCSP 初始化(init → initRcsp)

BluetoothOTAManager 的 init() 是升级能力的总入口,它分两步完成初始化:

public init() {
  //蓝牙 初始化
  this.initBluetooth()
  //OTAWrapper 初始化
  this.initRcsp()
}

Source: BluetoothOTAManager.ets

initBluetooth() 同时向 BLE 与 SPP 两条链路注册事件监听:扫描状态变化(SCAN_STATE_CHANGE)、发现设备(SCAN_DEVICE_FIND)、连接状态变化(CONNECT_STATE_CHANGE)、BLE 特征值变化(CONNECT_BLE_CHARACTERISTIC_CHANGE)以及 SPP 数据读取(CONNECT_DATA_READ_CHANGE)。这些回调随后会被转发给 OTAWrapper,从而把"蓝牙物理事件"翻译成"OTA 协议事件"。

initRcsp() 构造 OTAWrapperOption——这是协议层与传输层的解耦契约,共 5 个必须实现的回调:

回调语义实现要点(源码证据)
isUseAuth是否需要认证固定返回 true,升级前会走 JLAuth 认证
isInnerReconnect是否使用 SDK 内部回连固定返回 true;返回 false 时走自定义回连分支(Reconnect 类)
sanDevice扫描设备先扫 BLE(10 秒),若 communicationWay == "EDR" 再补扫 EDR,覆盖升级中设备以 BLE 广播存在的场景
connectDevice连接设备目前回连只有 BLE 设备,构造 BleDevice 后调用 bluetoothInstance.connect
disconnectDevice断开设备根据已连接列表判断设备是 BLE 还是 SPP,分别断开
sendData发送 RCSP 数据BLE 走 RCSP_UUID_SERVICE/RCSP_UUID_WRITE 特征值,SPP 走 RCSP_SOCKET_UUID
/**发送数据**/
sendData: (device: OTADevice, data: Uint8Array) => {
  // 此处需判断设备类型
  const isBle =
    this.bluetoothInstance.bleImpl.getConnectedDevice().findIndex(item => item.deviceId == device.deviceId) != -1
  const deviceId = device.deviceId
  if (isBle) {
    this.bluetoothInstance.bleImpl.sendData(new BleDevice(deviceId), RCSP_UUID_SERVICE, RCSP_UUID_WRITE, data)
  } else {
    this.bluetoothInstance.sppImpl.sendData(new SppDevice(deviceId), RCSP_SOCKET_UUID, data)
  }
}

Source: BluetoothOTAManager.ets

initRcsp() 最后执行 this.otaWrapper = new OTAWrapper(this.otaWrapperOption),把传输层能力注入协议层。注意:此阶段还没有建立任何 RCSP 连接,真正的 RCSP 握手发生在设备连接成功、RcspImpl 被创建并初始化之后。

升级启动(startOTA)

BluetoothOTAManager.startOTA(deviceId, otaCallback) 是业务方触发升级的唯一入口。它完成三件事:

  1. 构造 JL_OTA.OtaConfig 并开启新回连方式:otaConfig.isSupportNewRebootWay = true;
  2. 包装业务回调为 OTAUpgradeCallback(补齐回连、RCSP 初始化等 SDK 需要的内部逻辑);
  3. 调用 this.otaWrapper?.startOTA(new OTADevice(deviceId), otaConfig, tempOtaUpgradeCallback)。
public startOTA(deviceId: string, otaCallback: OTAUpgradeCallback) {
  const otaConfig: JL_OTA.OtaConfig = new JL_OTA.OtaConfig()
  otaConfig.isSupportNewRebootWay = true //支持新回连方式
  const tempOtaUpgradeCallback: OTAUpgradeCallback = {
    onStartOTA: () => {
      otaCallback.onStartOTA()
    },
    // ... 其余回调包装
    onReadData: (offset: number, size: number): Uint8Array | undefined => {
      return otaCallback.onReadData(offset,size)
    },
    onRCSPInit:(deviceId: string, isInit: boolean)=>{
      if (isInit) {// Rcsp回调-初始化成功
        this._ReconnectMap.forEach(reconnect => {
          reconnect.onDeviceConnected(new BluetoothDevice(deviceId))
        })
      }
    }
  }
  this.otaWrapper?.startOTA(new OTADevice(deviceId), otaConfig, tempOtaUpgradeCallback)
}

Source: BluetoothOTAManager.ets

值得注意的设计细节:

  • onReadData 是"拉模式"读取固件数据:SDK 在需要下发固件块时按 (offset, size) 向业务方要数据,业务方可以从文件、网络或内存中按需提供,避免一次性加载整个固件到内存;
  • onRCSPInit 驱动回连唤醒:升级过程中设备重启后重新连接,一旦 RCSP 在新连接上初始化成功,就遍历 _ReconnectMap 通知所有等待中的 Reconnect 实例"设备已上线",回连流程随即完成。

RCSP 实例管理与设备信息(OTAWrapper)

OTAWrapper 内部按 deviceId 维护五个 Map,形成"一设备一协议栈"的模型:

export class OTAWrapper implements OTAWrapperOption, IOTAWrapper {
  private _RcspOTAManagerMap = new Map<string, JL_OTA.RcspOTAManager>()
  private _RcspOTAUpgradeCallbackMap = new Map<string, OTAUpgradeCallback>()
  private _RcspImplMap = new Map<string, JL_RCSP.RcspImpl>()
  private _ReconnectMap = new Map<string, Reconnect>()
  private _AuthMap = new Map<string, JLAuth.Auth>()
  private _RcspCallbackManager = new JL_RCSP.RcspCallbackManager()
  private _OTAWrapperOption: OTAWrapperOption;
}

Source: OtaWrapper.ets

升级前,业务层通常会先调用两个前置检查:

  • isRCSPInit(device):确认该设备是否已完成 RCSP 初始化(内部检查 RcspImpl.getDeviceInfo(device) 是否存在);
  • isNeedMandatoryUpgrade(device):读取设备的目标信息,判断 mandatoryUpgradeFlag 是否为 CmdGetTargetInfo.FLAG_MANDATORY_UPGRADE,决定是普通升级还是强制升级(强制升级不允许用户取消)。
/**是否需要强制升级**/
isNeedMandatoryUpgrade(device: BluetoothDevice): Promise<boolean> {
  return new Promise<boolean>((resolve, reject) => {
    const rcspImpl = this._getRCSPImpl(device.deviceId)
    if (rcspImpl) {
      const deviceInfo = rcspImpl.getDeviceInfo(device)
      if (deviceInfo) {
        resolve(deviceInfo.mandatoryUpgradeFlag == JL_RCSP.CmdGetTargetInfo.FLAG_MANDATORY_UPGRADE)
      } else {
        reject(new JL_RCSP.RCSPError(JL_RCSP.RCSPErrorCode.ERR_OTHER, "No DeviceInfo."))
      }
    } else {
      reject(new JL_RCSP.RCSPError(JL_RCSP.RCSPErrorCode.ERR_OTHER, "No has RCSPImpl."))
    }
  })
}

Source: OtaWrapper.ets

OTAWrapper.startOTA() 内部对 RcspImpl 做三重防御检查后才真正创建升级管理器:rcspImpl 不存在、usingDevice 为空、设备信息未初始化,任一不满足都会直接返回并打印错误日志(如 'rcspImpl 没有初始化成功'),这是为了防止开发者在未建立 RCSP 会话时就误触发升级。

public startOTA(device: BluetoothDevice, otaConfig: JL_OTA.OtaConfig, otaUpgradeCallback: OTAUpgradeCallback) {
  const rcspImpl = this._getRCSPImpl(device.deviceId)
  if (rcspImpl == undefined) {
    Log.e(TAG, 'rcspImpl undefined')
    return
  }
  const usingDevice = rcspImpl.getUsingDevice()
  if (usingDevice == null) {
    return
  }
  if (rcspImpl.getDeviceInfo(usingDevice) == undefined) {
    Log.e(TAG, 'rcspImpl 没有初始化成功')
    return
  }
  const OTAManager = new JL_OTA.RcspOTAManager(rcspImpl)
  this._RcspOTAManagerMap.set(device.deviceId, OTAManager)
  this._RcspOTAUpgradeCallbackMap.set(device.deviceId, otaUpgradeCallback)
  // ...构造 OnUpgradeCallback 并启动升级
}

Source: OtaWrapper.ets

升级启动后,SDK 内部会依次执行 RCSP 指令序列:读取目标信息(CmdGetTargetInfo)→ 认证 → 下发升级包(分块 onReadData 拉取数据)→ 校验 → 断开连接 → 设备重启 → 回连 → 上报完成。onNeedReconnect 回调正是"断开后需要重连"的触发点。

核心流程(Core Flow)

下图以序列图展示一次完整的 RCSP OTA 升级,从业务发起、RCSP 初始化、固件下发、重启回连到最终完成:

sequenceDiagram
    participant App as 业务页面
    participant Mgr as BluetoothOTAManager
    participant Wrp as OTAWrapper
    participant RCSP as JL_RCSP.RcspImpl
    participant OTA as JL_OTA.RcspOTAManager
    participant BT as BleImpl/SppImpl
    participant Dev as 杰理设备

    App->>Mgr: startOTA(deviceId, callback)
    Mgr->>Wrp: startOTA(OTADevice, OtaConfig, callback)
    Wrp->>Wrp: 校验 rcspImpl / usingDevice / DeviceInfo
    Wrp->>OTA: new RcspOTAManager(rcspImpl)
    OTA->>RCSP: 获取设备信息 / 认证 (JLAuth)
    RCSP->>BT: sendData(RCSP_UUID_WRITE, 指令)
    BT->>Dev: BLE/SPP 写特征值
    Dev-->>BT: NOTIFY 响应
    BT-->>Mgr: onBLECharacteristicInfo (RCSP_UUID_NOTIFY)
    Mgr-->>Wrp: onReceiveData
    Wrp-->>OTA: RCSP 指令应答
    OTA-->>App: onStartOTA
    loop 固件分块下发
        OTA->>App: onReadData(offset, size)
        App-->>OTA: Uint8Array 固件块
        OTA->>BT: 下发固件数据
        BT-->>App: onProgress(type, progress)
    end
    OTA-->>App: onExecuteDisconnectDevice
    OTA-->>App: onNeedReconnect(ReconnectInfo)
    App->>BT: 断开旧连接
    Dev-->>BT: 设备重启
    BT-->>Mgr: 扫描到新广播 (D60541544F4C4A 厂商包)
    Mgr->>Wrp: onConnectStateSuccess / 连接
    Wrp->>RCSP: 新连接上重建 RcspImpl
    OTA->>RCSP: updateRcspImpl(新实例)
    RCSP-->>App: onRCSPInit(deviceId, true)
    OTA-->>App: onStopOTA / onCancelOTA / onError 结束

流程关键点解读:

  1. 前置检查:OTAWrapper.startOTA 必须确认 RCSP 实例与设备信息就绪,否则直接拒绝启动——这避免在设备尚未完成 RCSP 握手时下发升级指令导致协议错乱;
  2. 认证前置:isUseAuth 返回 true,升级前 SDK 通过 JLAuth 完成设备认证,防止未授权设备被刷写;
  3. 固件拉取模式:升级数据不整包入参,而是 SDK 按 (offset, size) 回调 onReadData 按需取块,业务方可从文件流/网络流读取,显著降低内存占用;
  4. 断线重连是升级成败关键:设备在烧写后必然重启,原 BLE 连接失效,SDK 通过 onNeedReconnect 触发回连,回连成功后必须调用 OTAManager.updateRcspImpl(rcspImpl) 把新连接上的协议实例同步给升级状态机,否则后续指令仍走旧连接。

蓝牙数据回调的分发路径

接收方向的数据流遵循"物理通道 → 协议适配 → OTA 层"的单向管道:

  • BLE 路径:onBLECharacteristicInfo 收到特征值变化后,只认 RCSP_UUID_NOTIFY 特征值的数据,其余特征值一律忽略,然后调用 otaWrapper?.onReceiveData(...);
  • SPP 路径:onSppDataReadInfo 只认 RCSP_SOCKET_UUID 的数据并同样转发给 onReceiveData。
private onBLECharacteristicInfo(bleCharacteristicInfo: BLECharacteristicInfo) {
  // 蓝牙回调-数据回调
  const deviceId = bleCharacteristicInfo.device.deviceId
  const data = bleCharacteristicInfo.characteristicChangeReq?.characteristicValue
  const characteristicUuid = bleCharacteristicInfo.characteristicChangeReq?.characteristicUuid
  if (data && characteristicUuid === RCSP_UUID_NOTIFY) {
    this.otaWrapper?.onReceiveData(new OTADevice(deviceId), new Uint8Array(data))
  }
}

private onSppDataReadInfo(sppDataReadInfo: SppDataReadInfo) {
  // 蓝牙回调-数据回调
  const deviceId = sppDataReadInfo.device.deviceId
  const data = sppDataReadInfo.data
  const characteristicUuid = sppDataReadInfo.uuid
  if (data && characteristicUuid === RCSP_SOCKET_UUID) {
    this.otaWrapper?.onReceiveData(new OTADevice(deviceId), new Uint8Array(data))
  }
}

Source: BluetoothOTAManager.ets

连接状态变化同样被翻译为 OTA 层语义:CONNECT_STATE_SUCCESS → onConnectStateSuccess,失败/断开分别映射到 onConnectStateFailed / onConnectStateDisconnect,并同步通知 _ReconnectMap 中的回连实例。

回连机制详解

回连是 RCSP OTA 升级中最复杂的环节,源码中实现了两套回连策略,由 isInnerReconnect 开关选择:

策略一:SDK 内部回连(默认)

OTAWrapper 内 _OTAWrapperOption.isInnerReconnect() 返回 true 时,onNeedReconnect 内部直接构造 ReconnectOp(扫描回调、设备识别回调、连接回调)并启动 Reconnect。识别目标设备的关键在于解析广播包中的厂商标识与 MAC:

  • 新回连方式(isSupportNewReconnectADV 为 true):设备升级后以特殊广播包出现,广播数据中包含 D60541544F4C4A 标志("JLOTA" 的 ASCII 十六进制),从该标志后 8 字节提取反转后的 MAC 与旧 MAC 比对;
  • 同时做两级模糊匹配(广播包包含旧 MAC 或其反转、扫描到的 deviceId 前缀与旧 MAC 前 10 位一致)用于日志优化。
const oldDeviceMac = reConnectMsg.deviceBleMac?.toUpperCase().replace(/:/g, "");
const oldDeviceMacReverse = oldDeviceMac?.split('')?.reverse()?.join(''); //mac反转
const oldDeviceMacPrefix = oldDeviceMac?.substring(0, 10);
// ...
if (reConnectMsg.isSupportNewReconnectADV) { //新回连方式
  const advertisStr = (JL_OTA.toHexString(scanDevice.advertiseData) as string).toUpperCase();
  const index = advertisStr.indexOf("D60541544F4C4A");
  if (index != -1 && scanDevice.advertiseData) {
    const unit8Array = new Uint8Array(scanDevice.advertiseData);
    const macArray = unit8Array.slice((index / 2) + 8, (index / 2) + 14).reverse();
    result = oldDeviceMac == JL_OTA.toHexString(macArray).toUpperCase();
  }
}

Source: OtaWrapper.ets

回连成功后,ReconnectCallback.onReconnectSuccess 会把新 deviceId 通过 reconnectCallback.onResult(deviceId) 交回 SDK,OTAWrapper 随即执行 OTAManager.updateRcspImpl(rcspImpl) 让升级状态机切换协议通道,然后删除 _ReconnectMap 中对应的回连实例。

策略二:自定义回连

当 isInnerReconnect() 返回 false 时,BluetoothOTAManager.startOTA 包装的回调走自定义分支:它把 ReconnectInfo 转交给业务方回调 otaCallback.onNeedReconnect(reConnectMsg, reconnectCallback),业务方拿到 reconnectCallback 后可自行实现扫描/识别/连接(示例代码完整实现了同样的 MAC 匹配逻辑,并管理一个 _ReconnectMap)。无论哪种策略,最终都必须:

  • 连接成功 → reconnectCallback.onResult(新 deviceId);
  • 超时/失败 → reconnectCallback.onError(JL_OTA.OtaError.ERR_OTA_RECONNECT_DEVICE_TIMEOUT, ...)。

onRCSPInit 回调是回连完成的关键信号:设备在新连接上完成 RCSP 初始化后,_ReconnectMap 中所有 Reconnect 实例会收到 onDeviceConnected,从而结束等待。

回连超时与终止

  • 超时控制:reconnect.startReconnect(JL_OTA.OTAImpl.RECONNECT_DEVICE_TIMEOUT) 启动带超时的回连;
  • 终止时机:onStopOTA、onCancelOTA、onError 三个终态回调中都会调用 reconnect?.stopReconnect() 清理回连实例,防止升级结束后扫描/连接动作泄漏;
  • 失败恢复:onDeviceConnectFailed 与 onDeviceConnectDisconnected 都会重新触发 sanDevice() 扫描,即"连接失败就重新扫",直到超时。

配置选项

RCSP OTA 升级的可配置项集中在 OTAWrapperOption(协议适配契约)与 JL_OTA.OtaConfig(升级行为配置)两处。

OTAWrapperOption

选项类型默认值(示例工程)说明
isUseAuth() => booleantrue升级前是否执行 JLAuth 认证
isInnerReconnect() => booleantruetrue 用 SDK 内部回连,false 用业务自定义回连
sanDevice() => void扫 BLE 10s;EDR 通信时补扫 EDR回连/升级时的设备扫描策略
connectDevice(device) => void按 BLE 连接建立物理连接
disconnectDevice(device) => void按已连接列表判断 BLE/SPP断开物理连接
sendData(device, data: Uint8Array) => voidBLE 写 RCSP_UUID_WRITE / SPP 写 RCSP_SOCKET_UUIDRCSP 指令字节的物理下发

全部实现证据见 BluetoothOTAManager.ets

OtaConfig 与常量

配置/常量类型值说明
otaConfig.isSupportNewRebootWaybooleantrue启用"新回连方式"(依赖 D60541544F4C4A 广播包携带 BLE 地址)
SUPPORT_RESET_FLAGbooleantrue是否支持重置认证标志命令,由 OtaWrapper.ets 导出
JL_OTA.OTAImpl.RECONNECT_DEVICE_TIMEOUTnumberSDK 内置回连超时时长,传入 Reconnect.startReconnect()
RCSP_UUID_SERVICE / RCSP_UUID_WRITE / RCSP_UUID_NOTIFYstring见 BleConnectSettingConfigureBLE 侧 RCSP 服务的三个 UUID
RCSP_SOCKET_UUIDstring见 SppConnectSettingConfigureSPP 侧 RCSP socket UUID

API 参考

BluetoothOTAManager

public init(): void

初始化蓝牙事件监听与 OTAWrapper。必须在 startOTA 之前调用。

public startOTA(deviceId: string, otaCallback: OTAUpgradeCallback): void

启动 RCSP OTA 升级。

  • 参数:deviceId 目标设备地址;otaCallback 升级回调集合(含 onStartOTA、onExecuteDisconnectDevice、onNeedReconnect、onProgress、onStopOTA、onCancelOTA、onError、onReadData、onRCSPInit)。
  • 前置条件:设备已完成蓝牙连接且 RCSP 已初始化(OTAWrapper.startOTA 内部会校验并静默返回)。
public getOTAWrapper(): IOTAWrapper | undefined

获取内部 OTAWrapper 实例,可用于调用 isRCSPInit / isNeedMandatoryUpgrade 等协议层能力。

OTAWrapper

isRCSPInit(device: BluetoothDevice): Promise<boolean>

判断设备是否完成 RCSP 初始化。返回 true 表示 RcspImpl.getDeviceInfo(device) 已就绪。

isNeedMandatoryUpgrade(device: BluetoothDevice): Promise<boolean>

判断设备是否处于强制升级状态(mandatoryUpgradeFlag == FLAG_MANDATORY_UPGRADE)。

  • Rejects:JL_RCSP.RCSPError(ERR_OTHER, "No DeviceInfo.") 或 "No has RCSPImpl."。
startOTA(device: BluetoothDevice, otaConfig: JL_OTA.OtaConfig, otaUpgradeCallback: OTAUpgradeCallback): void

创建 JL_OTA.RcspOTAManager 并驱动升级;内部会把 onNeedReconnect 的回连成功结果通过 updateRcspImpl 同步给升级状态机。

Reconnect(自定义回连工具类)

startReconnect(timeout: number): void   // 启动带超时的回连
stopReconnect(): void                   // 终止回连
onDeviceConnected(device: BluetoothDevice): void  // RCSP 初始化成功后唤醒
onDiscoveryDevices(devices: Array<OTADevice>): void // 注入扫描结果
onScanStop(): void                      // 扫描结束信号

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

失败模式与错误处理

失败场景处理方式源码证据
rcspImpl 不存在打印 'rcspImpl undefined' 并直接返回,不启动升级OtaWrapper.ets
usingDevice 为空直接返回同上 #L82-L86
设备信息未初始化打印 'rcspImpl 没有初始化成功' 并返回,防止误触发升级同上 #L88-L91
回连超时onReconnectFailed 回调 reconnectCallback.onError(ERR_OTA_RECONNECT_DEVICE_TIMEOUT),并删除 Map 中的回连实例BluetoothOTAManager.ets
回连连接失败/断开重新调用 sanDevice() 继续扫描同上 #L211-L216
升级终态(完成/取消/出错)一律 stopReconnect(),避免回连任务残留同上 #L226-L239
设备未返回 BLE 地址注释明确"RCSP协议未拿到设备的BLE地址",新回连匹配失败,退回模糊匹配同上 #L176-L178

边界情况

  • 新回连广播解析:D60541544F4C4A 标志的定位与 MAC 提取依赖广播包格式(标志后第 8~14 字节反转 MAC),若设备固件不支持新广播,则 isSupportNewReconnectADV 为 false,退化为"旧 deviceId 相同即命中";
  • MAC 大小写:比较前统一 toUpperCase() 并去除冒号,广播包内 MAC 为反转序,需要 reverse() 后再比较;
  • BLE/SPP 双栈:sendData/disconnectDevice 通过查询 bleImpl.getConnectedDevice() 判断设备归属,若同一 deviceId 同时出现在两条链路会出现误判——示例工程中回连固定为 BLE 以规避此问题;
  • 扫描超时:sanDevice 固定 10 秒,onScanState 在 SCAN_STATE_FINISH 时通知 onSanDeviceStop 与 Reconnect.onScanStop,避免回连逻辑在扫描结束后挂起。

并发与一致性

  • 多设备隔离:OTAWrapper 所有实例均按 deviceId 存于 Map,多个设备可并行升级互不干扰;
  • 回连状态同步:onRCSPInit 会遍历 _ReconnectMap 唤醒所有等待实例——这是有意为之的"广播"设计,但在多设备同时升级时,一个设备的 RCSP 初始化可能唤醒另一设备的回连,依赖 Reconnect.onDeviceConnected(deviceId) 内部再次比对设备地址来收敛;
  • 回调线程模型:蓝牙事件(onBLECharacteristicInfo 等)与 SDK 协议回调在同一 HarmonyOS 事件循环中串行分发,示例未引入额外锁,业务回调中不应执行耗时操作以免阻塞数据接收。

性能与运维注意事项

  • 内存优化:固件采用 onReadData(offset, size) 拉取模式,业务方务必按块读取(如文件流 seek),避免整包载入内存导致 OOM;大固件建议配合分片大小与进度上报做 UI 节流;
  • 日志降噪:源码中回连匹配日志做了两级模糊匹配过滤(仅打印"前缀相似"或"包含旧 MAC"的设备),生产环境建议保持 Log.i 级别,避免扫描期间海量广播日志拖垮性能;
  • 升级不可中断:onExecuteDisconnectDevice 之后设备进入烧写窗口,此时应避免用户切换页面销毁 BluetoothOTAManager(单例生命周期应长于升级会话);
  • 扫描窗口:回连扫描 10 秒窗口内不应并发启动业务侧其他扫描,SCAN_STATE_FINISH 是回连扫描结束的唯一可靠信号。

扩展点

  1. 自定义回连:将 isInnerReconnect 改为返回 false,在 otaCallback.onNeedReconnect 中实现自己的扫描/识别/连接逻辑,复用 Reconnect/ReconnectOp/ReconnectCallback 工具类(示例工程已给出完整参考实现);
  2. 自定义传输:替换 OTAWrapperOption 的 sendData/connectDevice/disconnectDevice/sanDevice,即可把 RCSP 协议栈跑在任意通道上(如 TCP、经典蓝牙)而不改动协议层;
  3. 升级策略扩展:升级前通过 isRCSPInit 与 isNeedMandatoryUpgrade 组合业务规则(如强制升级时隐藏取消按钮、弱网时提示用户保持蓝牙连接);
  4. 多固件支持:OtaConfig 与 onReadData 的组合可支持双分区/多固件包升级,只需按 offset/size 语义在业务侧切换数据源。

Related Links

  • BluetoothOTAManager.ets — 本流程的核心适配层源码
  • OtaWrapper.ets — 协议封装层与 RCSP 实例管理
  • lib_rcsp/Index.ets — SDK 库统一导出入口
  • BleConnectSettingConfigure.ets — RCSP BLE UUID 定义
  • SppConnectSettingConfigure.ets — RCSP SPP socket UUID 定义
  • 相关主题页:蓝牙连接管理(扫描/连接/断开)、JL Auth 认证流程、OTA 升级文件处理
Next
BLE 升级通道