小程序 蓝牙 低功耗蓝牙

608 阅读5分钟

1、 开启蓝牙适配 (wx.openBluetoothAdapter(Object object))

 2、 获取蓝牙适配器状态,判断设备蓝牙是否可用。(wx.getBluetoothAdapterState(Object object))  

3、 开启扫描蓝牙设备 (wx.startBluetoothDevicesDiscovery(Object object)) 

4、 获取蓝牙设备列表 (wx.getBluetoothDevices(Object object))

 5、 连接某个已发现的设备 (wx.createBLEConnection(Object object)) 

6、 停止搜索蓝牙设备 (wx.stopBluetoothDevicesDiscovery(Object object))

 7、 获取蓝牙设备服务  (wx.getBLEDeviceServices(Object object)) 

8、 获取服务下的所有特征值 (wx.getBLEDeviceCharacteristics(Object object))

 9、 启用响应特征值变化 (wx.notifyBLECharacteristicValueChange(Object object))

 10、接收蓝牙的返回信息 (wx.onBLECharacteristicValueChange(function callback)) 

11、发送信息 (wx.writeBLECharacteristicValue(Object object))) 

12、断开蓝牙设备的连接 (wx.closeBLEConnection(Object object)) 

上诉述蓝牙相关API 函数详情见微信官方开发文档:官方低功耗蓝牙接口API函数说明; 

小程序 蓝牙自动连接

1 初始化手机蓝牙

. 初始化成后添加 监听蓝牙是否会异常断开,监听蓝牙因为距离,手机蓝牙关闭 等其他情况断开
. 初始化成功后 监听蓝牙断开才能成功

initBlue() {
    var that = this;
    wx.openBluetoothAdapter({//调用微信小程序api 打开蓝牙适配器接口
      success: function (res) {
        that.countdown()
        that.getTheBlueDisConnectWithAccident();//监听蓝牙是否会异常断开
        that.findBlue()
        that.setData({
          isBloothOpen:20
        })
        that.monitorTheBlue();
      },

      fail: function (res) {//如果手机上的蓝牙没有打开,可以提醒用户
      if(that.data.isFirestShow){
        wx.showToast({
          title: '请开启蓝牙',
          icon: 'fails',
          duration: 3000,
        })
      }
        that.setData({
          remaiderString: '等待连接',
          connectionEquipment: '请先打开手机蓝牙,等待连接分析仪',
          isBloothOpen: 10,
          isFirestShow: false,
        })
        console.log(res)
        console.log("蓝牙为打开");
        setTimeout(function () {
          that.initBlue();
        }, 3000) 
      }
    })
  },

2 监听手机蓝牙开关 判定手机蓝牙是否打开

判定手机蓝牙是否打开

//监听手机蓝牙的开关
  monitorTheBlue:function(){
    var that =this;
    wx.onBluetoothAdapterStateChange(function(res){
      console.log(`adapterState changed, now is`, res)
      if (res.available){
        that.setData({
          isBloothOpen: 20,
          connectionEquipment: '请打开设备,并靠近手机',
        })
        wx.showToast({
          title: '蓝牙已开启',
          icon: 'fails',
          duration: 3000,
        })
      }else{
        that.setData({
          remaiderString: '等待连接',
          connectionEquipment: '请先打开手机蓝牙,等待连接分析仪',
          isBloothOpen: 10,
          isFirestShow: false,
        })
        wx.showToast({
          title: '蓝牙已关闭',
          icon: 'fails',
          duration: 3000,
        })
      }
    })
  },

3 开始获取附近的蓝牙设备

. 获取到附近的蓝牙数组 通过蓝牙特定的名称获取自己想要连接的蓝牙设备
. 获取附近蓝牙设备的数组

findBlue() {
    var that = this
    wx.startBluetoothDevicesDiscovery({
      allowDuplicatesKey: false,
      interval: 0,
     success: function (res) {
        if(that.data.isFirestShow){
          wx.showLoading({
            title: '正在搜索设备',
          })
        }
        that.getBlue()//3.0
        // that.stopFindBlue()
      },
      complete:function(){
      },
    })
  },

4 搜索获取附近的所有蓝牙设备 获取附近所有的蓝牙设备的相关信息 获取需要连接蓝牙设备的deviceID

. 通过bluetoothDeviceName 和 localName 来确定制定蓝牙
. 一般根据制定设备的名字去连接 设备的名字 是出产厂家设定

