微信小程序蓝牙功能

前言:
微信小程序目前只支持低功耗蓝牙(BLE),文档中的两套API是可以混合使用的,请大家不用再去社区问这些问题了。
微信的文档 已经很详细了,不懂的主要是流程,本文主要介绍流程,通信。

demo请戳:https://github.com/webwjg/blueTooth.git

1.正文

1.GPS
安卓手机需要GPS才能搜索到蓝牙设备,所以需要提醒用户开启GPS,在进入页面就先获取获取用户信息,判断是否开启GPS,然后提示用户
片段1:


	data: {
     
    devicesList:[],   //渲染数组(蓝牙设备列表)
    isHideList:true,    //是否隐藏蓝牙列表
    isHideConnect:false, //是否隐藏连接模块
    deviceId:'',  // 设备id
    connectName:'',  //连接的蓝牙名称
    writeNews:{
     }, //写数据三个id
    queryData:{
       //要写的16进制数组
      query:[0x02,0x09,0x00,0x01,0x6A,0x00,0x50,0x06],
      stateTest:[0x01,0x08,0x02,0x00,0x56,0x00,0x59,0x06],
    },


	},

  onLoad: function(options) {
     
    let that=this;
    wx.getSystemInfo({
     
        success (res) {
     
          console.log(res);
          let gps=res.locationEnabled;
          if(!gps){
     
            wx.showModal({
     
              title: '请打开GPS定位',
              content: '不打开GPS定位,可能无法搜索到蓝牙设备',
              showCancel: false
            })
          }else{
     
            that.openBluetoothAdapter(); //初始化蓝牙模块
          }
        }
      }) 

  },

2.初始化蓝牙模块(wx.openBluetoothAdapter)

蓝牙API都必须初始化之后才能调用。初始化之后需要调用监听蓝牙适配器状态变化事件(wx.onBluetoothAdapterStateChange),如果中途蓝牙适配器状态发生变化,可以提示用户
片段2:

openBluetoothAdapter(){
     
    wx.openBluetoothAdapter({
     
      success (res) {
     
        that.setData({
     isOpen:true});
        wx.onBluetoothAdapterStateChange(function (res) {
     
          if(!res.available){
     //蓝牙适配器是否可用
            wx.showModal({
     
                title: '温馨提示',
                content: '蓝牙蓝牙适配器不可用,请重新启动',
                showCancel: false
              })
          }
        })
        that.searchBlue(); //开始搜索蓝牙
      },
      fail(res){
     
        wx.showToast({
     
          title: '请检查手机蓝牙是否打开',
          icon:'none',
        })
      },
    })
},

3.搜索蓝牙设备(wx.startBluetoothDevicesDiscovery)

适配器打开之后就可以搜索蓝牙设备了,startBluetoothDevicesDiscovery就是开始搜索的API,搜索比较耗费资源,连接蓝牙之后不要忘记调用wx.stopBluetoothDevicesDiscovery结束搜索。这步和下一步是一起的,下步上代码。

4.获取蓝牙设备的信息(wx.getBluetoothDevices)

这步就可以获取到蓝牙列表数组,其中包含蓝牙设备的名称(name),设备id(deviceId),还有信号强度(RSSI)等,我们拿到信息数组就可以把蓝牙列表渲染出来了,
微信小程序蓝牙功能_第1张图片
上图就是返回的数组
片段3:

searchBlue(){
     
    let that=this;
    wx.startBluetoothDevicesDiscovery({
     
      allowDuplicatesKey: false,
      success (res) {
     
        console.log(res);
        wx.showLoading({
     title: '正在搜索设备',}); 
        wx.getBluetoothDevices({
     
          success: function(res) {
     
            console.log(res);
            let devicesListArr=[];
            if(res.devices.length>0){
      //如果有蓝牙设备就把蓝牙信息放到渲染列表里面
              wx.hideLoading();
              res.devices.forEach(device=>{
     
                if (!device.name && !device.localName) {
     
                  return
                }else{
     
                  devicesListArr.push(device);  //渲染数组
                }
              })
              that.setData({
     devicesList:devicesListArr,isHideList:false}); //渲染到页面中
            }else{
     
              wx.hideLoading();
              wx.showModal({
     
                title: '温馨提示',
                content: '无法搜索到蓝牙设备,请打开GPS重新尝试',
                showCancel: false
              });
              wx.closeBluetoothAdapter({
     
                success (res) {
     
                    console.log(res)
                }
              })
            }
          }
        })
      },
      fail: function(res) {
     
        wx.showToast({
     
            title: '搜索蓝牙外围设备失败,请重新初始化蓝牙!',
            icon:'none',
        })
      }
    })
  },

