【微信小程序连接BLE蓝牙】Uni-app开发微信小程序使用BLE低功耗蓝牙实现设备通信

2,343 阅读4分钟

引言

蓝牙低功耗是从蓝牙 4.0 起支持的协议,与经典蓝牙相比,功耗极低、传输速度更快,但传输数据量较小。常用在对续航要求较高且只需小数据量传输的各种智能电子产品中,比如智能穿戴设备、智能家电、传感器等,应用场景广泛。

本文将详细描述微信小程序如何连接设备蓝牙以及需要注意的事宜。

微信官方文档。在遇到问题前或者你想查阅某些API的具体作用和参数、回调函数、错误状态码等可查阅 developers.weixin.qq.com/minigame/de…

连接蓝牙和搜索到蓝牙设备的前提是打开手机蓝牙和定位(包括微信中蓝牙权限和定位权限)

1、连接蓝牙入口方法

在methods中定义以下方法,以下均为按步骤定义每个步骤的方法(一步一步套娃即可)

methods: {
    connectBlueTooth() {
      // 2、初始化蓝牙模块方法
      this.openBluetoothAdapter();
    },
}

2、初始化蓝牙模块

这里需要注意iOS上开启主机/从机模式时需分别调用一次 第一次的mode为central(开启主机) 第二次的mode为peripheral(可以理解代码就是为了同时兼容安卓和ios)。

openBluetoothAdapter() {
      var that = this;
      wx.openBluetoothAdapter({
        mode: "central", //开启主机
        success: function (res) {
          console.log("初始化主机模式蓝牙成功", res);
          wx.openBluetoothAdapter({
            mode: "peripheral", //开启从机
            success: function () {
              console.log("初始化从机模式蓝牙成功", res);
              //3、搜索蓝牙设备
              that.startBluetoothDevicesDiscovery();
            },
            fail: function (err) {
              console.log("初始化蓝牙模块失败", err);
            },
          });
          // 2. 开始搜索BLE设备
        },
        fail: function (err) {
            console.log("初始化蓝牙模块失败", err);
        },
      });
    },

3、搜索蓝牙设备

嵌入式工程师会告诉你设备的特征值(UUIDs)。需要用搜索出来的蓝牙是否与提供的UUIDs一致 搜索到目标蓝牙时你需要马上关闭蓝牙扫码搜索功能 ( 官方的解释是扫描周围蓝牙很耗性能 )

startBluetoothDevicesDiscovery() {
      var that = this;
      wx.startBluetoothDevicesDiscovery({
        success: function (res) {
          console.log("开始搜索BLE设备成功", res);
          // 监听搜索到的设备
          wx.onBluetoothDeviceFound(function (device) {
            // 遍历搜索到的设备
            if (device.devices.length) {
              device.devices.forEach((item) => {
                //搜到的每个设备
                if (
                  item.advertisServiceUUIDs?.includes(
                     //此处需要与嵌入式工程师沟通设备的特征值
                    "0000FF01-****-****-****-00805F9B****"
                  )
                ) {
                  console.log("找到目标设备", item);
                  //取消扫描
                  wx.stopBluetoothDevicesDiscovery();
                  //4、连接目标蓝牙设备
                  that.createBLEConnection(item);
                }
              });
            }
          });
        },
        fail: function (err) {
          console.error("开始搜索BLE设备失败", err);
        },
      });
    },

4、连接目标蓝牙设备

createBLEConnection(item) {
      var that = this;
      wx.createBLEConnection({
        deviceId: item.deviceId,
        success: function (res) {
          console.log("连接BLE设备成功", res);
          // 5、获取蓝牙设备可用服务
          that.getBLEDeviceServices(item);
        },
        fail: function (err) {
          console.error("连接BLE设备失败", err);
        },
      });
    }

5、获取蓝牙设备可用服务

getBLEDeviceServices(item) {
      var that = this;
      wx.getBLEDeviceServices({
        deviceId: item.deviceId,
        success: (res) => {
          console.log("获取BLE设备服务", res);
          for (let i = 0; i < res.services.length; i++) {
            if (
              res.services[i].isPrimary &&
              //此处需要与嵌入式工程师沟通设备服务的UUID
              res.services[i].uuid == "***FF01-***********" 
            ) {
              let deviceId = item.deviceId;
              let serviceId = res.services[i].uuid;
              //6、获取BLE设备特征值以及读写服务
              that.getBLEDeviceCharacteristics(deviceId, serviceId);
            }
          }
        },
      });
    },

6、获取BLE设备特征值和读写服务

这是嵌入式工程师提供的数据格式,代码块中的wifiInfo需要处理成如下16进制数据格式 代码中有很多复杂数据和业务处理与本文无关所以已被注释和简化 33360b66a42f4e25d21165f2cb11525.png

image.png

getBLEDeviceCharacteristics(deviceId, serviceId) {
      var that = this;
      wx.getBLEDeviceCharacteristics({
        // 搜索到设备的 deviceId
        deviceId,
        // 上一步中找到的某个服务
        serviceId,
        success: (res) => {
          console.log("搜索FF01的服务", res);
          //遍历当前服务。嵌入式工程师会提供读写对应服务
          for (let i = 0; i < res.characteristics.length; i++) {
            let item = res.characteristics[i];
            setTimeout(() => {
              //写
              if (item.uuid == "*****FF02*********") {
                // 该特征值可写 FF02写
                // 本示例是向蓝牙设备发送一个 0x00 的 16 进制数据
                // 实际使用时,应根据具体设备协议发送数据
                var wifiInfo = `wifi:123123, 密码:123456789`;
                wx.writeBLECharacteristicValue({
                  deviceId,
                  serviceId,
                  characteristicId: item.uuid,
                  //这的wifiInfo根据与嵌入式沟通好wifiInfo数据格式,因为公司需求需要让设备连接wifi 我需要将当前可用wifi的账号密码通过处理后写入蓝牙特征值
                  value: wifiInfo,
                  success: function (res) {
                    console.log("Wi-Fi信息发送成功", res);
                  },
                  fail: function (err) {
                    console.log("Wi-Fi信息发送失败", err);
                  },
                });
              }
              //读
              if (item.uuid == "*****FF03*********") {
                // 改特征值可读 FF03读
                wx.readBLECharacteristicValue({
                  deviceId,
                  serviceId,
                  characteristicId: item.uuid,
                  success: function (res) {
                    console.log("获取读的数据: ", res);
                  },
                });
              }
            }, 1000);
            //通知
            if (item.properties.notify) {
              // 必须先启用 wx.notifyBLECharacteristicValueChange 才能监听到设备 onBLECharacteristicValueChange 事件
              wx.notifyBLECharacteristicValueChange({
                deviceId,
                serviceId,
                characteristicId: item.uuid,
                state: true,
                success: function (res) {
                  wx.onBLECharacteristicValueChange((result) => {
                    console.log(
                      "拿到数据: ",
                      result,
                    );
                    //此处我根据result判断设备 的3个步骤状态
                    // 1连接wifi 2设备配网 3连接服务器
                    // 服务器注册数据后在合适的时机断开连接和关闭蓝牙适配器
                      console.log("关闭蓝牙");
                      wx.closeBLEConnection({
                        deviceId,
                      });
                      wx.closeBluetoothAdapter({});
                  });
                },
              });
            }
          }
        },
      });
    },