微信小程序连接蓝牙 并分包发送 接收数据完整版

佴波鸿
2023-12-01

初始化蓝牙

//初始化蓝牙适配器
wx.openBluetoothAdapter({
    success: function (res) {
      //获取本机蓝牙适配器状态
      wx.getBluetoothAdapterState({
        success: function (res) {
          //蓝牙可用 
          console.log('蓝牙可用 ')
        },
        fail: function (res) {
          //蓝牙不可用
          console.log('蓝牙不可用')
        }
      })
    },
    fail: function (res) {
      console.log('请打开蓝牙和定位功能')
    }
  })

初始化蓝牙设备

//初始化蓝牙设备
wx.openBluetoothAdapter({
  success: (res) => {
    console.log('初始化成功,接下来搜索蓝牙设备') 
  },
  fail: (res) => {}
})

搜索蓝牙设备

//搜索蓝牙设备
wx.startBluetoothDevicesDiscovery({
  allowDuplicatesKey: true,
  success: async (res) => {
    console.log('startBluetoothDevicesDiscovery success', res)
    // 监听寻找到新设备的事件
    wx.onBluetoothDeviceFound((res) => {
      res.devices.forEach(device => {
        if (!device.name && !device.localName) {
          return
        }
        const foundDevices = this.data.devices//页面存储蓝牙列表的数组
        const idx = inArray(foundDevices, 'deviceId', device.deviceId)
        const data = {};
        if (idx === -1) {
          data[`devices[${foundDevices.length}]`] = device
        } else {
          data[`devices[${idx}]`] = device
        }
        this.setData(data)
      })
    })
  },
})

连接蓝牙设备

//获取被点击连接蓝牙 页面设置的deviceId 用于连接蓝牙
const deviceId = e.currentTarget.dataset.deviceId
wx.createBLEConnection({
  deviceId: deviceId,
  success: (res) => {
    this.setData({
      connected: true,
      name,//保存蓝牙设备名称
      deviceId,//保存蓝牙设备ID
    })
    // 如果有读写操作则下面进行 获取蓝牙设备所有service
    
  }
})

获取蓝牙设备所有service(支持读写的)

//获取蓝牙设备所有service
var deviceId=this.data.deviceId
wx.getBLEDeviceServices({
  deviceId:deviceId,//蓝牙设备id   连接成功时保存在data中的
  success: (res) => {
    for (let i = 0; i < res.services.length; i++) {
      var serviceId=res.services[i].uuid
      if (res.services[i].isPrimary) {//判断该服务是否为主服务
        //获取蓝牙设备某个服务中所有特征值
        wx.getBLEDeviceCharacteristics({
          deviceId:deviceId,
          serviceId:serviceId,
          success: (res2) => {
            for (let j = 0; j < res2.characteristics.length; j++) {
              let item = res2.characteristics[j]
              if (item.properties.notify) {//判断该特征值是否支持 notify 操作
                if (item.properties.read) {
            	  //读取低功耗蓝牙设备的特征值的二进制数据值。
            	  //注意:必须设备的特征值支持 read 才可以成功调用。
            	  wx.readBLECharacteristicValue({
              	    deviceId:deviceId,
          			serviceId:serviceId,
              	    characteristicId: item.uuid,
            	  })
          	    }
                if (item.properties.write) {
                  this.setData({//在这里this已经不能指向data了,可以在方法的最开始用this指向自定义变量在这里代替this使用
                    canWrite: true,//是否可以写入
                    w_deviceId = deviceId,
                    w_serviceId = serviceId
                  })
	              if (_characteristicId == undefined) {
		            this.setData({
	                  w_characteristicId = item.uuid
	                })
	              }
	            }
	            //监听设备 characteristicValueChange 事件
	            if (item.properties.notify || item.properties.indicate) {
            		//启用低功耗蓝牙设备特征值变化时的 notify 功能,订阅特征值。
            		//注意:必须设备的特征值支持 notify 或者 indicate 才可以成功调用。
            		//另外,必须先启用 notifyBLECharacteristicValueChange 才能监听到设备 characteristicValueChange 事件
            		wx.notifyBLECharacteristicValueChange({
              		  deviceId,
              		  serviceId,
              		  characteristicId: item.uuid,
              		  state: true,
              		  success: function (e) {
                		console.log('success: ' + JSON.stringify(e));
                		// 操作之前先监听,保证第一时间获取数据
              		  },
              		  fail: function (e) {
                		console.log('error: ' + JSON.stringify(e));
              		  }
            	   })
          		}
              }
            }
          }
        })
      }
    }
  }
})

