uniapp 蓝牙通讯流程,简单又详尽!看这一篇足以!

4,859 阅读5分钟

uni-app上面封装的蓝牙功能api源于HTML5+所封装的,虽然uniapp莫名其妙进行了蓝牙和低功耗蓝牙的划分,但依旧和H5+上的能进行严格对应,如下图(不用细看);因此,若因为框架问题无法使用uniapp上的api,可放心使用H5+;

下面将以蓝牙功能开发时间线整理这些api的调用; image.png

第一步,初始界面进行【初始化蓝牙】【提示用户连接情况】

初始化蓝牙板块

【初始化蓝牙-onLoad】页面初始化时直接调用;

openBluetoothAdapter() {
	return new Promise((resolve, reject) => {
		uni.openBluetoothAdapter({
			success(res) {
				resolve(res)
			},
			fail(res) {
				console.log('蓝牙模块初始化失败', res)
				reject(res)
			}
		})
	})
},

获取本机蓝牙适配器状态

【提示用户连接情况-onLoad/onShow】监听蓝牙板块开启情况和搜索情况(蓝牙功能未开启时,提示用户)这里用H5+只是告诉大家可以不仅仅用uniapp的api,其实和uniapp的uni.getBluetoothAdapterState(OBJECT)一样;

onBluetoothAdapterStateChange() {
	return new Promise((resolve, reject) => {
		plus.bluetooth.getBluetoothAdapterState({
			success: (e) => {
				console.log('蓝牙设备情况', e)
				resolve(e)
			},
			fail: (e) => {
				uni.showToast({
					title: '蓝牙功能异常',
					icon: "error",
					duration: 1500
				})
				console.log('蓝牙设备异常', e)
				reject(e)
			}
		});
	})
},

第二步,蓝牙连接页面进行【设备搜索】【新设备捕获】【关闭搜索】【设备连接】【设备断开】

开始搜寻附近的蓝牙外围设备

【设备搜索-按钮启动】services参数可以有效过滤无关的蓝牙设备。所需的uuid需要参考蓝牙设备厂商提供的蓝牙协议;

uni.startBluetoothDevicesDiscovery({
	services: this.advertisServiceUUIDs,
	success(res) {
		console.log('开始搜索设备', res)
	}
})

监听寻找到新设备的事件

【新设备捕获-界面渲染】将搜索到的设备渲染到界面上,比如有BLEList这个数组通过for循环在页面渲染了新设备列表;

uni.onBluetoothDeviceFound((res) => {
	let new = res.devices[0]
	console.log('发现了新设备【无过滤】', res)
	// this.BLEList.push(res)
	if (new.advertisServiceUUIDs = this.advertisServiceUUIDs && new.localName) {
        //安卓需要加条件 要不然搜出很多奇怪设备
		this.BLEList.push(new)
		console.log('发现了新设备【uuid过滤】', res)
	}
})

停止搜寻附近的蓝牙外围设备

【关闭搜索-计时器或搜索成功调用】因为开启蓝牙搜索极其消耗性能,因此在不需要搜索后需要关闭。其条件可以是【计时器】或搜索到【目标设备】;

//【计时器】15s后没有搜索到设备 就关闭蓝牙搜索 并通知用户
setTimeout(() => {
	uni.stopBluetoothDevicesDiscovery({
	success(res) {
		console.log('关闭蓝牙搜索', res)
                //通知用户,搜索停止,如:关闭搜索动画,或弹窗提示
	}
})
}, 15000)
//【目标设备】搜索到目标设备后关闭搜索
uni.onBluetoothDeviceFound((res) => {
	let new = res.devices[0]
	if (new.advertisServiceUUIDs = this.advertisServiceUUIDs ) {
		this.BLEList.push(new)
		console.log('发现了目标设备【条件过滤】', res)
                uni.stopBluetoothDevicesDiscovery({
		     success(res) {
			console.log('关闭蓝牙搜索', res)
			}
		})
	}
})

连接低功耗蓝牙设备

