• Harmony os Next——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,精确回调自己想要的设备,如果不需要进行过滤就赋值为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.lastScanDeviceTime
        bleObject.lastScanDeviceTime = curTime
        if (diff < 10) return
        try {
          /*
         * 从扫描到的蓝牙设备中筛选出自己想要的Ble设备
         * 其中扫描的结果会返回很多deviceName为空的设备,可以对其进行过滤
         * 其中connectable为false 代表设备已经被配对;为true代表可连接
         * */
          let requireDevices = data.filter((ble) => {
            return ble.deviceName.length > 0 && ble.connectable 
          })
          // 进程中通信-将扫描到的设备传递到UI层
          // 定义一个eventId为1的事件,事件立即被传递
          // 发送eventId为1的事件,事件内容为eventData
          emitter.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.instance
          let 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.state
            if (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转ArrayBuffer
        writeCharacteristic.characteristicValue = buffer.from(command).buffer
    
        try {
        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)
        }
      }
    
  • 相关阅读:
    React——form的校验和验证规则(使用formik,yup)
    【1331. 数组序号转换】
    周赛368 合法分组的最少组数(灵神笔记)
    软件架构设计(八) 基于架构的软件开发方法
    跨域访问错误的这一种解决方法
    贪心算法-金条切割问题
    Java面向对象——多态
    vite构建项目不能使用require解决方案
    Git add回退 & commit回退
    华纳云:负载均衡服务器的作用是什么 有哪些方式
  • 原文地址:https://blog.csdn.net/News53231323/article/details/139390346