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

相关推荐
leobertlan3 小时前
2025年终总结
前端·后端·程序员
子兮曰4 小时前
OpenClaw架构揭秘:178k stars的个人AI助手如何用Gateway模式统一控制12+通讯频道
前端·javascript·github
百锦再4 小时前
Reactive编程入门:Project Reactor 深度指南
前端·javascript·python·react.js·django·前端框架·reactjs
莲华君5 小时前
React快速上手:从零到项目实战
前端·reactjs教程
百锦再5 小时前
React编程高级主题:测试代码
android·前端·javascript·react.js·前端框架·reactjs
易安说AI5 小时前
Ralph Loop 让Claude无止尽干活的牛马...
前端·后端
2501_916008896 小时前
全面介绍Fiddler、Wireshark、HttpWatch、SmartSniff和firebug抓包工具功能与使用
android·ios·小程序·https·uni-app·iphone·webview
webYin6 小时前
解决 Uni-App 运行到微信小程序时 “Socket合法域名校验出错” 问题
微信小程序·小程序·uni-app
失忆爆表症7 小时前
05_UI 组件库集成指南:Shadcn/ui + Tailwind CSS v4
前端·css·ui
小迷糊的学习记录7 小时前
Vuex 与 pinia
前端·javascript·vue.js