【设备连接-按钮点击】建议加上链接动效,以及成功与失败提醒;

createBLEConnection(deviceId) {
	return new Promise((resolve, reject) => {
		uni.createBLEConnection({
			deviceId,
			succes(res) {
				console.log("连接设备成功!", res)
                                uni.showToast({
	                                title: '连接成功',
	                                duration: 1500
                                })
				resolve(res)
			},
			fail(res) {
				uni.showToast({
					title: '连接失败',
					icon: "error",
					duration: 2000
				})
				console.log("连接设备失败!", res)
				reject(res)
			}
		})
	})
},

断开与低功耗蓝牙设备的连接

【设备断开-按钮点击】

closeBLEConnection(deviceId){
	uni.closeBLEConnection({
	  deviceId,
	  success(res) {
		  console.log('断开成功',res)
                 //写入断开连接操作,比如弹窗提醒,页面跳转
                 	uni.showToast({
					title: '断开设备成功',
					duration: 2000
				})
	  }
	})
},

第三步,设备数据交互页面进行【数据监听】【数据写入】

监听低功耗蓝牙设备的特征值变化事件

【数据监听-onShow】 注意:

  1. 开启监听特征值,写在onShow 这样在设置页连接设备后 再打开数据交互页面就可以正常开启,不能写在onload;
  2. 必须先启用 notifyBLECharacteristicValueChange 接口才能接收到设备推送的 notification;
  3. 接收到的数据是ArrayBuffer类型,一般是转16进度字符串;
  4. serviceId与characteristicId需要对应接口获取
openNotify() {
	uni.onBLECharacteristicValueChange(async (res) => {
		let value = this.ab2hex(res.value)
                console.log('接受到的数据是:', value)
                //这里书写获取到的16进制数据的处理,注意大小端颠倒

	uni.notifyBLECharacteristicValueChange({
		state: true, // 启用 notify 功能
		// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
		deviceId: this.deviceId,
		// 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
		serviceId: "696530001-0405-0607-0809-0A0B0C0D0E0F",
		// 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
		characteristicId: "69650002-0405-0607-0809-0A0B0C0D0E0F",
		success(res) {
			console.log('设备notify已开启', res)
		},
		fail(res) {
			console.log('notify开启失败', res)
		}
	})
},
//buffer转hex类型(设备返还数据转0x开头的16进制字符串)
ab2hex(buffer) {
	const hexArr = Array.prototype.map.call(
		new Uint8Array(buffer),
		function(bit) {
			return ('00' + bit.toString(16)).slice(-2)
		}
	)
	return hexArr.join('')
},

向低功耗蓝牙设备特征值中写入二进制数据

【数据写入】H5+和uni-app的API参数上,uni-app需要多一个writeType参数;

//写入调用 this.write(this.string2buffer(value))
write(value) {
	let that = this
	new Promise((resolve, reject) => {
		plus.bluetooth.writeBLECharacteristicValue({
			deviceId: that.deviceId,
			serviceId: "69650001-0405-0607-0809-0A0B0C0D0E0F",
			characteristicId: "69650003-0405-0607-0809-0A0B0C0D0E0F",
			value,
			success: function(e) {
				console.log('写入数据 success: ' + JSON.stringify(e));
				resolve(e)
			},
			fail: function(e) {
				console.log('写入数据 failed: ' + JSON.stringify(e));
				reject(e)
			
		});
	})
},
//字符串转buffer
string2buffer(str) {
	let val = ""
	if (!str) return;
	let length = str.length;
	let index = 0;
	let array = []
	while (index < length) {
		array.push(str.substring(index, index + 2));
		index = index + 2;
	}
	val = array.join(",");
	// 将16进制转化为ArrayBuffer
	return new Uint8Array(val.match(/[\da-f]{2}/gi).map(function(h) {
		return parseInt(h, 16)
	})).buffer
},

以上就是蓝牙功能整体开发所需要的各项主要api与其代码,若有疑惑的地方欢迎评论探讨!!!