当前位置: 首页 > news >正文

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_BLUETOOTHohos.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_DISCONNECTED0已断连
STATE_CONNECTING1正在连接
STATE_CONNECTED2已连接
STATE_DISCONNECTING3正在断连

通过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)}}

相关文章:

  • Linux 自动化升级Jar程序,指定Jar程序版本进行部署脚本
  • 【银角大王——Django课程——Ajax请求】
  • FJSP:波搜索算法(WSA)求解柔性作业车间调度问题(FJSP),提供MATLAB代码
  • 压测工具sysbench
  • 性能监控计算——封装带性能计算并上报的npm包(第三章)
  • 【TIPs】 Visual Stadio 2019 中本地误使用“git的重置 - 删除更改 -- hard”后,如何恢复?
  • 初识SDN
  • python-数据可视化(总)
  • Qt for Android
  • 代码随想录--哈希表--两数之和
  • 关于模拟信道和数字信道根本区别的探讨
  • 常用maven - jar 下载与 安装
  • 国产可视化爬虫助力AI大模型训练:精准爬取汉语词典
  • cv2函数实践-图像处理(中心外扩的最佳RoI/根据两个坐标点求缩放+偏移后的RoI/滑窗切片/VOC的颜色+调色板)
  • 顶点着色技术在AI去衣中的作用
  • 《Javascript高级程序设计 (第三版)》第五章 引用类型
  • 《微软的软件测试之道》成书始末、出版宣告、补充致谢名单及相关信息
  • es的写入过程
  • JavaScript 是如何工作的:WebRTC 和对等网络的机制!
  • JavaScript设计模式与开发实践系列之策略模式
  • Python学习之路16-使用API
  • VuePress 静态网站生成
  • 阿里云前端周刊 - 第 26 期
  • 笨办法学C 练习34:动态数组
  • 诡异!React stopPropagation失灵
  • 排序算法学习笔记
  • 判断客户端类型,Android,iOS,PC
  • 前端js -- this指向总结。
  • 前端之Sass/Scss实战笔记
  • 移动互联网+智能运营体系搭建=你家有金矿啊!
  • 责任链模式的两种实现
  • 怎么将电脑中的声音录制成WAV格式
  • 正则表达式-基础知识Review
  • ​经​纬​恒​润​二​面​​三​七​互​娱​一​面​​元​象​二​面​
  • !!Dom4j 学习笔记
  • !!java web学习笔记(一到五)
  • # 计算机视觉入门
  • ## 1.3.Git命令
  • #Datawhale AI夏令营第4期#AIGC方向 文生图 Task2
  • (33)STM32——485实验笔记
  • (C语言)fread与fwrite详解
  • (C语言)strcpy与strcpy详解,与模拟实现
  • (二)基于wpr_simulation 的Ros机器人运动控制,gazebo仿真
  • (附源码)spring boot校园健康监测管理系统 毕业设计 151047
  • (回溯) LeetCode 131. 分割回文串
  • (三)终结任务
  • (四)React组件、useState、组件样式
  • **登录+JWT+异常处理+拦截器+ThreadLocal-开发思想与代码实现**
  • .NetCore+vue3上传图片 Multipart body length limit 16384 exceeded.
  • .net开源工作流引擎ccflow表单数据返回值Pop分组模式和表格模式对比
  • /tmp目录下出现system-private文件夹解决方法
  • @angular/cli项目构建--http(2)
  • @Pointcut 使用
  • @Validated和@Valid校验参数区别
  • [ C++ ] 类和对象( 下 )