蓝牙模块

最近更新时间:2024-10-08 18:37:11

我的收藏

名词解释

名词
含义
serviceId
服务 id,蓝牙服务的 uuid,搜索设备时主要通过 serviceId 来过滤我们需要的设备。
deviceId
小程序 API 搜索出来的设备的标识,连接设备时主要通过 deviceId 来标识需要连接的设备。
explorerDeviceId
物联网开发平台侧定义的设备 ID,查询设备数据和上报设备数据时以设备 ID 作为设备标识。
BlueToothAdapter 蓝牙适配器
全局单例,实例上声明了蓝牙搜索、连接等方法。
DeviceAdapter 设备适配器
真正用来连接设备以及跟设备进行通信的模块,每一个设备连接对应一个设备适配器实例,设备适配器会在连接设备后实例化,并在设备断开连接后销毁。根据不同的 serviceId 来区别不同类型设备的适配器构造函数。

蓝牙适配器

添加设备适配器

添加一个设备适配器。使用蓝牙模块时需要根据具体设备情况创建一个设备适配器,并调用本接口将其构造函数添加到蓝牙适配器中。H5 SDK 默认添加了一个支持 LLSync 蓝牙协议的设备适配器。
接口定义
sdk.blueToothAdapter.addAdapter(deviceAdapter: DeviceAdapterConstructor) => void
参数说明
参数名
参数描述
类型
必填
deviceAdapter
要添加的设备适配器的构造函数。
DeviceAdapterConstructor
示例代码
class DemoDeviceAdapter extends DeviceAdapter {
static serviceId = '0000FFF0-0000-1000-8000-00805F9B34CC';
static deviceFilter(deviceInfo) {
if (deviceInfo.advertisServiceUUIDs) {
const matchedServiceId = deviceInfo.advertisServiceUUIDs.find(id => id === DemoDeviceAdapter.serviceId);
if (matchedServiceId && deviceInfo.advertisData) {
try {
const macArr = deviceInfo.advertisData.slice(2);
const mac = macArr.join(':');
return {
...deviceInfo,
deviceName: mac,
serviceId: matchedServiceId,
};
} catch (err) {
console.error('parse mac error', err);
}
}
}
}
handleBLEMessage(hex) {
return {
type: 'unknown',
data: hex,
};
}
}
sdk.blueToothAdapter.addAdapter(DemoDeviceAdapter);

初始化蓝牙模块

初始化蓝牙模块,包括初始化蓝牙模块、打通小程序间蓝牙通信以及注册全局回调等。本接口可重复调用,可在每次使用蓝牙模块前调用。
接口定义
sdk.blueToothAdapter.init() => Promise<void>
返回值 返回一个带缓存的 Promise,初始化成功后 resolve。若初始化未完成或已初始化成功,则多次调用后返回同一个 Promise。若初始化失败,则该缓存的 Promise 在 reject 之后会被释放,再次调用则将重新初始化。
示例代码
sdk.blueToothAdapter.init().then(() => {
// 调用蓝牙模块能力
});
开始搜索蓝牙设备。(将会调用 wx.startBluetoothDevicesDiscovery,比较耗费系统资源,务必在不需要搜索后调用 停止搜索蓝牙设备,如离开页面后)。
接口定义
sdk.blueToothAdapter.startSearch({
serviceId?: string,
serviceIds?: string[],
ignoreDeviceIds?: string[],
onSearch: (DeviceInfo[]) => void,
onError: (Error) => void,
timeout: number
}) => Promise<void>
参数说明
参数名
参数描述
类型
必填
serviceId
指定需要搜索的 serviceId,不传的话会使用当前支持的所有 DeviceAdapter 的 serviceId 来匹配。
string
serviceIds
参数描述同 serviceId。
string[]
ignoreDeviceIds
可选,需要过滤掉的 deviceId 列表(例如刚添加完的设备),搜索结果中将不会出现这些设备。
string[]
onSearch
当搜索结果更新后调用,返回搜索到的设备列表。
(DeviceInfo[]) => void
onError
当搜索过程中发生错误后调用,触发后设备搜索将会中止。
(Error) => void
timeout
可选,默认20000,单位毫秒,超过指定时长没有搜索到设备后将会触发超时错误。
number
返回值
返回一个 Promise。
接口定义
sdk.blueToothAdapter.stopSearch() => void