向蓝牙发送数据

//向蓝牙发送数据
var sendData = "12345f6ewaffew15f6ew4fewf4d2sa1554ew4a5fd5ef1d5s4few5few"//需要发送的数据
let buffer = hexStringToArrayBuffer(sendData );//转16进制
let pos = 0;
let bytes = buffer.byteLength;
var result = ''
while (bytes > 0) {
  let tmpBuffer;
  if (bytes > 20) {
    tmpBuffer = buffer.slice(pos, pos + 20);
    pos += 20;
    bytes -= 20;
    wx.writeBLECharacteristicValue({
      deviceId: this.data.w_deviceId,
      serviceId: this.data.w_serviceId,
      characteristicId: this.data.w_characteristicId,
      value: tmpBuffer,
      success(res) {
        console.log('发送成功!', res)
      }
    })
    sleep(0.02)
  } else {
    tmpBuffer = buffer.slice(pos, pos + bytes);
    pos += bytes;
    bytes -= bytes;
    wx.writeBLECharacteristicValue({
      deviceId: this.data.w_deviceId,
      serviceId: this.data.w_serviceId,
      characteristicId: this.data.w_characteristicId,
      value: tmpBuffer,
      success(res) {
        console.log('最后次发送', res)
        //发送完成获取返回值
        //注:蓝牙有可能会分包给你返回也有可能一次性返回
        wx.onBLECharacteristicValueChange(function (characteristic) {
          //判断是否已经接收完返回值
          //根据自己蓝牙硬件返回的格式判断是否接收完成,如果没接收完继续接收
          //ab2hex 是16进制转10进制
          result = result + ab2hex(characteristic.value)
          //比如硬件返回给你参数指定了长度,你就可以根据长度判断
          if (result.length == 18) {
            console.log("返回值为:"+result)
          }
        })
      },
      fail: function (res) {
        console.log('发送失败', res)
      }
    })
  }
}

断开蓝牙

//断开蓝牙
wx.closeBLEConnection({
   deviceId: this.data.deviceId
})

停止搜索蓝牙

//停止搜寻附近的蓝牙外围设备
wx.stopBluetoothDevicesDiscovery()

转16进制

//转16进制
function hexStringToArrayBuffer(command) {
  if (!command) {
    return new ArrayBuffer(0);
  }
  var buffer = new ArrayBuffer(command.length);
  let dataView = new DataView(buffer)
  let ind = 0;
  for (var i = 0, len = command.length; i < len; i += 2) {
    let code = parseInt(command.substr(i, 2), 16)
    dataView.setUint8(ind, code)
    ind++
  }
  return buffer;
}

ArrayBuffer转16进度字符串示例

// ArrayBuffer转16进度字符串示例
function ab2hex(buffer) {
  var hexArr = Array.prototype.map.call(
    new Uint8Array(buffer),
    function (bit) {
      return ('00' + bit.toString(16)).slice(-2)
    }
  )
  return hexArr.join('');
}
function inArray(arr, key, val) {
  for (let i = 0; i < arr.length; i++) {
    if (arr[i][key] === val) {
      return i;
    }
  }
  return -1;
}

总结

微信小程序连接蓝牙坑还是挺多的,连接蓝牙根据文档可以自己完成,但是在找一个能写入读取蓝牙数据的特征值是一般很多刚接触的朋友可能都不会去观察他的特征值为什么这个能行那个不行之类的,其次就是分包发送数据这个应该大家一查就知道了,最后分包接收数据根据自己硬件返回值的特定格式做判断接收完成即可,这个就是一个完整的微信小程序连接蓝牙并读写数据的功能了,欢迎大家交流。如果对你有帮助希望能给个关注,我会继续分享更多的内容!

注:初学者在使用的时候出现this指向报错,在当前方法第一行把this赋值给你的自定义变量然后用自定义变量代替this就行了!

 类似资料: