小程序蓝牙模块踩坑

2019-12-24  本文已影响0人  罂粟1995

此篇文章为我在做用到小程序蓝牙模块的项目过程中总结的经验。

一、小程序蓝牙连接流程梳理:

1.第一步,调用wx.openBluetoothAdapter,初始化蓝牙适配器;
2.第二步,调用wx.getBluetoothAdapterState,获取本机蓝牙适配器状态;
3.第三步,进行蓝牙连接,安卓系统直接调用wx.createBLEConnection连接蓝牙,使用示例:
wx.createBLEConnection({
  deviceId,//设备mac地址
  success (res) {
    console.log(res)
  }
})

如果是ios系统,则需先调用wx.startBluetoothDevicesDiscovery和wx.getBluetoothDevices搜索附近蓝牙设备并匹配,用mac地址匹配设备名称,获取其deviceId,拿到这个deviceId才能使用wx.createBLEConnection连接到蓝牙设备:

wx.startBluetoothDevicesDiscovery({
      success(res) {
          //获取搜索到的设备
          wx.getBluetoothDevices({
            success(res) {
              var devices = res.devices;//设备列表
              var realMac = '';
              //匹配
              if (devices.length > 0) {
                for (var i = 0; i < devices.length; i++) {
                  if (devices[i].name === _this.data.mac) {
                    realMac = devices[i].deviceId;//这个才是ios设备真正的deviceId
                    break;
                  }
                }
              }
           }
        });
      }
});
4.第四步,调用wx.getBLEDeviceServices获取蓝牙设备所有服务;
5.第五步,调用wx.getBLEDeviceCharacteristics获取某个服务的特征值;
6.第六步,调用wx.notifyBLECharacteristicValueChange启用蓝牙设备特征值变化时的 notify 功能;
7.第七步,调用wx.writeBLECharacteristicValue向蓝牙设备中写入二进制数据;
8.第八步,调用wx.onBLECharacteristicValueChange监听蓝牙设备特征值变化;
9.最后调用wx.closeBLEConnection断开蓝牙连接、调用wx.closeBluetoothAdapter关闭蓝牙模块。

二、项目中遇到的问题和解决方法总结:

区分ios和安卓,蓝牙需要做不同处理:

进行蓝牙连接时,安卓系统直接调用wx.createBLEConnection连接蓝牙,ios系统需先调用wx.startBluetoothDevicesDiscovery和wx.getBluetoothDevices搜索附近蓝牙设备并匹配,用mac地址匹配设备名称,获取其deviceId,拿到这个deviceId后才使用wx.createBLEConnection连接蓝牙设备。在这一步之前可以使用var system = wx.getSystemInfoSync();判断到当前系统类型,if(system == 'ios')时,搜索蓝牙设备,if(system == 'android')时直接通过mac地址连接蓝牙设备。

ios搜索并匹配蓝牙设备不一定能够一次成功:

ios搜索并匹配蓝牙设备不一定能够一次成功,处理方法,多匹配几次:

//链式处理
 this.openBluetoothAdapter()
        .then((res) => {
          //初始化蓝牙设备成功后,执行下一步获取本机蓝牙适配器状态
          return this.getBluetoothAdapterState();
        }).then((res) => {
          //获取本机蓝牙适配器状态成功后,执行下一步搜索附近蓝牙设备、获取以及匹配
          return this.serachAndGetBluetooth();
        }).then((res) => {
          //第一次匹配蓝牙设备成功后,执行接下来的连接操作
          return this.iosContinueConnect();
        },(reason) => {
          //匹配蓝牙设备失败,持续匹配,三次之后之后,若还匹配不到,则提示失败
          console.log('第一次匹配失败,进行第二次匹配');
          this.serachAndGetBluetooth().then((res) => {
            //第二次匹配成功
            return this.iosContinueConnect();
          }, (reason) => {
                console.log('第二次匹配失败,进行第三次匹配');
                  this.serachAndGetBluetooth().then((res) => {
                    //第三次匹配成功
                    return this.iosContinueConnect();
                  }, (reason) => {
                    //第三次仍匹配失败,结束搜索,关闭蓝牙设备
                    //停止搜索设备
                    wx.stopBluetoothDevicesDiscovery({
                      success(res) {
                        console.log("结束搜索")
                      }
                    });
                    //关闭蓝牙模块
                    wx.closeBluetoothAdapter({
                      success(res) {
                        console.log('已关闭蓝牙模块');
                      }
                    });
                    console.log('匹配蓝牙设备失败');
                  })
                })
              })
            })
          })
   })

