starcloud-sdk-uniapp/starCloud.js
2024-10-21 09:58:17 +08:00

1016 lines
33 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { defineStore } from 'pinia'
import { sm4 } from 'sm-crypto'
import { buildNumber, configs, version } from '@/starCloud/env'
import {
addCustomPassword,
getLockDetail,
getLockNetTokenRequest,
getOfflinePassword,
getServerDatetime,
getStarCloudToken,
getUserNoListRequest,
starCloudCreateUser,
updateLockUserNoRequest,
updatePassword
} from '@/starCloud/api'
import { getStorage, setStorage } from '@/starCloud/storage'
import {
closeBLEConnection,
onBLECharacteristicValueChange,
Result,
searchAndConnectDevice,
writeBLECharacteristicValue
} from '@/starCloud/basic'
import {
arrayToTimestamp,
convertWeekdaysToNumber,
createPackageEnd,
md5Encrypt,
timestampToArray,
uint8ArrayToString
} from '@/starCloud/format'
/**
* 锁信息
* @typedef {Object} lockInfo
* @property {Number} keyId - 钥匙ID
* @property {Number} lockId - 锁ID
* @property {String} lockName - 锁名称
* @property {String} lockAlias - 锁别名
* @property {Number} electricQuantity - 电量
* @property {Number} electricQuantityStandby - 备用电量
* @property {Number} electricQuantityDate - 电量更新时间
* @property {String} fwVersion - 固件版本
* @property {String} hwVersion - 硬件版本
* @property {Number} keyType - 钥匙类型
* @property {Number} passageMode - 常开模式
* @property {Number} userType - 用户类型
* @property {Number} startDate - 有效期开始时间
* @property {Number} endDate - 有效期结束时间
* @property {Object} weekDays - 循环周期
* @property {Number} remoteEnable - 是否支持远程开锁0-未知1-是2-否
* @property {Number} faceAuthentication - 是否实名认证0-未知1-是2-否
* @property {Number} lastFaceValidateTime - 最后一次人脸验证时间
* @property {Number} nextFaceValidateTime - 下次人脸验证时间
* @property {Number} keyRight - 是否授权管理员钥匙: 0-未知1-是2-否
* @property {Number} keyStatus - 钥匙状态
* @property {Object} bluetooth - 蓝牙
* @property {Number} sendDate - 发送时间
* @property {Number} isLockOwner - 是否是锁主
* @property {Object} lockFeature - 锁特征
* @property {Object} lockSetting - 锁设置
* @property {Number} lockUserNo - 用户编号
* @property {Number} senderUserId - 发送者用户ID
* @property {Number} isOnlyManageSelf - 如果是授权管理员此字段区分是否仅管理自己发的钥匙
* @property {Number} restoreCount - 重置次数
* @property {String} model - 模式
*/
/**
* 锁蓝牙信息
* @typedef {Object} bluetooth
* @property {String} bluetoothDeviceId - 设备ID
* @property {String} bluetoothDeviceName - 设备名称
* @property {String} publicKey - 公钥
* @property {String} privateKey - 私钥
* @property {String} signKey - 签名密钥
* @property {String} passwordKey - 密码密钥
*/
/**
* 锁设置信息
* @typedef {Object} lockSetting
* @property {Number} appUnlockOnline - 开门是否需要联网
*/
/**
* 请求返回数据
* @typedef {Object} requestData
* @property {String} userNos - 设备ID
*/
// 命令ID
const cmdIds = {
// 获取公钥
getPublicKey: 0x3090,
// 获取私钥
getCommKey: 0x3091,
// 获取锁状态
getLockStatus: 0x3040,
// 新增用户
addUser: 0x3001,
// 开门
openDoor: 0x3005,
// 重置设备
resetDevice: 0x3004,
// 清理用户
cleanUser: 0x300c,
// 扩展命令
expandCmd: 0x3030
}
// 子命令ID
const subCmdIds = {
// 设置开锁密码
setLockPassword: 3,
// 重置开锁密码
resetLockPassword: 19
}
// 特性值回调
let characteristicValueCallback = null
// 完整数据
let completeArray
// 完整内容数据长度
let length
// 请求参数
let requestParams = null
export const useStarCloudStore = defineStore('starCloud', {
state() {
return {
// 环境
env: null,
// 客户端Id
clientId: null,
// 客户端密码
clientSecret: null,
// 星云是否登录
loginStarCloud: false,
// 星云用户信息
userInfo: null,
// 账户信息
accountInfo: null,
// 锁信息
lockInfo: null,
// 消息序号
messageCount: 1,
// 服务器时间
serverTimestamp: 0,
// 时间差
timeDifference: 0,
// 小程序环境
envVersion: ''
}
},
actions: {
// 初始化星云
initStarCloud(clientId, clientSecret, env = 'XHJ') {
const appInfo = uni.getAccountInfoSync()
this.envVersion = appInfo.miniProgram.envVersion
this.env = env
this.clientId = clientId
this.clientSecret = clientSecret
// 监听特性值变化
onBLECharacteristicValueChange(this.listenCharacteristicValue)
},
// 注册星云
async register() {
const { code, data, message } = await starCloudCreateUser({
clientId: this.clientId,
clientSecret: this.clientSecret
})
return new Result(code, data, message)
},
// 登录星云
async login(username, password) {
this.accountInfo = {
username,
password
}
const token = getStorage('starCloudToken')
if (token) {
this.userInfo = getStorage('starCloudUser')
this.loginStarCloud = true
// 获取服务器时间
this.getServerTimestamp().then(() => {})
return Result.Success
}
console.log('登录星云', username, password)
const {
code,
data: userInfo,
message
} = await getStarCloudToken({
username,
password,
clientId: this.clientId,
clientSecret: this.clientSecret
})
if (code === Result.Success.code) {
this.userInfo = userInfo
setStorage('starCloudToken', userInfo.access_token)
setStorage('starCloudUser', userInfo)
this.loginStarCloud = true
// 获取服务器时间
this.getServerTimestamp().then(() => {})
}
return new Result(code, {}, message)
},
// 选择锁
async selectLock(lockId) {
const { code, data, message } = await getLockDetail({
lockId
})
if (code === Result.Success.code) {
const lockList = getStorage('lockList')
if (lockList) {
const index = lockList.findIndex(item => item.lockId === lockId)
if (index === -1) {
lockList.push(data)
} else {
lockList[index] = data
}
setStorage('lockList', lockList)
} else {
setStorage('lockList', [data])
}
this.lockInfo = data
} else {
const lockList = getStorage('lockList')
console.log('锁列表', lockList)
if (lockList) {
const index = lockList.findIndex(item => item.lockId === lockId)
if (index !== -1) {
this.lockInfo = lockList[index]
return new Result(Result.Success.code, this.lockInfo)
}
}
}
return new Result(code, data, message)
},
// 清理用户
async cleanLockUser(disconnect = false) {
// 确认设备连接正常
const searchResult = await searchAndConnectDevice(this.lockInfo.bluetooth.bluetoothDeviceName)
if (searchResult.code !== Result.Success.code) {
return searchResult
}
this.updateLockInfo(searchResult.data)
// 获取并处理锁信息
let { uid: authUid, keyId, token, bluetooth } = this.lockInfo
let { uid } = this.userInfo
authUid = authUid.toString()
uid = uid.toString()
keyId = keyId.toString()
const name = bluetooth.bluetoothDeviceName
// 获取用户列表
const { code: requestCode, data: requestData } = await getUserNoListRequest({
lockId: this.lockInfo.lockId
})
console.log('获取用户列表请求结果', requestCode, requestData)
if (requestCode !== 0) return Result.Fail
const userNoList = requestData.userNos
// 组装发送数据
const length = 2 + 40 + 20 + 40 + 20 + 2 + userNoList.length + 4 + 1 + 16
const headArray = this.createPackageHeader(3, length)
const contentArray = new Uint8Array(length)
contentArray[0] = cmdIds.cleanUser / 256
contentArray[1] = cmdIds.cleanUser % 256
for (let i = 0; i < name.length; i++) {
contentArray[i + 2] = name.charCodeAt(i)
}
for (let i = 0; i < authUid.length; i++) {
contentArray[i + 42] = authUid.charCodeAt(i)
}
for (let i = 0; i < keyId.length; i++) {
contentArray[i + 62] = keyId.charCodeAt(i)
}
for (let i = 0; i < uid.length; i++) {
contentArray[i + 102] = uid.charCodeAt(i)
}
contentArray[122] = userNoList.length / 256
contentArray[123] = userNoList.length % 256
for (let i = 0; i < userNoList.length; i++) {
contentArray[i + 124] = userNoList[i]
}
contentArray.set(token || new Uint8Array([0, 0, 0, 0]), 124 + userNoList.length)
contentArray[128 + userNoList.length] = 16
const md5Array = md5Encrypt(
authUid + keyId,
token || new Uint8Array([0, 0, 0, 0]),
bluetooth.publicKey
)
contentArray.set(md5Array, 129 + userNoList.length)
const cebArray = sm4.encrypt(contentArray, bluetooth.privateKey, {
mode: 'ecb',
output: 'array'
})
const packageArray = createPackageEnd(headArray, cebArray)
const writeResult = await writeBLECharacteristicValue(
this.lockInfo.deviceId,
this.lockInfo.serviceId,
this.lockInfo.writeCharacteristicId,
packageArray
)
if (writeResult.code !== Result.Success.code) {
return writeResult
}
return this.getWriteResult(this.cleanLockUser, disconnect)
},
// 开门
// eslint-disable-next-line default-param-last
async openDoor(type = 'open', disconnect) {
// 确认设备连接正常
const searchResult = await searchAndConnectDevice(this.lockInfo.bluetooth.bluetoothDeviceName)
if (searchResult.code !== Result.Success.code) {
return searchResult
}
this.updateLockInfo(searchResult.data)
// 检查是否已添加为用户
const checkResult = await this.checkLockUser()
if (checkResult.code !== Result.Success.code) {
return checkResult
}
// 是否需要联网
let onlineToken = ''
if (this.lockInfo.lockSetting.appUnlockOnline) {
const result = await this.getNetToken()
if (result.code === Result.Success.code) {
onlineToken = result.data.token
} else {
return result
}
}
// 开门方式
let openMode
if (type === 'close') {
openMode = this.lockInfo.lockSetting.appUnlockOnline ? 33 : 32
} else {
openMode = this.lockInfo.lockSetting.appUnlockOnline ? 1 : 0
}
const name = this.lockInfo.bluetooth.bluetoothDeviceName
const uid = this.userInfo.uid.toString()
const openTime = Math.ceil(new Date().getTime() / 1000) + this.timeDifference
const length = 2 + 40 + 20 + 1 + 4 + 4 + 1 + 16 + 16
const headArray = this.createPackageHeader(3, length)
const contentArray = new Uint8Array(length)
contentArray[0] = cmdIds.openDoor / 256
contentArray[1] = cmdIds.openDoor % 256
for (let i = 0; i < name.length; i++) {
contentArray[i + 2] = name.charCodeAt(i)
}
for (let i = 0; i < uid.length; i++) {
contentArray[i + 42] = uid.charCodeAt(i)
}
contentArray[62] = openMode
contentArray.set(timestampToArray(openTime), 63)
console.log('开门时token', this.lockInfo.token)
contentArray.set(this.lockInfo.token || timestampToArray(openTime), 67)
contentArray[71] = 16
const md5Array = md5Encrypt(
name + uid,
this.lockInfo.token || timestampToArray(openTime),
this.lockInfo.bluetooth.signKey
)
contentArray.set(md5Array, 72)
for (let i = 0; i < onlineToken.length; i++) {
contentArray[i + 88] = onlineToken.charCodeAt(i)
}
const cebArray = sm4.encrypt(contentArray, this.lockInfo.bluetooth.privateKey, {
mode: 'ecb',
output: 'array'
})
const packageArray = createPackageEnd(headArray, cebArray)
const writeResult = await writeBLECharacteristicValue(
this.lockInfo.deviceId,
this.lockInfo.serviceId,
this.lockInfo.writeCharacteristicId,
packageArray
)
if (writeResult.code !== Result.Success.code) {
return writeResult
}
return this.getWriteResult(this.openDoor, disconnect)
},
// 获取离线密码
async getOfflinePassword(password) {
return await getOfflinePassword({
...password,
lockId: this.lockInfo.lockId
})
},
// 自定义密码
async customPassword(password, disconnect) {
// 确认设备连接正常
const searchResult = await searchAndConnectDevice(this.lockInfo.bluetooth.bluetoothDeviceName)
if (searchResult.code !== Result.Success.code) {
return searchResult
}
this.updateLockInfo(searchResult.data)
// 检查是否已添加为用户
const checkResult = await this.checkLockUser()
if (checkResult.code !== Result.Success.code) {
return checkResult
}
requestParams = password
let { pwdNo, operate, keyboardPwd, startDate, endDate, pwdRight } = password
const uid = this.userInfo.uid.toString()
const keyId = this.lockInfo.keyId.toString()
const isAdmin = pwdRight
const userCountLimit = 0xffff
startDate = Math.floor(startDate / 1000)
endDate = Math.floor(endDate / 1000)
keyboardPwd = keyboardPwd.toString()
if (!pwdNo) {
pwdNo = 0
}
const length = 2 + 1 + 1 + 40 + 20 + 2 + 1 + 1 + 20 + 2 + 4 + 4 + 4 + 1 + 16
const headArray = this.createPackageHeader(3, length)
const contentArray = new Uint8Array(length)
contentArray[0] = cmdIds.expandCmd / 256
contentArray[1] = cmdIds.expandCmd % 256
// 子命令
contentArray[2] = subCmdIds.setLockPassword
contentArray[3] = length - 3
for (let i = 0; i < keyId.length; i++) {
contentArray[i + 4] = keyId.charCodeAt(i)
}
for (let i = 0; i < uid.length; i++) {
contentArray[i + 44] = uid.charCodeAt(i)
}
contentArray[64] = pwdNo / 256
contentArray[65] = pwdNo % 256
contentArray[66] = operate
contentArray[67] = isAdmin
for (let i = 0; i < keyboardPwd.length; i++) {
contentArray[i + 68] = keyboardPwd.charCodeAt(i)
}
contentArray[88] = userCountLimit / 256
contentArray[89] = userCountLimit % 256
contentArray.set(this.lockInfo.token || new Uint8Array([0, 0, 0, 0]), 90)
contentArray.set(timestampToArray(startDate), 94)
contentArray.set(timestampToArray(endDate), 98)
contentArray[102] = 16
const md5Array = md5Encrypt(
keyId + uid,
this.lockInfo.token || new Uint8Array([0, 0, 0, 0]),
this.lockInfo.bluetooth.signKey
)
contentArray.set(md5Array, 103)
const cebArray = sm4.encrypt(contentArray, this.lockInfo.bluetooth.privateKey, {
mode: 'ecb',
output: 'array'
})
const packageArray = createPackageEnd(headArray, cebArray)
const writeResult = await writeBLECharacteristicValue(
this.lockInfo.deviceId,
this.lockInfo.serviceId,
this.lockInfo.writeCharacteristicId,
packageArray
)
if (writeResult.code !== Result.Success.code) {
return writeResult
}
return this.getWriteResult(this.customPassword, disconnect, password)
},
// 获取联网token
async getNetToken() {
const { code, data, message } = await getLockNetTokenRequest({
lockId: this.lockInfo.lockId
})
return new Result(code, data, message)
},
// 获取服务器时间
async getServerTimestamp() {
const { code, data, message } = await getServerDatetime({})
if (code === Result.Success.code) {
this.serverTimestamp = Math.ceil(data.date / 1000)
this.timeDifference = Math.ceil((data.date - new Date().getTime()) / 1000)
}
return new Result(code, data, message)
},
// 添加用户
async addLockUser(data, disconnect = false) {
// 确认设备连接正常
const searchResult = await searchAndConnectDevice(this.lockInfo.bluetooth.bluetoothDeviceName)
if (searchResult.code !== Result.Success.code) {
return searchResult
}
this.updateLockInfo(searchResult.data)
const {
name,
authUid,
uid,
keyId,
openMode,
keyType,
startDate,
expireDate,
useCountLimit,
isRound,
weekRound,
startHour,
startMin,
endHour,
endMin,
role,
password
} = 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 contentArray = new Uint8Array(length)
contentArray[0] = cmdIds.addUser / 256
contentArray[1] = cmdIds.addUser % 256
for (let i = 0; i < name.length; i++) {
contentArray[i + 2] = name.charCodeAt(i)
}
for (let i = 0; i < authUid.length; i++) {
contentArray[i + 42] = authUid.charCodeAt(i)
}
for (let i = 0; i < keyId.length; i++) {
contentArray[i + 62] = keyId.charCodeAt(i)
}
for (let i = 0; i < uid.length; i++) {
contentArray[i + 102] = uid.charCodeAt(i)
}
contentArray[122] = openMode
contentArray[123] = keyType
contentArray.set(timestampToArray(startDate), 124)
contentArray.set(timestampToArray(expireDate), 128)
contentArray[132] = useCountLimit / 256
contentArray[133] = useCountLimit % 256
contentArray[134] = isRound
contentArray[135] = weekRound
contentArray[136] = startHour
contentArray[137] = startMin
contentArray[138] = endHour
contentArray[139] = endMin
contentArray[140] = role
for (let i = 0; i < password.length; i++) {
contentArray[i + 141] = password.charCodeAt(i)
}
contentArray.set(this.lockInfo.token || timestampToArray(startDate), 161)
contentArray[165] = 16
const md5Array = md5Encrypt(
authUid + keyId,
this.lockInfo.token || timestampToArray(startDate),
this.lockInfo.bluetooth.publicKey
)
contentArray.set(md5Array, 166)
const cebArray = sm4.encrypt(contentArray, this.lockInfo.bluetooth.privateKey, {
mode: 'ecb',
output: 'array'
})
const packageArray = createPackageEnd(headArray, cebArray)
const writeResult = await writeBLECharacteristicValue(
this.lockInfo.deviceId,
this.lockInfo.serviceId,
this.lockInfo.writeCharacteristicId,
packageArray
)
if (writeResult.code !== Result.Success.code) {
return writeResult
}
return this.getWriteResult(this.addLockUser, disconnect, data)
},
// 获取写入结果
// eslint-disable-next-line default-param-last
getWriteResult(request, disconnect = false, params) {
return new Promise(resolve => {
const getWriteResultTimer = setTimeout(() => {
resolve(Result.Fail)
}, 20000)
characteristicValueCallback = async data => {
// code 6 token过期,重新获取
if (data.code === Result.NotTokenLock.code) {
resolve(await request(params))
} else if (data.code === Result.NotRegisteredLock.code) {
const checkResult = await this.checkLockUser(true)
if (checkResult.code === Result.Success.code) {
resolve(await request(params))
} else {
clearTimeout(getWriteResultTimer)
resolve(checkResult)
}
} else {
clearTimeout(getWriteResultTimer)
if (disconnect) {
await this.disconnectDevice()
}
console.log('写入结果', data, request, params)
resolve(data)
}
}
})
},
// 检查是否已添加为用户
async checkLockUser(forceAdd = false) {
if (this.lockInfo.lockUserNo === 0 || forceAdd) {
const timestamp = Math.floor(new Date().getTime() / 1000)
const password = (Math.floor(Math.random() * 900000) + 100000).toString()
console.log('用户未添加,开始添加用户')
const addUserParams = {
name: this.lockInfo.bluetooth.bluetoothDeviceName,
keyId: this.lockInfo.keyId.toString(),
authUid: this.lockInfo.uid.toString(),
uid: this.userInfo.uid.toString(),
openMode: 1,
keyType: 0,
startDate:
this.lockInfo.startDate === 0 ? timestamp : Math.floor(this.lockInfo.startDate / 1000),
expireDate:
this.lockInfo.endDate === 0 ? 0xffffffff : Math.floor(this.lockInfo.endDate / 1000),
useCountLimit: this.lockInfo.keyType === 3 ? 1 : 0xffff,
isRound: this.lockInfo.keyType === 4 ? 1 : 0,
weekRound:
this.lockInfo.keyType === 4 ? convertWeekdaysToNumber(this.lockInfo.weekDays) : 0,
startHour: this.lockInfo.keyType === 4 ? new Date(this.lockInfo.startDate).getHours() : 0,
startMin:
this.lockInfo.keyType === 4 ? new Date(this.lockInfo.startDate).getMinutes() : 0,
endHour: this.lockInfo.keyType === 4 ? new Date(this.lockInfo.endDate).getHours() : 0,
endMin: this.lockInfo.keyType === 4 ? new Date(this.lockInfo.endDate).getMinutes() : 0,
role: 0,
password
}
const addUserResult = await this.addLockUser(addUserParams)
console.log('添加用户蓝牙结果', addUserResult)
if (addUserResult.code === Result.Success.code) {
const { code } = await updateLockUserNoRequest({
keyId: this.lockInfo.keyId,
lockUserNo: this.lockInfo.lockUserNo
})
console.log('添加用户请求结果', code)
return Result.Success
}
if (addUserResult.code === Result.NotMoreKeyLock.code) {
console.log('用户达上限,开始清理用户')
const { code: cleanCode } = await this.cleanLockUser()
console.log('清理用户蓝牙结果', cleanCode)
if (cleanCode === Result.Success.code) {
return await this.checkLockUser()
}
return Result.Fail
}
if (addUserResult.code === Result.ReadyHasKeyLock.code) {
return Result.Success
}
return Result.Fail
}
return Result.Success
},
// 更新锁信息
updateLockInfo(lockInfo) {
this.lockInfo = {
...this.lockInfo,
...lockInfo
}
},
// 特征值变化回调
listenCharacteristicValue(res) {
if (res.deviceId === this.lockInfo.deviceId) {
let binaryData = new Uint8Array(res.value)
if (
binaryData[0] === 0xef &&
binaryData[1] === 0x01 &&
binaryData[2] === 0xee &&
binaryData[3] === 0x02
) {
length = binaryData[8] * 256 + binaryData[9]
if (length + 14 > binaryData.length) {
completeArray = binaryData
} else {
this.parsingCharacteristicValue(binaryData).then(() => {})
}
} else if (completeArray) {
const combinedArray = new Uint8Array(completeArray.length + binaryData.length)
combinedArray.set(completeArray, 0)
combinedArray.set(binaryData, completeArray.length)
completeArray = combinedArray
if (length + 14 === completeArray.length) {
this.parsingCharacteristicValue(completeArray).then(() => {})
completeArray = null
}
}
}
},
// 解析特征值
async parsingCharacteristicValue(binaryData) {
// 0x20 明文 0x22 SM4事先约定密钥 0x23 SM4设备指定密钥
if (binaryData[7] === 0x20) {
if (binaryData[12] * 256 + binaryData[13] === cmdIds.getPublicKey) {
if (binaryData[14] === Result.Success.code) {
this.updateLockInfo({
bluetooth: {
...this.lockInfo.bluetooth,
publicKey: [...binaryData.slice(15, 31)]
}
})
}
characteristicValueCallback(new Result(binaryData[14]))
}
} else if (binaryData[7] === 0x22) {
// 截取入参
const cebBinaryData = binaryData.slice(12, binaryData.length - 2)
// 解密
const key = new Uint8Array(16)
for (let i = 0; i < this.lockInfo.bluetooth.bluetoothDeviceName.length; i++) {
key[i] = this.lockInfo.bluetooth.bluetoothDeviceName.charCodeAt(i)
}
const decrypted = sm4.decrypt(cebBinaryData, key, {
mode: 'ecb',
output: 'array'
})
console.log('ecb解密后的数据', decrypted)
if (decrypted[0] * 256 + decrypted[1] === cmdIds.getCommKey) {
if (decrypted[2] === Result.Success.code) {
this.updateLockInfo({
bluetooth: {
...this.lockInfo.bluetooth,
privateKey: decrypted.slice(3, 19),
signKey: decrypted.slice(19, 35),
pwdTimestamp: arrayToTimestamp(decrypted.slice(35, 39)) * 1000
}
})
console.log('privateKey', Array.from(this.lockInfo.bluetooth.privateKey))
console.log('signKey', Array.from(this.lockInfo.signKey))
}
characteristicValueCallback(new Result(decrypted[2]))
}
} else {
const cebBinaryData = binaryData.slice(12, binaryData.length - 2)
const decrypted = sm4.decrypt(cebBinaryData, this.lockInfo.bluetooth.privateKey, {
mode: 'ecb',
output: 'array'
})
console.log('ecb解密后的数据', decrypted)
const cmdId = decrypted[0] * 256 + decrypted[1]
switch (cmdId) {
case cmdIds.getLockStatus:
if (decrypted[2] === Result.Success.code) {
const lockConfig = {
vendor: uint8ArrayToString(decrypted.slice(3, 23)),
product: decrypted[23],
model: uint8ArrayToString(decrypted.slice(24, 44)),
fwVersion: uint8ArrayToString(decrypted.slice(44, 64)),
hwVersion: uint8ArrayToString(decrypted.slice(64, 84)),
serialNum0: uint8ArrayToString(decrypted.slice(84, 100)),
serialNum1: uint8ArrayToString(decrypted.slice(100, 116)),
btDeviceName: uint8ArrayToString(decrypted.slice(116, 132)),
electricQuantity: decrypted[132],
electricQuantityStandby: decrypted[133],
restoreCount: decrypted[134] * 256 + decrypted[135],
restoreDate: arrayToTimestamp(decrypted.slice(136, 140)),
icPartNo: uint8ArrayToString(decrypted.slice(140, 150)),
indate: arrayToTimestamp(decrypted.slice(150, 154)),
mac: uint8ArrayToString(decrypted.slice(154, 174)),
timezoneOffset: new Date().getTimezoneOffset() * 60
}
this.updateLockInfo({
featureValue: uint8ArrayToString(decrypted.slice(175, 175 + decrypted[174])),
featureSettingValue: uint8ArrayToString(
decrypted.slice(
176 + decrypted[174],
176 + decrypted[174] + decrypted[175 + decrypted[174]]
)
),
featureSettingParams: Array.from(
decrypted.slice(176 + decrypted[174] + decrypted[175 + decrypted[174]])
),
lockConfig
})
console.log('获取锁状态成功', this.lockInfo.lockConfig)
}
characteristicValueCallback(new Result(decrypted[2]))
break
case cmdIds.addUser:
this.updateLockInfo({
token: decrypted.slice(42, 46)
})
if (decrypted[46] === Result.Success.code) {
this.updateLockInfo({
lockUserNo: decrypted[47] * 256 + decrypted[48]
})
}
console.log('添加用户结果', decrypted[46], this.lockInfo.token)
characteristicValueCallback(new Result(decrypted[46]))
break
case cmdIds.expandCmd:
const subCmdId = decrypted[3]
switch (subCmdId) {
case subCmdIds.resetLockPassword:
this.updateLockInfo({
token: decrypted.slice(5, 9)
})
characteristicValueCallback(new Result(decrypted[4]))
break
case subCmdIds.setLockPassword:
this.updateLockInfo({
token: decrypted.slice(5, 9)
})
if (decrypted[2] === Result.Success.code) {
if (decrypted[11] === Result.Success.code) {
const pwdNo = decrypted[9] * 256 + decrypted[10]
if (requestParams.operate === 0) {
const addResult = await addCustomPassword({
...requestParams,
pwdUserNo: pwdNo,
lockId: this.lockInfo.lockId
})
if (addResult.code === Result.Success.code) {
characteristicValueCallback(
new Result(addResult.code, {
pwdNo,
keyboardPwdId: addResult.data.keyboardPwdId,
keyboardPwd: addResult.data.keyboardPwd
})
)
} else {
characteristicValueCallback(
new Result(addResult.code, addResult.data, addResult.message)
)
}
} else if (requestParams.operate === 1) {
const updateResult = await updatePassword({
...requestParams,
keyboardPwdId: this.lockInfo.keyboardPwdId
})
if (updateResult.code === Result.Success.code) {
characteristicValueCallback(new Result(updateResult.code))
} else {
characteristicValueCallback(
new Result(updateResult.code, updateResult.data, updateResult.message)
)
}
}
} else {
characteristicValueCallback(new Result(decrypted[11]))
}
} else {
characteristicValueCallback(new Result(decrypted[2]))
}
break
default:
break
}
break
case cmdIds.openDoor:
this.updateLockInfo({
token: decrypted.slice(2, 6)
})
console.log('开门', decrypted[6], this.lockInfo.token)
characteristicValueCallback(new Result(decrypted[6]))
break
default:
this.updateLockInfo({
token: decrypted.slice(2, 6)
})
console.log('默认结果', decrypted[6], this.lockInfo.token)
characteristicValueCallback(new Result(decrypted[6]))
break
}
}
},
// 获取配置
getConfig() {
let config = configs[this.env]
return {
...config,
version,
buildNumber
}
},
/*
* 生成包头
* encryptionType 加密类型 0明文1AES1282SM4事先约定密钥3SM4设备指定密钥
* originalLength 原始数据长度
* */
createPackageHeader(encryptionType, originalLength) {
// 头部数据
let headArray = new Uint8Array(12)
// 固定包头
headArray[0] = 0xef
headArray[1] = 0x01
headArray[2] = 0xee
headArray[3] = 0x02
// 包类型 发送
headArray[4] = 0x01
// 包序号
headArray[5] = this.messageCount / 256
headArray[6] = this.messageCount % 256
this.messageCount++
// 包标识
if (encryptionType === 0) {
headArray[7] = 0x20
} else if (encryptionType === 2) {
headArray[7] = 0x22
} else {
headArray[7] = 0x23
}
// 数据长度
if (encryptionType === 0) {
headArray[8] = originalLength / 256
headArray[9] = originalLength % 256
} else {
const length = Math.ceil(originalLength / 16) * 16
headArray[8] = length / 256
headArray[9] = length % 256
}
headArray[10] = originalLength / 256
headArray[11] = originalLength % 256
return headArray
},
// 断开与设备的连接
async disconnectDevice() {
return await closeBLEConnection(this.lockInfo.deviceId)
}
}
})