微信小程序使用蓝牙通信协议连接硬件整理总结(蓝牙连接、获取设备UUID、开水器notify及关闭蓝牙)

举报
穆雄雄 发表于 2022/12/02 16:30:44 2022/12/02
【摘要】 大家好,我是雄雄。@[TOC] 前言书接前文,上篇文章我们主要介绍了初始化蓝牙、以及搜索附近蓝牙设备以及展示搜索到的蓝牙设备,但是我们在真实的业务场景中,肯定是需要将搜到的设备“用”起来的,所以本文我们就介绍一下如何使用小程序连接蓝牙设备以及后续的操作。 进行蓝牙连接连接蓝牙设备主要使用wx.createBLEConnection方法,若小程序在之前已有搜索过某个蓝牙设备,并成功建立连接,可...

大家好,我是雄雄。

在这里插入图片描述
@[TOC]

前言

书接前文,上篇文章我们主要介绍了初始化蓝牙、以及搜索附近蓝牙设备以及展示搜索到的蓝牙设备,但是我们在真实的业务场景中,肯定是需要将搜到的设备“用”起来的,所以本文我们就介绍一下如何使用小程序连接蓝牙设备以及后续的操作。

进行蓝牙连接

连接蓝牙设备主要使用wx.createBLEConnection方法,若小程序在之前已有搜索过某个蓝牙设备,并成功建立连接,可直接传入之前搜索获取的 deviceId 直接尝试连接该设备,无需再次进行搜索操作。
实现代码如下:

//通过蓝牙设备的id进行蓝牙连接
      const createBLEConnection = () => {
        wx.createBLEConnection({
          deviceId: ConnectedDeviceRelated.deviceId,
          success: function (res) {
            wx.stopBluetoothDevicesDiscovery({
              success: function (res) {
                console.log('连接成功,关闭蓝牙搜索')
                ConnectedDeviceRelated.isSearchBluetooth_detectionBoard = false
              }
            })
            getBLEDeviceServices()
          },
          fail: function (res) {
            //连接失败后重连
            if (that.data.isconnect == 'false') {
              createBLEConnection()
            }
          }
        })
      }

其中,deviceId就是我们搜索到的蓝牙设备的id

注意:

  1. 请尽量成对的调用wx.createBLEConnectionwx.closeBLEConnection接口,安卓如果重复调用wx.createBLEConnection创建连接,有可能导致系统对同一设备持有多个连接实例,会导致调用closeBLEConnection的时候并不能真正的断开与设备的连接。
  2. 蓝牙连接随时有可能断开,可以调用wx.onBLEConnectionStateChange来监听设备断开,当设备断开时根据连接需求进行重连操作。

到这里蓝牙设备就连接上了**(因为安卓和iOS的区别,iOS连接上蓝牙后,可以在通知栏看到蓝牙图标显示或者在控制中心看到蓝牙设备连接的名称来判断是否已经连接;安卓只能通过小程序提供的API回调参数来判断)**,如果想要获取蓝牙设备的数据或向蓝牙设备写入指令,就需要下面的步骤:

获取蓝牙设备的UUID

我们需要使用wx.getBLEDeviceServices来获取蓝牙设备的UUID

获取蓝牙低功耗设备所有服务 (service),代码如下:

 //获取蓝牙设备的uuid
      const getBLEDeviceServices = () => {
        wx.getBLEDeviceServices({
          deviceId: ConnectedDeviceRelated.deviceId,
          success: function (res) {
            for (var i = 0; i < res.services.length; i++) {
              if (res.services[i].uuid.includes('xxxxx')) {
                ios_uuid.push({
                  'notify': res.services[i].uuid
                })
              } else if (res.services[i].uuid.includes('xxxx')) {
                ios_uuid.push({
                  'write': res.services[i].uuid
                })
              }
            }
            getBLEDeviceCharacteristics()
          }
        })
      }

其中deviceId为搜索蓝牙设备时获取的设备id;这里按照蓝牙设备的不同,会获取到一个或多个服务id
在这里插入图片描述
这个时候只需获取最关键的两个服务idnotifywrite,怎么判断呢?一般对接这些设备都会给你协议文档,里面会提及用到的服务id,以及他们的作用,那如果没有文档或者文档里面没有说呢?那你就要一个一个去试了…

获取UUID中的特征值

我们需要通过wx.getCLEDeviceCharacteristics方法来获取UUID的特征值。
代码如下:

//获取蓝牙设备uuid的notify特征值
      const getBLEDeviceCharacteristics = () => {
        var notify = null;
        for (var i = 0; i < ios_uuid.length; i++) {
          if (ios_uuid[i].hasOwnProperty('notify')) {
            notify = ios_uuid[i].notify
          }
        }
        wx.getBLEDeviceCharacteristics({
          deviceId: ConnectedDeviceRelated.deviceId,
          serviceId: notify,
          success: function (res) {
            ios_uuidEigenvalues.push(res.characteristics[0].uuid)
            setTimeout(() => (
              startNotice(notify)
            ), 800)
          },
          fail: function (res) {
            console.log('获取uuid的notify特征值失败', res)
          }
        })
      }

其中deviceId为前面搜索到的蓝牙设备的idserviceId为获取的支持开启notifyuuid
在这里插入图片描述
上图为获取服务中特征值成功的回调参数,其中在properties属性中就可以判断获取的uuid的作用,图示的是 只支持开启notifyuuid。部分蓝牙设备只会包含一个uuid,但会有同时开启notifywrite的能力。

开启notify