//搜索附近的蓝牙外围设备、获取、并匹配
  serachAndGetBluetooth: function () {
    var _this = this;
    var p = new Promise(function (resolve, reject) {
      wx.startBluetoothDevicesDiscovery({
        success(res) {
          //获取搜索到的设备
          wx.getBluetoothDevices({
            success(res) {
              var devices = res.devices;//设备列表
              var realMac = '';
              //匹配
              if (devices.length > 0) {
                for (var i = 0; i < devices.length; i++) {
                  if (devices[i].name === _this.data.mac) {
                    realMac = devices[i].deviceId;
                    break;
                  }
                }
              } else {
                reject('fail');
                console.log('匹配蓝牙设备失败');
              }

              if (realMac !== '') {
                //匹配成功
                _this.setData({
                  deviceId: realMac
                });
                resolve('success');
                console.log('成功匹配蓝牙设备');
                //成功后停止搜索设备
                wx.stopBluetoothDevicesDiscovery({
                  success(res) {
                    console.log("结束搜索")
                  }
                });
              } else {
                reject('fail');
                console.log('匹配蓝牙设备失败');
              }
            },
            fail(err) {
              reject('fail');
              console.log('匹配蓝牙设备失败');
            }
          });
        },
        fail(err) {
          reject('fail');
          console.log('搜索蓝牙设备失败');
        }
      });
    });
    return p;
  },

如果打开蓝牙适配器后立即搜索蓝牙,可能会导致搜索失败

有一个问题,如果打开蓝牙适配器后立即搜索蓝牙,可能会导致搜索失败,所以最好等待两秒后再进行搜索,则上段代码可优化为:

//链式处理
 this.openBluetoothAdapter()
        .then((res) => {
          //初始化蓝牙设备成功后,执行下一步获取本机蓝牙适配器状态
          return this.getBluetoothAdapterState();
        }).then((res) => {
          //获取本机蓝牙适配器状态成功后,执行下一步搜索附近蓝牙设备、获取以及匹配
          return this.serachAndGetBluetooth();
        }).then((res) => {
          //第一次匹配蓝牙设备成功后,执行接下来的连接操作
          return this.iosContinueConnect();
        },(reason) => {
          //匹配蓝牙设备失败,持续匹配,三次之后之后,若还匹配不到,则提示失败
          console.log('第一次匹配失败,进行第二次匹配');
          this.serachAndGetBluetooth().then((res) => {
            //第二次匹配成功
            return this.iosContinueConnect();
          }, (reason) => {
                console.log('第二次匹配失败,进行第三次匹配');
                  this.serachAndGetBluetooth().then((res) => {
                    //第三次匹配成功
                    return this.iosContinueConnect();
                  }, (reason) => {
                    //第三次仍匹配失败,结束搜索,关闭蓝牙设备
                    //停止搜索设备
                    wx.stopBluetoothDevicesDiscovery({
                      success(res) {
                        console.log("结束搜索")
                      }
                    });
                    //关闭蓝牙模块
                    wx.closeBluetoothAdapter({
                      success(res) {
                        console.log('已关闭蓝牙模块');
                      }
                    });
                    console.log('匹配蓝牙设备失败');
                  })
                })
              })
            })
          })
   })

//搜索附近的蓝牙外围设备、获取、并匹配
  serachAndGetBluetooth: function () {
    var _this = this;
    var p = new Promise(function (resolve, reject) {
     setTimeout(() => {
      wx.startBluetoothDevicesDiscovery({
        success(res) {
          //获取搜索到的设备
          wx.getBluetoothDevices({
            success(res) {
              var devices = res.devices;//设备列表
              var realMac = '';
              //匹配
              if (devices.length > 0) {
                for (var i = 0; i < devices.length; i++) {
                  if (devices[i].name === _this.data.mac) {
                    realMac = devices[i].deviceId;
                    break;
                  }
                }
              } else {
                reject('fail');
                console.log('匹配蓝牙设备失败');
              }

              if (realMac !== '') {
                //匹配成功
                _this.setData({
                  deviceId: realMac
                });
                resolve('success');
                console.log('成功匹配蓝牙设备');
                //成功后停止搜索设备
                wx.stopBluetoothDevicesDiscovery({
                  success(res) {
                    console.log("结束搜索")
                  }
                });
              } else {
                reject('fail');
                console.log('匹配蓝牙设备失败');
              }
            },
            fail(err) {
              reject('fail');
              console.log('匹配蓝牙设备失败');
            }
          });
        },
        fail(err) {
          reject('fail');
          console.log('搜索蓝牙设备失败');
        }
      });
     },2000);
    });
    return p;
  },

ios蓝牙连接优化方案

ios搜索并匹配蓝牙设备这一步耗时较长,可以在第一次匹配到蓝牙设备时,记录下设备的deviceId,第二次就可以直接使用这个deviceId进行连接,而不需要再进行搜索操作,提高效率。

//如果deviceId已保存,可直连
if (_this.data.deviceId){
      this.openBluetoothAdapter()
        .then((res) => {
          //初始化蓝牙设备成功后,执行下一步获取本机蓝牙适配器状态
          return this.getBluetoothAdapterState();
        }).then((res) => {
          //已经获取过一次devicId,使用旧的deviceId,直接连接
          return this.iosContinueConnect();
        })
 }else{
   //如果如果deviceId未保存,说明是第一次连接,搜索附近蓝牙设备
   //链式处理
   this.openBluetoothAdapter()
        .then((res) => {
          //初始化蓝牙设备成功后,执行下一步获取本机蓝牙适配器状态
          return this.getBluetoothAdapterState();
        }).then((res) => {
          //获取本机蓝牙适配器状态成功后,执行下一步搜索附近蓝牙设备、获取以及匹配
          return this.serachAndGetBluetooth();
        }).then((res) => {
          //第一次匹配蓝牙设备成功后,执行接下来的连接操作
          return this.iosContinueConnect();
        },(reason) => {
          //匹配蓝牙设备失败,持续匹配,三次之后之后,若还匹配不到,则提示失败
          console.log('第一次匹配失败,进行第二次匹配');
          this.serachAndGetBluetooth().then((res) => {
            //第二次匹配成功
            return this.iosContinueConnect();
          }, (reason) => {
                console.log('第二次匹配失败,进行第三次匹配');
                  this.serachAndGetBluetooth().then((res) => {
                    //第三次匹配成功
                    return this.iosContinueConnect();
                  }, (reason) => {
                    //第三次仍匹配失败,结束搜索,关闭蓝牙设备
                    //停止搜索设备
                    wx.stopBluetoothDevicesDiscovery({
                      success(res) {
                        console.log("结束搜索")
                      }
                    });
                    //关闭蓝牙模块
                    wx.closeBluetoothAdapter({
                      success(res) {
                        console.log('已关闭蓝牙模块');
                      }
                    });
                    console.log('匹配蓝牙设备失败');
                  })
                })
              })
            })
          })
   })

//搜索附近的蓝牙外围设备、获取、并匹配
  serachAndGetBluetooth: function () {
    var _this = this;
    var p = new Promise(function (resolve, reject) {
     setTimeout(() => {
      wx.startBluetoothDevicesDiscovery({
        success(res) {
          //获取搜索到的设备
          wx.getBluetoothDevices({
            success(res) {
              var devices = res.devices;//设备列表
              var realMac = '';
              //匹配
              if (devices.length > 0) {
                for (var i = 0; i < devices.length; i++) {
                  if (devices[i].name === _this.data.mac) {
                    realMac = devices[i].deviceId;
                    break;
                  }
                }
              } else {
                reject('fail');
                console.log('匹配蓝牙设备失败');
              }

              if (realMac !== '') {
                //匹配成功
                _this.setData({
                  deviceId: realMac
                });
                resolve('success');
                console.log('成功匹配蓝牙设备');
                //成功后停止搜索设备
                wx.stopBluetoothDevicesDiscovery({
                  success(res) {
                    console.log("结束搜索")
                  }
                });
              } else {
                reject('fail');
                console.log('匹配蓝牙设备失败');
              }
            },
            fail(err) {
              reject('fail');
              console.log('匹配蓝牙设备失败');
            }
          });
        },
        fail(err) {
          reject('fail');
          console.log('搜索蓝牙设备失败');
        }
      });
     },2000);
    });
    return p;
  },

一次连接,多次与蓝牙设备交互

项目中有个需求,第一次发送数据包给蓝牙设备后,等待蓝牙设备回应,再进行第二次发送数据包,这就要求监听两次蓝牙设备回应。
正确步骤是:开启notify功能->第一次写数据->监听->第二次写数据->监听->蓝牙回应后结束本次蓝牙连接

  wx.notifyBLECharacteristicValueChange({
        state: true, // 启用 notify 功能  
        deviceId: deviceId,
        serviceId: notifyServicweId,
        characteristicId: notifyCharacteristicsId,
        success: function (res) {
          console.log('启用低功耗蓝牙设备特征值变化时的 notify 功能成功');
          
         //使用定时器异步调用顺序执行,否则可能导致收不到设备返回的特征值变化信息
          //发包
          for (let i = 0; i < commonds.length; i++) {
            let hex = commonds[i];
            let typedArray = new Uint8Array(hex.match(/[\da-f]{2}/gi).map(function (h) {
              return parseInt(h, 16)
            }));
            let buffer = typedArray.buffer;
            setTimeout(function() {
              wx.writeBLECharacteristicValue({
                deviceId: deviceId,
                serviceId: writeServicweId,
                characteristicId: writeCharacteristicsId,
                value: buffer,
                success: function (res) {
                  if(i == commonds.length-1 ) {
                        //注意要发完最后一包后才进行接下来的操作
                        wx.onBLECharacteristicValueChange(function (characteristic) { 
                                //监听到蓝牙回应
                               //第二次写数据
                               wx.writeBLECharacteristicValue({
                                   deviceId: deviceId,
                                   serviceId: writeServicweId,
                                   characteristicId: writeCharacteristicsId,
                                   value: '00F0',
                                   success: function (res) {
                                           wx.onBLECharacteristicValueChange(function (characteristic) { 
                                                    //监听成功后结束蓝牙连接
                                                    wx.closeBLEConnection({
                                                         deviceId,
                                                         success(res) {
                                                              console.log('已断开蓝牙连接');
                                                              //关闭蓝牙模块
                                                              wx.closeBluetoothAdapter({
                                                                 success(res) {
                                                                   console.log('已关闭蓝牙模块');
                                                                 }
                                                              });
                                                          }
                                                    });
                                           });
                                   },fail(err){
                                          console.log(err)
                                   }
                               })
                        });
                  }
                },fail(err) {
                  console.log(err)
                }
              });
            }, 110);
          }

        }
});
上一篇 下一篇

猜你喜欢

热点阅读