2024-12-20 17:36:14 +08:00

296 lines
8.4 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 { cmdIds, Result, subCmdIds } from '../constant'
import { searchAndConnectDevice, writeBLECharacteristicValue } from '../uni/basic'
import { createPackageEnd, md5Encrypt, timestampToArray } from '../format'
import { checkPasswordRequest, getOfflinePasswordRequest } from '../api'
/**
* 离线密码
* 该功能无需蓝牙交互直接请求服务端,详细参数说明请看星云接口文档
* @typedef {Object} OfflinePassword
* @property {String} keyboardPwdName - 密码名称
* @property {Number} keyboardPwdType - 密码类型
* @property {Number} lockId - 锁 Id
* @property {Number} isCoerced - 胁迫 1:胁迫 2:非胁迫
* @property {Number} startDate - 开始时间
* @property {Number} endDate - 结束时间
* @property {Number} hoursStart - 开始小时
* @property {Number} hoursEnd - 结束小时
*/
/**
* 自定义密码
* @typedef {Object} CustomPassword
* @property {String} keyboardPwdName - 密码名称
* @property {Number} keyboardPwdType - 密码类型
* @property {Number} isCoerced - 胁迫 1:胁迫 2:非胁迫
* @property {Number} startDate - 开始时间
* @property {Number} endDate - 结束时间
* @property {Number} keyboardPwd - 密码
* @property {Number} addType - 添加方式当前仅支持1 1:蓝牙 2:网关
* @property {Number} operate - 操作类型0:注册 1修改
* @property {Number} pwdRight - 是否是管理员密码0:否 1:是
* @property {Number} keyboardPwdId - 密码ID
*/
/**
* 获取离线密码
* @param params
* @param {Number} [params.uid] 用户ID
* @param {OfflinePassword} params.password 密码信息
* @returns {Promise<Result>}
*/
export async function getOfflinePassword(params) {
const { password } = params
// 设置执行账号
const result = await this.login(params.uid)
if (result.code !== Result.Success.code) {
return result
}
return await getOfflinePasswordRequest(password)
}
/**
* 自定义密码
* @param params
* @param {Number} [params.uid] 用户ID
* @param {CustomPassword} params.password 密码信息
* @param {Boolean} [params.disconnect] 操作后是否断开连接,默认断开
* @returns {Promise<Result>}
*/
export async function customPassword(params) {
const { password } = params
// 设置执行账号
const result = await this.login(params.uid)
if (result.code !== Result.Success.code) {
return result
}
this.requestParams = password
let { pwdNo, operate, keyboardPwd, startDate, endDate, pwdRight } = password
if (operate === 0 || operate === 1) {
const checkPasswordParams = {
lockId: this.lockInfo.lockId,
keyboardPwd
}
if (password.keyboardPwdId) {
checkPasswordParams.keyboardPwdId = password.keyboardPwdId
}
const checkPasswordResult = await this.checkPassword(checkPasswordParams)
if (checkPasswordResult.code === -3) {
return Result.ReadyHasPassword
}
if (checkPasswordResult.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.accountInfo.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, params)
}
/**
* 修改管理员密码
* @param params
* @param {Number} [params.uid] 用户ID
* @param {String} params.adminPwd 管理员密码
* @param {Boolean} [params.disconnect] 操作后是否断开连接,默认断开
* @returns {Promise<Result>}
*/
export async function updateAdminPassword(params) {
const { adminPwd } = 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
}
this.requestParams = params
const uid = this.lockInfo.uid.toString()
const keyId = this.lockInfo.keyId.toString()
const pwdNo = 1
const userCountLimit = 0xff
const startDate = Math.floor(this.lockInfo.startDate / 1000)
const endDate = Math.floor(this.lockInfo.endDate / 1000)
const length = 2 + 1 + 1 + 40 + 20 + 2 + 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.updateAdminPassword
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
for (let i = 0; i < adminPwd.length; i++) {
contentArray[i + 66] = adminPwd.charCodeAt(i)
}
contentArray[86] = userCountLimit / 256
contentArray[87] = userCountLimit % 256
contentArray.set(this.lockInfo.token || new Uint8Array([0, 0, 0, 0]), 88)
contentArray.set(timestampToArray(startDate), 92)
contentArray.set(timestampToArray(endDate), 96)
contentArray[100] = 16
const md5Array = md5Encrypt(
keyId + uid,
this.lockInfo.token || new Uint8Array([0, 0, 0, 0]),
this.lockInfo.bluetooth.signKey
)
contentArray.set(md5Array, 101)
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.updateAdminPassword, params)
}
// 检查密码名称与密码是否已存在
export async function checkPassword(params) {
return await checkPasswordRequest(params)
}