uniApp低功耗蓝牙一键开门、多对多查找、数组匹配数组、开锁

文章目录


html

html 复制代码
<view class="m_t_36">
	<view class="w_50_ h_100 lh_100 m_l_a m_r_a bc_409eff radius_10 color_fff ta_c" @click="openBluetoothAdapter()">一键开门</view>
</view>

JavaScript

javascript 复制代码
export default {
	data() {
		return {
			timeout: undefined,
			// 后端保存蓝牙信息
			bluetooths: [
				{
					deviceId: "0A:45:32:0C:78:C6",
					name: "YX_0A45320C78C6",
					serviceId: '0000FFB0-0000-1000-8000-00805F9B34FB',
					notifyId: '0000FFB2-0000-1000-8000-00805F9B34FB',
					writeId: '0000FFB1-0000-1000-8000-00805F9B34FB',
					instruction: 'EE03E30100'
				},
				{
					deviceId: "5C:C3:36:8D:B9:FC",
					name: "RTK_BT_4.1v",
					serviceId: '0000FFB0-0000-1000-8000-00805F9B34FB',
					notifyId: '0000FFB2-0000-1000-8000-00805F9B34FB',
					writeId: '0000FFB1-0000-1000-8000-00805F9B34FB',
					instruction: 'EE03E30100'
				}
			],
			bluetooth: {}
		}
	},
	methods: {
		/**
		 * 根据不同方法名调用方法,统一定时器的触发判断,
		 * 当定时器触发时,无法确定当前调用的方法是哪个
		 * @param {String} fnName 
		 */
		methodExecution(fnName = '') {
			if (this.timeout) {
				this[fnName]();
			} else {
				console.log('执行方法');
			}
		},

		// 数据初始化
		initInfo() {
			// 清除定时器无效的解决方案
			this.timeout = undefined;
			this.bluetooth = {};
		},

		// 初始化蓝牙模块
		openBluetoothAdapter() {
			let that = this;

			// 向低功耗蓝牙设备特征值中写入二进制数据。
			// 注意:必须设备的特征值支持 write 才可以成功调用。
			if (Object.keys(that.bluetooth).length) return that.writeBLECharacteristicValue();

			// 数据初始化
			that.initInfo();

			// 初始化蓝牙模块
			uni.openBluetoothAdapter({
				// 主服务的UUID是YX。传入这个参数,只搜索主服务UUID为YX的设备
				// services: ['YX'],
				success() {
					// 开始搜索附近的蓝牙设备
					that.startBluetoothDevicesDiscovery();
				},
				fail() {
					uni.showToast({
						icon: 'none',
						title: '查看手机蓝牙是否打开'
					});
				}
			});
		},

		// 开始搜索附近的蓝牙设备
		startBluetoothDevicesDiscovery() {
			let that = this;

			uni.showLoading({
				title: '加载中',
				mask: true
			});

			that.timeout = setTimeout(() => {
				// 数据初始化
				that.initInfo();

				uni.hideLoading();
				uni.showToast({
					icon: 'none',
					title: '开门失败'
				});
			}, 1000 * 20);

			// 开始搜索附近的蓝牙设备
			uni.startBluetoothDevicesDiscovery({
				success() {
					// 监听返回的蓝牙设备
					uni.onBluetoothDeviceFound(({
						devices
					}) => {
						if (devices.length) {
							let bluetooths = that.bluetooths;

							// 多对多查找
							for (let i = 0; i < devices.length; i++) {
								let itemI = devices[i];
								if (itemI.name) {
									for (let j = 0; j < bluetooths.length; j++) {
										let itemJ = bluetooths[i];

										if (itemI.deviceId === itemJ.deviceId && itemI.name === itemJ.name) {
											that.bluetooth = itemJ;
											setTimeout(() => { that.createBLEConnection() }, 0);
											return undefined;
										}
									}
								}
							}
						}
					});
				},
				fail() {
					that.methodExecution('startBluetoothDevicesDiscovery');
				}
			});
		},

		// 连接低功耗蓝牙设备
		createBLEConnection() {
			let that = this;

			// 连接低功耗蓝牙设备
			uni.createBLEConnection({
				deviceId: that.bluetooth.deviceId,
				success() {
					// 停止搜寻附近的蓝牙外围设备
					uni.stopBluetoothDevicesDiscovery({
						success() {
							// 获取蓝牙服务
							// that.getBLEDeviceServices();

							// 启用低功耗蓝牙设备特征值变化时的notify功能,订阅特征值
							that.notifyBLECharacteristicValueChange();
						},
						fail() { }
					});
				},
				fail() {
					// 连接低功耗蓝牙设备
					that.methodExecution('createBLEConnection');
				}
			});
		},
		
		// 启用低功耗蓝牙设备特征值变化时的notify功能,订阅特征值
		notifyBLECharacteristicValueChange() {
			let that = this,
				{ deviceId, serviceId, notifyId } = that.bluetooth;

			// 启用低功耗蓝牙设备特征值变化时的notify功能,订阅特征值
			uni.notifyBLECharacteristicValueChange({
				state: true,
				deviceId,
				serviceId,
				characteristicId: notifyId,
				success() {
					// 监听低功耗蓝牙设备的特征值变化事件。
					// 必须先启用 notifyBLECharacteristicValueChange 接口才能接收到设备推送的 notification。
					that.onBLECharacteristicValueChange();
				},
				fail() {
					// 启用低功耗蓝牙设备特征值变化时的notify功能,订阅特征值
					that.methodExecution('notifyBLECharacteristicValueChange');
				}
			});
		},

		// 监听低功耗蓝牙设备的特征值变化事件。
		// 必须先启用 notifyBLECharacteristicValueChange 接口才能接收到设备推送的 notification。
		onBLECharacteristicValueChange() {
			let that = this;

			// 监听低功耗蓝牙设备的特征值变化事件。
			// 必须先启用 notifyBLECharacteristicValueChange 接口才能接收到设备推送的 notification。
			uni.onBLECharacteristicValueChange(() => {
				that.writeBLECharacteristicValue();
			});
		},

		// 向低功耗蓝牙设备特征值中写入二进制数据。
		// 注意:必须设备的特征值支持 write 才可以成功调用。
		writeBLECharacteristicValue() {
			let that = this,
				{ deviceId, serviceId, writeId, instruction } = that.bluetooth,
				typedArray = new Uint8Array(instruction.match(/[\da-f]{2}/gi).map((h) => parseInt(h, 16))),
				buffer = typedArray.buffer;

			// 向低功耗蓝牙设备特征值中写入二进制数据。
			// 注意:必须设备的特征值支持 write 才可以成功调用。
			uni.writeBLECharacteristicValue({
				deviceId,
				serviceId,
				characteristicId: writeId,
				value: buffer,
				success() {
					uni.showToast({
						title: '开门成功',
						icon: 'none'
					});
				},
				fail() {
					uni.showToast({
						title: '开门失败',
						icon: 'none'
					});
				},
				complete() {
					clearTimeout(that.timeout);
					that.timeout = undefined;
					uni.hideLoading();
				}
			});
		},

		// 关闭(断开)蓝牙模块
		closeBluetoothAdapter() {
			let that = this;

			// 关闭(断开)蓝牙模块
			uni.closeBluetoothAdapter({
				success: () => {
					uni.showToast({
						title: '蓝牙已关闭',
						icon: 'none'
					});
					clearTimeout(that.timeout);
					that.timeout = undefined;
					uni.hideLoading();
					that.initInfo();
				},
				fail() {
					that.closeBluetoothAdapter();
				}
			});
		},

		// 监听页面隐藏
		onHide() {
			// 关闭(断开)蓝牙模块
			// this.closeBluetoothAdapter();
		},

		// 监听页面卸载
		onUnload() {
			// 关闭(断开)蓝牙模块
			this.closeBluetoothAdapter();
		}
	}
}

