1278 lines
49 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 {sm4} from 'sm-crypto'
import {
arrayToTimestamp,
convertWeekdaysToNumber,
createPackageEnd,
md5Encrypt,
removeTrailingZeros,
timestampToArray,
uint8ArrayToString
} from './format'
import {configs} from './env'
import {cmdIds, Result, subCmdIds} from './constant'
import {
closeBLEConnection,
searchAndConnectDevice,
writeBLECharacteristicValue
} from './uni/basic'
import {
addCustomPasswordRequest, addFaceRequest,
addFingerprintRequest,
addIcCardRequest,
changeAdminKeyboardPwdRequest, clearAllFace,
clearAllFingerprint,
clearAllIcCard,
deleteFaceRequest,
deleteFingerprintRequest,
deleteIcCardRequest,
deleteLockRequest,
deletePasswordRequest,
getLastRecordTimeRequest,
getLockNetTokenRequest,
getStarCloudToken,
getUserNoListRequest,
updateElectricQuantityRequest,
updateFaceRequest,
updateFingerprintRequest,
updateIcCardRequest,
updateLockUserNoRequest,
updatePasswordRequest,
uploadRecordRequest
} from './api'
import {
buildNumber,
emitRegisterCardConfirmEvent, emitRegisterFaceConfirmEvent, emitRegisterFaceProcessEvent,
emitRegisterFingerprintConfirmEvent, emitRegisterFingerprintProcessEvent,
getStorage,
setStorage,
version
} from './export'
import log from './log'
/**
* 同步开门记录
* @param params
* @param {Number} [params.uid] 用户ID
* @param {Boolean} [params.disconnect] 操作后是否断开连接, 默认断开
* @returns {Promise<Result>}
*/
export async function syncOpenRecord(params) {
// 设置执行账号
const result = await this.login(params.uid)
if (result.code !== Result.Success.code) {
return result
}
// 确认设备连接正常
if (!params.connected) {
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
}
const uid = this.lockInfo.uid.toString()
const keyId = this.lockInfo.keyId.toString()
const logsCount = 10
const timeResult = await getLastRecordTimeRequest({
lockId: this.lockInfo.lockId
})
if (timeResult.code !== Result.Success.code) {
return timeResult
}
const operateDate = Math.ceil(timeResult.data.operateDate / 1000)
const currentDate = Math.ceil(timeResult.data.currentDate / 1000)
const length = 2 + 1 + 1 + 40 + 20 + 2 + 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.syncOpenRecord
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] = logsCount / 256
contentArray[65] = logsCount % 256
contentArray.set(timestampToArray(operateDate), 66)
contentArray.set(timestampToArray(currentDate), 70)
contentArray[74] = 16
const md5Array = md5Encrypt(
uid + keyId,
this.lockInfo.token || new Uint8Array([0, 0, 0, 0]),
this.lockInfo.bluetooth.publicKey
)
contentArray.set(md5Array, 75)
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.syncOpenRecord, params)
}
/**
* 清理用户
* @returns {Promise<Result>}
*/
export async function cleanLockUser() {
// 确认设备连接正常
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: false})
}
/**
* 登录星云
* @param {Number} [uid] 用户ID
* @returns Result
*/
export async function login(uid) {
let accounts = getStorage('starCloudAccount')
let userInfos = getStorage('starCloudUser')
if (!accounts) {
accounts = {}
}
if (!userInfos) {
userInfos = {}
}
const id = uid || this.accounts[0].uid
this.accountInfo = accounts[id]
if (this.accountInfo) {
if (this.accountInfo.token) {
this.userInfo = userInfos[id]
setStorage('starCloudToken', this.accountInfo.token)
return Result.Success
}
const {
code,
data: userInfo,
message
} = await getStarCloudToken({
username: this.accountInfo.username,
password: this.accountInfo.password,
clientId: this.clientId,
clientSecret: this.clientSecret
})
if (code === Result.Success.code) {
this.userInfo = userInfo
this.accountInfo = {
username: this.accountInfo.username,
password: this.accountInfo.password,
token: userInfo.access_token,
uid: userInfo.uid
}
setStorage('starCloudToken', userInfo.access_token)
accounts[userInfo.uid] = {
uid: userInfo.uid,
username: this.accountInfo.username,
password: this.accountInfo.password,
token: userInfo.access_token
}
setStorage('starCloudAccount', accounts)
userInfos[userInfo.uid] = userInfo
setStorage('starCloudUser', userInfos)
}
return new Result(code, {}, message)
}
return Result.Fail
}
// 获取公钥
export async function getPublicKey() {
const headArray = this.createPackageHeader(0, 42)
const contentArray = new Uint8Array(42)
contentArray[0] = cmdIds.getPublicKey / 256
contentArray[1] = cmdIds.getPublicKey % 256
const name = this.lockInfo.bluetooth.bluetoothDeviceName
for (let i = 0; i < name.length; i++) {
contentArray[i + 2] = name.charCodeAt(i)
}
const packageArray = createPackageEnd(headArray, contentArray)
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.getPublicKey, {disconnect: false})
}
// 获取私钥
export async function getCommKey() {
const length = 2 + 40 + 40 + 20 + 4 + 1 + 16
const headArray = this.createPackageHeader(2, length)
const contentArray = new Uint8Array(length)
contentArray[0] = cmdIds.getCommKey / 256
contentArray[1] = cmdIds.getCommKey % 256
const name = this.lockInfo.bluetooth.bluetoothDeviceName
const keyId = '0'
const authUid = this.accountInfo.uid.toString()
await this.getServerTimestamp()
const nowTime = this.serverTimestamp
for (let i = 0; i < name.length; i++) {
contentArray[i + 2] = name.charCodeAt(i)
}
for (let i = 0; i < keyId.length; i++) {
contentArray[i + 42] = keyId.charCodeAt(i)
}
for (let i = 0; i < authUid.length; i++) {
contentArray[i + 82] = authUid.charCodeAt(i)
}
contentArray.set(timestampToArray(nowTime), 102)
contentArray[106] = 16
const md5Array = md5Encrypt(
authUid + keyId,
contentArray.slice(102, 106),
this.lockInfo.bluetooth.publicKey
)
contentArray.set(md5Array, 107)
const cebArray = sm4.encrypt(contentArray, contentArray.slice(2, 18), {
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.getCommKey, {disconnect: false})
}
// 获取锁状态
export async function getLockStatus() {
const length = 2 + 40 + 20 + 4 + 4
const headArray = this.createPackageHeader(3, length)
const contentArray = new Uint8Array(length)
contentArray[0] = cmdIds.getLockStatus / 256
contentArray[1] = cmdIds.getLockStatus % 256
const name = this.lockInfo.bluetooth.bluetoothDeviceName
const uid = this.accountInfo.uid.toString()
await this.getServerTimestamp()
const nowTime = this.serverTimestamp
const date = new Date()
const localTime = this.serverTimestamp - date.getTimezoneOffset() * 60
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.set(timestampToArray(nowTime), 62)
contentArray.set(timestampToArray(localTime), 66)
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.getLockStatus, {disconnect: false})
}
// 获取联网token
export async function getNetToken() {
const {code, data, message} = await getLockNetTokenRequest({
lockId: this.lockInfo.lockId
})
return new Result(code, data, message)
}
// 添加用户
export async function addLockUser(params) {
const {params: data} = params
// 确认设备连接正常
if (!params.connected) {
const searchResult = await searchAndConnectDevice(
this.lockInfo.bluetooth.bluetoothDeviceName,
data.role !== 0xff
)
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, params)
}
// 获取写入结果
export function getWriteResult(request, params) {
return new Promise(resolve => {
const getWriteResultTimer = setTimeout(() => {
resolve(Result.Fail)
}, 20000)
this.characteristicValueCallback = async data => {
// code 6 token过期,重新获取
if (data.code === Result.NotTokenLock.code) {
log.info({
...new Result(
data.code,
{
lockName: this.lockInfo.bluetooth.bluetoothDeviceName,
lockId: this.lockInfo.lockId,
time: new Date().getTime()
},
`token过期${data.message}`
),
name: 'openDoor'
})
resolve(await request.call(this, {...params, connected: true}))
} else if (data.code === Result.NotRegisteredLock.code) {
const checkResult = await this.checkLockUser(true)
if (checkResult.code === Result.Success.code) {
resolve(await request.call(this, {...params, connected: true}))
} else {
clearTimeout(getWriteResultTimer)
resolve(checkResult)
}
} else {
clearTimeout(getWriteResultTimer)
if (params.disconnect !== false) {
await this.disconnectDevice()
}
console.log('写入结果', data, request, params)
log.info({
...new Result(
data.code,
{
lockName: this.lockInfo.bluetooth.bluetoothDeviceName,
lockId: this.lockInfo.lockId,
time: new Date().getTime()
},
`开门结果:${data.message}`
),
name: 'openDoor'
})
resolve(data)
}
}
})
}
// 检查是否已添加为用户
export async function 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.accountInfo.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({
params: addUserParams,
disconnect: false
})
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
}
// 更新锁信息
export function updateLockInfo(lockInfo) {
this.lockInfo = {
...this.lockInfo,
...lockInfo
}
const lockList = getStorage('starLockList')
if (lockList[this.accountInfo.uid]) {
const index = lockList[this.accountInfo.uid].findIndex(
item => item.lockId === this.lockInfo.lockId
)
if (index !== -1) {
lockList[this.accountInfo.uid][index] = this.lockInfo
}
setStorage('starLockList', lockList)
}
}
// 特征值变化回调
export function 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
) {
this.length = binaryData[8] * 256 + binaryData[9]
if (this.length + 14 > binaryData.length) {
this.completeArray = binaryData
} else {
this.parsingCharacteristicValue(binaryData).then(() => {
})
}
} else if (this.completeArray) {
const combinedArray = new Uint8Array(this.completeArray.length + binaryData.length)
combinedArray.set(this.completeArray, 0)
combinedArray.set(binaryData, this.completeArray.length)
this.completeArray = combinedArray
if (this.length + 14 === this.completeArray.length) {
this.parsingCharacteristicValue(this.completeArray).then(() => {
})
this.completeArray = null
}
}
}
}
// 解析特征值
export async function 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)]
}
})
}
this.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.bluetooth.signKey))
}
this.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',
padding: 'none'
})
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: removeTrailingZeros(Array.from(
decrypted.slice(176 + decrypted[174] + decrypted[175 + decrypted[174]])
)),
lockConfig
})
console.log('获取锁状态成功', this.lockInfo.lockConfig)
}
this.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.lockUserNo)
this.characteristicValueCallback(new Result(decrypted[46]))
break
case cmdIds.expandCmd:
const subCmdId = decrypted[3]
switch (subCmdId) {
case subCmdIds.updateAdminPassword:
this.updateLockInfo({
token: decrypted.slice(5, 9)
})
if (decrypted[2] === Result.Success.code) {
const result = await changeAdminKeyboardPwdRequest({
password: this.requestParams.adminPwd,
lockId: this.lockInfo.lockId
})
return this.characteristicValueCallback(new Result(result.code))
}
this.characteristicValueCallback(new Result(decrypted[2]))
break
case subCmdIds.resetLockPassword:
this.updateLockInfo({
token: decrypted.slice(5, 9)
})
this.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 (this.requestParams.operate === 0) {
const addResult = await addCustomPasswordRequest({
...this.requestParams,
pwdUserNo: pwdNo,
lockId: this.lockInfo.lockId
})
if (addResult.code === Result.Success.code) {
this.characteristicValueCallback(
new Result(addResult.code, {
pwdNo,
keyboardPwdId: addResult.data.keyboardPwdId,
keyboardPwd: addResult.data.keyboardPwd,
keyboardPwdStatus: addResult.data.keyboardPwdStatus,
pwdUserNo: pwdNo
})
)
} else {
this.characteristicValueCallback(
new Result(addResult.code, addResult.data, addResult.message)
)
}
} else if (this.requestParams.operate === 1) {
const updateResult = await updatePasswordRequest(this.requestParams)
if (updateResult.code === Result.Success.code) {
this.characteristicValueCallback(new Result(updateResult.code))
} else {
this.characteristicValueCallback(
new Result(updateResult.code, updateResult.data, updateResult.message)
)
}
} else if (this.requestParams.operate === 3) {
const deleteResult = await deletePasswordRequest(this.requestParams)
if (deleteResult.code === Result.Success.code) {
this.characteristicValueCallback(new Result(deleteResult.code))
} else {
this.characteristicValueCallback(
new Result(deleteResult.code, deleteResult.data, deleteResult.message)
)
}
}
} else {
this.characteristicValueCallback(new Result(decrypted[11]))
}
} else {
this.characteristicValueCallback(new Result(decrypted[2]))
}
break
case subCmdIds.syncOpenRecord:
if (decrypted[2] === Result.Success.code && decrypted[6] > 0) {
const records = []
const count = decrypted[6] || 0
for (let i = 0; i < count; i++) {
let password = decrypted.slice(14 + 17 * i, 14 + 17 * i + 10)
if (password.every(item => item === 0)) {
password = null
} else {
password = uint8ArrayToString(password)
}
const record = {
type: decrypted[7 + 17 * i],
user: decrypted[8 + 17 * i] * 256 + decrypted[9 + 17 * i],
date: arrayToTimestamp(decrypted.slice(10 + 17 * i, 14 + 17 * i)) * 1000,
success: 1,
password
}
records.push(record)
}
const {code, message} = await uploadRecordRequest({
records,
lockId: this.lockInfo.lockId
})
this.characteristicValueCallback(
new Result(
code,
{
count
},
message
)
)
} else {
this.characteristicValueCallback(new Result(decrypted[2]))
}
break
case subCmdIds.registerCard:
if (decrypted[2] === Result.Success.code) {
// 锁版应答成功
switch (this.requestParams.operate) {
case 1:
// 修改
const updateResult = await updateIcCardRequest({
...this.requestParams,
cardId: this.requestParams.cardId,
cardRight: this.requestParams.isAdmin,
lockId: this.lockInfo.lockId,
cardNumber: this.requestParams.cardNo,
cardType: this.requestParams.cardType,
cardUserNo: this.requestParams.cardUserNo
})
this.characteristicValueCallback(updateResult)
await this.disconnectDevice()
break;
case 2:
// 删除
const deleteResult = await deleteIcCardRequest({
cardId: this.requestParams.cardId,
lockId: this.lockInfo.lockId,
})
this.characteristicValueCallback(deleteResult)
await this.disconnectDevice()
break;
case 3:
// 删除全部
const deleteAllResult = await clearAllIcCard({
lockId: this.lockInfo.lockId,
})
this.characteristicValueCallback(deleteAllResult)
await this.disconnectDevice()
break;
default:
this.characteristicValueCallback(new Result(decrypted[2]))
break;
}
}
break;
case subCmdIds.registerCardConfirm:
// 收到锁版回复判断操作类型进行对应api操作
if (decrypted[2] === Result.Success.code) {
switch (this.requestParams.operate) {
case 0:
// 注册
const addResult = await addIcCardRequest({
...this.requestParams,
isCoerced: this.requestParams.isForce,
cardRight: this.requestParams.isAdmin,
lockId: this.lockInfo.lockId,
cardNumber: this.requestParams.cardNo,
cardUserNo: this.requestParams.cardUserNo
})
if (addResult.code === Result.Success.code) {
// 增加返回一个卡序号
addResult.data.cardNo = decrypted[6] * 256 + decrypted[7];
}
// 触发卡片确认事件
emitRegisterCardConfirmEvent(addResult)
// 断开蓝牙连接
await this.disconnectDevice()
break;
}
}
break;
case subCmdIds.registerFingerprint:
if (decrypted[2] === Result.Success.code) {
// 锁版应答成功
switch (this.requestParams.operate) {
case 0:
// 注册开始返回最大注册次数
this.characteristicValueCallback(new Result(Result.Success.code, {
maxRegCount: decrypted[11],
}, Result.Success.message))
await this.disconnectDevice()
break;
case 1:
// 修改
const updateResult = await updateFingerprintRequest({
...this.requestParams,
fingerprintId: this.requestParams.fingerprintId,
fingerRight: this.requestParams.isAdmin
})
this.characteristicValueCallback(updateResult)
await this.disconnectDevice()
break;
case 2:
// 删除
const deleteResult = await deleteFingerprintRequest({
fingerprintId: this.requestParams.fingerprintId,
lockId: this.lockInfo.lockId,
})
this.characteristicValueCallback(deleteResult)
await this.disconnectDevice()
break;
case 3:
// 删除全部
const deleteAllResult = await clearAllFingerprint({
lockId: this.lockInfo.lockId,
})
this.characteristicValueCallback(deleteAllResult)
await this.disconnectDevice()
break;
default:
this.characteristicValueCallback(new Result(decrypted[2]))
break;
}
}
break;
case subCmdIds.registerFingerprintProcess:
emitRegisterFingerprintProcessEvent({
status: decrypted[5],
process: decrypted[6]
})
break;
case subCmdIds.registerFingerprintConfirm:
if (this.requestParams.operate === 0) {
const addResult = await addFingerprintRequest({
...this.requestParams,
isCoerced: this.requestParams.isForce,
fingerRight: this.requestParams.isAdmin,
lockId: this.lockInfo.lockId,
fingerprintNumber: this.requestParams.no || this.requestParams.fingerprintNumber,
fingerprintUserNo: this.requestParams.fingerprintUserNo
})
if (addResult.code === Result.Success.code) {
// 增加返回一个指纹序号
addResult.data.fingerprintNumber = decrypted[9] * 256 + decrypted[10];
}
// 触发指纹确认事件
emitRegisterFingerprintConfirmEvent(addResult)
// 断开蓝牙连接
await this.disconnectDevice()
}
break;
case subCmdIds.registerFace:
if (decrypted[2] === Result.Success.code) {
// 锁版应答成功
switch (this.requestParams.operate) {
case 0:
// 注册开始返回最大注册次数
this.characteristicValueCallback(new Result(Result.Success.code, {
maxRegCount: decrypted[11],
}, Result.Success.message))
await this.disconnectDevice()
break;
case 1:
// 修改
const updateResult = await updateFaceRequest({
...this.requestParams,
faceId: this.requestParams.faceId,
faceRight: this.requestParams.isAdmin
})
this.characteristicValueCallback(updateResult)
await this.disconnectDevice()
break;
case 2:
// 删除
const deleteResult = await deleteFaceRequest({
faceId: this.requestParams.faceId,
lockId: this.lockInfo.lockId,
})
this.characteristicValueCallback(deleteResult)
await this.disconnectDevice()
break;
case 3:
// 删除全部
const deleteAllResult = await clearAllFace({
lockId: this.lockInfo.lockId,
})
this.characteristicValueCallback(deleteAllResult)
await this.disconnectDevice()
break;
default:
this.characteristicValueCallback(new Result(decrypted[2]))
break;
}
}
break;
case subCmdIds.registerFaceProcess:
emitRegisterFaceProcessEvent({
status: decrypted[5],
process: decrypted[6]
})
break;
case subCmdIds.registerFaceConfirm:
if (this.requestParams.operate === 0) {
const addResult = await addFaceRequest({
...this.requestParams,
isCoerced: this.requestParams.isForce,
fingerRight: this.requestParams.isAdmin,
lockId: this.lockInfo.lockId,
faceNumber: this.requestParams.no || this.requestParams.faceNumber,
faceUserNo: this.requestParams.faceUserNo
})
if (addResult.code === Result.Success.code) {
// 增加返回一个序号
addResult.data.faceNumber = decrypted[9] * 256 + decrypted[10];
}
// 触发事件
emitRegisterFaceConfirmEvent(addResult)
// 断开蓝牙连接
await this.disconnectDevice()
}
break;
default:
break
}
break
case cmdIds.openDoor:
this.updateLockInfo({
token: decrypted.slice(2, 6),
electricQuantity: decrypted[7],
electricQuantityStandby: decrypted[9]
})
if (decrypted[6] === Result.Success.code) {
updateElectricQuantityRequest({
lockId: this.lockInfo.lockId,
electricQuantity: decrypted[7],
electricQuantityStandby: decrypted[9]
}).then(() => {
})
}
this.characteristicValueCallback(new Result(decrypted[6], {lock: this.lockInfo}))
break
case cmdIds.resetDevice:
this.updateLockInfo({
token: decrypted.slice(2, 6)
})
if (decrypted[6] === Result.Success.code) {
const {code, message} = await deleteLockRequest({
lockId: this.lockInfo.lockId
})
if (code === Result.Success.code) {
const lockList = getStorage('starLockList')
if (lockList[this.accountInfo.uid]) {
const index = lockList[this.accountInfo.uid].findIndex(
item => item.lockId === this.lockInfo.lockId
)
if (index !== -1) {
lockList[this.accountInfo.uid].splice(index, 1)
}
setStorage('starLockList', lockList)
}
}
this.characteristicValueCallback(new Result(code, {}, message))
} else {
this.characteristicValueCallback(new Result(decrypted[6]))
}
break
default:
this.updateLockInfo({
token: decrypted.slice(2, 6)
})
console.log('默认结果', decrypted[6], this.lockInfo.token)
this.characteristicValueCallback(new Result(decrypted[6]))
break
}
}
}
// 获取配置
export function getConfig() {
const config = this.env === "LOCAL" ? {
name: 'LOCAL',
baseUrl: this.clientUrl
} : configs[this.env];
return {
...config,
version,
buildNumber
}
}
/*
* 生成包头
* encryptionType 加密类型 0明文1AES1282SM4事先约定密钥3SM4设备指定密钥
* originalLength 原始数据长度
* */
export function 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
}
// 断开与设备的连接
export async function disconnectDevice() {
return await closeBLEConnection(this.lockInfo.deviceId)
}