微信小程序蓝牙流程及代码

该代码段主要涉及蓝牙设备的管理,包括初始化蓝牙、搜索设备、连接设备、监听状态变化、读写特征值等操作。当蓝牙适配器状态改变时,会根据状态执行相应的操作,如搜索设备或连接设备。同时,它还实现了数据的分包写入和异常情况下的重连机制。

在这里插入图片描述

import {
	SERVICEID,
	NOTIFYID,
	WRITEID,
	BLUETOOTH_MESSAGE,
	OPERATE_PROCESS
} from "./config.js"
import {
	openBluetoothAdapterFailCallback,
	onBluetoothAdapterStateChangeCallback,
	onBluetoothDeviceFoundCallback,
	getBluetoothAdapterStateSuccessCallback,
	getBluetoothAdapterStateFailCallback,
	createBLEConnectioSuccessCallback,
	createBLEConnectioFailCallback,
	onBLEConnectionStateChangeCallback,
	onBLECharacteristicValueChangeCallback,
	initStoreState,
	notifyBLECharacteristicValueChangeFailCallback
} from "./tool.js"
import {
	hexStringToArrayBuffer,
	sleep,
	getBufferArrayBy20,
	arrayBufferToHexString,
	setCommunicationListUtil,
	getNowTime,
	getMac,
	filterDevices,
	filterDevicesByRe,
	unique,
	showModalByMethod

} from "./utils.js"

let util = require('@/static/utils/utils.js');

import vm from "@/main.js"

//正常蓝牙流程开始
export let bluetoothStart = () => {
	getBluetoothAdapterState();

}

export let onBluetoothAdapterStateChange = () => {
	//如果蓝牙打开-关闭-再打开-监听不到?
	uni.onBluetoothAdapterStateChange(async (res) => {
		bluetoothExecByAdapterStatus(res);
	})
}

//根据蓝牙适配器的状态、是否正在搜索设备执行不同的操作流程
export let bluetoothExecByAdapterStatus = (res) => {
	console.log("蓝牙适配器状态", res);
	if (!res.available) {
		util.showModal("蓝牙适配器不可用,请打开蓝牙");
	} else {
		if (!res.discovering && !vm.isNormalDiscoveryStatus) { // 防止正常停止搜索的时候会触发这个条件
			//如果前面已经搜索过蓝牙,则不需要再次搜索
			vm.$u.vuex("isImmediateWhitePackage", false); //防止打开手机蓝牙后并连接成功后,直接让蓝牙发送指令
			if (vm.isBluetoothDiscovery) {
				getBluetoothDevices();
			} else {
				startAndStopbluetoothDevicesDiscovery();
			}
		}

	}

}

//获取在蓝牙模块生效期间所有已发现的蓝牙设备。包括已经和本机处于连接状态的设备
export let getBluetoothDevices = () => {
	uni.getBluetoothDevices({
		success(res) {
			let devices = res.devices;
			let devicesList = filterDevices(res.devices, vm.currentBike);
			if (devicesList.length > 0) {
				vm.$u.vuex('bluetoothDevice', devicesList[0])
				vm.$u.vuex('connectCount', 0)
				createBLEConnection(devicesList[0])
			} else {
				startAndStopbluetoothDevicesDiscovery();
			}
		}
	})
}


//打开蓝牙设备并监听蓝牙设备
export let openAndOnBluetoothAdapter = () => {
	vm.$u.vuex("bluetoothContent", "正在初始化蓝牙");
	uni.openBluetoothAdapter({
		success(res) {
			console.log("打开蓝牙适配器成功");
			startAndStopbluetoothDevicesDiscovery();
		},
		fail(res) {
			console.log("打开蓝牙设备器失败", res)
			console.log(res.errMsg == "openBluetoothAdapter:fail already opened")
			//蓝牙适配器已经打开
			if (res.errMsg == "openBluetoothAdapter:fail already opened") {
				startAndStopbluetoothDevicesDiscovery();
			} else {
				console.log("打开蓝牙适配器失败:", BLUETOOTH_MESSAGE[res.errCode]);
				util.showModal("蓝牙适配器不可用,请打开蓝牙或微信APP开启蓝牙权限");
				openBluetoothAdapterFailCallback();
			}

		},
		complete() {
			onBluetoothAdapterStateChange();
		}

	})
}