1、notifyBLECharacteristicValueChange方法用的是读取的特征值。
2、writeBLECharacteristicValue发送指令,返回成功,蓝牙设备无反应,大概率是指令问题。
3、关闭蓝牙有两个API,目前测试只有closeBluetoothAdapter彻底断开蓝牙。
4、setTimeout无法彻底清除定时器,需要手动设置属性值为undefined

相关推荐
子非鱼3733 分钟前
JS树形结构与列表结构之间的相互转换
前端
嘉小华4 分钟前
大白话讲解 Android LayoutInflater
前端
加17 分钟前
95%代码AI生成,是的你没听错...…
前端·ai编程
小赵学鸿蒙7 分钟前
如何使用第三方库中的picker_utils (API12) PickerUtil类
前端
3Katrina9 分钟前
深入理解 JavaScript 中的柯里化
前端·javascript
BillKu11 分钟前
Vue3 axios 请求设置 signal 信号属性,以便 abort 取消请求
前端·javascript·vue.js
憨憨是条狗21 分钟前
ArcGIS API for JavaScript 中的数据聚合功能深度解析
前端
lyc23333321 分钟前
鸿蒙Next断点适配:跨设备布局的黄金法则
前端
南囝coding1 小时前
《独立开发工具 • 半月刊》 第 012 期
前端·后端
Jack魏1 小时前
React学习001-创建 React 应用
前端·学习·react.js