getBlue() {
    var that = this
    wx.getBluetoothDevices({
      success: function (res) {
        wx.hideLoading();
        console.log(res);
        var index = 10
        for (var i = 0; i < res.devices.length; i++) {
          if(res.devices[i].name && res.devices[i].localName){
            var arr = res.devices[i].name.split("-")
            var secArr = res.devices[i].localName.split("-")
            if (arr[0] == that.data.bluetoothDeviceName || secArr[0] == that.data.bluetoothDeviceName) {
              console.log(that.data.bluetoothDeviceName);
              index = 20
              that.setData({
                deviceId: res.devices[i].deviceId,
                devices: res.devices,
                connectionEquipment: '已连接到设备:' + res.devices[i].localName + '请开始测量',
                remaiderString: '测量中',
              })
              console.log("设备:" + res.devices[i].deviceId + that.data.deviceId);
              that.connetBlue();//4.0
            }
          }         
        }
        if(index == 10){
          if (that.data.isFirestShow) {
            that.showFailReminder("未搜索到配套设备")
          }
          that.setData({
            connectionEquipment: '请打开设备,并靠近手机',
            remaiderString: '等待连接',
          })
        }
      },
      fail: function () {
        if (that.data.isFirestShow) {
          that.showFailReminder("未搜索到配套设备")
        } 
        that.setData({
          connectionEquipment: '请打开设备,并靠近手机',
          remaiderString: '等待连接',
        })
      },
      complete:function(){
        that.setData({
          isFirestShow:false,
        })
      },
    })
  },

5 连接蓝牙设备

通过deviceId 连接蓝牙

 connetBlue(deviceId) {
    var that = this;
    wx.createBLEConnection({
      // 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
      deviceId: that.data.deviceId,//设备id
      success: function (res) {
        that.setData({
          remaiderString: '正在测量',
        })
       wx.showToast({
          title: '连接成功',
          icon: 'success',
          duration: 1000
        })
      var isConnect = that.data.isConnected;
      if(isConnect == 10){
        that.getServiceId()//5.0
        that.setData({
          isConnected:20,
        })
      }
      },
      fail:function(res){
      },
    })
  },

6 连接上需要的蓝牙设备之后,获取这个蓝牙设备的服务uuid

获取设备的uuid

getServiceId() {
    var that = this
    wx.getBLEDeviceServices({
      // 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
      deviceId: that.data.deviceId,
     success: function (res) {
        var model = res.services[1]
        console.log(res)
        that.setData({
          servicesUUID: model.uuid
        })
       that.getCharacteId()//6.0
      }
    })
  },

7 如果一个蓝牙设备需要进行数据的写入以及数据传输,就必须具有某些特征值,所以通过上面步骤获取的id可以查看当前蓝牙设备的特征值

notify write read 当只有 notify为true的时候才能 接收蓝牙设备传来的数据,
write 为true 才能传入数据
read 为true 才能读取设备数据

getCharacteId() {
    var that = this
    wx.getBLEDeviceCharacteristics({
      // 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
      deviceId: that.data.deviceId,
      // 这里的 serviceId 需要在上面的 getBLEDeviceServices 接口中获取
      serviceId: that.data.servicesUUID,
      success: function (res) {
        console.log(res);
        for (var i = 0; i < res.characteristics.length; i++) {//2个值
          var model = res.characteristics[i]
          if (model.properties.notify == true) {
          that.setData({
            characteristicId: model.uuid//监听的值
          })
          that.startNotice(model.uuid)//7.0
          }
          if (model.properties.read == true) {
            that.readData(model.uuid)
          }
          if (model.properties.write == true) {
            that.setData({
              writeId: model.uuid//用来写入的值
            })
          }
        }
      }
    })
  },

8 如果一个蓝牙设备需要进行数据的写入以及数据传输,就必须具有某些特征值,所以通过上面步骤获取的id可以查看当前蓝牙设备的特征值

开启设备数据监听 监听蓝牙设备返回来的数据

