Harmony os Next——Ble蓝牙模块
Harmony os Next——Ble蓝牙模块的使用
- 描述
- 权限
- 扫描Ble蓝牙设备
- 传递扫描的Ble设备
- 接收扫描到的Ble设备
- 取消扫描Ble设备
- 连接Ble设备
- 断开连接
- 发现服务
- 订阅Ble特征值变化事件
- 订阅特征值通知
- 订阅特征值变化事件
- 取消订阅特征值变化事件
- 写入特征值
描述
本文将对Ble蓝牙模块的扫描、连接、订阅、发送指令等操作进行阐述。
需要导入如下依赖即可使用ble相关功能
import ble from '@ohos.bluetooth.ble'
权限
对Ble蓝牙进行操作需要系统权限和用户授权权限,其中系统权限包括ohos.permission.USE_BLUETOOTH
和ohos.permission.DISCOVER_BLUETOOTH
,用户授权权限包括ohos.permission.ACCESS_BLUETOOTH
扫描Ble蓝牙设备
其中ble.on("BLEDeviceFind", this.onReceiveEvent)
为定义蓝牙扫描事件,即为如果扫描到Ble蓝牙设备就会回调到此方法中。同时也可以添加过滤事件Array<ScanFilter>
,精确回调自己想要的设备,如果不需要进行过滤就赋值为null
即可
startScanBluetooth() {try {ble.on("BLEDeviceFind", this.onReceiveEvent) //订阅蓝牙let scanOptions: ble.ScanOptions = {interval: 500, //表示扫描结果上报延迟时间dutyMode: ble.ScanDuty.SCAN_MODE_LOW_POWER, //表示扫描模式matchMode: ble.MatchMode.MATCH_MODE_AGGRESSIVE, //表示硬件的过滤匹配模式}ble.startBLEScan(null, scanOptions)} catch (err) {LoggerJoy.error('BLEDeviceFind---> errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message)}}
传递扫描的Ble设备
从扫描到的蓝牙设备中筛选出自己想要的Ble设备,其中扫描的结果会返回很多DeviceName为空的设备,可以对其进行过滤,其中connectable为false,代表设备已经被配对;为true代表可连接。然后Emitter
进行进程间的通信,将扫描到的设备传递到UI层或者其他需要的地方
//扫描到的设备private onReceiveEvent(data: Array<ble.ScanResult>) {let bleObject = BluetoothStatusManager.getInstance()//如果在极短时间内发现新的设备,则不进行回调let curTime = new Date().getTime()let diff: number = curTime - bleObject.lastScanDeviceTimebleObject.lastScanDeviceTime = curTimeif (diff < 10) returntry {/** 从扫描到的蓝牙设备中筛选出自己想要的Ble设备* 其中扫描的结果会返回很多deviceName为空的设备,可以对其进行过滤* 其中connectable为false 代表设备已经被配对;为true代表可连接* */let requireDevices = data.filter((ble) => {return ble.deviceName.length > 0 && ble.connectable })// 进程中通信-将扫描到的设备传递到UI层// 定义一个eventId为1的事件,事件立即被传递// 发送eventId为1的事件,事件内容为eventDataemitter.emit({eventId: BluetoothStatusManager.BluetoothScanEventID,priority: emitter.EventPriority.IMMEDIATE}, {data: {'bleDevices': connectableDevices}})} catch (err) {LoggerJoy.error('BLEDeviceFind---> errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message)}}
接收扫描到的Ble设备
然后在UI层可以通过emitter.on
订阅指定事件,来获取传递的ble设备
getConnectableDevice(){//订阅eventId:1的事件-接受来自蓝牙扫描的设备let innerEvent: emitter.InnerEvent = {eventId: BluetoothStatusManager.BluetoothScanEventID}// 收到eventId为1的事件后执行回调函数emitter.on(innerEvent, (eventData: emitter.EventData) => {if (eventData.data === undefined) {LoggerJoy.info('BLEDeviceFind---> Scan device is empty!')return}let connectableDevice = eventData.data['bleDevices'] as Array<ble.ScanResult>//对扫描的ble设备进行处理})}
取消扫描Ble设备
在停止蓝牙扫描设备时,同样也需要通过emitter.off
取消订阅蓝牙传递事件
//停止扫描蓝牙设备stopScanBluetooth() {emitter.off(BluetoothStatusManager.BluetoothScanEventID) //断开订阅蓝牙扫描结果事件ble.stopBLEScan() //停止扫描蓝牙}
连接Ble设备
蓝牙状态 | 值 | 备注 |
---|---|---|
STATE_DISCONNECTED | 0 | 已断连 |
STATE_CONNECTING | 1 | 正在连接 |
STATE_CONNECTED | 2 | 已连接 |
STATE_DISCONNECTING | 3 | 正在断连 |
通过device.connect()
连接ble蓝牙设备,需要指定扫描ble蓝牙设备时返回的数据中的deviceId
,此字断即为ble设备的MAC地址
,此地址可能会在ble设备下线、断开连接情况下发生变化。
然后可以通过device.on('BLEConnectionStateChange')
订阅此设备的连接状态
/** 连接蓝牙设备--通过ble Mac地址进行连接* */connectBleDevice(deviceId: string) {try {let objetClass = BluetoothStatusManager.instancelet device: ble.GattClientDevice = ble.createGattClientDevice(deviceId)LoggerJoy.info(`BLEDeviceFind---> start connection ble device`)device.connect()device.on('BLEConnectionStateChange', (state: ble.BLEConnectionChangeState) => {//0:STATE_DISCONNECTED 已断连//1:STATE_CONNECTING 正在连接//2:STATE_CONNECTED 已连接//3:STATE_DISCONNECTING 正在断连let connectState: ble.ProfileConnectionState = state.stateif (connectState === constant.ProfileConnectionState.STATE_CONNECTED) {//连接成功之后的事件处理} else if (connectState === constant.ProfileConnectionState.STATE_DISCONNECTED) {//已经断开连接}})} catch (err) {LoggerJoy.error('errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message)}}
断开连接
在与设备断开连接时,也可以取消订阅连接状态事件
disconnectionBleDevice(deviceId: string) {try {if (this.gattClientDevice) {this.gattClientDevice.disconnect()this.gattClientDevice.off('BLEConnectionStateChange')LoggerJoy.info(`BLEDeviceFind---> stop connection ble device`)}} catch (err) {LoggerJoy.error('errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message)}}
发现服务
在连接ble设备之后可以进行发现服务操作,获取Ble设备的相关操作,例如读和写。其中包含Ble设备的ServiceUUID、特征值内容和描述符内容等
device.getServices().then((result: Array<ble.GattService>) => {//对服务进行操作}).catch((err: BusinessError) => {LoggerJoy.error('errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message)})
订阅Ble特征值变化事件
订阅特征值通知
只有在发现服务之后,通过发现服务所返回的数据,即可对特定特征值通知进行订阅
/** 订阅通知消息-只有打开了订阅,才能接受特征值变化响应* */setNotificationChannel() {if (!this.gattServiceInfo || !this.gattClientDevice) {LoggerJoy.info('BLEDeviceFind---> bluetooth gattServiceInfo is undefined ');return}//在发现服务中返回的数据中,过滤出自己特定所需事件即可let readCharacteristic = readCharacteristics[0]try {LoggerJoy.info('BLEDeviceFind---> setCharacteristicChangeNotification finish')this.gattClientDevice?.setCharacteristicChangeNotification(readCharacteristic, true)} catch (err) {LoggerJoy.error('errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message);}}
订阅特征值变化事件
只有打开特征值通知订阅(上节内容),才能接受特征值变化响应。
然后通过 this.gattClientDevice?.on('BLECharacteristicChange')
即可响应特征值变化事件
onBleCharacteristicChange() {if (!this.gattClientDevice) {LoggerJoy.info('BLEDeviceFind---> bluetooth device is disconnected')return}try {this.gattClientDevice?.on('BLECharacteristicChange', (characteristicChangeReq: ble.BLECharacteristic) => {LoggerJoy.info(`BLEDeviceFind---> onBleCharacteristicChange: ${JSON.stringify(characteristicChangeReq)}`)} catch (err) {LoggerJoy.error('errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message)}}
取消订阅特征值变化事件
offBleCharacteristicChange() {if (!this.gattClientDevice) {LoggerJoy.info('BLEDeviceFind---> bluetooth device is disconnected')return}try {this.gattClientDevice.off('BLECharacteristicChange')LoggerJoy.info('BLEDeviceFind---> cancel BLECharacteristicChange')} catch (err) {LoggerJoy.error('errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message)}}
写入特征值
同意需要在发现服务中过滤出写入特征值的服务。此处以传入Uint8Array
为例,因为writeCharacteristic.characteristicValue
所需要数据为ArrayBuffer
,所以通过buffer.from(需要转换的数据).buffer
进行转换。最后通过this.gattClientDevice?.writeCharacteristicValue(writeCharacteristic, ble.GattWriteType.WRITE)
完成特征值写入事件。
async writeCharacteristicValue(command: Uint8Array) {if (!this.gattServiceInfo || !this.gattClientDevice) {return}//从发现服务中过滤出写入事件let writeCharacteristic = writeCharacteristics[0]//Uint8Array转ArrayBufferwriteCharacteristic.characteristicValue = buffer.from(command).buffertry {this.gattClientDevice?.writeCharacteristicValue(writeCharacteristic, ble.GattWriteType.WRITE, ()=>{LoggerJoy.info('BLEDeviceFind---> writeCharacteristicValue success')})} catch (err) {LoggerJoy.error('errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message)}}