296 lines
8.4 KiB
JavaScript
Raw Normal View History

2024-12-19 16:01:45 +08:00
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
2024-12-20 17:36:14 +08:00
* @param {Number} [params.uid] 用户ID
2024-12-19 16:01:45 +08:00
* @param {OfflinePassword} params.password 密码信息
* @returns {Promise<Result>}
*/
export async function getOfflinePassword(params) {
2024-12-20 17:36:14 +08:00
const { password } = params
2024-12-19 16:01:45 +08:00
// 设置执行账号
2024-12-20 17:36:14 +08:00
const result = await this.login(params.uid)
2024-12-19 16:01:45 +08:00
if (result.code !== Result.Success.code) {
return result
}
return await getOfflinePasswordRequest(password)
}
/**
* 自定义密码
* @param params
2024-12-20 17:36:14 +08:00
* @param {Number} [params.uid] 用户ID
2024-12-19 16:01:45 +08:00
* @param {CustomPassword} params.password 密码信息
2024-12-20 17:36:14 +08:00
* @param {Boolean} [params.disconnect] 操作后是否断开连接默认断开
2024-12-19 16:01:45 +08:00
* @returns {Promise<Result>}
*/
export async function customPassword(params) {
2024-12-20 17:36:14 +08:00
const { password } = params
2024-12-19 16:01:45 +08:00
// 设置执行账号
2024-12-20 17:36:14 +08:00
const result = await this.login(params.uid)
2024-12-19 16:01:45 +08:00
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
2024-12-20 17:36:14 +08:00
* @param {Number} [params.uid] 用户ID
2024-12-19 16:01:45 +08:00
* @param {String} params.adminPwd 管理员密码
2024-12-20 17:36:14 +08:00
* @param {Boolean} [params.disconnect] 操作后是否断开连接默认断开
2024-12-19 16:01:45 +08:00
* @returns {Promise<Result>}
*/
export async function updateAdminPassword(params) {
2024-12-20 17:36:14 +08:00
const { adminPwd } = params
2024-12-19 16:01:45 +08:00
// 设置执行账号
2024-12-20 17:36:14 +08:00
const result = await this.login(params.uid)
2024-12-19 16:01:45 +08:00
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)
}