当前位置:   article > 正文

微信小程序-蓝牙配网功能_小程序蓝牙配网代码

小程序蓝牙配网代码

蓝牙配网-连接设备


注:这两天接手了一个设备运维端小程序,需要在上面加一个新功能,蓝牙配网,就是通过扫描设备二维码,拿到该设备的uuid、设备名等信息,然后通过蓝牙连接上该设备并往设备中写入数据、读取设备特征值、解析等。小白一个,所以在写的时候遇到了一些坑,想着记录下来
微信小程序官方文档上有相关的蓝牙API详细描写,我在这就不多说了

  1. 使用蓝牙功能去连接一个蓝牙设备,我们需要知道这个设备的名称,这个设备名称我是通过扫码得到的,得到这个设备的详细信息以后,我们就需要初始化蓝牙模块
 //初始化蓝牙模块
  clickbtn() {
    var that = this
    // 初始化蓝牙模块
    wx.openBluetoothAdapter({
      success: function (res) {
        // 获取蓝牙适配器状态
        that.getBluetoothAdapterState()
      },
      fail: function (res) {
        if (res.errCode == 10001) {
          //手机蓝牙不可用
          // console.log('手机蓝牙不可用')
          wx.showToast({
            title: '手机蓝牙不可用,请开启蓝牙再试~',
            icon: 'none',
            duration: 2000
          })
        }
      }
    })
  },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

在初始化蓝牙模块的时候我遇到了第一个问题,可谓出师不利,在我初始化手机上蓝牙模块的时候,wx.openBluetoothAdapter这个api一直调用失败,说我手机没有打开蓝牙,可是我检查了好几遍,手机上的蓝牙我是开启了的,代码也没啥问题,手动狗头。最后面向百度编程,才得知,当你使用苹果手机的时候(安卓的没试过),光打开设置了里面的蓝牙是不够的,还得将设置–>微信–>蓝牙打开才OK。

  1. 获取本机蓝牙适配器状态
  //获取本机蓝牙适配器状态
  //检测本机蓝牙是否可用
  getBluetoothAdapterState() {
    var that = this
    //获取本机蓝牙适配器状态
    wx.getBluetoothAdapterState({
      success: function (res2) {
        if (res2.errMsg == 'getBluetoothAdapterState:ok') {
          //搜寻附近的蓝牙设备
          that.startBluetoothDevicesDiscovery()
        }
        //{errMsg: "getBluetoothAdapterState:ok", available: true, discovering: false}
      },
      fail: function (res2) {
        // console.log('获取本机蓝牙适配器状态', res2)
      },
    })
  },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

3.开始搜寻附近的蓝牙设备

 //开始搜寻附近的蓝牙外围设备
  startBluetoothDevicesDiscovery() {
    var that = this;
    // console.log('开始搜寻附近的蓝牙外围设备')
    wx.startBluetoothDevicesDiscovery({
      powerLevel: "high",
      success: function (res) {
        console.log('开始搜寻附近的蓝牙外围设备', res)
        if (res.errCode == 0) {
        // 监听寻找到新设备的事件
          that.onBluetoothDeviceFound()
        }
      },
      fail: function (res) {
        console.log('开始搜寻附近的蓝牙外围设备', res)
      }
    })
  },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

4.监听寻找到新设备的事件

  //监听寻找到新设备的事件
  onBluetoothDeviceFound() {
    var that = this
    wx.onBluetoothDeviceFound((res) => {
      console.log(res);
      res.devices.forEach(device => {
        if (!device.name && !device.localName) {
          return
        }
        const foundDevices = this.data.devices
        const idx = that.inArray(foundDevices, 'deviceId', device.deviceId)
        console.log(idx);
        
        const data = {}
        if (idx === -1) {
          data[`devices[${foundDevices.length}]`] = device
        } else {
          data[`devices[${idx}]`] = device
        }
        this.setData(data)
      })
    })
    // 筛选数据自动连接对应设备
    var deviceName = 'FT_' + this.data.bluetoothName;
    for (var i = 0; i < that.data.devices.length; i++) {
      if (that.data.devices[i].localName == deviceName) {
      //筛选完成,连接蓝牙
        that.createBLEConnection(that.data.devices[i].deviceId)
        // console.log(that.data.devices[i])
        this.setData({
          newBluetoothData: [that.data.devices[i]],
          myDeviceId: [that.data.devices[i].deviceId],
        })
        wx.showToast({
          title: '匹配设备成功~',
          icon: 'success',
          duration: 2000
        })
        clearInterval(this.data.TimeFn)
        return
      }
    }
  },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

5.连接蓝牙

