HarmonyOS 鸿蒙Next 物联网Iot开发-BLE设备连接

发布于 1周前 作者 h691938207 来自 鸿蒙OS

HarmonyOS 鸿蒙Next 物联网Iot开发-BLE设备连接

概述

蓝牙技术是一种无线通信技术,可以在短距离内传输数据。它是由爱立信公司于1994年提出的,使用2.4 GHz的ISM频段,可以在10米左右的距离内进行通信。可以用于连接手机、耳机、音箱、键盘、鼠标、打印机等各种设备。特点是低功耗、低成本、简单易用。目前已经发展到了第五代,支持更高的数据传输速率和更广的覆盖范围。

实现原理

蓝牙的实现原理是基于无线电技术的短距离通信协议,使用2.4GHz频段的无线电波进行通信,使用频率跳跃技术(Frequency Hopping Spread Spectrum,FHSS)来避免与其他无线设备的干扰。在通信过程中,蓝牙设备会发送和接收数据包,并且使用不同的蓝牙协议来控制通信流程和数据传输。

蓝牙服务

在连接蓝牙设备时,查找蓝牙服务是一项重要的步骤。蓝牙服务是蓝牙设备上提供的功能或特性的抽象表示,它们定义了设备可以提供的各种功能,比如数据传输、音频播放、传感器数据等。每个蓝牙服务都包含一个或多个特征(Characteristics),这些特征描述了服务所提供的具体功能或属性。

查找蓝牙服务的主要作用包括:

  1. 识别设备功能:通过查找蓝牙服务,可以了解到连接的蓝牙设备所提供的功能和特性。这有助于应用程序确定如何与设备进行交互,并选择正确的服务来执行所需的操作。
  2. 建立通信通道:一旦找到了需要的蓝牙服务,应用程序可以与设备建立通信通道,以便发送和接收数据。通常,应用程序需要与设备的特定服务进行通信,才能执行相应的操作。
  3. 配置和控制设备:通过蓝牙服务,应用程序可以向设备发送命令或配置参数,以控制设备的行为或进行设置。例如,控制蓝牙音箱的音量、切换播放模式等。
  4. 获取设备信息:蓝牙服务通常还包含有关设备的一些信息,如设备名称、型号、制造商信息等。应用程序可以通过服务获取这些信息,以便在用户界面中显示或用于其他目的。

总之,查找蓝牙服务是连接蓝牙设备并与之通信的重要步骤,它允许应用程序识别设备功能并与之交互,从而实现各种有用的功能和应用场景。

蓝牙连接流程分析

下边我们来分析下鸿蒙中使用BLE蓝牙进行连接和通信的流程。以下是对BLE蓝牙连接流程的总结,结合了GattClientDevice相关的API方法:

1. 扫描发现设备

  • 启动扫描:使用startBLEScan()方法开始扫描周围的蓝牙LE设备。可以通过ScanSettingsScanFilter配置扫描参数,比如扫描模式、超时时间、需要匹配的设备条件等。
  • 监听扫描结果:注册ble.on('BLEDeviceFind', onReceiveEvent)事件监听器,当发现设备时,系统会回调此事件,提供发现的设备信息,如设备ID、名称等。

2. 建立连接

  • 获取GattClientDevice实例:在扫描结果的回调中,使用发现的设备ID调用ble.createGattClientDevice('设备 id')获取GattClientDevice实例,代表远程蓝牙设备。
  • 连接设备:调用GattClientDevice.connect()方法建立与蓝牙设备的连接。连接成功或失败可以通过监听GattClientDevice实例上的BLEConnectionStateChange事件得知。

3. 获取蓝牙服务并通信

  • 发现服务:连接成功后,调用GattClientDevice.getServices()方法来发现远程设备支持的服务。这些服务是设备提供的特定功能集。
  • 获取特征值:发现服务后,通过服务UUID获取特定服务下的特征值(Characteristic)对象。
  • 通信过程
    • 通知特征值对象(监听数据更新):若要接收蓝牙设备主动发送的数据,需要启用特征值的通知功能。
    • 写入特征值对象(向蓝牙设备发送数据):若要向设备发送数据,使用特征值对象的writeCharacteristicValue方法。

蓝牙连接流程封装

连接前,需要先检测授权

授权检测

// 1. 授权扫描和连接设备
scanAndConnect=()=>{
  
}
aboutToAppear(): void {
  // 先检查授权和开关状态,然后搜索设备和连接
  ecBlue.checkBluePermission(this.scanAndConnect)
}

设备扫描

  1. 设置连接 loading
  2. 调用扫描方法,获取设备 id(连接使用)
  3. 没有扫到设备,重连提示
scanAndConnect = () => {
  this.loading.open()
  ecDevice.scanDevice({
    type: "mac",
    value: deviceParamsStore.getStore()
      .nodeId!
  }, (list) => {
    if (list.length > 0) {
      const deviceId: string = list[0].deviceId
      Log.info('发现设备:' + deviceId)
    } else {
      // 连接失败
      this.loading.close()
      this.blueDialog.open()
    }
  })
}

封装连接

import { ble, constant } from '@kit.ConnectivityKit';
import { Log } from '@abner/log';

class EcDevice {
  
  // ...
  
  // 客户端连接实例
  dev: ble.GattClientDevice | null = null

  /**
   * 1. 连接BLE设备
   * @param deviceId
   */
  connectBloodDevice(deviceId: string) {
    this.destroy()
    this.dev = ble.createGattClientDevice(deviceId)
    // 1. 连接设备
    this.dev.connect()
    this.dev.on('BLEConnectionStateChange', async (res) => {
      if (res.state === constant.ProfileConnectionState.STATE_CONNECTED) {
        Log.info('连上设备了')
        try {
          // 2. 发现服务
          const res = await this.dev?.getServices()
          // 3. 获取服务
          const ser = res?.find(item => item.serviceUuid.startsWith('00001000'))
          if (ser) {
            // 写入特征值对象(给蓝牙设备发送数据)
            const writeChar = ser.characteristics.find(c => c.characteristicUuid.startsWith('00001001'))
            // 通知特征值对象(获取蓝牙设备发送数据)
            const notifyChar = ser.characteristics.find(c => c.characteristicUuid.startsWith('00001002'))

            // 4. 开启特征值监听:获取连接状态和测量结果
            this.dev?.on('BLECharacteristicChange', (res) => {
              // TODO:coding...
            })
            await this.dev?.setCharacteristicChangeNotification(notifyChar, true)

            // 5. 发送通信数据包, 连接设备
            if (writeChar) {
              await this.dev?.writeCharacteristicValue({
                serviceUuid: writeChar.serviceUuid,
                characteristicUuid: writeChar.characteristicUuid,
                // 数据包
                characteristicValue: null,
                descriptors: []
              }, ble.GattWriteType.WRITE)

            }
          }
        } catch (e) {
          this.destroy()
          Log.error('设备连接报错:' + JSON.stringify(e))
        }
      }
    })
  }

  destroy() {
    if (this.dev) {
      try {
        this.dev.disconnect()
      } catch (e) {
        Log.error('设备断开报错:' + JSON.stringify(e))
      }
      this.dev.close()
      this.dev = null
    }
  }
  
}

连接设备

  1. 定义连接方法
dev: ble.GattClientDevice | null = null

/**
 * 1. 连接某血糖设备
 * @param deviceId
 * @param cb:state=》0 连接成功 | 1 测量中 | 2 测量结果  val=> 测量结果
 */
connectBloodDevice(deviceId: string, cb: BloodLinkCallback) {
  this.dev = ble.createGattClientDevice(deviceId)
  // 1. 连接设备
  this.dev.connect()
  this.dev.on('BLEConnectionStateChange', (res) => {
    if (res.state === constant.ProfileConnectionState.STATE_CONNECTED) {
      Log.info('连上设备了')
    }
  })
}
  1. 定义连接销毁方法
destroy() {
  if (this.dev) {
    try {
      this.dev.disconnect()
    } catch (e) {
      Log.error('设备断开报错:' + JSON.stringify(e))
    }
    this.dev.close()
    this.dev = null
  }
}
  1. 获取设备蓝牙服务和特征值