搜索单个蓝牙设备

开始搜索蓝牙设备,并在搜索到第一个满足条件的设备后停止搜索。
接口定义
sdk.blueToothAdapter.searchDevice({
deviceName: string,
serviceId?: string,
serviceIds?: string[],
ignoreDeviceIds?: string[]
}) => Promise<DeviceInfo>
参数说明
参数名
参数描述
类型
必填
deviceName
指定需要搜索的设备 deviceName。
string
serviceId
指定需要搜索的 serviceId,不传的话会使用当前支持的所有 DeviceAdapter 的 serviceId 来匹配。
string
serviceIds
参数描述同 serviceId。
string[]
ignoreDeviceIds
可选,需要过滤掉的 deviceId 列表(例如刚添加完的设备),搜索结果中将不会出现这些设备。
string[]
返回值
返回一个 Promise,在找到第一个满足条件的设备后 resolve。

连接蓝牙设备

连接指定蓝牙设备。
接口定义
blueToothAdapter.connectDevice(deviceInfo: DeviceInfo, options?: { autoNotify?: boolean }) => Promise<DeviceAdapter>
参数说明
参数名
参数描述
类型
必填
deviceInfo
传入 开始搜索蓝牙设备搜索单个蓝牙设备 接口搜索出来的 DeviceInfo。
DeviceInfo
options.autoNotify
可选,默认为 true。指定为 true 时,在连接设备后,会自动去拉取服务列表,以及主服务下的特征值列表,并会自动订阅第一个 notifyId 或 indicateId 特征值的 notify。若设备含有多个服务或多个 notify 特征值,请传 false,并自行通过 getBLEDeviceServices、getBLEDeviceCharacteristics、notifyBLECharacteristicValueChange 等方法获取及订阅特征值。
boolean
返回值
返回一个 Promise,连接成功后返回设备适配器。

获取设备适配器实例

根据 deviceId 查询对应的设备适配器实例。
接口定义
sdk.blueToothAdapter.getDeviceAdapter({ explorerDeviceId: string }) => DeviceAdapter
参数说明
参数名
参数描述
类型
必填
explorerDeviceId
设备适配器实例的 explorerDeviceId,可以通过 sdk.deviceId 获得。
string
返回值
返回与传入 explorerDeviceId 相匹配的设备适配器实例,如果找不到,则返回 undefined

上报设备信息

蓝牙设备不能通过mqtt直接上报设备的mac地址等信息,所以需要H5端进行上报,对应的是设备详情里面的设备信息


注意:
图片里面厂家名称和产品型号是在设备量产时在控制台填写的,mac 地址,固件版本等由 H5 端进行上报
接口定义
sdk.blueToothAdapter.reportDeviceInfo({ productId: string, deviceName: string, deviceInfo: any }) => Promise;
参数说明
参数名
参数描述
类型
productId
产品 ID。
string
deviceName
设备名称。
string
deviceInfo
设备信息。
any,详情见下面示例
deviceInfo: {
"module_hardinfo": "模组具体硬件型号 N10",
"module_softinfo": "模组软件版本",
"fw_ver": "mcu 固件版本",
"imei": "设备 imei 号,可选上报",
"mac": "设备 mac 地址,可选上报",
"device_label": {
"append_info": "设备商自定义的产品附加信息"
}
}

监听蓝牙适配器事件

监听蓝牙适配器事件。
接口定义
sdk.blueToothAdapter.on(type: string, listener: (...args) => void) => void
参数说明
参数名
参数描述
类型
必填
type
要监听的事件。
string
listener
事件触发时的回调函数。
(...args) => void

取消监听蓝牙适配器事件

取消监听蓝牙适配器事件。
接口定义
sdk.blueToothAdapter.off(type: string, listener: (...args) => void) => void
参数说明
参数名
参数描述
类型
必填
type
要取消监听的事件。
string
listener
要取消监听的事件的回调函数,不传则清除该事件的所有回调函数。
(...args) => void

