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

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

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

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

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

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

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

蓝牙抽象层与基础组件

本文档介绍 JL OTA Harmony 工程中 ets/bluetooth/base 目录下的蓝牙抽象层与基础组件:设备抽象基类 BluetoothDevice、数据发送处理器抽象类 BaseSendDataHandler、异步缓冲队列 BufferQueue、统一错误码 BluetoothErrorConstant,以及扫描/连接契约 IScan、IConnect 在整体蓝牙架构中的定位与使用方式。

Purpose and Scope

本页聚焦于蓝牙模块的基础层(base layer),即所有传输栈(BLE、SPP)共享的抽象契约、基类与基础设施组件:

  • 设备模型抽象:BluetoothDevice 抽象类与 BluetoothDeviceType 类型联合
  • 发送链路的抽象契约:BaseSendDataHandler 抽象类
  • 异步数据缓冲:BufferQueue<T> 通用队列
  • 统一错误码体系:BluetoothErrorConstant 枚举
  • 扫描/连接契约:IScan、IConnect 接口文件在基础层的定位

以下内容不在本页范围内,由兄弟页面分别承载:

  • BLE 传输栈的具体实现(BleImpl、BleDevice、BleSendDataHandler、IBleConnect、IBleScan 及扫描/连接配置)→ 见 BLE 层页面
  • SPP(经典蓝牙串口)传输栈的具体实现(SppImpl、SppDevice 等)→ 见 SPP 层页面
  • 模块级门面与 OTA 业务流程编排(BluetoothManager、BluetoothOTAManager)→ 见蓝牙管理页面

本页只描述基础层自身的结构、行为与设计意图;传输栈如何继承/实现这些契约,以各自页面的源码为准。

Overview

JL OTA 的蓝牙模块采用分层 + 契约解耦的架构。OTA 业务层(BluetoothOTAManager)不直接依赖具体的蓝牙传输协议,而是通过模块门面(BluetoothManager)与基础层定义的一组抽象契约交互;基础层则把"设备长什么样"(BluetoothDevice)、"数据怎么发"(BaseSendDataHandler)、"数据怎么缓冲"(BufferQueue)、"出错怎么表示"(BluetoothErrorConstant)统一抽象出来,由 BLE 与 SPP 两个传输栈分别落地。

这种设计的目的(WHY):

  1. 传输协议可替换:同一套 OTA 协议逻辑可以跑在 BLE 或 SPP 之上,切换传输栈不触碰业务代码。
  2. 统一错误语义:所有传输层错误都归一为 BluetoothErrorConstant 中的数值,上层只需判断一个枚举,而不必关心底层异常类型。
  3. 异步解耦:数据发送与接收方通过 BufferQueue 的 Promise 化接口解耦,发送方不必轮询、接收方不必忙等。

基础层组件全部位于 entry/src/main/ets/bluetooth/base/ 目录,共 6 个文件:

文件角色
BluetoothDevice.ets设备抽象基类 + 设备类型联合
BaseSendDataHandler.ets发送数据处理器抽象基类(契约壳)
BufferQueue.ets通用异步 FIFO 缓冲队列
BluetoothErrorConstant.ets蓝牙错误码枚举
IScan.ets扫描操作抽象契约
IConnect.ets连接操作抽象契约

架构

flowchart TD
    subgraph sg_App["应用 / OTA 业务层"]
        OTA["BluetoothOTAManager"]
        BT["BluetoothManager"]
    end

    subgraph sg_Base["基础层(本页主题)"]
        DEV["BluetoothDevice(抽象类)"]
        SEND["BaseSendDataHandler(抽象类)"]
        QUEUE["BufferQueue<T>"]
        ERR["BluetoothErrorConstant"]
        ISCAN["IScan(契约)"]
        ICONN["IConnect(契约)"]
    end

    subgraph sg_BLE["BLE 传输栈(另页)"]
        BLE["BleImpl"]
        BLEDEV["BleDevice"]
        BLESEND["BleSendDataHandler"]
    end

    subgraph sg_SPP["SPP 传输栈(另页)"]
        SPP["SppImpl"]
        SPPDEV["SppDevice"]
    end

    OTA --> BT
    BT --> ISCAN
    BT --> ICONN
    ISCAN --> BLE
    ISCAN --> SPP
    ICONN --> BLE
    ICONN --> SPP
    DEV -. "被具体设备类继承" .-> BLEDEV
    DEV -. "被具体设备类继承" .-> SPPDEV
    SEND -. "被具体发送处理器继承" .-> BLESEND
    QUEUE --> SEND
    ERR -. "统一错误码引用" .-> BLE
    ERR -. "统一错误码引用" .-> SPP

