From 1130b198b9cc3b748bb0396e11126b818bb88412 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8C=83=E9=B9=8F?= Date: Fri, 16 Aug 2024 11:51:27 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E6=B7=BB=E5=8A=A0=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E3=80=81=E5=BC=80=E9=97=A8=E3=80=81=E6=81=A2=E5=A4=8D?= =?UTF-8?q?=E5=87=BA=E5=8E=82=E8=AE=BE=E7=BD=AE=E3=80=81=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E9=94=81=E7=8A=B6=E6=80=81=E7=9A=84=E5=86=99=E5=85=A5=E4=B8=8E?= =?UTF-8?q?=E5=B0=81=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/index/index.vue | 96 +++++++++++------ stores/bluetooth.js | 246 ++++++++++++++++++++++++++++++++++-------- 2 files changed, 267 insertions(+), 75 deletions(-) diff --git a/pages/index/index.vue b/pages/index/index.vue index bcb119c..c7c1a05 100644 --- a/pages/index/index.vue +++ b/pages/index/index.vue @@ -7,14 +7,12 @@ - - + + + 名称:{{currentLockInfo.name}} 设备Id:{{currentLockInfo.deviceId}} - 服务:{{currentLockInfo.serviceId}} - 写入特征值Id:{{currentLockInfo.writeCharacteristicId}} - 监听特征值Id:{{currentLockInfo.notifyCharacteristicId}} @@ -29,7 +27,8 @@ showAdd: true, showConnect: false, keyId: '0', - authUid: '294' + authUid: '294', + onlineToken: '0' } }, computed: { @@ -38,7 +37,36 @@ onLoad () {}, methods: { ...mapActions(useBluetoothStore, ['getBluetoothDevices', 'stopGetBluetoothDevices', 'updateCurrentLockInfo', - 'connectBluetoothDevice', 'getPublicKey', 'getCommKey', 'getLockStatus', 'addLockUser']), + 'connectBluetoothDevice', 'getPublicKey', 'getCommKey', 'getLockStatus', 'addLockUser', 'timestampToArray', + 'openDoor', 'resetDevice']), + async openDoorOperate() { + const { code } = await this.openDoor({ + name: this.currentLockInfo.name, + uid: this.authUid, + openMode: 0, + openTime: parseInt(new Date().getTime() / 1000), + onlineToken: this.onlineToken + }) + console.log('开门返回', code) + }, + async closeDoorOperate() { + const { code } = await this.openDoor({ + name: this.currentLockInfo.name, + uid: this.authUid, + openMode: 32, + openTime: parseInt(new Date().getTime() / 1000), + onlineToken: this.onlineToken + }) + console.log('关门返回', code) + }, + async reset() { + const { code } = await this.resetDevice({ + name: this.currentLockInfo.name, + authUid: this.authUid, + keyId: this.keyId + }) + console.log('恢复出厂设置返回', code) + }, getList() { this.getBluetoothDevices() this.showAdd = false @@ -65,37 +93,43 @@ return } const { code: getCommKeyCode } = await this.getCommKey(this.currentLockInfo.name, this.keyId, this.authUid, - parseInt(new Date().getTime() / 1000), this.currentLockInfo.publicKey) + parseInt(new Date().getTime() / 1000)) console.log('获取私钥返回', getCommKeyCode) if(getCommKeyCode !== 0) { return } - // this.addLockUser({ - // name: this.currentLockInfo.name, - // keyId: this.keyId, - // authUid: this.authUid, - // uid: this.authUid, - // publicKey: this.currentLockInfo.publicKey, - // openMode: 1, - // keyType: 1, - // startDate: parseInt(new Date().getTime() / 1000), - // expireDate: 0xffffffff, - // useCountLimit: 0xffff, - // isRound: 0, - // weekRound: 0, - // startHour: 0, - // startMin: 0, - // endHour: 0, - // endMin: 0, - // role: 0xff, - // token: this.currentLockInfo.token || new Uint8Array([0,0,0,0]), - // password: (Math.floor(Math.random() * 900000) + 100000).toString() - // }) + const timestamp = parseInt(new Date().getTime() / 1000) + const { code: addUserCode } = await this.addLockUser({ + name: this.currentLockInfo.name, + keyId: this.keyId, + authUid: this.authUid, + uid: this.authUid, + publicKey: this.currentLockInfo.publicKey, + commKey: this.currentLockInfo.commKey, + openMode: 1, + keyType: 1, + startDate: timestamp, + expireDate: 0xffffffff, + useCountLimit: 0xffff, + isRound: 0, + weekRound: 0, + startHour: 0, + startMin: 0, + endHour: 0, + endMin: 0, + role: 0xff, + password: (Math.floor(Math.random() * 900000) + 100000).toString() + }) + console.log('添加用户返回', addUserCode) }, getLockStatusResult() { const timnestamp = parseInt(new Date().getTime() / 1000) - this.getLockStatus(this.currentLockInfo.name, this.authUid,timnestamp, timnestamp, - this.currentLockInfo.commKey) + this.getLockStatus({ + name: this.currentLockInfo.name, + uid: this.authUid, + nowTime: timnestamp, + localTime: timnestamp + }) } } } diff --git a/stores/bluetooth.js b/stores/bluetooth.js index d3431bd..63a39b7 100644 --- a/stores/bluetooth.js +++ b/stores/bluetooth.js @@ -166,18 +166,59 @@ export const useBluetoothStore = defineStore('ble', { console.log('ecb解密后的数据', decrypted) const cmdId = decrypted[0] * 256 + decrypted[1] - if(cmdId === cmdIds.getLockStatus) { - if (decrypted[2] === 0) { - console.log('获取锁状态成功', decrypted) - } - } else if(cmdId === cmdIds.openDoor) { - if (decrypted[2] === 0) { - console.log('开门成功', decrypted) - } - } else if(cmdId === cmdIds.addUser) { - if (decrypted[2] === 0) { - console.log('添加用户', decrypted) - } + + switch (cmdId) { + case cmdIds.getLockStatus: + if (decrypted[2] === 0) { + const lockConfig = { + vendor: decrypted.slice(3, 23), + product: decrypted[23], + model: decrypted.slice(24, 44), + fwVersion: decrypted.slice(44, 64), + hwVersion: decrypted.slice(64, 84), + serialNum0: decrypted.slice(84, 100), + serialNum1: decrypted.slice(100, 116), + btDeviceName: decrypted.slice(116, 132), + battRemCap: decrypted[132], + battRemCapStandby: decrypted[133], + restoreCounter: decrypted.slice(134, 136), + restoreDate: decrypted.slice(136, 140), + icPartNo: decrypted.slice(140, 150), + inDate: decrypted.slice(150, 154), + mac: decrypted.slice(154, 174), + featurevalueLength: decrypted[174], + featureValue: decrypted.slice(175, 175 + decrypted[174]), + featureEnValLength: decrypted[175 + decrypted[174]], + featureEnVal: decrypted.slice(176 + decrypted[174], 176 + decrypted[174] + decrypted[175 + decrypted[174]]), + } + that.updateCurrentLockInfo({ + ...that.currentLockInfo, + lockConfig + }) + console.log('获取锁状态成功', that.currentLockInfo.lockConfig) + } + characteristicValueCallback({ + code: decrypted[2] + }) + break + case cmdIds.addUser: + that.updateCurrentLockInfo({ + ...that.currentLockInfo, + token: decrypted.slice(42,46) + }) + characteristicValueCallback({ + code: decrypted[46] + }) + break + default: + that.updateCurrentLockInfo({ + ...that.currentLockInfo, + token: decrypted.slice(2,6) + }) + characteristicValueCallback({ + code: decrypted[6] + }) + break } } }, @@ -478,9 +519,6 @@ export const useBluetoothStore = defineStore('ble', { serviceId: that.currentLockInfo.serviceId, characteristicId: that.currentLockInfo.writeCharacteristicId, value: writeData.buffer, - success() { - console.log('数据写入成功', Array.from(writeData)) - }, fail(res) { console.log('写入失败', res) } @@ -568,7 +606,7 @@ export const useBluetoothStore = defineStore('ble', { return this.getWriteResult() }, // 获取私钥 - async getCommKey(name, keyId, authUid, nowTime, publicKey) { + async getCommKey(name, keyId, authUid, nowTime) { const length = 2 + 40 + 40 + 20 + 4 + 1 + 16 const headArray = this.createPackageHeader(2, length) const conentArray = new Uint8Array(length) @@ -592,7 +630,7 @@ export const useBluetoothStore = defineStore('ble', { conentArray[106] = 16 - const md5Array = this.platformMd5Encrypte(authUid, keyId, conentArray.slice(102, 106), publicKey) + const md5Array = this.md5Encrypte(authUid + keyId, conentArray.slice(102, 106), this.currentLockInfo.publicKey) conentArray.set(md5Array, 107) @@ -603,33 +641,24 @@ export const useBluetoothStore = defineStore('ble', { await this.writeBLECharacteristicValue(packageArray) return this.getWriteResult() }, - /* - * 锁与平台md5加密 - * authUid - * keyId - * token | nowTime - * publicKey - * */ - platformMd5Encrypte(authUid, keyId, token, publicKey) { - const length = authUid.length + keyId.length + 4 + 16 + // md5加密 + md5Encrypte(text, token, key) { + const length = text.length + 4 + 16 const md5Array = new Uint8Array(length) - for (let i = 0; i < authUid.length; i++) { - md5Array[i] = authUid.charCodeAt(i) + for (let i = 0; i < text.length; i++) { + md5Array[i] = text.charCodeAt(i) } - for (let i = 0; i < keyId.length; i++) { - md5Array[authUid.length + i] = keyId.charCodeAt(i) - } - - md5Array.set(token, authUid.length + keyId.length) - md5Array.set(publicKey, authUid.length + keyId.length + 4) + md5Array.set(token , text.length) + md5Array.set(key, text.length + 4) const md5Text= md5(md5Array) return new Uint8Array(md5Text.match(/.{1,2}/g).map(byte => parseInt(byte, 16))) }, // 获取锁状态 - async getLockStatus(name, uid, nowTime, localTime, commKey) { + async getLockStatus(data) { + const { name, uid, nowTime, localTime } = data const length = 2 + 40 + 20 + 4 + 4 const headArray = this.createPackageHeader(3, length) @@ -645,11 +674,13 @@ export const useBluetoothStore = defineStore('ble', { conentArray.set(this.timestampToArray(nowTime), 62) conentArray.set(this.timestampToArray(localTime), 66) - const cebArray = sm4.encrypt(conentArray, commKey, { mode: 'ecb', output: 'array' }) + const cebArray = sm4.encrypt(conentArray, this.currentLockInfo.commKey, { mode: 'ecb', output: 'array' }) const packageArray = this.createPackageEnd(headArray, cebArray) await this.writeBLECharacteristicValue(packageArray) + + return this.getWriteResult(this.getLockStatus, data) }, // 时间戳转二进制 timestampToArray(timestamp) { @@ -661,9 +692,9 @@ export const useBluetoothStore = defineStore('ble', { return array }, // 添加用户 - addLockUser(data) { + async addLockUser(data) { const { name, authUid, uid, keyId, openMode, keyType, startDate, expireDate, useCountLimit, isRound, weekRound, - startHour, startMin, endHour, endMin, role, password, token, publicKey} = data + startHour, startMin, endHour, endMin, role, password, publicKey, commKey } = data const length = 2 + 40 + 20 + 40 + 20 + 1 + 1 + 4 + 4 + 2 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 20 + 4 + 1 + 16 const headArray = this.createPackageHeader(3, length) const conentArray = new Uint8Array(length) @@ -671,19 +702,146 @@ export const useBluetoothStore = defineStore('ble', { conentArray[0] = cmdIds.addUser / 256 conentArray[1] = cmdIds.addUser % 256 - // 尚未完成 + for(let i = 0; i < name.length; i++) { + conentArray[i + 2] = name.charCodeAt(i) + } + + for(let i = 0; i < authUid.length; i++) { + conentArray[i + 42] = authUid.charCodeAt(i) + } + + for(let i = 0; i < keyId.length; i++) { + conentArray[i + 62] = keyId.charCodeAt(i) + } + + for(let i = 0; i < uid.length; i++) { + conentArray[i + 102] = uid.charCodeAt(i) + } + + conentArray[122] = openMode + conentArray[123] = keyType + + conentArray.set(this.timestampToArray(startDate), 124) + conentArray.set(this.timestampToArray(expireDate), 128) + + conentArray[132] = useCountLimit / 256 + conentArray[133] = useCountLimit % 256 + + conentArray[134] = isRound + conentArray[135] = weekRound + conentArray[136] = startHour + conentArray[137] = startMin + conentArray[138] = endHour + conentArray[139] = endMin + conentArray[140] = role + + for(let i = 0; i < password.length; i++) { + conentArray[i + 141] = password.charCodeAt(i) + } + + conentArray.set(this.currentLockInfo.token || this.timestampToArray(startDate), 161) + + conentArray[165] = 16 + + const md5Array = this.md5Encrypte(authUid + keyId, this.currentLockInfo.token || this.timestampToArray(startDate), this.currentLockInfo.publicKey) + + conentArray.set(md5Array, 166) + + const cebArray = sm4.encrypt(conentArray, commKey, { mode: 'ecb', output: 'array' }) + + const packageArray = this.createPackageEnd(headArray, cebArray) + await this.writeBLECharacteristicValue(packageArray) + return this.getWriteResult(this.addLockUser, data) }, // 获取写入结果 - getWriteResult() { + getWriteResult(request, params) { return new Promise(resolve => { const timer = setTimeout(() => { resolve({ code: -1 }) - }, 7000) - characteristicValueCallback = (data) => { - clearTimeout(timer) - resolve(data) + }, 20000) + characteristicValueCallback = async (data) => { + // code 6 token过期,重新获取 + if(data.code === 6) { + resolve(await request(params)) + } else { + clearTimeout(timer) + resolve(data) + } } }) + }, + // 开门 + async openDoor(data) { + const { name, uid, openMode, openTime, onlineToken } = data + const length = 2 + 40 + 20 + 1 + 4 + 4 + 1 + 16 + 16 + const headArray = this.createPackageHeader(3, length) + + const conentArray = new Uint8Array(length) + conentArray[0] = cmdIds.openDoor / 256 + conentArray[1] = cmdIds.openDoor % 256 + + for(let i = 0; i < name.length; i++) { + conentArray[i + 2] = name.charCodeAt(i) + } + + for (let i = 0; i < uid.length; i++) { + conentArray[i + 42] = uid.charCodeAt(i) + } + + conentArray[62] = openMode + + conentArray.set(this.timestampToArray(openTime), 63) + + conentArray.set(this.currentLockInfo.token, 67) + + conentArray[71] = 16 + + const md5Array = this.md5Encrypte(name + uid, this.currentLockInfo.token, this.currentLockInfo.signKey) + + conentArray.set(md5Array, 72) + + for (let i = 0; i < onlineToken.length; i++) { + conentArray[i + 88] = onlineToken.charCodeAt(i) + } + + const cebArray = sm4.encrypt(conentArray, this.currentLockInfo.commKey, { mode: 'ecb', output: 'array' }) + + const packageArray = this.createPackageEnd(headArray, cebArray) + + await this.writeBLECharacteristicValue(packageArray) + + return this.getWriteResult(this.openDoor, data) + }, + // 恢复出厂设置 + async resetDevice(data) { + const { name, authUid, keyId } = data + const length = 2 + 40 + 20 + 4 + 1 + 16 + const headArray = this.createPackageHeader(3, length) + const conentArray = new Uint8Array(length) + + conentArray[0] = cmdIds.resetDevice / 256 + conentArray[1] = cmdIds.resetDevice % 256 + + for(let i = 0; i < name.length; i++) { + conentArray[i + 2] = name.charCodeAt(i) + } + + for(let i = 0; i < authUid.length; i++) { + conentArray[i + 42] = authUid.charCodeAt(i) + } + conentArray.set(this.currentLockInfo.token, 62) + conentArray[66] = 16 + + const md5Array = this.md5Encrypte(name, this.currentLockInfo.token, this.currentLockInfo.publicKey) + conentArray.set(md5Array, 67) + + const cebArray = sm4.encrypt(conentArray, this.currentLockInfo.commKey, { mode: 'ecb', output: 'array' }) + + const packageArray = this.createPackageEnd(headArray, cebArray) + + await this.writeBLECharacteristicValue(packageArray) + + return this.getWriteResult(this.resetDevice, data) } } })