小程序蓝牙API在iOS平台时无法获取蓝牙设备名称


前言

目前主流的蓝牙设备使用的都是原生APP来进行连接的,因此官方对于蓝牙API做的改进比较少,在iOS设备上还是存在许多小问题,但是在Android设备上按照官方文档操作基本没有任何问题。但是种所周知,作为小公司不可能花费两笔钱来开发APP。话不多说,这里我将主要讲一下我在开发中是如何解决这个问题的。

一、微信小程序蓝牙是如何运行的?

在这里插入图片描述

二、使用步骤

1.代码

1.话不多说上代码,首先就是初始化蓝牙适配器、获取蓝牙状态、开启扫描外围设备:

/**
 * 开启蓝牙适配器
 * 获取蓝牙适配器的状态
 * 开启蓝牙扫描外围设备
 * 监听蓝牙扫描到的设备
 */
  openBluetoothAdapter(){
    let that = this
    wx.openBluetoothAdapter({
      success(res){
        // console.log("\n成功打开adapter")
        wx.getBluetoothAdapterState({
          success: (res) => {
            if(res.available){
              if(res.discovering){
                that.onBluetoothDeviceFound()
              }else{
                wx.startBluetoothDevicesDiscovery({
                  //过滤serviceId
                  services:["xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"],
                  //允许重复名字的设备
                  allowDuplicatesKey: true,
                  success(){
                    // console.log("\n开启扫描成功")
                    that.onBluetoothDeviceFound()
                  }
                })
              }
            }
          },
        })
      }
    })
  },

2.开启设备扫描监听:

  /**
   * 将扫描到的设备存起来
   */
  onBluetoothDeviceFound() {
    let that = this
    wx.onBluetoothDeviceFound((res) => {
        res.devices.forEach(device => {
          if (!device.name && !device.localName) {
            //将没有名字的设备命名为了“未知设备”
            device.name = '未知设备'
            // return
          }
        const foundDevices = that.data.devices
        //console.log(foundDevices)
        const idx = that.inArray(foundDevices,'deviceId',device.deviceId)
        const data = {}
        if (idx === -1) {
          //新设备,直接存起来
          data[`devices[${foundDevices.length}]`] = device
        } else {
          //老设备覆盖一遍
          data[`devices[${idx}]`] = device
        }
        // console.log(data)
        that.setData(data)
        })
    })
},

3.点击连接指定设备,同时开启设备连接状态的监听,随时获取连接状态,及时做出反应:

  /**
   * 点击连接设备
   * @param {点击事件} e 
   */
  tapToCreatBLEConnection(e){
      let that = this
      //防止连接多个设备,导致通信干扰
      if(that.data.connected){
        wx.showToast({
          title: '已连接到设备,若要切换设备请断开当前设备',
          icon: 'none',
          duration:2000
        })
      }else{
            const ds = e.currentTarget.dataset
            const deviceId = ds.deviceId
            const name = ds.name
            wx.createBLEConnection({
              deviceId,
              success: (res) => {
                that.getBLEDeviceServices(deviceId)
                //监听蓝牙设备是否掉线
                wx.onBLEConnectionStateChange((res) => {
                  if(!res.connected){
                    that.setData({
                      //相关操作
                      connected: false,
                    })
                  }
                })
            that.stopBluetoothDevicesDiscovery()
            }
        })
     }
  },

4.获取设备服务列表:

  /**
   * 获取设备的服务列表
   * @param {设备id} deviceId 
   */
  getBLEDeviceServices(deviceId) {
    //获取服务列表
    wx.getBLEDeviceServices({
      deviceId,
      success: (res) => {
        for (let i = 0; i < res.services.length; i++) {
          if (res.services[i].isPrimary) {
            //获取服务权限并进行相应操作
            this.getBLEDeviceCharacteristics(deviceId, res.services[i].uuid)
            return
          }
        }
      }
    })
  },

5.获取特征值,并开启特征值变化监听,保证第一时间获取到数据:

  /**
   * 获取设备的特征值、监听特征值变化,保证第一事件获取数据
   * @param {设备id} deviceId 
   * @param {服务id} serviceId 
   */
  getBLEDeviceCharacteristics(deviceId, serviceId) {
    let that = this
    //获取服务具体权限
    wx.getBLEDeviceCharacteristics({
      deviceId,
      serviceId,
      success: (res) => {
        device_data.deviceId = deviceId
        device_data.serviceId = serviceId
        let item = res.characteristics[0]
        device_data.characteristicId = item.uuid
            //读取数据
            wx.readBLECharacteristicValue({
              deviceId,
              serviceId,
              characteristicId: item.uuid,
            })
            //开启notify
            wx.notifyBLECharacteristicValueChange({
              deviceId,
              serviceId,
              characteristicId: item.uuid,
              state: true,
              success:function(res){
                // console.log("开启notify成功\n")
              }
            })
      },
      fail(res) {
        console.error('getBLEDeviceCharacteristics', res)
      }
    })
    // 操作之前先监听,保证第一时间获取数据
    wx.onBLECharacteristicValueChange((characteristic) => {
    //接收数据并进行存储
    
    })
  },

6.发送数据,提供一下ArrayBuffer与字符串相互转换的函数,之前找了挺久的:

/**
 * ArrayBuffer转字符串
 * @param {接收到的arrayBuffer} arrayBuffer 
 */
function ab2str(arrayBuffer){
  let unit8Arr = new Uint8Array(arrayBuffer);
  let encodedString = String.fromCharCode.apply(null, unit8Arr);
  return encodedString;
}

/**
 * 将要发送的str转换成ArrayBuffer
 * @param {需要发送的str} str 
 */
function str2ab(str){
  var buf = new ArrayBuffer(str.length)// 每个字符占用2个字节
  var bufView = new Uint8Array(buf)
  for (var i = 0, strLen = str.length; i < strLen; i++) {
    bufView[i] = str.charCodeAt(i)
  }
  return buf
}

  /**
   * 发送数据
   */
  bindSentMessage(){
    wx.writeBLECharacteristicValue({
      deviceId: device_data.deviceId,
      serviceId:  device_data.serviceId,
      characteristicId:  device_data.characteristicId,
      value:  buff,//发送的数据,要是ArrayBuffer类型的
    })
  },

2.iOS无法扫描到设备名称的解决办法

经过多次测试发现,一些设备的芯片型号和蓝牙协议的不同会导致iOS设备无法获取到设备的名称,无论是name还是LocalName都无法获取。我问了一下官方,官方的回答我就不说了,说了和不说一样。LocalName是广播数据中带的一个字段,我想可能是解析出了问题,想到官方API中好像还有其他几个广播字段我就都打印了一下,发现除了serviceId有东西其它都为空。没办法官方API也改不动啊,就从name下手,name这个字段是连接设备后才能获取到,于是就想到一个很笨的办法:通过serviceId过滤蓝牙设备,再将设备列表的所有设备一一建立连接,然后断开,再次扫描,虽然很难受,但是问题是解决了,等一手官方API的完善吧。(当然可能还有大佬知道有其它办法解决,望看到这篇文章的大佬能热心的给我指导指导)


备注

代码掺杂了很多业务逻辑,由于涉及到公司保密的义务,就都善了,所以代码想复制粘贴的话会有很大的问题。(/皮一下)

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值