架构说明:

  • 基础层是本页主题,处于中间位置:向上提供业务层可用的抽象(设备、发送、错误、队列),向下定义传输栈必须实现的契约(IScan、IConnect)。
  • BLE 传输栈与 SPP 传输栈是基础层契约的两个落地实现,分别位于 bluetooth/ble 与 bluetooth/spp 目录;虚线箭头表示"继承/实现"关系,其具体细节以 BLE、SPP 各自页面的源码为准(本页未展开读取这两个目录的实文件)。
  • BufferQueue<T> 服务于发送链路:发送处理器(如 BleSendDataHandler)借助队列在异步回调与上层发送请求之间做缓冲,避免数据丢失与回调重入。
  • BluetoothErrorConstant 是全模块共享的错误语义:BLE 与 SPP 实现都把底层错误翻译为该枚举值,保证上层错误处理路径唯一。

说明:IScan/IConnect 与具体实现(BleImpl/SppImpl)之间的精确绑定关系(是否通过 IBleScan/ISppScan 等中间接口继承)属于传输栈页面的内容,本页不臆测其细节。

基础组件深度分析

设备抽象:BluetoothDevice

BluetoothDevice 是蓝牙模块对"一台可连接设备"的最小抽象,也是 BLE 与 SPP 两类设备模型的公共基类。其完整定义如下:

export type BluetoothDeviceType = "EDR" | "BLE"

export abstract class BluetoothDevice {
  deviceId: string;
  isSystemConnected = false
  type: BluetoothDeviceType = "BLE"
  deviceName?: string
  connectable: boolean = true
  rssi?:number
  constructor(deviceId: string) {
    this.deviceId = deviceId
  }
}

Source: BluetoothDevice.ets

设计要点:

  • deviceId 是唯一标识:构造器强制要求传入,扫描结果与连接操作都以它为键。这也是错误码 ERROR_INVALID_DATA(deviceId 为空或格式不正确)的校验对象。
  • type 区分传输族:BluetoothDeviceType = "EDR" | "BLE" 覆盖经典蓝牙(EDR/SPP)与低功耗蓝牙(BLE)两条链路;默认值是 "BLE",即未显式指定时按 BLE 处理——这反映了该 SDK 以 BLE 为主链路的默认取向。
  • isSystemConnected 记录系统级连接态:初始为 false,由各传输栈在系统连接/断开回调中维护,与上层"逻辑连接"状态解耦。
  • connectable / rssi / deviceName 是扫描结果的通用属性:rssi 与 deviceName 为可选字段(?),因为某些扫描场景(如只按 MAC 过滤)拿不到名称或信号强度。

抽象类本身不可实例化,具体设备模型(BLE 栈的 BleDevice、SPP 栈的 SppDevice)继承它并补充各自传输特有的字段(服务 UUID、特征、波特率等),详见对应传输栈页面。

发送链路契约:BaseSendDataHandler

export abstract class BaseSendDataHandler {
}

Source: BaseSendDataHandler.ets

该抽象类目前是一个空契约壳:文件中没有任何成员声明。它的作用在于为发送数据处理器建立类型边界——各传输栈的发送处理器(如 BLE 栈的 BleSendDataHandler)继承它,从而让上层可以面向 BaseSendDataHandler 编程而不依赖具体传输协议。当前版本的具体发送逻辑(分片、流控、队列消费)实现在各传输栈的派生类中,本文件只负责抽象定位。

注:由于本文件没有方法签名,具体发送接口(参数、返回值、异常)必须以派生类源码为准,见 BLE/SPP 层页面。

异步缓冲队列:BufferQueue<T>

BufferQueue<T> 是基础层最具分量的运行时组件:一个支持异步等待出队的通用 FIFO 队列,用于在数据发送路径上衔接"生产方(上层调用)"与"消费方(底层回调/发送循环)"。

export class BufferQueue<T> {
  private items: T[] = [];
  private dequeuePromise?: Promise<T | undefined>;
  private resolveDequeue?: (value: T | undefined) => void;

  enqueue(item: T): void {
    this.items.push(item);
    // 如果有等待的dequeue操作,则解决它
    if (this.resolveDequeue) {
      this.resolveDequeue(this.dequeue());
      this.resetDequeuePromise();
    }
  }

  dequeue(): T | undefined {
    return this.items.shift();
  }