startNotice(uuid) {
    var that = this;
    wx.notifyBLECharacteristicValueChange({
      state: true, // 启用 notify 功能
      deviceId: that.data.deviceId,
      serviceId: that.data.servicesUUID,
      characteristicId: uuid,  //第一步 开启监听 notityid  第二步发送指令 write
      success: function (res) {
        // 设备返回的方法
        wx.onBLECharacteristicValueChange(function (res) {
          console.log(res  + "蓝牙测试返回的数据" + res.value);
           var nonceId = that.ab2hex(res.value)
          }
          setTimeout(function () {
            that.setData({
              isDeleteRepetition: 100,
            })
          }, 20000)       
        })
      },
      fail: function (res) {
        console.log(res);
      }
    })
  },

/**
    * 将ArrayBuffer转换成字符串
    */
ab2hex(buffer) {
    var hexArr = Array.prototype.map.call(
      new Uint8Array(buffer),
      function (bit) {
        return ('00' + bit.toString(16)).slice(-2)
      }
    )
    return hexArr.join('');
  },

10 监听异常断开

. 当蓝牙设备异常断开时 就开始重新开启计时器
. 注意异常返回 android 和iOS 返回的标示不是完全相同 使用res.connected 返回值来判定蓝牙是否连接

//监听蓝牙设备是否会异常断开
  getTheBlueDisConnectWithAccident:function(e){
    var that = this;
    wx.onBLEConnectionStateChange(function (res) {
      console.log(res)
      if (!res.connected){
      wx.closeBluetoothAdapter({
        success: function(res) {
          wx.openBluetoothAdapter({
           success: function(res) {
            },
          })
        },
      })
        that.setData({
          showBacGroundImageView: '../../images/button_bg_disabled@2x.png',//背景图片
          remaiderString: "等待连接",
          ishindden: true,
          isSugarHidden: true,
          isConnected: 10,
          isFirestShow: false,
          testResultIndex: 0,
        })
        that.countdown()//开启计时
      } 
    })
  },

11 异常断开再次开始

. 我使用的是再次初始化 蓝牙 ,前面思路只是继续搜索蓝牙设备,但发现返回的数值一直都是一样的,比如设备的蓝牙已经关闭,但是设备数组中还是会有原来设备存在 但是就是连接不上

// 倒计时
  countdown: function() {
    var that = this;
    that.init(that);          //这步很重要,没有这步,重复点击会出现多个定时器
    var time = that.data.time;
    console.log("倒计时开始")
    var interval = setInterval(function () {
      time--;
      that.setData({
        time: time
      })
      if (time == 0) {          //归0时回到60
          var countId = that.data.isConnected;
          if(countId == 10){
            that.restartTap();
            that.findBlue()
          }
          if(countId == 20){
            that.clearTimeInterval()
          }
      }
    }, 1000)
    that.setData({
      interval: interval
    })
  },

下面直接上完整代码

<template>
	<view class="">
		<view style="padding: 20rpx;font-size: 30rpx;">
			<view style="font-size: 34rpx;">测试结果:</view>
			<view>{{showtext}}</view>
		</view>
		<view>
			<view style="padding: 20rpx;font-size: 36rpx;">蓝牙设备列表:</view>
			<view v-for="(item,index) in infolist" :key="index" @tap="BLEConnect(item.deviceId)"
				style="padding: 20rpx;font-size: 36rpx;border-bottom: 1px solid #C0C0C0;">
				{{item.name}}
			</view>
		</view>
	</view>
