头图

前言

因为小程序官方是支持接入低能蓝牙(BLE)的,所以在一个项目中也尝试使用如何接入蓝牙,我们从微信的官方网站就可以清楚知道如何使用,但是其中也是有很多坑的。本着学习的心态,自己也手把手带你摸坑,一起处理一些平台兼容性的问题以及一些逻辑判断问题

作者在开发一款共享干衣机小程序,用的是uniapp框架进行开发的,开发期间时遇到了 苹果(ios) 和 安卓(android)手机 获取到的 deviceId(mac)地址不一致问题;

1、设备绑定

在共享设备铺货到酒店等场所时,我们会让工作人员使用小程序码对共享干衣机设备进行绑定,这个目的就是为了解决,用户打开蓝牙连接时会出现N个蓝牙,用户会不知所措的问题。

绑定过程需要填写以下信息:

  • 1、蓝牙名称:自动生成
  • 2、设备编码:扫描提前生成的小程序码(里面包含了设备编码)
  • 3、设备:选择设备就是我们选择蓝牙然后拿到deviceId(mac地址)
  • 4、代理商
  • 5、商户
  • 6、网点

2、用户使用流程

我们这个共享项目的用户使用流程是:

  • 1、用户扫码(生成的小程序码) 里面包含设备蓝牙信息;
  • 2、弹出连接蓝牙给用户连接 (通过小程序码里的蓝牙信息里的deviceId(mac地址)过滤掉其他蓝牙,只显示用户扫码设备的蓝牙);
  • 3、用户连接成功后 隐藏连接蓝牙按钮显示 立即使用按钮;
  • 4、用户选择使用时长(默认30分钟);
  • 5、点击立即使用调用支付;
  • 6、支付成功后 (小程序下发开关定时指令给干衣机设备进行使用);

3、平台差异化

因为我们使用的是uniapp框架开发所以没看到uniapp说明这个...(大坑)
后来我们从微信文档上面看到这样一段话:

看到这里我就想着,完犊子了,因为我们的手机平台有安卓和苹果,唯一标识蓝牙的就是deviceId,但是苹果搜索出来就不是这个了,而是uuid的一串字符串。因为苹果官方认为透露deviceId(MAC地址)会有安全问题,索性直接屏蔽了。

4、问题分析

开发安卓和IOS的APP中,在获取蓝牙模块的MAC地址的时候有区别。
安卓系统在蓝牙这一块,给了获取蓝牙模块MAC地址的接口,所以直接用就行,包括安卓端的微信小程序或者其他小程序。
IOS比较严谨,不允许获取蓝牙模块的MAC地址,没有给出API,所以必须要在蓝牙模块这一端做一些特别的设置。

在设备绑定时工作人员用安卓绑定的设备是唯一的,而用户使用ios搜索蓝牙时,每个用户搜索到的蓝牙设备都是uuid随机的deviceId与我们绑定deviceId的不匹配,因此也就无法在用户使用的时候过滤其他蓝牙了。

5、解决方案

方法1-特定的UUID去读取MAC地址

其实这类型的应用并不多,因为他需要建立连接之后,才能获取到mac地址,这样就不实用了

在程序开发中我们很少有采用这样的方式的 。其实实现也很简单,一说就懂

所以这个方法,暂时不推荐使用,请详细了解一下方法二。

方法2--MAC地址存放在蓝牙模块广播包里面

在广播包里面,查找蓝牙的 MAC 地址,一般良心厂商都会存放在广播包里面,所以可以获取到。
作者开发的蓝牙线路板厂商没有写进去...,然后联系厂商重新烧录进去。


经过了九九八十一天来回邮寄线路板,厂商终于把 mac 地址写入进advertisData去了。

下面是原始数据

这里我们称之为:advertisData(当前蓝牙设备的广播数据段中的 ManufacturerData 数据段, 类型为:ArrayBuffer)

做这个的目的,有如下原因:

  • 1、微信小程序开发:无法直接获取蓝牙芯片的 mac 地址,没有相应的API,所以可以通过这个获取到,具体网上可以搜一下
  • 2、APP 开发--IOS 端,也没办法直接获取 MAC 地址,也是通过这个方式得到蓝牙芯片的 MAC 地址
  • 3、APP 开发--安卓端,没有这个问题,直接通过 API 时可以获取到蓝牙芯片的 mac 地址的。所以用不用这个功能,都无所谓

实现代码:

// 初始化蓝牙模块
uni.openBluetoothAdapter({
  success(res) {
    // 开始搜寻附近的蓝牙外围设备
    uni.startBluetoothDevicesDiscovery({
      success(res) {
        // 监听寻找到新设备的事件
       uni.onBluetoothDeviceFound((devices) =>{
          console.log(ab2hex(devices[0].advertisData)) // 获取到 mac 地址
        })
      }
    })
  }
})

// ArrayBuffer转16进度字符串示例
function ab2hex(buffer) {
  const hexArr = Array.prototype.map.call(
    new Uint8Array(buffer),
    function (bit) {
      return ('00' + bit.toString(16)).slice(-2)
    }
  )
  return hexArr.reverse().join(':')
}

至此成功,我们拿到了蓝牙的mac地址,然后就可以进行后续操作了。


憨厚的登山鞋
1 声望0 粉丝