  getItemList() {
    return this.items
  }

  setItemList(items: T[]) {
    this.items = items
  }

  async dequeueAsync(): Promise<T | undefined> {
    // 如果队列为空,则创建一个新的Promise并等待
    if (this.isEmpty()) {
      if (!this.dequeuePromise) {
        this.dequeuePromise = new Promise(resolve => {
          this.resolveDequeue = resolve;
        });
      }
      return this.dequeuePromise;
    }
    // 如果队列不为空,则直接出队并返回结果
    return Promise.resolve(this.dequeue());
  }

  clear() {
    this.items = [];
    // 如果队列被清空且有等待的dequeue操作,则拒绝它(可选)
    if (this.resolveDequeue) {
      this.resolveDequeue(undefined);
      this.resetDequeuePromise();
    }
  }

  isEmpty(): boolean {
    return this.items.length === 0;
  }

  private resetDequeuePromise() {
    this.dequeuePromise = undefined;
    this.resolveDequeue = undefined;
  }
}

Source: BufferQueue.ets

工作机制(逐行解读):

  1. 内部状态:items 保存数据;dequeuePromise 保存"当前正在等待的 Promise";resolveDequeue 保存该 Promise 的 resolve 函数。后两者构成一个单等待者的异步门闩。
  2. enqueue(item):先 push 入队;随后检查是否存在等待者(resolveDequeue 非空)。若存在,立即调用 resolveDequeue(this.dequeue()) —— 把刚入队的元素 shift 出来直接交付给等待者,并 resetDequeuePromise() 复位门闩。也就是说,当队列为空且有消费者在等待时,入队与出队被融合为一次操作,数据零延迟到达消费者。
  3. dequeueAsync():若队列为空,创建(或复用)一个 Promise 并返回它,调用方 await 挂起;若队列非空,则同步 shift 一个元素并返回已解决的 Promise。这使消费方可以写成自然的 while (true) { const item = await queue.dequeueAsync(); ... } 循环,无需轮询。
  4. clear():清空数据并把等待者以 undefined 唤醒(注释标注"拒绝它(可选)",实际实现是 resolve 而非 reject),随后复位门闩,防止悬挂 Promise。
  5. getItemList() / setItemList(items):提供对内部数组的直接访问/替换能力,供上层在特殊场景(如批量回灌、调试)使用。

关键并发语义:BufferQueue 依赖 ArkTS 单线程事件循环模型,enqueue 与 dequeueAsync 之间不需要锁;但它同一时刻只支持一个等待者(dequeuePromise 是单值)。若多个消费者同时 await dequeueAsync() 且队列为空,后到者拿到的仍是同一个 Promise,只有一个会被唤醒——因此该队列面向"单生产者/单消费者"或"多生产者/单消费者"场景,不适用于多消费者竞争取数。

统一错误码:BluetoothErrorConstant

export enum BluetoothErrorConstant {
  //蓝牙错误
  ERROR_NONE = 0, //ok | 正常 |adapter
  ERROR_CONNECTED = -1, // already connect | 已连接 |
  ERROR_ADAPTER_NOT_INIT = 10000, // not init | 未初始化蓝牙适配器 |
  ERROR_ADAPTER_NOT_AVAILABLE = 10001, // not available | 当前蓝牙适配器不可用 |
  ERROR_NO_DEV = 10002, // no device | 没有找到指定设备 |
  ERROR_CONNECTION_FAIL = 10003, // connection fail | 连接失败 |
  ERROR_NO_SERVICE = 10004, // no service | 没有找到指定服务 |
  ERROR_NO_CHARACTERISTIC = 10005, // no characteristic | 没有找到指定特征 |
  ERROR_NO_CONNECTION = 10006, // no connection | 当前连接已断开 |
  ERROR_PROPERTY_NOT_SUPPORT = 10007, // property not support | 当前特征不支持此操作 |
  ERROR_SYSTEM_ERROR = 10008, // system error | 其余所有系统上报的异常 |
  ERROR_SYSTEM_NOT_SUPPORT = 10009, // system not support | Android 系统特有,系统版本低于 4.3 不支持 BLE |
  ERROR_OPERATE_TIME_OUT = 10012, // operate time out | 连接超时 |
  ERROR_INVALID_DATA = 10013, // invalid_data | 连接 deviceId 为空或者是格式不正确 |
  ERROR_INIT_MTU_FAIL = 20000, // init mtu fail | 初始化MTU失败 |
  ERROR_GET_SERVICE_FAIL = 20001, // get service fail | 获取服务失败 |
  ERROR_NOTIFY_NECESSARY_CHARACTERISTIC_FAIL = 20002, // notify necessary characteristic fail | 使能必须的特征失败 |
  ERROR_IS_CONNECTING = 20003, // is connecting | 正在连接 |
}

Source: BluetoothErrorConstant.ets

错误码按语义分四段,设计意图清晰:

  • 0 / -1:特殊状态。ERROR_NONE 表示成功;ERROR_CONNECTED 用负值表示"已连接",属于状态提示而非失败。
  • 10000–10013:通用蓝牙错误。覆盖适配器状态(未初始化/不可用)、设备查找、连接失败/超时、服务与特征查找、连接断开、属性不支持、系统异常、系统不支持、非法数据。这些错误对 BLE 与 SPP 两条链路通用。
  • 20000–20003:连接初始化链路错误,主要服务于 BLE 的 GATT 连接流程:MTU 协商失败、获取服务失败、使能必要特征失败、正在连接(防止重入)。

上层统一用该枚举判断结果:例如值为 ERROR_NONE 即成功,ERROR_OPERATE_TIME_OUT 触发重试策略,ERROR_IS_CONNECTING 提示调用方避免重复发起连接。错误码的数值稳定性是其作为跨层契约的关键——任何传输栈实现都必须原样透传这些数值,不得自行改写。

契约接口:IScan 与 IConnect

IScan.ets 与 IConnect.ets 定义了蓝牙操作的两个高层契约:扫描(发现设备)与连接(建立会话)。它们位于基础层,表示"任何传输栈都必须具备这两类能力";具体方法签名由各传输栈的派生接口(BLE 侧的 IBleScan/IBleConnect、SPP 侧的 ISppScan/ISppConnect,见 bluetooth/ble 与 bluetooth/spp 目录)细化并实现。

由于本页未读取这两个文件的方法体,此处不臆测其签名;它们的角色定位(扫描/连接抽象)与实现绑定方式,请以 BLE、SPP 传输栈页面的源码为准。

核心流程

数据缓冲的异步消费流程

BufferQueue 是本页唯一有运行时行为的组件,其核心交互——"空队列等待 + 入队即唤醒"——是理解发送链路的关键:

sequenceDiagram
    participant Sender as 生产者(上层发送调用)
    participant Q as BufferQueue&lt;T&gt;
    participant Receiver as 消费者(发送循环/回调)

    Receiver->>Q: dequeueAsync()(队列为空)
    Note over Q: 创建 dequeuePromise 并挂起
    Sender->>Q: enqueue(item)
    Note over Q: resolveDequeue(dequeue())<br/>将刚入队的元素直接交付
    Q-->>Receiver: 返回 item(Promise 解决)
    Receiver->>Receiver: 处理/发送该数据块
    Receiver->>Q: dequeueAsync()(再次等待下一块)

Source: BufferQueue.ets

流程要点:

  1. 消费者先 await dequeueAsync(),因队列为空而挂起,内部保存 resolveDequeue。
  2. 生产者 enqueue(item):push 后立即发现等待者,执行 resolveDequeue(this.dequeue()),把元素交付。
  3. 消费者被唤醒拿到元素,处理完毕后再次 dequeueAsync(),进入下一轮等待——形成无轮询的生产者-消费者循环。
  4. 若队列非空时调用 dequeueAsync(),则直接 shift 返回,无需挂起。

错误码的归一化路径

flowchart LR
    Err["底层异常/系统回调"] --> Trans["BleImpl / SppImpl<br/>错误翻译"]
    Trans --> Code["BluetoothErrorConstant 枚举值"]
    Code --> Mgr["BluetoothManager / 业务层判断"]
    Mgr -->|"ERROR_NONE"| Ok["继续流程"]
    Mgr -->|"ERROR_OPERATE_TIME_OUT"| Retry["重试策略"]
    Mgr -->|"ERROR_IS_CONNECTING"| Guard["防重入"]

所有传输栈实现把系统层异常(连接失败、服务/特征缺失、超时等)翻译为 BluetoothErrorConstant 中的统一数值,业务层只依赖该枚举做分支判断,不感知底层 API 差异。

使用示例

示例一:定义具体设备类并继承抽象基类

以下代码展示 BluetoothDevice 作为抽象基类的用法——具体设备类通过 extends 复用公共字段,并补充传输特有字段(示例结构参照 BLE/SPP 设备类的模式):

export abstract class BluetoothDevice {
  deviceId: string;
  isSystemConnected = false
  type: BluetoothDeviceType = "BLE"
  deviceName?: string
  connectable: boolean = true
  rssi?:number
  constructor(deviceId: string) {
    this.deviceId = deviceId
  }
}

Source: BluetoothDevice.ets

实际工程中,BleDevice(BLE 栈)与 SppDevice(SPP 栈)继承本类并各自持有传输特有的配置字段;它们的完整定义见对应传输栈页面。

示例二:异步消费 BufferQueue

dequeueAsync() 允许消费方写出"等待-取数-处理"的自然循环,无需定时轮询:

async dequeueAsync(): Promise<T | undefined> {
  // 如果队列为空,则创建一个新的Promise并等待
  if (this.isEmpty()) {
    if (!this.dequeuePromise) {
      this.dequeuePromise = new Promise(resolve => {
        this.resolveDequeue = resolve;
      });
    }
    return this.dequeuePromise;
  }
  // 如果队列不为空,则直接出队并返回结果
  return Promise.resolve(this.dequeue());
}

Source: BufferQueue.ets

典型消费循环(示意):

const queue = new BufferQueue<Uint8Array>();
// 消费方:持续取数据块并发送
while (true) {
  const chunk = await queue.dequeueAsync();
  if (chunk === undefined) break;   // clear() 后返回 undefined,循环退出
  sendToDevice(chunk);
}

注意 clear() 会把等待者以 undefined 唤醒,因此消费者需要用 undefined 作为"队列已清空/停止"的退出信号。

示例三:错误码判断

export enum BluetoothErrorConstant {
  ERROR_NONE = 0, //ok | 正常 |adapter
  ERROR_CONNECTED = -1, // already connect | 已连接 |
  ERROR_OPERATE_TIME_OUT = 10012, // operate time out | 连接超时 |
  ERROR_IS_CONNECTING = 20003, // is connecting | 正在连接 |
}

Source: BluetoothErrorConstant.ets

业务层通过数值比较即可完成分支:=== ERROR_NONE 判成功、=== ERROR_OPERATE_TIME_OUT 触发重试、=== ERROR_IS_CONNECTING 拒绝重复连接。

配置选项

BluetoothDevice 的字段即基础层的"设备配置面",由扫描结果或调用方赋值:

字段类型默认值说明
deviceIdstring构造器必填设备唯一标识(MAC/地址),连接与错误校验的依据
typeBluetoothDeviceType"BLE"传输族:"EDR"(经典蓝牙/SPP)或 "BLE"
isSystemConnectedbooleanfalse系统级连接状态,由传输栈回调维护
deviceNamestring?无设备名称(扫描可选信息)
connectablebooleantrue设备是否可连接
rssinumber?无信号强度(扫描可选信息)

API Reference

BufferQueue<T> 类

泛型异步 FIFO 队列,单等待者语义。

方法:

方法签名说明返回
enqueue(item: T): void入队;若有等待者则立即交付并复位门闩无
dequeue(): T | undefined同步出队(shift),空队列返回 undefinedT | undefined
dequeueAsync(): Promise<T | undefined>异步出队;空队列时挂起等待 enqueue 唤醒Promise<T | undefined>
clear(): void清空数据,以 undefined 唤醒等待者并复位门闩无
isEmpty(): boolean是否为空boolean
getItemList(): T[]返回内部数组引用T[]
setItemList(items: T[]): void整体替换内部数组无

Throws:无显式异常;clear() 使用 resolve(而非 reject)唤醒等待者。

BluetoothDevice 抽象类

构造器:constructor(deviceId: string) —— 必须传入设备 ID,空值/格式错误对应 ERROR_INVALID_DATA。

字段:见上方配置表。

Throws:无(抽象类不可实例化)。

BaseSendDataHandler 抽象类

空契约壳,无成员;派生类提供具体发送实现。

BluetoothErrorConstant 枚举

完整取值与语义见上文代码块;数值分段规则:0/-1 状态值、10000–10013 通用错误、20000–20003 连接初始化错误。

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