这一步已经拿到了设备id(deviceId),我会把设备id以自定义属性放入到标签中,然后用户选择连接那个蓝牙设备,就能拿到那个设备的deviceId。

5.连接低功耗蓝牙(wx.createBLEConnection)

上一步把列表渲染出来了,用户会选择一个设备连接,拿到deviceId,然后去调用createBLEConnection这个API,就能连接到蓝牙了,记住,连接成功之后要关闭搜索蓝牙。
片段4:

connectTo(e){
     
    let that=this;
    let deviceId=e.currentTarget.dataset.id; //设备id
    let connectName=e.currentTarget.dataset.name; //连接的设备名称
    wx.showLoading({
     title: '连接中...',});
    wx.createBLEConnection({
     
      deviceId,// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
      success (res) {
     
        wx.hideLoading();
        that.stopBluetoothDevicesDiscovery(); //停止搜索蓝牙
        console.log(res);
        if(res.errCode==0){
     
          console.log('连接成功');
          that.setData({
      
              deviceId:deviceId,  
              connectName:connectName,
              isHideConnect:false,  //显示已连接的蓝牙
          })
          that.getBLEDeviceServices(deviceId); //获取已连接蓝牙的服务
        }else if(res.errCode==10012){
     
          wx.showToast({
     
            title: '连接超时,请重试!',
          })
        }
      },
      fail(error){
     
         wx.hideLoading();
          wx.showToast({
     
            title: error,
          })
      }
    });
  },

stopBluetoothDevicesDiscovery(){
     
  wx.stopBluetoothDevicesDiscovery({
     
    success (res) {
     
      console.log(res)
    }
  })
 },

6.获取蓝牙的服务(wx.getBLEDeviceServices)

连接到蓝牙之后就是获取蓝牙的服务了,每个蓝牙都有数个服务,起到不同的功能,每个服务有独立的uuid,我们要做的就是拿到服务的uuid也就是serviceId。
微信小程序蓝牙功能_第2张图片

我们需要用到我们需要的服务的uuid,这个一般是跟硬件沟通,知道需要操作哪个服务,我这边需要第二个服务,我就去操作第二个服务
片段5:

  //获取服务以及服务的uuid                                             
  getBLEDeviceServices(deviceId){
       
  	let that=this; 
    let serviceId;
    wx.getBLEDeviceServices({
      //获取蓝牙设备所有服务
      deviceId, 
      success: (res) => {
      //services:设备服务列表 uuid:服务id
        console.log(res);
        serviceId=res.services[1].uuid;
        that.getBLEDeviceCharacteristics(deviceId, serviceId); //去获取特征值
      },
    }) 
  },

7.获取服务的特征值(wx.getBLEDeviceCharacteristics)
我拿第二个服务的uuid,去获取这个服务的所有特征值,特征值我们可以读,写(发送请求),监听(接收数据)
微信小程序蓝牙功能_第3张图片
获取到的特征值如上图
片段6:

  getBLEDeviceCharacteristics(deviceId, serviceId) {
      
    console.log(deviceId,'serviceId='+ serviceId)
    let that=this;
    wx.getBLEDeviceCharacteristics({
     
      deviceId,
      serviceId,
      success: (res) => {
     
        console.log(res);
        let characteristicId=res.characteristics[0].uuid; //要写数据的特征id
        let notifyId=res.characteristics[3].uuid;  //监听特征变化的特征id(接收数据)
        that.notifyBLECharacteristicValueChange(serviceId,notifyId); 
        let writeNews={
     deviceId,serviceId,characteristicId};
        that.setData({
     writeNews:writeNews}); //写的时候需要用到
      },
      fail(err){
     
        console.log('获取特征值失败:');
        console.log(err)
      },
    });

  },

