本页目录
底层传输插件(Low-level Transport Plugin)
仅在 WebUSB / React Native BLE / 官方原生适配器无法满足需求时使用。你需要自管原生 BLE 生命周期和有序收发,维护成本更高。
注意:
lowlevel环境和LowlevelTransportSharedPlugin仅用于 BLE(蓝牙) 通信。对于 Node.js/CLI 环境下的 USB 通信,请使用NodeUsbTransport(env 为node-usb)—— 它通过 libusb 直接处理协议编解码和 USB I/O,不需要插件。
我们的蓝牙 SDK 基于 React Native。如果你使用 Swift/Kotlin/Flutter 等非 RN 技术栈,引入 RN 依赖可能不合适。可通过 LowlevelTransportSharedPlugin 自行适配底层传输,负责”连接/断开/收发数据”协议。
快速参考
OneKey BLE UUID
| 用途 | UUID |
|---|---|
| 服务 | 00000001-0000-1000-8000-00805f9b34fb |
| 写入特征 | 00000002-0000-1000-8000-00805f9b34fb |
| 通知特征 | 00000003-0000-1000-8000-00805f9b34fb |
Protocol V1 BLE 头部数据示例
以下帧头仅适用于 Protocol V1,不能用于解析 Protocol V2 通知。
原始数据: 3F 23 23 00 02 00 00 00 0A 12 08 ...
│ │ │ │ │ │ │ └─ Protobuf 载荷开始
│ │ │ │ │ └────────┴─ 载荷长度: 0x0000000A = 10 字节
│ │ │ └──┴─ 消息类型: 0x0002
└──┴──┴─ Magic: 0x3F 0x23 0x23 (固定标识)检测头部包:前 3 字节为 3F 23 23
原生示例(均基于低层插件):
- Android 原生 — WebView + JSBridge + Nordic BLE
- iOS 原生 — WebView + JSBridge + CoreBluetooth
- Flutter 原生 — WebView + platform channel + BLE
LowlevelTransportSharedPlugin 接口
import type { OneKeyDeviceInfoBase } from '@onekeyfe/hd-transport';
export type LowLevelDevice = OneKeyDeviceInfoBase & { id: string; name: string };
export type LowlevelTransportSharedPlugin = {
enumerate: () => Promise<LowLevelDevice[]>;
send: (uuid: string, data: string, options?: { withoutResponse?: boolean }) => Promise<void>;
receive: (uuid?: string) => Promise<string>;
connect: (uuid: string) => Promise<void>;
disconnect: (uuid: string) => Promise<void>;
getProtocolV2PacketCapacity?: (uuid: string) => number | undefined | Promise<number | undefined>;
init: () => Promise<void>;
version: string;
};WebUSB vs BLE:Protocol V1 帧格式
下表描述 Protocol V1。低层插件是 BLE 适配器;协议探测、编码和重组由 SDK 负责。
| WebUSB (桌面端) | BLE (原生移动端) | |
|---|---|---|
| 数据包大小 | 固定 64 字节 | 可变长度 (取决于 MTU) |
| 每个包前缀 | 所有包都有 0x3F | 仅头部包有 0x3F 0x23 0x23 |
| 填充 | 零填充到 64 字节 | 无需填充 |
receive() 返回 | 每次一个 64 字节帧 | 原始 BLE 通知数据块(hex) |
WebUSB Protocol V1(桌面端)
传输使用固定 64 字节帧,SDK 负责消息组装。
Magic bytes 说明:
0x3F 0x23 0x23是协议固定的标识字节,用于识别数据包的起始位置。
首帧:
| Offset | Length | Content |
|---|---|---|
| 0 | 3 | Magic: 0x3F 0x23 0x23 |
| 3 | 2 | 消息类型 (大端 u16) |
| 5 | 4 | 载荷长度 (大端 u32) |
| 9 | 55 | 前 55 字节 protobuf(零填充) |
后续帧:
| Offset | Length | Content |
|---|---|---|
| 0 | 1 | Magic: 0x3F |
| 1 | 63 | 剩余 protobuf 字节(零填充) |
BLE 协议(原生移动端)
每次 receive(uuid) 从队列返回一个未经修改的 BLE 通知数据块,编码为 hex。保留通知顺序,并缓存早于读取请求到达的数据。插件不要删除协议头、填充为 USB 的 64 字节包或解码 protobuf。
- Protocol V1: SDK 识别
3F2323帧头、读取载荷长度并收集后续数据块。为兼容旧插件,V1 也接受预先重组的type + length + payload消息。 - Protocol V2: SDK 将原始数据块组装为帧,处理 CRC、序号和消息重组。不能用仅支持 V1 的帧头检测或重组逻辑处理这些数据。
send(uuid, data, options)接收 SDK 准备好的 hex 数据,按顺序写入字节,传递 I/O 错误,并在提供withoutResponse时遵循该选项。- 通过
getProtocolV2PacketCapacity返回单次 BLE 特征写入实际支持的最大字节数。SDK 默认使用 192 字节,V2 包上限为 244 字节。返回可写入容量,不是包含协议开销的 ATT MTU。 - 断开时拒绝待处理的读取并清除旧连接的通知队列,不要在重连后继续交付旧数据。
初始化示例
以下适配片段委托给实现上述接口的原生桥接层。各方法应在对应操作完成后 resolve,失败时 reject。
import HardwareSDK from '@onekeyfe/hd-common-connect-sdk';
import type { LowlevelTransportSharedPlugin } from '@onekeyfe/hd-transport';
// Implement these methods in your native BLE bridge before initialization.
declare const nativeBle: LowlevelTransportSharedPlugin;
const plugin: LowlevelTransportSharedPlugin = {
enumerate: () => nativeBle.enumerate(),
send: (uuid, data, options) => nativeBle.send(uuid, data, options),
receive: uuid => nativeBle.receive(uuid),
connect: uuid => nativeBle.connect(uuid),
disconnect: uuid => nativeBle.disconnect(uuid),
getProtocolV2PacketCapacity: uuid => nativeBle.getProtocolV2PacketCapacity?.(uuid),
init: () => nativeBle.init(),
version: nativeBle.version,
};
const result = await HardwareSDK.init({ env: 'lowlevel', debug: false }, undefined, plugin);
if (!result) throw new Error('SDK initialization failed');下一步
- Android 指南 — 配对、权限与连接完成条件
- iOS 指南 — CoreBluetooth 实现
- Flutter 指南 — Platform channel 桥接