BufferQueue 的边界语义

  • 空队列 + 多消费者竞争:dequeuePromise/resolveDequeue 是单值门闩,同一时刻仅支持一个等待者。若多个消费者同时 await dequeueAsync() 且队列为空,它们拿到的是同一个 Promise,只有首个 enqueue 会唤醒其中一个;其余消费者需要再次调用才能保证取到数据。因此该队列不适合"多消费者竞争取数"场景,设计上假定消费方唯一(如单条发送循环)。
  • enqueue 与等待者的融合出队:enqueue 在存在等待者时执行 resolveDequeue(this.dequeue()),等价于"入队即出队"——被唤醒的消费者拿到的正是刚入队的元素,不会造成数据错位;但若调用方在 enqueue 后仍期望元素留在队列中(例如还准备用 getItemList() 读取),需注意该元素可能已被交付。
  • clear() 的唤醒约定:clear() 以 undefined resolve 等待者并复位门闩,而不是 reject。消费者必须以 undefined 作为"队列已清空/停止"的退出信号(参见上文消费循环示例),否则会因拿到 undefined 而误判为正常数据。
  • shift() 的数组开销:dequeue() 使用 Array.prototype.shift(),对长队列是 O(n) 移动;OTA 发送场景单块数据通常较小,可接受,但不建议用本队列承载超大数据量的高频吞吐。
  • 直接暴露内部数组:getItemList() 返回内部 items 的引用,外部修改会直接影响队列状态;setItemList() 可整体替换。这两个方法突破了封装边界,应仅在调试/特殊回灌场景使用。

错误码相关边界

  • ERROR_CONNECTED = -1 是状态提示而非错误,上层逻辑需把它与真正的失败(正数错误码)区分处理。
  • ERROR_SYSTEM_NOT_SUPPORT 注释标明为"Android 系统特有",在 HarmonyOS 侧该值仍被保留以维持数值契约稳定,跨平台移植时不应改动枚举数值。
  • 连接初始化链路错误(20000–20003)集中在 BLE 的 GATT 流程:MTU 协商、服务发现、特征使能任一环节失败都会以独立错误码暴露,便于上层定位是"设备能力不足"还是"时序问题"。

并发模型

基础层全部组件运行在 ArkTS 单线程事件循环之上:BufferQueue 的 Promise 门闩无需互斥锁;BluetoothDevice 的字段读写也不存在多线程竞争。真正的并发风险来自异步回调重入——例如连接回调与上层重试同时修改 isSystemConnected/连接状态,需要依赖 ERROR_IS_CONNECTING 这类防重入错误码在上层做串行化。

性能与运维

  • 零轮询等待:dequeueAsync() 的 Promise 门闩设计使消费方在无数据时完全不消耗 CPU,这是相对轮询方案的关键优势。
  • 入队延迟为 O(1)(有等待者时):入队+出队融合为一次 shift,数据交付延迟最小。
  • 错误码数值契约:枚举值在模块间作为协议传输,任何版本迭代都不应重排数值;新增错误码应追加新成员而非复用已有值。
  • 基础层无网络/文件 IO,运行期开销集中在 BufferQueue 的数组操作与 Promise 创建上;大量短促 enqueue/dequeueAsync 会频繁创建/销毁 Promise,若有极致性能诉求可考虑对象池复用。

扩展点

基础层的抽象设计为传输栈扩展提供了明确的接缝:

  1. 新增设备模型:继承 BluetoothDevice,补充传输特有字段(BLE 的 UUID/MTU、SPP 的波特率/通道等),现有模式参照 BleDevice/SppDevice。
  2. 新增发送处理器:继承 BaseSendDataHandler,实现具体分片与发送逻辑,现有实现 BleSendDataHandler 即挂接在 BLE 栈发送链路上。
  3. 实现扫描/连接契约:IScan/IConnect 定义了能力边界,新增传输栈(如未来的双模合并栈)只需实现这两个契约并接入 BluetoothManager,上层 OTA 流程无需改动。
  4. 复用统一错误码:新传输栈的所有失败路径都应翻译为 BluetoothErrorConstant 数值,保持上层错误处理单一化。

测试覆盖

本页所读取的基础层源码中未包含单元测试文件;BufferQueue 的异步门闩行为(空队列挂起、入队唤醒、clear 以 undefined 退出)是值得补充测试的关键路径,可参照其源码注释中的语义编写用例(等待者存在/不存在、多次 dequeueAsync、clear 后继续 enqueue 等分支)。

Related Links

  • 蓝牙 BLE 传输栈(BleImpl、BleDevice、BleSendDataHandler、IBleScan、IBleConnect)
  • 蓝牙 SPP 传输栈(SppImpl、SppDevice、ISppScan、ISppConnect)
  • 蓝牙管理与 OTA 编排(BluetoothManager、BluetoothOTAManager)
  • 基础层源码目录:ets/bluetooth/base
  • 错误码定义:BluetoothErrorConstant.ets
Next
BLE 模块实现