开启notify需要调用wx.notifyBLECharacteristicValueChange方法,启用蓝牙低功耗设备特征值变化时的 notify 功能,订阅特征。注意:必须设备的特征支持 notify或者 indicate 才可以成功调用。
代码如下:

const startNotice = notify => {
        wx.notifyBLECharacteristicValueChange({
          state: true,
          deviceId: ConnectedDeviceRelated.deviceId,
          serviceId: notify,
          characteristicId: ios_uuidEigenvalues[0],
          success: function (res) {
            console.log("开启notify成功")
            //获取蓝牙设备uuid的write特征值
            getBLEDeviceCharacteristics_write()
          },
          fail: function (res) {
            console.log("notity失败", res)
          }
        })
      }

其中,state为是否启用notifydeviceId为步骤3中获取的设备idserviceId为获取的uuidcharacteristicIduuid特征值.

还是因为设备的不同,有的设备不需要主机(你的设备)主动触发从机(蓝牙设备)的功能,所以直接在开启notify的方法中 监听蓝牙设备返回的数据就可以了
代码如下:

	wx.onBLECharacteristicValueChange(function (characteristic) {
              isOk = true
              if (that.ab2hex(characteristic.value).substring(0, 4) == 'xxxxx') {
                that.judgingElectricity(that.ab2hex(characteristic.value))
              } else if (that.ab2hex(characteristic.value) == ConnectedDeviceRelated.turnSuccess_notify) {
                sendMy(ConnectedDeviceRelated.approve)
              } else if (that.ab2hex(characteristic.value) == 'xxxx') {
                console.log('认证成功')
                ConnectedDeviceRelated.disconnect = true
                app.globalData.isturn = 'true'
                app.globalData.isconnect = 'true'
                that.setData({
                  isturn: 'true',
                  isconnect: 'true',
                  BluetoothNotConnected_icon: that.data.BluetoothIsConnected_icon,
                  electricityNotConnected_icon: that.data.electricityIsConnected_icon
                })
                that.isDeviceUnique(0)
              }
            })

注意:
这里蓝牙设备返回的数据格式是arraybuffer需要再转一下字符串,代码如下:

// arraybuffer转字符串
  ab2hex: function (buffer) {
    var hexArr = Array.prototype.map.call(
      new Uint8Array(buffer),
      function (bit) {
        return ('00' + bit.toString(16)).slice(-2)
      }
    )
    return hexArr.join('');
  },

如果你对接的蓝牙设备需要被动的触发功能(比如主机发送对应的功能指令),就要通过步骤中获取支持writeuuid,通过上面的方法获取UUID特征值,然后向蓝牙设备写入``,写入成功,触发了成功的回调后,接着调用wx.onBLECharacteristicValueChange监听蓝牙设备返回的数据:
代码如下:

 wx.writeBLECharacteristicValue({
          deviceId: ConnectedDeviceRelated.deviceId,
          serviceId: ConnectedDeviceRelated.services_write,
          characteristicId: ConnectedDeviceRelated.write,
          value: arrayBuffer,
          success: function (res) {
            wx.showToast({
              title: '正在连接中...',
              icon: 'none',
              duration: 2000
            })
            //检测板子自己关闭 再打开后自动连接 如果写入后没反应,就再写入
            setTimeout(function (params) {
              if (isOk == false) {
                sendMy('notify')
              }
            }, 1500)
            //监听设备返回的值
            wx.onBLECharacteristicValueChange(function (characteristic) {
              isOk = true
              if (that.ab2hex(characteristic.value).substring(0, 4) == 'fdf4') {
                that.judgingElectricity(that.ab2hex(characteristic.value))
              } else if (that.ab2hex(characteristic.value) == ConnectedDeviceRelated.turnSuccess_notify) {
                sendMy(ConnectedDeviceRelated.approve)
              } else if (that.ab2hex(characteristic.value) == 'xxxx') {
                console.log('认证成功')
                ConnectedDeviceRelated.disconnect = true
                app.globalData.isturn = 'true'
                app.globalData.isconnect = 'true'
                that.setData({
                  isturn: 'true',
                  isconnect: 'true',
                  BluetoothNotConnected_icon: that.data.BluetoothIsConnected_icon,
                  electricityNotConnected_icon: that.data.electricityIsConnected_icon
                })
                that.isDeviceUnique(0)
              }
            })
            //监听连接断开
            that.disconnect()
          },
          fail: function (res) {
            console.log('写入失败', res)
          },
        })

注意:
这里的value需要的是arraybuffer格式的数据指令,所以需要把字符转成arraybuffer

关闭蓝牙

断开与蓝牙低功耗设备的连接,代码如下:

wx.showModal({
            title: '提示',
            content: '要关闭蓝牙吗?',
            success: function (res) {
              if (res.confirm) {
                if (app.globalData.bluetooth == 'W8') {
                  deviceId = ConnectedDeviceRelated.deviceId_sphygmomanometer
                } else if (app.globalData.bluetooth == 'Yuwell BP-YE8900A') {
                  deviceId = ConnectedDeviceRelated.deviceId_YYSphygmomanometer
                }
                wx.closeBLEConnection({
                  deviceId: deviceId,
                  success(res) {
                    console.log("关闭蓝牙成功")
                    ConnectedDeviceRelated.disconnect = false
                    app.globalData.isconnect_bloodPressure = false
                    that.setData({
                      isconnect_bloodPressure: false,
                      SphygmomanometerBluetoothNotConnected_icon: config.ImageAddr_url + 'applets/images/jiance/YRSphygmomanometerBluetoothNotConnected.png',
                    })
                  }
                })
              }
            }
          })
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。