//开始和停止蓝牙搜索
export let startAndStopbluetoothDevicesDiscovery = () => {
	//1、关闭蓝牙-杀掉进程,开启蓝牙不会重新连接,没有监听搜索到的设备
	onBluetoothDeviceFound();
	//2、接步骤1,再关闭,再开发蓝牙,连接成功,但是不会触发蓝牙连接
	onBLEConnectionStateChange();
	
	vm.$u.vuex('bluetoothContent', '正在搜索蓝牙设备');
	vm.$u.vuex("isBluetoothDiscovery", true);
	vm.$u.vuex("bluetoothDevice", {}); //清空
	//如果60s都还未搜索到蓝牙,提示未搜索到,提示蓝牙不在可搜索范围内,
	let timer = setTimeout(() => {
		clearTimeout(timer);
		//没有找到设备并且定时器还在
		if (vm.validatenull(vm.bluetoothDevice)) {
			util.showModal('蓝牙不在可搜索范围内');
			stopBluetoothDevicesDiscovery();
		}
	}, 10000);
	vm.$u.vuex('blueToothSearchTimer', timer);
	uni.startBluetoothDevicesDiscovery({
		services: [], //添加了SERVICEID搜索不到蓝牙
		allowDuplicatesKey: true,
		powerLevel: 'high',
		success() {
			console.log("开始蓝牙搜索成功");
		},
		fail(res) {
			console.log(res);
			util.showModal('开始蓝牙搜索失败');
			console.log("开始蓝牙搜索失败:", BLUETOOTH_MESSAGE[res.errCode]);
		}
	})
}


export let stopBluetoothDevicesDiscovery = () => {
	uni.stopBluetoothDevicesDiscovery({
		success() {
			console.log("停止蓝牙搜索成功");
		},
		fail(res) {
			console.log("停止蓝牙搜索失败:", BLUETOOTH_MESSAGE[res.errCode]);
		},
		complete() {
			vm.$u.vuex("isNormalDiscoveryStatus", true);
			setTimeout(()=>{
				vm.$u.vuex("isNormalDiscoveryStatus", false);
			},1000)
			
		}
	})
}
//监听寻找到新设备的事件
export let onBluetoothDeviceFound = () => {
	uni.onBluetoothDeviceFound((res) => {
		//搜索到的蓝牙设备并唯一
		let devices = filterDevices(res.devices, vm.currentBike);
		if (devices.length) {
			console.log("搜索到的目标设备", devices)
			vm.$u.vuex('bluetoothDevice', devices[0])
			clearTimeout(vm.blueToothSearchTimer);
			vm.$u.vuex('connectCount', 0)
			createBLEConnection(devices[0]);
			stopBluetoothDevicesDiscovery();
		}
	})
}

export let getBluetoothAdapterState = () => {
	uni.getBluetoothAdapterState({
		success(res) {
			bluetoothExecByAdapterStatus(res);
		},
		fail(res) {
			console.log("获取蓝牙适配器状态失败:", BLUETOOTH_MESSAGE[res.errCode]);
			openAndOnBluetoothAdapter();
			util.showModal('蓝牙适配器不可用,请打开蓝牙');
		}
	})
}

//ios必须要执行
let getBLEDeviceServices = (device) => {
	uni.getBLEDeviceServices({
		deviceId: device.deviceId,
		success(res) {
			console.log(`获取${device.deviceId}服务成功`, res);
			getBLEDeviceCharacteristics(device);
		},
		fail(res) {
			console.log(`获取${device.deviceId}服务失败:`, BLUETOOTH_MESSAGE[res.errCode]);
			getBLEDeviceCharacteristics(device);
		}
	})
}

export let createBLEConnection = (device) => {
	console.log("正在连接蓝牙")
	vm.$u.vuex('bluetoothContent', '正在连接蓝牙设备');
	//如果当前状态没有连接,只去连接蓝牙
	if (!vm.isConnected && !vm.validatenull(vm.bluetoothDevice)) {
		uni.createBLEConnection({
			deviceId: device.deviceId,
			success(res) {
				console.log(`与蓝牙设备${device.name}创建连接成功`, res);
				getBLEDeviceServices(device);
				createBLEConnectioSuccessCallback();
			},
			fail(res) {
				console.log(res)
				if(res.errCode == 10001) return;//如果是蓝牙设配器没有打开,则直接退出连接
				if (vm.connectCount < 4) {
					createBLEConnection(device);
					let connectCount = vm.connectCount;
					let newConnectCount = connectCount + 1;
					vm.$u.vuex('connectCount', newConnectCount);
				} else {
					util.showModal('蓝牙连接失败');
				}
			}
		})
	}

}

//ios必须要执行
let getBLEDeviceCharacteristics = (device) => {
	uni.getBLEDeviceCharacteristics({
		deviceId: device.deviceId,
		serviceId: SERVICEID,
		success: function(res) {
			console.log(`获取${device.deviceId}特征值成功`, res);
			notifyAndOnBLECharacteristicValueChange(device);
		},
		fail: function(res) {
			console.log(`获取${device.deviceId}特征值失败`, res);
		},
	})
}

