starcloud-sdk-uniapp/star-cloud/generalExtend.js

411 lines
15 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 {searchAndConnectDevice, writeBLECharacteristicValue} from "../uni/basic.js";
import {cmdIds, Result, subCmdIds} from '../constant'
import {convertWeekdaysToNumber, createPackageEnd, md5Encrypt, parseTimeToList, timestampToArray} from "../format.js";
import {sm4} from "sm-crypto";
import {
checkRepeatCardName, checkRepeatFaceName, checkRepeatFingerprintName,
clearAllIcCard,
deleteIcCardRequest, getFingerprintListRequest,
getIcCardListRequest,
updateIcCardRequest
} from "../api.js";
/**
* 检查并返回具体哪个参数为空
* @param {Object} params - 参数对象
* @param {Array<string>} requiredFields - 必填字段列表
* @returns {string | null} - 如果有字段为空则返回错误消息否则返回null
*/
function _checkRequiredFields(params, requiredFields) {
for (let field of requiredFields) {
if (!params[field]) {
return `${field} 不能为空`;
}
}
return null;
}
/**
* 注册扩展产品(卡片、指纹等)
*
* @param {Object} params - 所需参数
* @param {string} params.type - 产品类型,['card','fingerprint','face']
* @param {string} params.keyId - 钥匙 ID
* @param {string} params.uid - 用户 ID
* @param {number} params.userCountLimit - 使用次数限制整型0xFFFF 表示不限次数
* @param {number} params.operate - 操作类型整型0: 注册, 1: 修改, 2: 删除, 3: 删除全部
* @param {number} params.isAdmin - 是否管理员整型1 表示是0 表示否
* @param {number} params.isForce - 是否胁迫整型1 表示是0 表示否
* @param {number} params.isRound - 是否循环整型1 表示是0 表示否
* @param {array} params.weekDays - 循环周期数组Bit0 -- 6 置位分别代表周日 -- 周六,例如:循环星期一、星期二、星期四,对应为:[124]
* @param {number} params.startDate - 生效日期时间戳永久则填0
* @param {number} params.endDate - 失效日期时间戳永久则填0
* @param {string} params.startTime - 生效时间,字符串,例如:'00:00'
* @param {string} params.endTime - 失效时间,字符串,例如:'00:00'
* @param {number} params.cardId - 卡片Id仅当 type 为 'card' 且operate=1 时需要
* @param {number} params.cardNo - 卡片序号,仅当 type 为 'card' 时需要
* @param {string} params.cardName - 卡片名称,仅当 type 为 'card' 时需要
* @param {number} params.cardType - 卡片类型1:永久2期限4:循环,仅当 type 为 'card' 时需要
* @param {number} params.cardUserNo - 卡UserNo仅当 type 为 'card' 时需要 (选填)
* @param {number} params.fingerprintName - 指纹名,仅当 type 为 'fingerprint' 时需要
* @param {string} params.fingerprintNumber - 指纹序号,仅当 type 为 'fingerprint' 时需要
* @param {number} params.fingerprintType - 指纹类型1:永久2期限3单次4:循环,仅当 type 为 'fingerprint' 时需要
* @param {number} params.fingerprintUserNo - 指纹UserNo仅当 type 为 'fingerprint' 时需要 (选填)
* @param {number} params.faceName - 人脸名,仅当 type 为 'face' 时需要
* @param {string} params.faceNumber - 指纹序号,仅当 type 为 'face' 时需要
* @param {number} params.faceType - 指纹类型1:永久2期限4:循环,仅当 type 为 'face' 时需要
* @param {number} params.faceUserNo - 指纹UserNo仅当 type 为 'face' 时需要 (选填)
* @returns {Promise<Result>} - 返回注册结果的 Promise 对象
*/
export async function registerExtendedProducts(params) {
// 确认产品类型存在
if (!params.type) {
return new Result(Result.NotMoreData, null, '注册扩展产品类型type不能为空');
}
// 如果是卡片的话需要增加的参数
if (params.type === 'card') {
// 注册卡片时的参数校验
if (params.operate === 0) {
const cardRequiredFields = ['cardName', 'cardType', 'cardNo'];
const missingField = _checkRequiredFields(params, cardRequiredFields);
if (missingField) {
return new Result(Result.NotMoreData, null, `卡片信息不完整: ${missingField}`);
}
// 检查卡昵称是否重复
const checkRepeatCardNameResult = await checkRepeatCardName({
lockId: this.lockInfo.lockId,
cardName: params.cardName
})
if (checkRepeatCardNameResult.code !== Result.Success.code) {
return checkRepeatCardNameResult
}
}
// 修改卡片时的参数校验
if (params.operate === 1 || params.operate === 2) {
let cardRequiredFields = ['cardId'];
if (params.operate === 1) {
cardRequiredFields.push('cardType')
}
if (params.operate === 2) {
cardRequiredFields.push('cardNo')
}
const missingField = _checkRequiredFields(params, cardRequiredFields);
if (missingField) {
return new Result(Result.NotMoreData, null, `卡片信息不完整: ${missingField}`);
}
}
}
// 如果是指纹的话需要增加的参数
if (params.type === 'fingerprint') {
if (params.operate === 0) {
const cardRequiredFields = ['fingerprintName', 'fingerprintNumber', 'fingerprintType'];
const missingField = _checkRequiredFields(params, cardRequiredFields);
if (missingField) {
return new Result(Result.NotMoreData, null, `指纹信息不完整: ${missingField}`);
}
// 检查卡昵称是否重复
const checkRepeatFingerprintNameResult = await checkRepeatFingerprintName({
lockId: this.lockInfo.lockId,
fingerprintName: params.fingerprintName
})
if (checkRepeatFingerprintNameResult.code !== Result.Success.code) {
return checkRepeatFingerprintNameResult
}
}
// 修改指纹时的参数校验
if (params.operate === 1 || params.operate === 2) {
let cardRequiredFields = ['fingerprintId'];
if (params.operate === 1) {
cardRequiredFields.push('fingerprintType')
}
if (params.operate === 2) {
cardRequiredFields.push('fingerprintNumber')
}
const missingField = _checkRequiredFields(params, cardRequiredFields);
if (missingField) {
return new Result(Result.NotMoreData, null, `指纹信息不完整: ${missingField}`);
}
}
}
// 如果是人脸的话需要增加的参数
if (params.type === 'face') {
if (params.operate === 0) {
const cardRequiredFields = ['faceName', 'faceNumber', 'faceType'];
const missingField = _checkRequiredFields(params, cardRequiredFields);
if (missingField) {
return new Result(Result.NotMoreData, null, `人脸信息不完整: ${missingField}`);
}
// 检查卡昵称是否重复
const checkRepeatFaceNameResult = await checkRepeatFaceName({
lockId: this.lockInfo.lockId,
faceName: params.faceName
})
if (checkRepeatFaceNameResult.code !== Result.Success.code) {
return checkRepeatFaceNameResult
}
}
// 修改指纹时的参数校验
if (params.operate === 1 || params.operate === 2) {
let cardRequiredFields = ['faceId'];
if (params.operate === 1) {
cardRequiredFields.push('faceType')
}
if (params.operate === 2) {
cardRequiredFields.push('faceNumber')
}
const missingField = _checkRequiredFields(params, cardRequiredFields);
if (missingField) {
return new Result(Result.NotMoreData, null, `人脸信息不完整: ${missingField}`);
}
}
}
// 添加类型1蓝牙2远程3发卡器
params.addType = 1;
// 操作后不断开蓝牙
params.disconnect = false;
let {
type,
keyId,
uid,
cardNo,
operate,
isAdmin,
userCountLimit,
isForce,
isRound,
weekDays,
startDate,
endDate,
startTime,
endTime,
} = params
// 设置执行账号
const result = await this.login(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) {
return {
code: -1
}
}
this.requestParams = params
startDate = Math.floor(startDate / 1000)
endDate = Math.floor(endDate / 1000)
const length = 2 + 1 + 1 + 40 + 20 + 2 + 2 + 1 + 1 + 1 + 4 + 1 + 1 + 4 + 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
// 子命令
if (type === 'card') {
contentArray[2] = subCmdIds.registerCard
} else if (type === 'fingerprint') {
contentArray[2] = subCmdIds.registerFingerprint
} else if (type === 'face') {
contentArray[2] = subCmdIds.registerFace
} else if (type === 'remote') {
contentArray[2] = subCmdIds.registerRemote
} else if (type === 'palmVein') {
contentArray[2] = subCmdIds.registerPalmVein
}
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] = (cardNo || 0) / 256
contentArray[65] = (cardNo || 0) % 256
contentArray[66] = (userCountLimit || 0xffff) / 256
contentArray[67] = (userCountLimit || 0xffff) % 256
contentArray[68] = operate
contentArray[69] = isAdmin || 0
contentArray[70] = isForce || 0
contentArray.set(this.lockInfo.token || new Uint8Array([0, 0, 0, 0]), 71)
contentArray[75] = isRound
contentArray[76] = convertWeekdaysToNumber(weekDays)
contentArray.set(timestampToArray(startDate), 77)
contentArray.set(timestampToArray(endDate), 81)
if (isRound) {
contentArray.set(parseTimeToList(startTime), 85)
contentArray.set(parseTimeToList(endTime), 89)
} else {
contentArray.set(new Uint8Array([0, 0, 0, 0]), 85)
contentArray.set(new Uint8Array([0, 0, 0, 0]), 89)
}
contentArray[93] = 16
const md5Array = md5Encrypt(
keyId + uid,
this.lockInfo.token || new Uint8Array([0, 0, 0, 0]),
this.lockInfo.bluetooth.signKey
)
contentArray.set(md5Array, 94)
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.registerExtendedProducts, params)
}
/**
* 取消注册扩展产品
*
* @param {Object} params - 所需参数
* @param {string} params.Type - 产品类型,['card','fingerprint','face','remote','palmVein']
* @param {string} params.KeyID - 钥匙 ID
* @param {string} params.uid - 用户 ID
*/
export async function registerExtendedProductsCancel(params) {
const {type, keyId, uid} = params
// 设置执行账号
const result = await this.login(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) {
return {
code: -1
}
}
this.requestParams = params
const length = 2 + 1 + 1 + 40 + 20 + 4 + 1 + 16
const headArray = this.createPackageHeader(3, length)
const contentArray = new Uint8Array(length)
contentArray[0] = cmdIds.expandCmd / 256
contentArray[1] = cmdIds.expandCmd % 256
// 子命令
if (type === 'card') {
contentArray[2] = subCmdIds.registerCardCancel
} else if (type === 'fingerprint') {
contentArray[2] = subCmdIds.registerFingerprintCancel
} else if (type === 'face') {
contentArray[2] = subCmdIds.registerFaceCancel
} else if (type === 'remote') {
contentArray[2] = subCmdIds.registerRemoteCancel
} else if (type === 'palmVein') {
contentArray[2] = subCmdIds.registerPalmVeinCancel
}
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.set(this.lockInfo.token || new Uint8Array([0, 0, 0, 0]), 64)
contentArray[68] = 16
const md5Array = md5Encrypt(
keyId + uid,
this.lockInfo.token || new Uint8Array([0, 0, 0, 0]),
this.lockInfo.bluetooth.signKey
)
contentArray.set(md5Array, 69)
const cebArray = sm4.encrypt(contentArray, this.lockInfo.bluetooth.privateKey, {
mode: 'ecb',
output: 'array'
})
const packageArray = createPackageEnd(headArray, cebArray)
await writeBLECharacteristicValue(this.lockInfo.deviceId,
this.lockInfo.serviceId,
this.lockInfo.writeCharacteristicId,
packageArray)
}
/**
* 获取Ic卡列表
* @param params.lockId 锁id (必填)
* @param params.pageNo 页码(选填)
* @param params.pageSize 每页显示数(选填)
* @returns {Promise<unknown>}
*/
export async function getIcCardList(params) {
return await getIcCardListRequest(params)
}
/**
* 获取指纹列表
* @param params.lockId 锁id (必填)
* @param params.pageNo 页码(选填)
* @param params.pageSize 每页显示数(选填)
* @returns {Promise<unknown>}
*/
export async function getFingerprintList(params) {
return await getFingerprintListRequest(params)
}