蓝牙适配器事件

adapterStateChange 事件:当适配器状态变化时触发。
参数名
参数描述
类型
available
蓝牙适配器是否可用
boolean
discovering
蓝牙适配器是否处于搜索状态
boolean

设备适配器

自定义设备适配器

自定义设备适配器类需要继承 DeviceAdapter,并补充以下实现。
serviceId:自定义设备适配器类需要设置该属性,代表该设备的主服务 ID。
deviceFilter:自定义设备适配器类需要实现该静态方法,在搜索蓝牙设备时会将每个搜出的设备信息传入该方法,如果判断是本产品的设备,则需在除入参 deviceInfo 之外返回设备唯一标识 deviceName 及 serviceId,否则返回空。
DeviceAdapter.deviceFilter: (deviceInfo: DeviceInfo) => {
deviceName: string,
serviceId: string,
...deviceInfo
}
handleBLEMessage:自定义设备适配器类需要实现该方法,用于处理收到 onBLECharacteristicValueChange 回调后的协议解析。
DeviceAdapter.handleBLEMessage: (hexString, { serviceId, characteristicId }) => {
reportData?: any,
...any
}
返回值中如果返回 reportData,则会将该部分数据上报到云端(注意需与产品定义物模型匹配),其他字段则会透传到 message 事件的 payload 中。

设备适配器属性

属性名
属性描述
类型
explorerDeviceId
只读,设备的 explorerDeviceId。
string
isConnected
只读,当前是否已连接设备。
boolean
deviceId
只读,设备的 deviceId。
string
serviceId
只读,设备的主服务 ID,与构造函数上的静态属性 DeviceAdapter.serviceId 一致。
string
originName
只读,设备的原始名称,即小程序接口搜索出来时的 name 字段。
string

断开设备连接

接口定义
deviceAdapter.disconnectDevice() => void

获取设备服务列表

接口定义
deviceAdapter.getBLEDeviceServices() => Promise<ServiceList>
返回值
返回一个 Promise,ServiceList 数据结构请参见 wx.getBLEDeviceServices

获取设备指定服务的特征值列表

获取设备指定服务中的特征值列表,并将特征值存放在 deviceAdapter 实例上。
接口定义
deviceAdapter.getBLEDeviceCharacteristics({ serviceId: string }) => Promise<CharacteristicsList>
参数说明
参数名
参数描述
类型
必填
serviceId
可选,指定要获取特征值列表的服务 ID,默认为主服务 ID。
string
返回值
返回一个 Promise,CharacteristicsList 数据结构请参见 wx.getBLEDeviceCharacteristics
说明
将获取到的特征值按照如下数据结构存放在 deviceAdapter 实例上。
deviceAdapter.characteristicsMap[serviceId] = {
notifyIds: string[],
indicateIds: string[],
writeIds: string[],
readIds: string[]
}

协商设置蓝牙最大传输单元

本接口仅支持在 Android 系统下调用,iOS 因系统限制不支持。
接口定义
deviceAdapter.setBLEMTU({ mtu: number }) => Promise
参数说明
参数名
参数描述
类型
必填
mtu
最大传输单元。设置范围为 (22,512) 区间内,单位为 bytes。
number
返回值
返回一个 Promise。

读取指定特征值的二进制数据

接口定义
deviceAdapter.readBLECharacteristicValue({
serviceId?: string,
characteristicId: string
}) => Promise<void>
参数说明
参数名
参数描述
类型
必填
serviceId
可选,默认为主服务 ID。
string
characteristicId
需要读取的特征值 ID,默认会取主服务下的第一个 read 特征值。
string
返回值
返回一个 Promise。接口读取到的信息需要在 onBLECharacteristicValueChange 方法注册的回调中获取,具体参见 wx.readBLECharacteristicValue

获取蓝牙设备信号强度

接口定义
deviceAdapter.getBLEDeviceRSSI() => Promise
返回值
返回一个 Promise,具体数据结构请参见 wx.getBLEDeviceRSSI