export let onBLEConnectionStateChange = () => {
	uni.onBLEConnectionStateChange((res) => {
		console.log("监听蓝牙是否断开", res);
		if(vm.lastConnectionStatus == res.connected){
			let bluetoothDisconnectedCount = vm.bluetoothDisconnectedCount;
			let newBluetoothDisconnectedCount = bluetoothDisconnectedCount+1;
			vm.$u.vuex("bluetoothDisconnectedCount",newBluetoothDisconnectedCount);
		}else{
			vm.$u.vuex("bluetoothDisconnectedCount",0);
		}
		vm.$u.vuex("isConnected", res.connected);
		if (!res.connected && !vm.isNormalBluetoothDisconnect && vm.bluetoothDisconnectedCount < 2) { //当前检测到时异常断开状态,则进行重连操作,连接不上,还是会触发这个监听
			vm.$u.vuex('connectCount', 0);
			createBLEConnection(vm.bluetoothDevice);
		}
		vm.$u.vuex("lastConnectionStatus", res.connected);
		onBLEConnectionStateChangeCallback(res);
	})
}

//开始并且监听特征值的变化
export let notifyAndOnBLECharacteristicValueChange = (device) => {
	//防止没有更换状态
	uni.notifyBLECharacteristicValueChange({
		state: true,
		deviceId: device.deviceId,
		serviceId: SERVICEID,
		characteristicId: NOTIFYID,
		success(res) {
			console.log("开启notify通知模式成功", res);
			uni.onBLECharacteristicValueChange((res) => {
				console.log("监听特征值", res);
				clearTimeout(vm.notifyTimerId);
				//关闭蓝牙连接
				onBLECharacteristicValueChangeCallback(device, res);
			})
		},
		fail(res) {
			notifyBLECharacteristicValueChangeFailCallback(device, res);
			console.log("开启notify通知模式失败:", BLUETOOTH_MESSAGE[res.errCode]);
		}
	})
}


let writeBLECharacteristicValue = (device, value) => {
	console.log("写入数据", arrayBufferToHexString(value));

	uni.writeBLECharacteristicValue({
		deviceId: device.deviceId,
		serviceId: SERVICEID,
		characteristicId: WRITEID,
		value,
		success(res) {
			console.log("写入数据成功", res);
			//判断是否是最后一包,如果是最后一包,则开启通讯计时器
		},
		fail(res) {
			console.log("写入数据失败", BLUETOOTH_MESSAGE[res.errCode]);
			console.log("写入数据失败", res);
			util.showModal("写入数据失败");
		}

	})
}

export let closeBLEConnection = (device, callback = () => {}) => {
	vm.$u.vuex("isNormalBluetoothDisconnect", true);
	uni.closeBLEConnection({
		deviceId: device.deviceId,
		success() {
			console.log("关闭蓝牙连接成功");
		},
		fail(res) {
			console.log("关闭蓝牙连接失败", res);

			console.log("关闭蓝牙连接失败", BLUETOOTH_MESSAGE[res.errCode]);
		},
		complete() {
			setTimeout(() => {
				vm.$u.vuex("isNormalBluetoothDisconnect", false);
			}, 1000)
			callback();
		}
	})
}


export let closeBluetoothAdapter = (callback) => {
	return new Promise((resolve, reject) => {
		uni.closeBluetoothAdapter({
			success() {
				console.log("关闭蓝牙适配器成功");
			},
			fail(res) {
				console.log("关闭蓝牙适配器失败:", BLUETOOTH_MESSAGE[res.errCode]);
			},
			complete() {
				callback();
			}
		})
	})
}

//不分包写数据
export let writeDataToDevice = (device, data) => {
	console.log("发送数据", data);
	vm.$u.vuex("bluetoothContent", "正在发送指令");

	let allBuffer = hexStringToArrayBuffer(data);
	writeBLECharacteristicValue(device, allBuffer);
}

//分包写数据
export let writeDataToDeviceBySubPackage = (data) => {
	vm.$u.vuex("commandMessage", '');
	vm.$u.vuex("bluetoothContent", `正在发送${vm.commandName}指令`);

	let bufferArray = getBufferArrayBy20(data);
	console.log('bufferArray.length', bufferArray.length);
	for (let i = 0; i < bufferArray.length; i++) {
		//sleep(1); //同步延迟1ms
		writeBLECharacteristicValue(bufferArray[i], i == bufferArray.length - 1);
	}

	// let allBuffer = hexStringToArrayBuffer(data);
	// writeBLECharacteristicValue(allBuffer);
}


export let getConnectedBluetoothDevices = (callback) => {
	uni.getConnectedBluetoothDevices({
		services: [SERVICEID],
		success(res) {
			console.log("获取连接的蓝牙设备成功", res);
			callback(res.devices)
		},
		fail(res) {
			console.log("获取连接的蓝牙设备失败", res);
			callback([]);
		},
		complete() {

		}
	})

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值