</template>
<script>
        export default {
		data() {
			return {
				infolist: [],
				delayTimer: null,
				servicesUUID: '',
				deviceId: '',
				characteristicId: '',
				writeId: '',
				isDeleteRepetition: '',
				modeluuid: [],
				showtext: '',
				ACPC: ''
			}
		},
		onLoad() {},
		onShow() {
			this.BLEInit()
		},
		methods: {

			/****************1.蓝牙初始化***************/
			BLEInit(event) {
				var that = this;
				uni.openBluetoothAdapter({
					success: function(res) {
						wx.getBluetoothAdapterState({
							success: function(res) {
								// 初始化成功后调用搜索蓝牙方法
								that.Search()
								//打印相关信息
								console.log(JSON.stringify(res.errMsg) + "\n蓝牙是否可用:" + res
									.available);
							},

							fail: function(res) {
								//打印相关信息
								console.log(JSON.stringify(res.errMsg) + "\n蓝牙是否可用:" + res
									.available);
							}
						})
					},
					fail: function(res) {
						wx.showToast({
							title: '手机蓝牙未开启',
							icon: 'none',
							duration: 2000
						})
					}
				})
			},
			// 搜索蓝牙
			Search() {
				var that = this;
				wx.startBluetoothDevicesDiscovery({
					services: ['0000FFE0'], //限定蓝牙搜索类型  避免搜索到没有用的蓝牙 
					success(res) {
						wx.showLoading({
							title: '正在搜索设备',
						})
						//定时没两秒刷新一次搜索列表
						var delayTimer = setInterval(function() {
							that.findBlue();
						}, 2000);
						that.delayTimer = delayTimer
					},
					fail() {
						that.closeFindBlue();
					}
				})
			},
			// 搜索列表
			findBlue() {
				var that = this;
				wx.getBluetoothDevices({
					success: function(res) {
						var deviceNum = 0;
						if (res.devices && (deviceNum = res.devices.length) >= 1) {
							console.log("搜索设备数量:", res)
							that.infolist = res.devices
							// 这里我设置的是搜索到一个蓝牙时就调用关闭搜索蓝牙方法
							if (that.infolist.length > 0) {
								setTimeout(() => {
									that.closeFindBlue()
								}, 1500)
							}
						}
					}
				})
			},
			// 连接蓝牙 
			BLEConnect(deviceId) {
				var that = this;
				wx.setStorageSync('deviceId', that.deviceId)
				that.deviceId = deviceId
				that.closeFindBlue()
				wx.showLoading({
					title: '正在连接',
				})
				wx.createBLEConnection({
					timeout: 10000,
					deviceId: that.deviceId,
					success: function(res) {
						that.closeFindBlue()
						setTimeout(() => {
							wx.showToast({
								title: '连接成功'
							});
						}, 600)
						//获取设备的uuid
						that.getServiceId()
					},
					fail: function() {
						wx.hideLoading()
						wx.showToast({
							title: '无法连接此设备',
							icon: 'none',
							duration: 2000
						})
					},
				})
			},
			// 停止搜索
			closeFindBlue() {
				var that = this;
				clearInterval(that.delayTimer);
				wx.stopBluetoothDevicesDiscovery({
					success: function(res) {
						wx.hideLoading()
					}
				})
			},
			//获取设备的uuid
			getServiceId() {
				var that = this
				wx.getBLEDeviceServices({
					// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
					deviceId: that.deviceId,
					success: function(res) {
						var model = res.services[0]
						that.servicesUUID = model.uuid
						console.log(that.servicesUUID, 'that.servicesUUID')
						that.getCharacteId() //6.0

					}
				})
			},
			getCharacteId() {
				var that = this
				wx.getBLEDeviceCharacteristics({
					// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
					deviceId: that.deviceId,
					// 这里的 serviceId 需要在上面的 getBLEDeviceServices 接口中获取
					serviceId: that.servicesUUID,
					success: function(res) {
						console.log(res);
						for (var i = 0; i < res.characteristics.length; i++) { //2个值
							var model = res.characteristics[i]
							if (model.properties.notify == true) {
								that.characteristicId = model.uuid //监听的值
								that.startNotice(model.uuid)
							}
							if (model.properties.read == true) {
								that.modeluuid = model.uuid
							}
							if (model.properties.write == true) {
								that.writeId = model.uuid //用来写入的值
							}
						}
					}
				})
			},

			startNotice(uuid) {
				var that = this;
				that.BLEDataSend()
				wx.notifyBLECharacteristicValueChange({
					state: true, // 启用 notify 功能
					deviceId: that.deviceId,
					serviceId: that.servicesUUID,
					characteristicId: uuid, //第一步 开启监听 notityid  第二步发送指令 write
					success: function(res) {
						// 蓝牙设备返回的数据
						wx.onBLECharacteristicValueChange(function(res) {
							var nonceId = that.ab2hex(res.value)
							console.log(nonceId, '蓝牙返回数据')
							if (nonceId == 'f5a05008b000009d') {
								wx.showToast({
									title: '插入试纸',
									icon: 'none'
								});
							}
							if (nonceId == 'f5a05008b2aa519a') {
								wx.showToast({
									title: '当前试纸已经使用过',
									icon: 'none'
								});
							}
							if (nonceId == 'f5a05008b40000a1') {
								wx.showToast({
									title: '请滴入血液',
									icon: 'none'
								});
							}
							if (nonceId == 'f5a05008ba0000a7') {
								wx.showToast({
									title: '机器已关闭'
								});
							}
							if (nonceId.length == 30) {
								//把字符串分割成每两个数字一个数组
								const arr = that.stringsplit(nonceId)
								let year = that.hex2int(arr[5])
								let mon = that.hex2int(arr[6])
								let date = that.hex2int(arr[7])
								let hour = that.hex2int(arr[8])
								let min = that.hex2int(arr[9])
								let sec = that.hex2int(arr[10])
								let mg = that.hex2int(arr[11] + arr[12])
								var nummg = parseInt(mg) / 18;
								let toFixedmg = nummg.toFixed(1)
								switch (arr[13]) {
									case '00':
										that.ACPC = 'GC'
										break
									case '01':
										that.ACPC = 'AC'
										break
									case '02':
										that.ACPC = 'PC'
										break
									case '03':
										that.ACPC = 'CTRL'
										break
								}
								that.showtext =
									`${'20' + year +'年'}${ mon +'月'}${ date +'日'}${ hour +'时'}${min +'分'}${sec +'秒'}${'测试血糖数据'+ toFixedmg + 'mg/' + that.ACPC }`
							}
						})
					},
					fail: function(res) {
						console.log(res);
					}
				})
			},

			BLEDataSend() {
				var that = this
				console.log('要发送的信息是:')
				var hex = 'F5 A0 50 08 B0 00 00 9D'
				var typedArray = new Uint8Array(hex.match(/[\da-f]{2}/gi).map(function(h) {
					return parseInt(h, 16)
				}))
				var buffer = typedArray.buffer
				console.log(that.deviceId, 'deviceId')
				console.log(that.servicesUUID, 'servicesUUID')
				console.log(that.characteristicId, 'characteristicId')
				console.log(buffer, 4444)

				wx.writeBLECharacteristicValue({
					deviceId: that.deviceId,
					serviceId: that.servicesUUID,
					characteristicId: that.characteristicId,
					// 这里的value是ArrayBuffer类型
					value: buffer,
					success: function(res) {
						console.log('写入成功', res.errMsg)
					},
					fail(res) {
						console.log('写入失败', res.errMsg)
					}
				})
			},
			/**
			 * 将ArrayBuffer转换成字符串
			 */
			ab2hex(buffer) {
				var hexArr = Array.prototype.map.call(
					new Uint8Array(buffer),
					function(bit) {
						return ('00' + bit.toString(16)).slice(-2)
					}
				)
				return hexArr.join('');
			},
			// 将字符串转为每两个字符一个数组
			stringsplit(nonceId) {
				var bbb = [...nonceId];
				var ccc = nonceId.split('');
				var a, b;
				var aIndex = 0;
				var bIndex = 1;
				var arr = [];
				bbb.forEach((str, index) => {
					if (index % 2 === 0) {
						a = str;
						aIndex += 1
					} else {
						b = str
						bIndex += 1
					}
					if (a && b && (bIndex - aIndex === 1)) {
						arr.push(a + b)
					}
				});
				return arr
			},
			// 16进制转10
			hex2int(hex) {
				var len = hex.length,
					a = new Array(len),
					code;
				for (var i = 0; i < len; i++) {
					code = hex.charCodeAt(i);
					if (48 <= code && code < 58) {
						code -= 48;
					} else {
						code = (code & 0xdf) - 65 + 10;
					}
					a[i] = code;
				}
				return a.reduce(function(acc, c) {
					acc = 16 * acc + c;
					return acc;
				}, 0);
			},
		}
	}
</script>

<style>

</style>

也可以参考以下这个连接

blog.csdn.net/weixin_4362…

  • 首先初始化蓝牙检测蓝牙是否可用,蓝牙可用就开始搜索蓝牙,不可用就提示用户蓝牙不可用或者去打开蓝牙 
  • 搜索蓝牙可以限定搜索蓝牙的类型 使用UUID,那么只会搜索出含有这个UUID的设备,建议一开始先不填写 
  • 当搜索到我们的蓝牙以后就调用停止搜索方法结束搜索 // 连接蓝牙 拿到蓝牙的deviceId, 连接设备就提示 连接成功就获取设备的uuid保存起来 
  • 获取所有的特征值 notify write read , 当只有 notify为true的时候才能 接收蓝牙设备传来的数据,write 为true 才能传入数据read 为true 才能读取设备数据 
  •  在每个特性里面操作对应的方法 如特性是notify就是接收蓝牙设备传来的数据