启用特征值变化时的 notify 功能

接口定义
deviceAdapter.notifyBLECharacteristicValueChange({
characteristicId?: string,
serviceId?: string,
state?: boolean
}) => Promise<void>
参数说明
参数名
参数描述
类型
必填
serviceId
需要订阅的服务 ID,默认会取主服务 ID。
string
characteristicId
需要订阅的特征值 ID,默认会取主服务下的第一个 notify 或 indicate 特征值。
string
state
是否启用 notify,默认为 true。
boolean
返回值
返回一个 Promise。

写入二进制数据到指定特征值中

接口定义
deviceAdapter.write(hexString: string, options?: {
writeId?: string,
serviceId?: string
}) => Promise
参数说明
参数名
参数描述
类型
必填
hexString
需要写给蓝牙设备的十六进制字符串。
string
options.writeId
可选,需要写入的特征值 ID,默认会取主服务下的第一个 writeId。
string
options.serviceId
可选,需要写入的服务 ID,默认会取主服务 ID。
string

监听事件

可以使用 deviceAdapter.on监听设备适配器事件
接口定义
deviceAdapter.on(type: string, listener: (...args) => void) => void
参数说明
参数名
参数描述
类型
必填
type
要监听的事件。
string
listener
事件触发时的回调函数。
(...args) => void

取消监听事件

取消监听设备适配器事件。
接口定义
deviceAdapter.off(type: string, listener: (...args) => void) => void
参数说明
参数名
参数描述
类型
必填
type
要取消监听的事件。
string
listener
要取消监听的事件的回调函数,不传则清除该事件的所有回调函数。
(...args) => void

设备适配器事件

connect 事件:设备连接后触发。
disconnect 事件:设备断开后触发。
message 事件:当收到 onBLECharacteristicValueChange 回调,并经过 handleBLEMessage 处理后触发。
参数名
参数描述
类型
timestamp
收到设备消息的时间戳,单位毫秒。
number
dataReported
收到设备的消息是否已上报云端。
boolean
(其他)
handleBLEMessage 函数返回的其他参数将会透传到 message 事件中。
any
bLEConnectionStateChange 事件:当 onBleConnectionStateChange 触发时触发,若 connected 为 true,则接下来会触发 connect 事件,否则会触发 disconnect 事件。
参数名
参数描述
类型
connected
设备是否连接。
boolean

标准蓝牙协议

LLSync 标准蓝牙协议设备的绑定流程在小程序中进行,开发者只需在自定义 H5 面板中关注设备的连接、控制操作与事件监听。自定义 H5 面板已默认添加 LLSync 标准蓝牙协议的设备适配器(StandardDeviceAdapter),支持通过 LLSync 标准蓝牙协议与设备通信。H5 面板 Demo 中提供了 标准蓝牙协议 demo 供开发者参考。

搜索并连接设备

与标准蓝牙协议设备建立连接的过程分为三个步骤:搜索设备、连接设备、连接鉴权。示例代码如下:
import { StandardDeviceAdapter } from 'qcloud-iotexplorer-h5-panel-sdk';

// 初始化蓝牙适配器
await sdk.blueToothAdapter.init();

// 搜索设备
const deviceInfo = await sdk.blueToothAdapter.searchDevice({
deviceName: sdk.deviceName,
serviceId: StandardDeviceAdapter.serviceId,
productId: sdk.productId,
disableCache: true,
});

if (!deviceInfo) {
throw new Error('未搜索到设备');
}

// 连接设备
const deviceAdapter = await sdk.blueToothAdapter.connectDevice({
...device,
productId: sdk.productId,
});

// 连接鉴权
if (!deviceAdapter.authorized) {
await deviceAdapter.authenticateConnection({
deviceName: sdk.deviceName,
});
}

设备通信