if (res.state === constant.ProfileConnectionState.STATE_CONNECTED) {
  Log.info('连上设备了')
  try {
    // 2. 发现服务
    const res = await this.dev?.getServices()
    // 3. 找到服务
    const ser = res?.find(item => item.serviceUuid.startsWith('00001000'))
    if (ser) {
      // 写入特征值对象(给蓝牙设备发送数据)
      const writeChar = ser.characteristics.find(c => c.characteristicUuid.startsWith('00001001'))
      // 通知特征值对象(获取蓝牙设备发送数据)
      const notifyChar = ser.characteristics.find(c => c.characteristicUuid.startsWith('00001002'))


    }
  } catch (e) {
    this.destroy()
    Log.error('设备报错:' + JSON.stringify(e))
  }
}

设备通信

  1. 开启通知特征值监听:获取连接状态和结果
// 4. 开启特征值监听:获取连接状态和结果
this.dev?.on('BLECharacteristicChange', (res) => {
  Log.info(res.characteristicValue)
})
await this.dev?.setCharacteristicChangeNotification(notifyChar, true)
  1. 使用写入特征值给血糖设备发送连接确认数据
 if (ser) {
    // 写入特征值对象(给蓝牙设备发送数据)
    const writeChar = ser.characteristics.find(c => c.characteristicUuid.startsWith('00001001'))
    // 通知特征值对象(获取蓝牙设备发送数据)
    const notifyChar = ser.characteristics.find(c => c.characteristicUuid.startsWith('00001002'))
  
    // 4. 开启特征值监听:获取连接状态和结果
    // ...
  
    // 5. 发送00数据包, 连接设备
    if (writeChar) {
      const data = this.createData('0x00')
      await this.dev?.writeCharacteristicValue({
        serviceUuid: writeChar.serviceUuid,
        characteristicUuid: writeChar.characteristicUuid,
        characteristicValue: data.buffer,
        descriptors: []
      }, ble.GattWriteType.WRITE)
  
    }
 }
  1. 处理特征值监听回调
// 4. 开启特征值监听:获取连接状态和结果
this.dev?.on('BLECharacteristicChange', (res) => {
  const buff = new Uint8Array(res.characteristicValue)
  Log.warn('设备数据:' + buff)
  Log.warn('数据长度:' + buff.length)
  if (buff.length === 18) {
    // 1. 连接成功
    cb(0)
  }
  if (buff.length === 6) {
    // 2. 测量中
    cb(1)
  } else if (buff.length === 12) {
    // 3. 测量结果
    const result = this.getResult(buff)
    cb(2, result)
    this.destroy()
  }
})

总结

本文基于鸿蒙BLE模块,对设备连接的通用流程做了抽象封装。实际开发中,开发者可能需要根据实际情况分别处理不同 BLE 设备连接通信过程,不同设备间通信确认的方式有所不同,这里需要特别注意!


更多关于HarmonyOS 鸿蒙Next 物联网Iot开发-BLE设备连接的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html

1 回复

更多关于HarmonyOS 鸿蒙Next 物联网Iot开发-BLE设备连接的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


针对帖子标题“HarmonyOS 鸿蒙Next 物联网Iot开发-BLE设备连接”的问题,以下是专业且简洁的回答:

在HarmonyOS鸿蒙Next物联网(IoT)开发中,连接BLE(蓝牙低功耗)设备通常涉及以下几个关键步骤:

  1. 初始化BLE管理器:首先,需要在应用中初始化BLE管理器,以准备进行BLE设备的扫描和连接。

  2. 扫描BLE设备:使用BLE管理器提供的扫描功能,搜索附近的BLE设备。扫描过程中,可以设置过滤条件以快速定位目标设备。

  3. 连接BLE设备:一旦找到目标设备,即可发起连接请求。连接过程中,可能需要处理设备认证和配对等流程。

  4. 通信与服务发现:连接成功后,可以开始与BLE设备进行数据通信,并发现设备提供的服务及特征值。这通常涉及读写操作,以实现具体功能。

  5. 断开连接:当不再需要与BLE设备通信时,应主动断开连接以释放资源。

请注意,HarmonyOS鸿蒙Next平台可能提供了特定的API和框架来简化BLE设备的连接和管理。开发者应参考官方文档和示例代码,确保正确实现上述步骤。

如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html

回到顶部