我这边是对此服务的第一个特征进行写操作(就是发送数据),然后监听第四个特征(接收数据)

8.监听特征值变化(接收数据)

我们需要先订阅特征值,才能监听特征值变化,订阅的API是:wx.notifyBLECharacteristicValueChange,然后在调用wx.onBLECharacteristicValueChange,去监听特征值变化(接收数据),

片段7:

  notifyBLECharacteristicValueChange(serviceId,characteristicId){
     
    let that=this;
    wx.notifyBLECharacteristicValueChange({
     
      state: true, // 启用 notify 功能
      deviceId: that.data.deviceId,
      serviceId,
      characteristicId,
      success (res) {
     
        console.log('notifyBLECharacteristicValueChange success');
        console.log(res);
        wx.onBLECharacteristicValueChange(function (res){
     
            console.log(res); 
            let str=that.ab2hex(res.value); //转为16进制字符串
			//这就是需要的字符了
        })
      }
    })
  },
   // ArrayBuffer转16进制字符串
ab2hex(buffer){
     
    var hexArr = Array.prototype.map.call(
      new Uint8Array(buffer),
      function (bit) {
     
        return ('00' + bit.toString(16)).slice(-2)
      }
    )
    return hexArr.join('');
  },

这一步就能获取到数据了,我们是先开启监听,然后写数据,就能接收到数据了。

9.写入数据(发送请求) (wx.writeBLECharacteristicValue)

写入数据其实就是发送请求,我们已经开启监听了,就要发送请求了,
片段8:

  writeBLECharacteristicValue(){
      //页面有个按钮
    // 向蓝牙设备发送的16进制数据
     let that=this;
     let buffer = new ArrayBuffer(8);
     let dataView = new DataView(buffer);
     console.log(dataView);//第一个参数是字节序号,表示从哪个字节开始写入,第二个参数为写入的数据。
     let arr=that.data.queryData.query;
     arr.forEach((item,i)=>{
     
      dataView.setInt8(i, arr[i]);  
     })
     console.log(buffer)
     wx.writeBLECharacteristicValue({
     
       deviceId: that.data.writeNews.deviceId,
       serviceId: that.data.writeNews.serviceId,
       characteristicId:that.data.writeNews.characteristicId,
       value: buffer,
       success:(res)=>{
     
          console.log(res);
       },
       fail:(err)=>{
     
          console.log(err)
       }
     })
  },

发送需要设备id(deviceId),服务id(serviceId),特征值id(characteristicId),一般情况下,我们写入成功之后就能接收到数据了,
微信小程序蓝牙功能_第4张图片
value就是接收到的数据。

基本流程就是这样的,断开连接什么的需要你们自己根据自己的情况来了,我就不写了。
如果需要全部demo的可以在本文开头给的链接去github去拷贝。下面就只贴js了。有问题的可以下方评论询问。
如果本文对大家有帮助,请给我点个赞,蟹蟹!

js:

// pages/blueTooth/blueTooth.js
Page({
     
	data: {
     
	
    devicesList:[],
    isHideList:true,    //是否隐藏蓝牙列表
    isHideConnect:false, //是否隐藏连接模块
    deviceId:'',
    connectName:'',
    writeNews:{
     }, //写数据三个id
    queryData:{
     
      query:[0x02,0x09,0x00,0x01,0x6A,0x00,0x50,0x06],
      stateTest:[0x01,0x08,0x02,0x00,0x56,0x00,0x59,0x06],
    },

	},

	/**
	 * 生命周期函数--监听页面加载
	 */

     // ****流程,大纲
  onLoad: function(options) {
     
      //目前只支持低功耗蓝牙,文档上的两套api是可以结合使用的,安卓
    let that=this;
    wx.getSystemInfo({
     
        success (res) {
     
          console.log(res);
          let gps=res.locationEnabled;
          if(!gps){
     
            wx.showModal({
     
              title: '请打开GPS定位',
              content: '不打开GPS定位,可能无法搜索到蓝牙设备',
              showCancel: false
            })
          }else{
     
            that.openBluetoothAdapter();
          }
        }
      }) 

  },
openBluetoothAdapter(){
     
    wx.openBluetoothAdapter({
     
      success (res) {
     
      
        wx.onBluetoothAdapterStateChange(function (res) {
     
          if(!res.available){
     //蓝牙适配器是否可用
            wx.showModal({
     
                title: '温馨提示',
                content: '蓝牙蓝牙适配器不可用,请重新启动',
                showCancel: false
              })
          }
        })
        that.searchBlue(); //开始搜索蓝牙
      },
      fail(res){
     
     
        console.log(res);
        wx.showToast({
     
          title: '请检查手机蓝牙是否打开',
          icon:'none',
        })
      },
    })
},
 
searchBlue(){
     
    let that=this;
    wx.startBluetoothDevicesDiscovery({
     
      allowDuplicatesKey: false,
      success (res) {
     
        console.log(res);
        wx.showLoading({
     title: '正在搜索设备',}); 
        wx.getBluetoothDevices({
     
          success: function(res) {
     
            console.log(res);
            let devicesListArr=[];
            if(res.devices.length>0){
      //如果有蓝牙就把蓝牙信息放到渲染列表里面
              wx.hideLoading();
              res.devices.forEach(device=>{
     
                if (!device.name && !device.localName) {
     
                  return
                }else{
     
                  devicesListArr.push(device);
                }
              })
              that.setData({
     devicesList:devicesListArr,isHideList:false}); //渲染到页面中
            }else{
     
              wx.hideLoading();
              wx.showModal({
     
                title: '温馨提示',
                content: '无法搜索到蓝牙设备,请打开GPS重新尝试',
                showCancel: false
              });
              wx.closeBluetoothAdapter({
     
                success (res) {
     
                    console.log(res)
                }
              })
            }
          }
        })
      },
      fail: function(res) {
     
        wx.showToast({
     
            title: '搜索蓝牙外围设备失败,请重新初始化蓝牙!',
            icon:'none',
        })
      }
    })
  },
  //开始连接,获取deviceId
  connectTo(e){
     
    let that=this;
    let deviceId=e.currentTarget.dataset.id; //设备id
    let connectName=e.currentTarget.dataset.name; //连接的设备名称
    wx.showLoading({
     title: '连接中...',});
    wx.createBLEConnection({
     
      deviceId,// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
      success (res) {
     
        wx.hideLoading();
        that.stopBluetoothDevicesDiscovery(); //停止搜索蓝牙
        console.log(res);
        if(res.errCode==0){
     
          console.log('连接成功');
          that.setData({
      
              deviceId:deviceId,
              connectName:connectName,
              isHideConnect:false,
          })
          that.getBLEDeviceServices(deviceId); //获取已连接蓝牙的服务
        }else if(res.errCode==10012){
     
          wx.showToast({
     
            title: '连接超时,请重试!',
          })
        }
      },
      fail(error){
     
         wx.hideLoading();
          wx.showToast({
     
            title: error,
          })
      }
    });
  },
  //每个蓝牙都有数个服务,起到不同的功能,每个服务有独立的uuid
  //获取服务以及服务的uuid                                             
  getBLEDeviceServices(deviceId){
        
    let serviceId;
    wx.getBLEDeviceServices({
      //获取蓝牙设备所有服务
      deviceId, 
      success: (res) => {
      //services:设备服务列表 uuid:服务id
        console.log(res);
        serviceId=res.services[1].uuid;
        this.getBLEDeviceCharacteristics(deviceId, serviceId);
        
      },
    }) 
  },
  //每个服务都有特征值,特征值也有uuid,
  //获取特征值(是否能读写)
  getBLEDeviceCharacteristics(deviceId, serviceId) {
      
    console.log(deviceId,'serviceId='+ serviceId)
    let that=this;
    wx.getBLEDeviceCharacteristics({
     
      deviceId,
      serviceId,
      success: (res) => {
     
        console.log(res);
        let characteristicId=res.characteristics[0].uuid; //要写数据的特征id
        let writeNews={
     deviceId,serviceId,characteristicId};
        that.setData({
     writeNews:writeNews});
        let notifyId=res.characteristics[3].uuid;  //监听特征变化的特征id(接收数据)
        that.notifyBLECharacteristicValueChange(serviceId,notifyId); 
      },
      fail(err){
     
        console.log('获取特征值失败:');
        console.log(err)
      },
    });

  },
  writeBLECharacteristicValue(){
      //页面有个按钮
    // 向蓝牙设备发送的16进制数据
     let that=this;
     let buffer = new ArrayBuffer(8);
     let dataView = new DataView(buffer);
     console.log(dataView);//第一个参数是字节序号,表示从哪个字节开始写入,第二个参数为写入的数据。
     let arr=that.data.queryData.query;
     arr.forEach((item,i)=>{
     
      dataView.setInt8(i, arr[i]);  
     })
     console.log(buffer)
     wx.writeBLECharacteristicValue({
     
       deviceId: that.data.writeNews.deviceId,
       serviceId: that.data.writeNews.serviceId,
       characteristicId:that.data.writeNews.characteristicId,
       value: buffer,
       success:(res)=>{
     
          console.log(res);
       },
       fail:(err)=>{
     
          console.log(err)
       }
     })
  },

  notifyBLECharacteristicValueChange(serviceId,characteristicId){
     
    let that=this;
    wx.notifyBLECharacteristicValueChange({
     
      state: true, // 启用 notify 功能
      deviceId: this.data.deviceId,
      serviceId,
      characteristicId,
      success (res) {
     
        console.log('notifyBLECharacteristicValueChange success');
        console.log(res);
        wx.onBLECharacteristicValueChange(function (res){
     
            console.log(res); 
            let str=util.ab2hex(res.value);
            that.setData({
     initializationArr:util.initialization(str)})
            console.log(util.initialization(str));
        })
      }
    })
  },

   // ArrayBuffer转16进制字符串
ab2hex(buffer){
     
    var hexArr = Array.prototype.map.call(
      new Uint8Array(buffer),
      function (bit) {
     
        return ('00' + bit.toString(16)).slice(-2)
      }
    )
    return hexArr.join('');
  },
  //断开连接
  closeBLEConnection() {
      
    let that=this;
    console.log(that.data)
   wx.closeBLEConnection({
     
     deviceId: this.data.deviceId,
     success(){
     
       wx.showToast({
     
         title: '已断开连接',
       });
       that.setData({
     
         deviceId:'',
         connectName:'',
         isHideConnect:true,
       });
     }
   })
   that.closeBluetoothAdapter();

 },
 stopBluetoothDevicesDiscovery(){
     
  wx.stopBluetoothDevicesDiscovery({
     
    success (res) {
     
      console.log(res)
    }
  })
 },

  //关闭蓝牙模块
  closeBluetoothAdapter() {
     
    wx.closeBluetoothAdapter({
     
      success (res) {
     
        console.log('关闭蓝牙模块')
        that.setData({
     
          devicesList:[],
          isHideList:true,    //是否隐藏蓝牙列表
          isHideConnect:true, //是否隐藏连接模块
        })
      }
    })
  },



	/**
	 * 生命周期函数--监听页面初次渲染完成
	 */
	onReady: function () {
     

	},

	/**
	 * 生命周期函数--监听页面显示
	 */
	onShow: function () {
     
  
	},

	/**
	 * 生命周期函数--监听页面隐藏
	 */
	onHide: function () {
     

	},

	/**
	 * 生命周期函数--监听页面卸载
	 */
	onUnload: function () {
     

	},

	/**
	 * 页面相关事件处理函数--监听用户下拉动作
	 */
	onPullDownRefresh: function () {
     

	},

	/**
	 * 页面上拉触底事件的处理函数
	 */
	onReachBottom: function () {
     

	},

	/**
	 * 用户点击右上角分享
	 */
	onShareAppMessage: function () {
     

	}
})

你可能感兴趣的:(小程序,小程序)