createBLEConnection(deviceId) {
    var that = this
    // console.log('连接蓝牙', that.data.deviceId)
    for (var i = 0; i < that.data.devices.length; i++) {
  
    //连接蓝牙前先关闭已连接蓝牙
    wx.createBLEConnection({
      deviceId: deviceId,
      success: function (res) {
        // console.log('连接蓝牙成功', res)
        //获取连接设备的service服务
        that.getBLEDeviceServices(deviceId);
        //停止搜寻附近的蓝牙外围设备
        // wx.stopBluetoothDevicesDiscovery({
        //   success: function(res) {
        //     console.log('停止搜寻附近的蓝牙外围设备',res)
        //   },
        //   fail:function(res){

        //   }
        // })
      },
      fail: function (res) {
        console.log('连接蓝牙失败', res)
      },
    })
  },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  1. 获取连接设备的service服务
  getBLEDeviceServices(deviceId) {
    var that = this
    wx.getBLEDeviceServices({
      deviceId: deviceId,
      success: function (res) {
        that.setData({
          service: res.services
        })
        console.log('获取连接设备的service服务', res)
        // that.getBLEDeviceCharacteristics(deviceId, res.services[0]['uuid'])
        for (let i = 0; i < res.services.length; i++) {
          if (res.services[i].isPrimary && res.services[i].uuid == '0000AA00-0000-1000-8000-00805F9B34FB') {
            that.setData({
              myId: deviceId,
              serviceId: res.services[i].uuid
            })
            //获取连接设备的所有特征值
            that.getBLEDeviceCharacteristics(deviceId, res.services[i].uuid)
            // return
          }
        }
      },
      fail: function (res) {
        console.log('获取蓝牙失败', res)
      }
    })
  },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  1. 获取连接设备的所有特征值
 getBLEDeviceCharacteristics(deviceId, serviceId) {
    var that = this
    wx.getBLEDeviceCharacteristics({
      deviceId: deviceId,
      serviceId: serviceId,
      success: function (res) {
        console.log('获取连接设备的所有特征值', res);
        if (res.errCode == 0) {
          that.setData({
            characteristicId: res.characteristics,
            // clickFlag: true,
            showModal: false, //loading关闭
            wifiFlag: true // wifi弹窗开启
          })
          // that.onBLECharacteristicValueChange()
          for (var i = 0; i < res.characteristics.length; i++) {
          //启用低功耗蓝牙设备特征值变化时的 notify 功能
            that.notifyBLECharacteristicValueChange(deviceId, serviceId, that.data.characteristicId[i]['uuid'])
            // 获取可以写入的设备的特征值uuid
            if (that.data.characteristicId[i]['properties']['write']) {
              that.setData({
                uuId: that.data.characteristicId[i]['uuid']
              })
            }
          }
        } else {
          console.log('获取特征值失败')
        }
      },
    })
  },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  1. 启用低功耗蓝牙设备特征值变化时的 notify 功能
 notifyBLECharacteristicValueChange(deviceId, serviceId, characteristicId) {
    var that = this
    wx.notifyBLECharacteristicValueChange({
      deviceId: deviceId,
      serviceId: serviceId,
      characteristicId: characteristicId,
      state: true,
      success: function (res) {
        console.log('启用低功耗蓝牙设备特征值变化时的 notify 功能', res)
        //  console.log('启用低功耗蓝牙设备特征值变化时的 notify 功能', that.data.uuId)
        /*用来监听手机蓝牙设备的数据变化*/

        that.onBLECharacteristicValueChange()
      },
      fail: function (res) {
        console.log('启用低功耗蓝牙设备特征值变化时的 notify 功能失败', res)
      }
    })
  },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  1. 监听低功耗蓝牙设备的特征值变化事件(必须先启用 notifyBLECharacteristicValueChange 接口才能接收到设备推送的 notification)这个方法我其实是没有用到的,我在第七步连接蓝牙成功并且获取到连接设备的特征值以后就打开wifi弹窗进行蓝牙配网了,完整的蓝牙连接设备我会在文章末尾放一个前辈的连接,我是参考他的写的
 onBLECharacteristicValueChange() {
    var that = this
    wx.onBLECharacteristicValueChange(function (res) {
      console.log('监听低功耗蓝牙设备的特征值变化事件', res)
      // console.log(`characteristic ${res.characteristicId} has changed, now is ${res.value}`)
      // console.log(that.ab2hex(res.value))
      // console.log(that.hexCharCodeToStr(that.ab2hex(res.value)))
      var message = that.ab2hex(res.value)
      that.readOrder(message)
    })
  },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  1. 连接wifi
 // 连接wifi
  wifiConnect() {
    if (!this.data.wifiAccount || !this.data.wifiPassword) {
      wx.showToast({
        title: '不能为空',
        icon: 'error',
        duration: 2000
      })
      return false
    }
    // 处理要写入设备的值
    this.getBluetoothValue()
  },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

11.获取要写入蓝牙设备的值

 // 获取要写入蓝牙设备的值
  getBluetoothValue() {
    //  1.0x50,2.wifi账号,3.0x8B,4.wifi密码,5.0xCF 6.服务器IP 端口号 子网信息
    let that = this
    let {
      useValueOne,
      wifiAccount,
      useValueTwo,
      wifiPassword,
      useValueThree,
      serverIp,
      portNumber,
      subnetInfo
    } = that.data
    
     // 字符串转16进制
     let a = that.strToHexCharCode(wifiAccount) // wifi账号
     let b = that.strToHexCharCode(wifiPassword) // wifi密码
     let c = that.strToHexCharCode(subnetInfo)// 服务器子网
     //按硬件的需求 将3个定值 以及 wifi账号和密码拼成16进制字符串
    let hesCaarCode = useValueOne + a + useValueTwo + b + useValueThree + serverIp + portNumber + c
   
    // 2个字符等于一个字节 往设备写入数据一次只能发一个包20个字节
    var len = parseInt(hesCaarCode.length / 40) + 1
    console.log(len);
    // 向设备写入数据 有几个包就发几次
    for (var i = 0; i < len; i++) {
      // 截取每一个包的数据
      var code = hesCaarCode.substr(i * 40, 40)
      that.writeBLECharacteristicValue(that.codebuffer(code))
    }
  },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  1. 发送数据(我是根据硬件的需求往设备里面写入数据)
//发送数据
  writeBLECharacteristicValue(value) {
    var that = this
    //连接蓝牙是记录session
    // console.log('写入设备', that.data.myId)
    // console.log('写入服务', that.data.serviceId)
    // console.log('写入特征值', that.data.uuId.toString())
    console.log(value);

    wx.writeBLECharacteristicValue({
      deviceId: that.data.myId,
      serviceId: that.data.serviceId,
      characteristicId: that.data.uuId.toString(),
      value: value,
      success: function (res) {
        if (res.errCode == 0) {
          that.setData({
            wifiFlag: false,
          })
          wx.showToast({
            title: '连接成功',
            icon: 'success',
            duration: 2000
          })
          // // 暂时断开
          // var closeTimeBlue = setInterval(() => {
          //   that.closeBlueFn();
          //   wx.navigateBack({
          //     delta: 1,
          //   })
          //   clearInterval(closeTimeBlue)
          // }, 5000);
        } else {
          wx.showToast({
            title: '连接失败',
            icon: 'none',
            duration: 2000
          })
        }
      },
      fail: function (err) {
        // console.log('写入数据返回值失败', err)
      },
    })
  },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

到这里我这个蓝牙配网功能就初步完成了,后续会和硬件对接,有问题会及时更新,然后在附上几个小方法

//字符串转16进制
  strToHexCharCode(str) {
    if (str === "")
      return "";
    var hexCharCode = [];
    // hexCharCode.push("0x");
    for (var i = 0; i < str.length; i++) {
      hexCharCode.push((str.charCodeAt(i)).toString(16));
    }
    return hexCharCode.join("");
  },
   //将16进制转ArrayBuffer
  codebuffer: function (val) {
    // 将16进制转化为ArrayBuffer
    return new Uint8Array(val.match(/[\da-f]{2}/gi).map(function (h) {
      return parseInt(h, 16)
    })).buffer
  },
    //16进制转字符串
  hexCharCodeToStr(hexCharCodeStr) {
    var trimedStr = hexCharCodeStr.trim();
    var rawStr =
      trimedStr.substr(0, 2).toLowerCase() === "0x" ?
      trimedStr.substr(2) :
      trimedStr;
    var len = rawStr.length;
    if (len % 2 !== 0) {
      alert("Illegal Format ASCII Code!");
      return "";
    }
    var curCharCode;
    var resultStr = [];
    for (var i = 0; i < len; i = i + 2) {
      curCharCode = parseInt(rawStr.substr(i, 2), 16); // ASCII Code Value
      resultStr.push(String.fromCharCode(curCharCode));
    }
    return resultStr.join("");
  },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

为什么我上面往设备发送数据的时候要分包

BLE 4.0 中发送一个数据包只能包含 20 字节的数据,大于 20 字节只能分包发送。微信小程序提供的 API 中似乎没有自动分包的功能,这就只能自己手动分包了。调试中发现,在 iOS 系统中调用 wx.writeBLECharacteristicValue 发送数据包,回调 success 后紧接着发送下一个数据包,很少出现问题,可以很快全部发送完毕。而安卓系统中,发送一个数据包成功后紧接着发送下一个,很大概率会出现发送失败的情况,在中间稍做延时再发送下一个就可以解决这个问题(不同安卓手机的时间长短也不一致),照顾下一些比较奇葩的手机,大概需要延时 250 ms 。不太好的但是比较科学的办法是,只要成功发送一个数据包则发送下一个,否则不断重发,具体就是
wx.writeBLECharacteristicValue 回调 fail 则重新发送,直至发送完毕

下面这个链接是我一个前辈的博客,对我这个功能的开发帮组非常大,比我的更完善
https://www.cnblogs.com/guhonghao/p/9947144.html

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/321150
推荐阅读
相关标签
  

闽ICP备14008679号