From 2f1c89ebf1ab6f4fbaec574f56cd032372ecdec3 Mon Sep 17 00:00:00 2001 From: peng fan Date: Fri, 9 Aug 2024 19:22:58 +0800 Subject: [PATCH] =?UTF-8?q?1.=20=E5=AE=8C=E6=88=90=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E5=8A=9F=E8=83=BD=202.=20=E5=AE=8C=E5=96=84?= =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E6=96=87=E6=A1=A3=203.=20=E5=AE=8C=E6=88=90?= =?UTF-8?q?=E5=BC=80=E9=97=A8=E4=BB=A3=E7=A0=81=E9=80=BB=E8=BE=91=EF=BC=88?= =?UTF-8?q?=E7=9B=AE=E5=89=8D=E5=9B=9E=E8=B0=830x09=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 7 +- pages/demo/demo.vue | 335 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 336 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 12915ef..4b0a536 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,10 @@ ## 使用工具 #### HBuilderX + 微信开发者工具(推荐使用IntelliJ工具编写,HBuilderX代码提示等功能做的较差) -## 技术栈 -#### Uni-app创建的Vue3项目 -#### 运行只需npm i 安装依赖,然后在HBuilderX中运行即可 +## 技术栈 + 运行方式 +#### Uni-app创建的vue3项目,vue3 + pinia + uview-plus +#### 在HBuilderX中点击 文件 -> 导入 -> 从本地目录导入,选择项目目录即可导入项目 +#### 运行只需执行`npm i` 安装依赖(node版本 v20.16),然后在HBuilderX中点击运行 -> 运行到微信开发者工具即可(运行前勾选运行时压缩代码) ## 目录 1. api 项目接口 diff --git a/pages/demo/demo.vue b/pages/demo/demo.vue index 7c17357..3fce7b7 100644 --- a/pages/demo/demo.vue +++ b/pages/demo/demo.vue @@ -11,6 +11,8 @@ + + @@ -35,7 +37,15 @@ export default { signKey: new Uint8Array(16), showList: true, number: 1, - lockStatus: new Uint8Array(1) + lockStatus: new Uint8Array(1), + token: new Uint8Array([0,0,0,0]), + keyId: '0', + uid: '294', + userId: '294', + // userId: '336', + password: '', + config: {}, + notify: false } }, onLoad() { @@ -63,11 +73,314 @@ export default { }) }, methods: { + // 添加超级管理员 + addUser() { + // 头部数据 + let headArray = new Uint8Array(12) + + // 固定包头 + headArray[0] = 0xEF + headArray[1] = 0x01 + headArray[2] = 0xEE + headArray[3] = 0x02 + + // 包类型 发送 + headArray[4] = 0x01 + + // 包序号 + headArray[5] = this.number / 256 + headArray[6] = this.number % 256 + this.number++ + + // 包标识 + headArray[7] = 0x23 + + // 数据长度 + headArray[8] = 192 / 256 + headArray[9] = 192 % 256 + headArray[10] = 182 / 256 + headArray[11] = 182 % 256 + + // 入参 + let paramsArray = new Uint8Array(182) + + // 命令 + paramsArray[0] = 0x3001 / 256 + paramsArray[1] = 0x3001 % 256 + + // 锁ID + for (let i = 0; i < this.lockId.length; i++) { + paramsArray[2 + i] = this.lockId.charCodeAt(i) + } + + // 用户ID + for (let i = 0; i < this.uid.length; i++) { + paramsArray[42 + i] = this.uid.charCodeAt(i) + } + + // keyId + for (let i = 0; i < this.keyId.length; i++) { + paramsArray[62 + i] = this.keyId.charCodeAt(i) + } + + // userId + for (let i = 0; i < this.userId.length; i++) { + paramsArray[102 + i] = this.userId.charCodeAt(i) + } + + // 开锁方式 + paramsArray[122] = 0x01 + + // 钥匙类型 + paramsArray[123] = 0x01 + + // 启用日期 + const nowTime = parseInt(new Date().getTime() / 1000) + + paramsArray[124] = (nowTime & 0xff000000) >> 24 + paramsArray[125] = (nowTime & 0xff0000) >> 16 + paramsArray[126] = (nowTime & 0xff00) >> 8 + paramsArray[127] = (nowTime & 0xff) + + // 结束日期 + const endTime = 0x11223344 + + paramsArray[128] = (endTime & 0xff000000) >> 24 + paramsArray[129] = (endTime & 0xff0000) >> 16 + paramsArray[130] = (endTime & 0xff00) >> 8 + paramsArray[131] = (endTime & 0xff) + + // 有效次数 + paramsArray[132] = 0xffff / 256 + paramsArray[133] = 0xffff % 256 + + // 是否循环 + paramsArray[134] = 0 + // 循环周期 + paramsArray[135] = 0 + // 开始小时 + paramsArray[136] = 0 + // 开始分钟 + paramsArray[137] = 0 + // 结束小时 + paramsArray[138] = 0 + // 结束分钟 + paramsArray[139] = 0 + // 用户角色 + paramsArray[140] = 0xff + + // 随机密码 + const password = this.password == '' ? (Math.floor(Math.random() * 900000) + 100000).toString() : this.password.toString() + console.log('随机密码', password) + for(let i = 0; i < password.length; i++){ + paramsArray[141 + i] = password.charCodeAt(i) + } + + for(let i = 0; i < this.token.length; i++){ + paramsArray[161 + i] = this.token[i] + } + // MD5长度 + paramsArray[165] = 16 + + const originAuthCodeLen = this.keyId.length + this.uid.length + 4 + 16 + let authCodeBinaryData = new Uint8Array(originAuthCodeLen) + + for(let i=0; i < this.uid.length; i++){ + authCodeBinaryData[i] = this.uid.charCodeAt(i) + } + + for(let i=0; i < this.keyId.length; i++){ + authCodeBinaryData[this.uid.length + i] = this.keyId.charCodeAt(i) + } + + const number = this.keyId.length + this.uid.length + + if(this.token[0] === 0 && this.token[1] === 0 && this.token[2] === 0 && this.token[3] === 0){ + authCodeBinaryData[number + 0] = (nowTime & 0xff000000) >> 24 + authCodeBinaryData[number + 1] = (nowTime & 0xff0000) >> 16 + authCodeBinaryData[number + 2] = (nowTime & 0xff00) >> 8 + authCodeBinaryData[number + 3] = (nowTime & 0xff) + } else { + authCodeBinaryData[number + 0] = this.token[0] + authCodeBinaryData[number + 1] = this.token[1] + authCodeBinaryData[number + 2] = this.token[2] + authCodeBinaryData[number + 3] = this.token[3] + } + + for(let i=0; i < 16; i++){ + authCodeBinaryData[number + 4 + i] = this.publicKey[i] + } + + console.log('md5前的数据', Array.from(authCodeBinaryData)) + const md5Hex = md5(authCodeBinaryData) + const md5Array = new Uint8Array(md5Hex.match(/.{1,2}/g).map(byte => parseInt(byte, 16))) + console.log('md5后的数据', Array.from(md5Array)) + + for(let i = 0; i < md5Array.length; i++) { + paramsArray[166 + i] = md5Array[i] + } + + console.log('未加密的数据', Array.from(paramsArray)) + const encryptArray = sm4.encrypt(paramsArray, this.commKey, { mode: 'ecb', output: 'array' }) + console.log('加密后的数据', Array.from(encryptArray)) + + // 合并头部数据和加密数据 + let mergeBuffer = new ArrayBuffer(204) + let mergeArray = new Uint8Array(mergeBuffer) + for(let i = 0; i < 12; i++){ + mergeArray[i] = headArray[i] + } + for(let i = 0; i < 192; i++){ + mergeArray[i + 12] = encryptArray[i] + } + + console.log('crc前的数据', Array.from(mergeArray)) + let resultBuffer = new ArrayBuffer(206) + let resultArray = new Uint8Array(resultBuffer) + for(let i = 0; i < 204; i++){ + resultArray[i] = mergeArray[i] + } + resultArray[204] = crc.crc16kermit(mergeBuffer) / 256 + resultArray[205] = crc.crc16kermit(mergeBuffer) % 256 + this.writeBLECharacteristicValue(resultBuffer) + }, + reconnect() { + return new Promise(resolve => setTimeout(resolve, 2000)) + }, + // 开门 + async openDoor() { + const that = this + + that.connect(that.config) + // 重连 + const result = await that.reconnect() + + // 头部数据 + let headArray = new Uint8Array(12) + + // 固定包头 + headArray[0] = 0xEF + headArray[1] = 0x01 + headArray[2] = 0xEE + headArray[3] = 0x02 + + // 包类型 发送 + headArray[4] = 0x01 + + // 包序号 + headArray[5] = this.number / 256 + headArray[6] = this.number % 256 + this.number++ + + // 包标识 + headArray[7] = 0x23 + + // 数据长度 + headArray[8] = 112 / 256 + headArray[9] = 112 % 256 + headArray[10] = 104 / 256 + headArray[11] = 104 % 256 + + // 入参 + let paramsArray = new Uint8Array(104) + + // 命令 + paramsArray[0] = 0x3005 / 256 + paramsArray[1] = 0x3005 % 256 + + // 锁ID + for (let i = 0; i < this.lockId.length; i++) { + paramsArray[2 + i] = this.lockId.charCodeAt(i) + } + + // 用户ID + for (let i = 0; i < this.uid.length; i++) { + paramsArray[42 + i] = this.uid.charCodeAt(i) + } + + // 开锁方式 + paramsArray[62] = 0 + + // 启用日期 + const nowTime = parseInt(new Date().getTime() / 1000) + + paramsArray[63] = (nowTime & 0xff000000) >> 24 + paramsArray[64] = (nowTime & 0xff0000) >> 16 + paramsArray[65] = (nowTime & 0xff00) >> 8 + paramsArray[66] = (nowTime & 0xff) + + // token + for (let i = 0; i < this.token.length; i++) { + paramsArray[67 + i] = this.token[i] + } + + // authCode长度 + paramsArray[71] = 16 + + const originAuthCodeLen = this.keyId.length + this.uid.length + 4 + 16 + let authCodeBinaryData = new Uint8Array(originAuthCodeLen) + + for (let i = 0; i < this.keyId.length; i++) { + authCodeBinaryData[i] = this.keyId.charCodeAt(i) + } + + for (let i = 0; i < this.uid.length; i++) { + authCodeBinaryData[this.keyId.length + i] = this.uid.charCodeAt(i) + } + + const number = this.keyId.length + this.uid.length + + authCodeBinaryData[number + 0] = this.token[0] + authCodeBinaryData[number + 1] = this.token[1] + authCodeBinaryData[number + 2] = this.token[2] + authCodeBinaryData[number + 3] = this.token[3] + + for (let i = 0; i < 16; i++) { + authCodeBinaryData[number + 4 + i] = this.signKey[i] + } + + console.log('md5前的数据', Array.from(authCodeBinaryData)) + const md5Hex = md5(authCodeBinaryData) + const md5Array = new Uint8Array(md5Hex.match(/.{1,2}/g).map(byte => parseInt(byte, 16))) + console.log('md5后的数据', Array.from(md5Array)) + + for (let i = 0; i < md5Array.length; i++) { + paramsArray[72 + i] = md5Array[i] + } + + const onlineToken = '0' + for (let i = 0; i < onlineToken.length; i++) { + paramsArray[88 + i] = onlineToken.charCodeAt(i) + } + + console.log('未加密的数据', Array.from(paramsArray)) + const encryptArray = sm4.encrypt(paramsArray, this.commKey, { mode: 'ecb', output: 'array' }) + console.log('加密后的数据', Array.from(encryptArray)) + + // 合并头部数据和加密数据 + let mergeBuffer = new ArrayBuffer(124) + let mergeArray = new Uint8Array(mergeBuffer) + for (let i = 0; i < 12; i++) { + mergeArray[i] = headArray[i] + } + for (let i = 0; i < 112; i++) { + mergeArray[i + 12] = encryptArray[i] + } + + console.log('crc前的数据', Array.from(mergeArray)) + let resultBuffer = new ArrayBuffer(126) + let resultArray = new Uint8Array(resultBuffer) + for (let i = 0; i < 124; i++) { + resultArray[i] = mergeArray[i] + } + resultArray[124] = crc.crc16kermit(mergeBuffer) / 256 + resultArray[125] = crc.crc16kermit(mergeBuffer) % 256 + this.writeBLECharacteristicValue(resultBuffer) + }, // 获取锁状态 getLockStatus() { // 头部数据 - let buffer = new ArrayBuffer(12) - let binaryData = new Uint8Array(buffer) + let binaryData = new Uint8Array(12) // 固定包头 binaryData[0] = 0xEF @@ -411,6 +724,18 @@ export default { if(decrypted[0] === 48 && decrypted[1] === 64) { that.lockStatus = decrypted console.log('锁状态', that.lockStatus) + } else { + that.token = decrypted.slice(42,46) + console.log('token', Array.from(that.token)) + if(decrypted[0] === 48 && decrypted[1] === 1) { + if(decrypted[46] === 6) { + that.addUser() + } + } else if(decrypted[0] === 48 && decrypted[1] === 5) { + if(decrypted[46] === 6) { + that.openDoor() + } + } } } }, @@ -427,7 +752,9 @@ export default { type: 'notification', success(res) { console.log(res) + if(that.notify) return uni.onBLECharacteristicValueChange(function (res) { + that.notify = true let binaryData = new Uint8Array(res.value) console.log('设备返回的数据', Array.from(binaryData), Array.from(binaryData, byte => byte.toString(16)).join(',')) @@ -454,8 +781,10 @@ export default { } }) }, + // 连接蓝牙设备 connect(item) { + this.config = item const that = this if(item.pair) { return