From 5b6ee58df39726b55e5f5126dc2d83e5ed4ccebd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8C=83=E9=B9=8F?= Date: Wed, 14 Aug 2024 18:33:23 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E5=86=99=E5=85=A5=E5=92=8C?= =?UTF-8?q?=E7=9B=91=E5=90=AC=E5=A4=96=E6=89=80=E6=9C=89=E8=93=9D=E7=89=99?= =?UTF-8?q?=E4=BA=A4=E4=BA=92=E6=96=B9=E6=B3=95=E7=9A=84=E5=B0=81=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- App.vue | 10 +- pages/index/index.vue | 57 ++++++++++-- stores/bluetooth.js | 209 +++++++++++++++++++++++++++++++++++++++++- 3 files changed, 267 insertions(+), 9 deletions(-) diff --git a/App.vue b/App.vue index b1d4b27..8cfa375 100644 --- a/App.vue +++ b/App.vue @@ -7,15 +7,23 @@ ...mapState(useBluetoothStore, ['bluetoothStatus']) }, onLaunch: function() { + // 检查强制升级 this.updateMiniProgram() + // 初始化蓝牙 this.initBluetooth() + // 监听蓝牙开关状态 this.onBluetoothState() + // 监听蓝牙连接状态 + this.onBluetoothConnectStatus() + // 监听设备特征值变化 + this.onBluetoothCharacteristicValueChange() }, onShow: function() { this.checkSetting() }, methods: { - ...mapActions(useBluetoothStore, ['initBluetooth', 'onBluetoothState', 'updateBluetoothStatus', 'checkSetting']), + ...mapActions(useBluetoothStore, ['initBluetooth', 'onBluetoothState', 'updateBluetoothStatus', 'checkSetting', + 'onBluetoothConnectStatus', 'onBluetoothCharacteristicValueChange']), // 强制升级 updateMiniProgram() { const updateManager = uni.getUpdateManager() diff --git a/pages/index/index.vue b/pages/index/index.vue index 15cb1f9..54a5f4e 100644 --- a/pages/index/index.vue +++ b/pages/index/index.vue @@ -1,8 +1,20 @@ @@ -12,19 +24,36 @@ export default { data() { - return {} + return { + showAdd: true, + showConnect: false + } }, computed: { - ...mapState(useBluetoothStore, ['deviceList']) + ...mapState(useBluetoothStore, ['deviceList', 'currentLockInfo']) }, async onLoad () {}, methods: { - ...mapActions(useBluetoothStore, ['getBluetoothDevices', 'stopGetBluetoothDevices']), + ...mapActions(useBluetoothStore, ['getBluetoothDevices', 'stopGetBluetoothDevices', 'updateCurrentLockInfo', + 'connectBluetoothDevice']), getList() { this.getBluetoothDevices() + this.showAdd = false }, stopGetList() { this.stopGetBluetoothDevices() + this.showAdd = true + }, + async connect(item) { + this.updateCurrentLockInfo({ + name: item.name, + deviceId: item.deviceId + }) + const result = await this.connectBluetoothDevice() + if(result) { + this.showConnect = true + this.stopGetBluetoothDevices() + } } } } @@ -32,7 +61,7 @@ diff --git a/stores/bluetooth.js b/stores/bluetooth.js index 2326d31..eaa5eb1 100644 --- a/stores/bluetooth.js +++ b/stores/bluetooth.js @@ -19,7 +19,9 @@ export const useBluetoothStore = defineStore('ble', { */ bluetoothStatus: -1, // 设备列表 - deviceList: [] + deviceList: [], + // 当前锁信息 + currentLockInfo: {} } }, actions: { @@ -79,6 +81,27 @@ export const useBluetoothStore = defineStore('ble', { } }) }, + // 监听蓝牙设备连接状态 + onBluetoothConnectStatus() { + const that = this + uni.onBLEConnectionStateChange(function (res) { + if(res.deviceId === that.currentLockInfo.deviceId) { + console.log('设备连接状态改变', res) + that.updateCurrentLockInfo({ + ...that.currentLockInfo, + connected: res.connected + }) + } + }) + }, + // 监听蓝牙设备特征值改变 + onBluetoothCharacteristicValueChange() { + const that = this + uni.onBLECharacteristicValueChange(function (res) { + // 待完善 + console.log('特征值改变', res) + }) + }, // 开始搜索蓝牙设备 getBluetoothDevices() { const that = this @@ -191,6 +214,190 @@ export const useBluetoothStore = defineStore('ble', { console.log('蓝牙权限', bluetooth, that.bluetoothStatus) } }) + }, + // 连接蓝牙设备+获取设备服务+获取设备特征值 + connectBluetoothDevice() { + const that = this + return new Promise((resolve) => { + if(that.bluetoothStatus !== 0) { + console.log('连接未执行', that.bluetoothStatus) + that.getBluetoothStatus() + resolve(false) + return + } + uni.createBLEConnection({ + deviceId: that.currentLockInfo.deviceId, + success(res) { + console.log('连接成功', res) + // 获取设备服务 + uni.getBLEDeviceServices({ + deviceId: that.currentLockInfo.deviceId, + success (res) { + let serviceId + for(let i = 0; i < res.services.length; i++) { + if(res.services[i].isPrimary) { + serviceId = res.services[i].uuid + } + } + // 获取设备对应服务的特征值 + uni.getBLEDeviceCharacteristics({ + deviceId: that.currentLockInfo.deviceId, + serviceId: serviceId, + success (res) { + let notifyCharacteristicId + let writeCharacteristicId + for(let i = 0; i < res.characteristics.length; i++) { + const characteristic = res.characteristics[i] + if(characteristic.properties.notify) { + notifyCharacteristicId = characteristic.uuid + } + if(characteristic.properties.write) { + writeCharacteristicId = characteristic.uuid + } + } + that.updateCurrentLockInfo({ + ...that.currentLockInfo, + serviceId, + notifyCharacteristicId, + writeCharacteristicId + }) + that.notifyBluetoothCharacteristicValueChange() + resolve(true) + }, + fail(res) { + if(res.errCode === 10006) { + uni.showToast({ + title: '连接失败,请靠近设备并保持设备处于唤醒状态', + icon: 'none' + }) + } + console.log('获取设备特征值失败', res) + resolve(false) + } + }) + }, + fail(res) { + if(res.errCode === 10006) { + uni.showToast({ + title: '连接失败,请靠近设备并保持设备处于唤醒状态', + icon: 'none' + }) + } + console.log('获取设备服务失败', res) + resolve(false) + } + }) + }, + fail(res) { + uni.showToast({ + title: '连接失败,请靠近设备并保持设备处于唤醒状态', + icon: 'none' + }) + console.log('连接失败', res) + resolve(false) + } + }) + }) + }, + // 更新当前锁信息 + updateCurrentLockInfo(lockInfo) { + console.log('更新当前锁信息', lockInfo) + this.currentLockInfo = lockInfo + }, + // 订阅设备特征值改变 + notifyBluetoothCharacteristicValueChange() { + const that = this + uni.notifyBLECharacteristicValueChange({ + state: true, + deviceId: that.currentLockInfo.deviceId, + serviceId: that.currentLockInfo.serviceId, + characteristicId: that.currentLockInfo.notifyCharacteristicId, + success() { + console.log('订阅成功', res) + }, + fail(res) { + console.log('订阅失败', res) + } + }) + }, + // 重新连接设备 + reconnectDevice() { + const that = this + return new Promise(async resolve => { + uni.createBLEConnection({ + deviceId: that.currentLockInfo.deviceId, + success (res) { + console.log('重连成功', res) + that.notifyBluetoothCharacteristicValueChange() + resolve(true) + }, + fail(res) { + console.log('重连失败', res) + uni.showModal({ + title: '提示', + content: '设备连接已断开,请靠近设备并保持设备处于唤醒状态', + showCancel: false, + confirmText: '确定' + }) + resolve(false) + } + }) + }) + }, + // 断开蓝牙连接 + closeBluetoothConnection() { + const that = this + uni.closeBLEConnection({ + deviceId: that.currentLockInfo.deviceId, + success(res) { + console.log('断开连接成功', res) + }, + fail(res) { + console.log('断开连接失败', res) + } + }) + }, + // 写入特征值 + async writeBLECharacteristicValue(binaryData) { + const that = this + + // 确认蓝牙状态正常 + if(this.bluetoothStatus !== 0) { + console.log('写入未执行', this.bluetoothStatus) + this.getBluetoothStatus() + return + } + + // 确认设备连接正常 + if(!that.currentLockInfo.connected) { + const result = await that.reconnectDevice() + if(!result) return + } + + console.log('设备ID:', that.currentLockInfo.deviceId) + console.log('设备名称:', that.currentLockInfo.name) + console.log('设备主服务:', that.currentLockInfo.serviceId) + console.log('设备写入特征值:', that.currentLockInfo.writeCharacteristicId) + console.log('设备写入数据:', Array.from(binaryData)) + + // 次数 + const count = Math.ceil(binaryData.length / 20) + for(let i = 0; i < count; i++) { + const writeData = binaryData.slice(i * 20, i === (count - 1) ? binaryData.length - 1 : (i + 1) * 20) + + uni.writeBLECharacteristicValue({ + deviceId: that.currentLockInfo.deviceId, + serviceId: that.currentLockInfo.serviceId, + characteristicId: that.currentLockInfo.writeCharacteristicId, + value: writeData, + success() { + console.log('数据写入成功') + }, + fail(res) { + console.log('写入失败', res) + } + }) + } } } })