通过上述流程与设备建立连接后,H5 面板即可控制设备,接收设备的属性、事件上报。
控制设备
接口定义请参见 控制设备属性,示例代码如下:
sdk.controlDeviceData({
// 要控制的设备属性
power_switch: 1
});
监听设备事件 接口定义请参见 事件监听,示例代码如下:
// 监听设备属性上报
sdk.on('wsReport', ({ deviceId, deviceData }) => {
console.log('device', deviceId, 'report_property', deviceData);
});

// 监听设备事件上报
sdk.on('wsEventReport', ({ deviceId, Payload }) => {
console.log('device', deviceId, 'report_event', Payload);
});

设备适配器属性

属性名
属性描述
类型
explorerDeviceId
只读,设备在物联网开发平台的 DeviceId。
string
isConnected
只读,当前是否已连接设备。
boolean
deviceId
只读,小程序蓝牙接口提供的 deviceId。
string
serviceId
只读,设备的主服务 ID,与构造函数上的静态属性 DeviceAdapter.serviceId 一致。
string
originName
只读,设备的原始名称,即小程序接口搜索出来时的 name 字段。
string
bleVersion
只读,LLSync 协议版本号。
number
mtu
只读,设备要求设置的最大传输单元 (MTU) 大小。
number
otaVersion
只读,设备固件版本号。
string
extendInfo.macStr
只读,设备的 mac 地址。
string
authorized
只读,是否与设备完成鉴权。
boolean

BLE + WIFI 双路通信

针对 Wi-Fi + BLE Combo 模组,提供设备端 SDK 和 H5 SDK,支持设备 Wi- Fi 离线状态下,小程序通过 LLSync 标准蓝牙协议与设备通信,为用户提供 Wi-Fi 断网下的更佳体验。设备端 SDK 请参考 开发指引
对于自定义 H5 面板,配网流程无需开发者关注,开发者需要在面板中关注:
1. 监听设备在线状态,wifi连接是否正常。
2. 当设备离线时启用蓝牙进行通信。下面分开说明。

监听设备在线状态

我们可以通过监听 WebSocket 事件 中的 wsStatusChange 事件来感知设备的在线离线状态。
sdk.on('wsStatusChange', ({deviceId, deviceStatus}) => {
if (deviceStatus === 0) {
// 设备已离线,开始启用蓝牙连接进行通信,见第二步
}
})

启用蓝牙通信

我们提供了 双路通信 demo 供参考。
1. 添加 BleComboDualModeDeviceAdapter4H5
BleComboDualModeDeviceAdapter4H5 是一个设备适配器实例,如果您还不了解设备适配器,请阅读 设备适配器部分
import { BleComboDualModeDeviceAdapter4H5 } from 'qcloud-iotexplorer-appdev-plugin-wificonf-blecombo/lib/protocols/BleComboDualMode';

const sdk = window.h5PanelSdk;
BleComboDualModeDeviceAdapter4H5.injectOptions({ appDevSdk: sdk.appDevSdk });


sdk.blueToothAdapter.addAdapter(BleComboDualModeDeviceAdapter4H5, true);
2. 搜索设备
searchDevice 的参数详见 蓝牙适配器 搜索单个蓝牙设备的参数说明部分。
await blueToothAdapter.init();
console.log('开始搜索设备', sdk.deviceName);
const deviceInfo = await blueToothAdapter.searchDevice({
deviceName: sdk.deviceName,
serviceId: BleComboDualModeDeviceAdapter4H5.serviceId,
productId: sdk.productId,
disableCache: true,
});
3. 连接设备
使用上一步获取到的 deviceInfo, 我们可以调用 connectDevice 连接设备以获得 deviceAdapter,传入参数定义详见 连接蓝牙设备 部分。
const deviceAdapter = await blueToothAdapter.connectDevice({
...device,
productId: sdk.productId,
});
console.log('deviceAdapter:', deviceAdapter);
// authorized之后,才能向设备发送控制数据
if (!deviceAdapter.authorized) {
await deviceAdapter.authenticateConnection({
deviceName: sdk.deviceName,
});
}
当小程序和设备间的蓝牙连接成功后,面板就可以对设备进行控制了,sdk会将控制数据通过蓝牙发送到设备。例如进行开关的控制:
sdk.controlDeviceData({ power_switch: 1 });