feat:增加更新支持功能项设置(带参数)、读取支持功能项设置、远程开锁

This commit is contained in:
liyi 2025-04-10 15:01:55 +08:00
parent 4695b66ee4
commit 9bc62bc6fb
7 changed files with 1020 additions and 567 deletions

40
api.js
View File

@ -739,3 +739,43 @@ export function getRemoteListRequest(data) {
data data
}) })
} }
/**
* 远程开锁
* @param data.lockId 锁id
* @returns {Promise<unknown>}
*/
export function remoteUnLockRequest(data) {
return request({
url: '/v1/gateway/unlock',
method: 'POST',
data
})
}
/**
* 获取锁设置
* @param data.lockId 锁id
* @returns {Promise<unknown>}
*/
export function getLockSettingRequest(data) {
return request({
url: '/v1/lockSetting/getLockSetting',
method: 'POST',
data
})
}
/**
* 更新锁设置
* @param data.lockId 锁id
* @returns {Promise<unknown>}
*/
export function updateLockSettingRequest(data) {
return request({
url: '/v1/lockSetting/updateLockSetting',
method: 'POST',
data
})
}

143
common.js
View File

@ -9,7 +9,7 @@ import {
uint8ArrayToString uint8ArrayToString
} from './format' } from './format'
import {configs} from './env' import {configs} from './env'
import {cmdIds, Result, subCmdIds} from './constant' import {cmdIds, Result, subCmdIds, supportFunctionsFeatureBit} from './constant'
import { import {
closeBLEConnection, closeBLEConnection,
searchAndConnectDevice, searchAndConnectDevice,
@ -34,7 +34,7 @@ import {
updateElectricQuantityRequest, updateElectricQuantityRequest,
updateFaceRequest, updateFaceRequest,
updateFingerprintRequest, updateFingerprintRequest,
updateIcCardRequest, updateIcCardRequest, updateLockSettingRequest,
updateLockUserNoRequest, updatePalmVeinRequest, updateLockUserNoRequest, updatePalmVeinRequest,
updatePasswordRequest, updateRemoteRequest, updatePasswordRequest, updateRemoteRequest,
uploadRecordRequest uploadRecordRequest
@ -788,7 +788,6 @@ export async function parsingCharacteristicValue(binaryData) {
const cmdId = decrypted[0] * 256 + decrypted[1] const cmdId = decrypted[0] * 256 + decrypted[1]
switch (cmdId) { switch (cmdId) {
case cmdIds.getLockStatus: case cmdIds.getLockStatus:
if (decrypted[2] === Result.Success.code) { if (decrypted[2] === Result.Success.code) {
@ -992,6 +991,8 @@ export async function parsingCharacteristicValue(binaryData) {
this.characteristicValueCallback(new Result(decrypted[2])) this.characteristicValueCallback(new Result(decrypted[2]))
break; break;
} }
} else {
this.characteristicValueCallback(new Result(decrypted[2]))
} }
break; break;
case subCmdIds.registerCardConfirm: case subCmdIds.registerCardConfirm:
@ -1018,6 +1019,8 @@ export async function parsingCharacteristicValue(binaryData) {
await this.disconnectDevice() await this.disconnectDevice()
break; break;
} }
} else {
this.characteristicValueCallback(new Result(decrypted[2]))
} }
break; break;
case subCmdIds.registerFingerprint: case subCmdIds.registerFingerprint:
@ -1063,6 +1066,8 @@ export async function parsingCharacteristicValue(binaryData) {
this.characteristicValueCallback(new Result(decrypted[2])) this.characteristicValueCallback(new Result(decrypted[2]))
break; break;
} }
} else {
this.characteristicValueCallback(new Result(decrypted[2]))
} }
break; break;
case subCmdIds.registerFingerprintProcess: case subCmdIds.registerFingerprintProcess:
@ -1092,6 +1097,8 @@ export async function parsingCharacteristicValue(binaryData) {
// 断开蓝牙连接 // 断开蓝牙连接
await this.disconnectDevice() await this.disconnectDevice()
} }
} else {
this.characteristicValueCallback(new Result(decrypted[2]))
} }
break; break;
case subCmdIds.registerFace: case subCmdIds.registerFace:
@ -1135,6 +1142,8 @@ export async function parsingCharacteristicValue(binaryData) {
this.characteristicValueCallback(new Result(decrypted[2])) this.characteristicValueCallback(new Result(decrypted[2]))
break; break;
} }
} else {
this.characteristicValueCallback(new Result(decrypted[2]))
} }
break; break;
case subCmdIds.registerFaceProcess: case subCmdIds.registerFaceProcess:
@ -1161,6 +1170,8 @@ export async function parsingCharacteristicValue(binaryData) {
emitRegisterFaceConfirmEvent(addResult) emitRegisterFaceConfirmEvent(addResult)
// 断开蓝牙连接 // 断开蓝牙连接
await this.disconnectDevice() await this.disconnectDevice()
} else {
this.characteristicValueCallback(new Result(decrypted[2]))
} }
break; break;
case subCmdIds.registerPalmVein: case subCmdIds.registerPalmVein:
@ -1202,6 +1213,8 @@ export async function parsingCharacteristicValue(binaryData) {
this.characteristicValueCallback(new Result(decrypted[2])) this.characteristicValueCallback(new Result(decrypted[2]))
break; break;
} }
} else {
this.characteristicValueCallback(new Result(decrypted[2]))
} }
break; break;
case subCmdIds.registerPalmVeinConfirm: case subCmdIds.registerPalmVeinConfirm:
@ -1228,6 +1241,8 @@ export async function parsingCharacteristicValue(binaryData) {
await this.disconnectDevice() await this.disconnectDevice()
break; break;
} }
} else {
this.characteristicValueCallback(new Result(decrypted[2]))
} }
break; break;
case subCmdIds.registerRemote: case subCmdIds.registerRemote:
@ -1267,6 +1282,8 @@ export async function parsingCharacteristicValue(binaryData) {
this.characteristicValueCallback(new Result(decrypted[2])) this.characteristicValueCallback(new Result(decrypted[2]))
break; break;
} }
} else {
this.characteristicValueCallback(new Result(decrypted[2]))
} }
break; break;
case subCmdIds.registerRemoteConfirm: case subCmdIds.registerRemoteConfirm:
@ -1293,8 +1310,67 @@ export async function parsingCharacteristicValue(binaryData) {
await this.disconnectDevice() await this.disconnectDevice()
break; break;
} }
} else {
this.characteristicValueCallback(new Result(decrypted[2]))
} }
break; break;
case subCmdIds.supportFunctionsWithParams:
// 收到锁版回复判断操作类型进行对应api操作
if (decrypted[2] === Result.Success.code) {
const {data, featureEnable} = this.requestParams
console.log('this.requestParams', this.requestParams)
let updateResult = new Result();
switch (this.requestParams.featureBit) {
case supportFunctionsFeatureBit.passageMode:
updateResult = await updateLockSettingRequest({
lockId: this.lockInfo.lockId,
passageMode: data.passageMode,
passageModeConfig: [
{
startTime: data.startTime,
endTime: data.endTime,
isAllDay: data.isAllDay,
weekDays: data.weekDay,
autoUnlock: data.autoUnlock,
}
],
})
break;
case supportFunctionsFeatureBit.automaticLocking:
updateResult = await updateLockSettingRequest({
lockId: this.lockInfo.lockId,
autoLock: data > 0 ? 1 : 0,
autoLockSecond: data,
})
break;
case supportFunctionsFeatureBit.antiPrySwitch:
updateResult = await updateLockSettingRequest({
lockId: this.lockInfo.lockId,
antiPrySwitch: featureEnable
})
break;
case supportFunctionsFeatureBit.lockSound:
updateResult = await updateLockSettingRequest({
lockId: this.lockInfo.lockId,
lockSound: data > 0 ? 1 : 0,
lockSoundVolume: data,
})
break;
default:
this.characteristicValueCallback(new Result(decrypted[2]))
break;
}
this.characteristicValueCallback(new Result(updateResult.code))
} else {
this.characteristicValueCallback(new Result(decrypted[2]))
}
break;
case subCmdIds.supportFunctions:
this.updateLockInfo({
token: decrypted.slice(5, 9)
})
this.characteristicValueCallback(new Result(decrypted[2]))
break;
default: default:
break break
} }
@ -1419,6 +1495,7 @@ export async function disconnectDevice() {
return await closeBLEConnection(this.lockInfo.deviceId) return await closeBLEConnection(this.lockInfo.deviceId)
} }
/** /**
* 用于判断时间戳是否是秒级别的如果是的话则补充到毫秒级别 * 用于判断时间戳是否是秒级别的如果是的话则补充到毫秒级别
* @param timestamp 时间戳 * @param timestamp 时间戳
@ -1429,3 +1506,63 @@ export function _convertToMilliseconds(timestamp) {
if (!timestamp) return timestamp; if (!timestamp) return timestamp;
return timestamp.toString().length === 10 ? timestamp * 1000 : timestamp; return timestamp.toString().length === 10 ? timestamp * 1000 : timestamp;
} }
/**
* 检查并返回具体哪个参数为空
* @param {Object} params - 参数对象
* @param {Array<string>} requiredFields - 必填字段列表
* @returns {string | null} - 如果有字段为空则返回错误消息否则返回null
*/
export function checkRequiredFields(params, requiredFields) {
for (let field of requiredFields) {
if (params[field] === undefined || params[field] === null) {
return `${field} 不能为空`;
}
}
return null;
}
/**
* 辅助函数将分钟时间转换为两个字节的数组
* @param minutes
* @returns {(number|number)[]}
*/
export function convertTimeToBytes(minutes) {
return [
Math.floor(minutes / 256), // 高字节
minutes % 256 // 低字节
];
}
/**
* 二进制字符串转换为十进制数字数组
* 例如 '0111110' 会被转换为 [1, 2, 3, 4, 5]表示周一到周五
* @param weekdayBit
* @returns {*[]}
*/
export function convertWeekdayBitToArray(weekdayBit) {
const weekdays = [];
const bits = weekdayBit.split('');
bits.forEach((bit, index) => {
if (bit === '1') {
weekdays.push(index);
}
});
return weekdays;
}
/**
* 十进制数字数组转为二进制字符串
* 例如 [1,2,3,4,5] 转换回 '0111110'
* @param weekdays
* @returns {string}
*/
export function convertWeekdayArrayToBit(weekdays) {
const bits = new Array(7).fill('0');
weekdays.forEach(day => {
if (day >= 0 && day < 7) {
bits[day] = '1';
}
});
return bits.join('');
}

View File

@ -1,4 +1,6 @@
// 命令ID // 命令ID
import {updateAutomaticLocking, updateSupportFunctionsWithParams} from "./star-cloud/generalExtend.js";
export const cmdIds = { export const cmdIds = {
// 获取公钥 // 获取公钥
getPublicKey: 0x3090, getPublicKey: 0x3090,
@ -62,6 +64,24 @@ export const subCmdIds = {
registerPalmVeinConfirm: 43, registerPalmVeinConfirm: 43,
// 注册掌纹取消 // 注册掌纹取消
registerPalmVeinCancel: 44, registerPalmVeinCancel: 44,
// 设置支持功能(带参数)
supportFunctionsWithParams: 72,
// 设置支持功能
supportFunctions: 70,
}
// 支持项对于功能位
export const supportFunctionsFeatureBit = {
// 自动闭锁
automaticLocking: 29,
// 支持防撬开关配置(启用/禁用)
antiPrySwitch: 30,
// 支持重置键配置(启用/禁用)
resetSwitch: 30,
// 支持语音提示管理(音量大小/禁用)
lockSound: 33,
// 常开模式
passageMode: 50
} }
// 回调事件key昵称 // 回调事件key昵称

View File

@ -1,5 +1,5 @@
import {searchAndConnectDevice, writeBLECharacteristicValue} from "../uni/basic.js"; import {searchAndConnectDevice, writeBLECharacteristicValue} from "../uni/basic.js";
import {cmdIds, Result, subCmdIds} from '../constant' import {cmdIds, Result, subCmdIds, supportFunctionsFeatureBit} from '../constant'
import {convertWeekdaysToNumber, createPackageEnd, md5Encrypt, parseTimeToList, timestampToArray} from "../format.js"; import {convertWeekdaysToNumber, createPackageEnd, md5Encrypt, parseTimeToList, timestampToArray} from "../format.js";
import {sm4} from "sm-crypto"; import {sm4} from "sm-crypto";
import { import {
@ -11,26 +11,11 @@ import {
clearAllIcCard, clearAllIcCard,
deleteIcCardRequest, getFaceListRequest, deleteIcCardRequest, getFaceListRequest,
getFingerprintListRequest, getFingerprintListRequest,
getIcCardListRequest, getPalmVeinListRequest, getRemoteListRequest, getIcCardListRequest, getLockSettingRequest, getPalmVeinListRequest, getRemoteListRequest,
updateIcCardRequest updateIcCardRequest
} from "../api.js"; } from "../api.js";
import {_convertToMilliseconds} from "../common.js";
import {_convertToMilliseconds, checkRequiredFields, convertTimeToBytes, convertWeekdayArrayToBit} from "../common.js";
/**
* 检查并返回具体哪个参数为空
* @param {Object} params - 参数对象
* @param {Array<string>} requiredFields - 必填字段列表
* @returns {string | null} - 如果有字段为空则返回错误消息否则返回null
*/
function _checkRequiredFields(params, requiredFields) {
for (let field of requiredFields) {
if (params[field] === undefined || params[field] === null) {
return `${field} 不能为空`;
}
}
return null;
}
/** /**
@ -45,7 +30,7 @@ function _checkRequiredFields(params, requiredFields) {
* @param {number} params.isAdmin - 是否管理员整型1 表示是0 表示否 * @param {number} params.isAdmin - 是否管理员整型1 表示是0 表示否
* @param {number} params.isForce - 是否胁迫整型1 表示是0 表示否 * @param {number} params.isForce - 是否胁迫整型1 表示是0 表示否
* @param {number} params.isRound - 是否循环整型1 表示是0 表示否 * @param {number} params.isRound - 是否循环整型1 表示是0 表示否
* @param {array} params.weekDays - 循环周期数组Bit0 -- 6 置位分别代表周日 -- 周六例如循环星期一星期二星期四,对应为[124] * @param {array} params.weekDay - 循环周期数组Bit0 -- 6 置位分别代表周日 -- 周六例如循环星期一星期二星期四,对应为[124]
* @param {number} params.startDate - 生效日期时间戳永久则填0 * @param {number} params.startDate - 生效日期时间戳永久则填0
* @param {number} params.endDate - 失效日期时间戳永久则填0 * @param {number} params.endDate - 失效日期时间戳永久则填0
* @param {string} params.startTime - 生效时间字符串例如'00:00' * @param {string} params.startTime - 生效时间字符串例如'00:00'
@ -81,7 +66,7 @@ function _checkRequiredFields(params, requiredFields) {
export async function registerExtendedProducts(params) { export async function registerExtendedProducts(params) {
const cardRequiredFields = ['type', 'keyId', 'uid', 'userCountLimit', 'operate', 'isAdmin', 'isForce', 'isRound', 'startDate', 'endDate']; const cardRequiredFields = ['type', 'keyId', 'uid', 'userCountLimit', 'operate', 'isAdmin', 'isForce', 'isRound', 'startDate', 'endDate'];
const missingField = _checkRequiredFields(params, cardRequiredFields); const missingField = checkRequiredFields(params, cardRequiredFields);
if (missingField) { if (missingField) {
return new Result(Result.NotMoreData, null, `参数信息不完整: ${missingField}`); return new Result(Result.NotMoreData, null, `参数信息不完整: ${missingField}`);
} }
@ -91,7 +76,7 @@ export async function registerExtendedProducts(params) {
// 注册卡片时的参数校验 // 注册卡片时的参数校验
if (params.operate === 0) { if (params.operate === 0) {
const cardRequiredFields = ['cardName', 'cardType', 'cardNumber']; const cardRequiredFields = ['cardName', 'cardType', 'cardNumber'];
const missingField = _checkRequiredFields(params, cardRequiredFields); const missingField = checkRequiredFields(params, cardRequiredFields);
if (missingField) { if (missingField) {
return new Result(Result.NotMoreData, null, `卡片信息不完整: ${missingField}`); return new Result(Result.NotMoreData, null, `卡片信息不完整: ${missingField}`);
} }
@ -114,7 +99,7 @@ export async function registerExtendedProducts(params) {
if (params.operate === 2) { if (params.operate === 2) {
cardRequiredFields.push('cardNumber') cardRequiredFields.push('cardNumber')
} }
const missingField = _checkRequiredFields(params, cardRequiredFields); const missingField = checkRequiredFields(params, cardRequiredFields);
if (missingField) { if (missingField) {
return new Result(Result.NotMoreData, null, `卡片信息不完整: ${missingField}`); return new Result(Result.NotMoreData, null, `卡片信息不完整: ${missingField}`);
} }
@ -125,7 +110,7 @@ export async function registerExtendedProducts(params) {
if (params.type === 'fingerprint') { if (params.type === 'fingerprint') {
if (params.operate === 0) { if (params.operate === 0) {
const cardRequiredFields = ['fingerprintName', 'fingerprintNumber', 'fingerprintType']; const cardRequiredFields = ['fingerprintName', 'fingerprintNumber', 'fingerprintType'];
const missingField = _checkRequiredFields(params, cardRequiredFields); const missingField = checkRequiredFields(params, cardRequiredFields);
if (missingField) { if (missingField) {
return new Result(Result.NotMoreData, null, `指纹信息不完整: ${missingField}`); return new Result(Result.NotMoreData, null, `指纹信息不完整: ${missingField}`);
} }
@ -149,7 +134,7 @@ export async function registerExtendedProducts(params) {
cardRequiredFields.push('deleteType') cardRequiredFields.push('deleteType')
cardRequiredFields.push('fingerprintNumber') cardRequiredFields.push('fingerprintNumber')
} }
const missingField = _checkRequiredFields(params, cardRequiredFields); const missingField = checkRequiredFields(params, cardRequiredFields);
if (missingField) { if (missingField) {
return new Result(Result.NotMoreData, null, `指纹信息不完整: ${missingField}`); return new Result(Result.NotMoreData, null, `指纹信息不完整: ${missingField}`);
} }
@ -160,7 +145,7 @@ export async function registerExtendedProducts(params) {
if (params.type === 'face') { if (params.type === 'face') {
if (params.operate === 0) { if (params.operate === 0) {
const cardRequiredFields = ['faceName', 'faceNumber', 'faceType']; const cardRequiredFields = ['faceName', 'faceNumber', 'faceType'];
const missingField = _checkRequiredFields(params, cardRequiredFields); const missingField = checkRequiredFields(params, cardRequiredFields);
if (missingField) { if (missingField) {
return new Result(Result.NotMoreData, null, `人脸信息不完整: ${missingField}`); return new Result(Result.NotMoreData, null, `人脸信息不完整: ${missingField}`);
} }
@ -183,7 +168,7 @@ export async function registerExtendedProducts(params) {
if (params.operate === 2) { if (params.operate === 2) {
cardRequiredFields.push('faceNumber') cardRequiredFields.push('faceNumber')
} }
const missingField = _checkRequiredFields(params, cardRequiredFields); const missingField = checkRequiredFields(params, cardRequiredFields);
if (missingField) { if (missingField) {
return new Result(Result.NotMoreData, null, `人脸信息不完整: ${missingField}`); return new Result(Result.NotMoreData, null, `人脸信息不完整: ${missingField}`);
} }
@ -194,7 +179,7 @@ export async function registerExtendedProducts(params) {
if (params.type === 'palmVein') { if (params.type === 'palmVein') {
if (params.operate === 0) { if (params.operate === 0) {
const cardRequiredFields = ['palmVeinName', 'palmVeinNumber', 'palmVeinType']; const cardRequiredFields = ['palmVeinName', 'palmVeinNumber', 'palmVeinType'];
const missingField = _checkRequiredFields(params, cardRequiredFields); const missingField = checkRequiredFields(params, cardRequiredFields);
if (missingField) { if (missingField) {
return new Result(Result.NotMoreData, null, `掌静脉信息不完整: ${missingField}`); return new Result(Result.NotMoreData, null, `掌静脉信息不完整: ${missingField}`);
} }
@ -217,7 +202,7 @@ export async function registerExtendedProducts(params) {
if (params.operate === 2) { if (params.operate === 2) {
cardRequiredFields.push('palmVeinNumber') cardRequiredFields.push('palmVeinNumber')
} }
const missingField = _checkRequiredFields(params, cardRequiredFields); const missingField = checkRequiredFields(params, cardRequiredFields);
if (missingField) { if (missingField) {
return new Result(Result.NotMoreData, null, `掌静脉信息不完整: ${missingField}`); return new Result(Result.NotMoreData, null, `掌静脉信息不完整: ${missingField}`);
} }
@ -228,7 +213,7 @@ export async function registerExtendedProducts(params) {
if (params.type === 'remote') { if (params.type === 'remote') {
if (params.operate === 0) { if (params.operate === 0) {
const cardRequiredFields = ['remoteName', 'remoteNumber', 'remoteType']; const cardRequiredFields = ['remoteName', 'remoteNumber', 'remoteType'];
const missingField = _checkRequiredFields(params, cardRequiredFields); const missingField = checkRequiredFields(params, cardRequiredFields);
if (missingField) { if (missingField) {
return new Result(Result.NotMoreData, null, `遥控信息不完整: ${missingField}`); return new Result(Result.NotMoreData, null, `遥控信息不完整: ${missingField}`);
} }
@ -251,7 +236,7 @@ export async function registerExtendedProducts(params) {
if (params.operate === 2) { if (params.operate === 2) {
cardRequiredFields.push('remoteNumber') cardRequiredFields.push('remoteNumber')
} }
const missingField = _checkRequiredFields(params, cardRequiredFields); const missingField = checkRequiredFields(params, cardRequiredFields);
if (missingField) { if (missingField) {
return new Result(Result.NotMoreData, null, `遥控信息不完整: ${missingField}`); return new Result(Result.NotMoreData, null, `遥控信息不完整: ${missingField}`);
} }
@ -263,8 +248,6 @@ export async function registerExtendedProducts(params) {
// 操作后不断开蓝牙 // 操作后不断开蓝牙
params.disconnect = false; params.disconnect = false;
console.log('params', params)
let { let {
type, type,
keyId, keyId,
@ -274,7 +257,7 @@ export async function registerExtendedProducts(params) {
userCountLimit, userCountLimit,
isForce, isForce,
isRound, isRound,
weekDays, weekDay,
startDate, startDate,
endDate, endDate,
startTime, startTime,
@ -381,7 +364,7 @@ export async function registerExtendedProducts(params) {
contentArray.set(this.lockInfo.token || new Uint8Array([0, 0, 0, 0]), 71) contentArray.set(this.lockInfo.token || new Uint8Array([0, 0, 0, 0]), 71)
contentArray[75] = isRound contentArray[75] = isRound
contentArray[76] = convertWeekdaysToNumber(weekDays) contentArray[76] = convertWeekdaysToNumber(weekDay)
contentArray.set(timestampToArray(startDate), 77) contentArray.set(timestampToArray(startDate), 77)
contentArray.set(timestampToArray(endDate), 81) contentArray.set(timestampToArray(endDate), 81)
@ -511,6 +494,195 @@ export async function registerExtendedProductsCancel(params) {
packageArray) packageArray)
} }
/**
* 更新支持功能项设置带参数
*
* @param {Object} params - 所需参数
* @param {Object} params.accountInfo - 用户信息
* @param {Number} params.featureBit - 支持功能对应的位
* @param {boolean} params.withParams - 是否携带参数
* @param {Object} params.data - 是否携带参数
* @param {Number} params.featureEnable - 不携带参数时的开关1-0-
*/
export async function updateSupportFunctionsWithParams(params) {
// 需要校验的参数
const baseRequiredFields = [
'accountInfo',
'featureBit',
'withParams',
];
// 定义功能位对应的必填字段映射
const featureBitFields = {
[supportFunctionsFeatureBit.passageMode]: [
'passageMode',
'startTime',
'endTime',
'isAllDay',
'weekDay',
'autoUnlock'
]
};
// 根据operate值动态添加必填字段
let cardRequiredFields = [...baseRequiredFields];
if (params && params.withParams && params.withParams === true) {
cardRequiredFields.push('data');
// 如果存在对应的功能位字段配置,则添加相应字段
if (featureBitFields[params.featureBit]) {
const dataFields = featureBitFields[params.featureBit];
for (const field of dataFields) {
if (params.data === undefined || params.data[field] === undefined) {
return new Result(Result.NotMoreData, null, `data参数信息不完整: ${field}`);
}
}
}
} else if (params && params.withParams && params.withParams === false) {
cardRequiredFields.push('featureEnable');
}
const missingField = checkRequiredFields(params, cardRequiredFields);
if (missingField) {
return new Result(Result.NotMoreData, null, `参数信息不完整: ${missingField}`);
}
// 深拷贝一份参数赋值
this.requestParams = JSON.parse(JSON.stringify(params))
// 转换参数
if (params && params.withParams && params.withParams === true && params.data) {
try {
switch (params.featureBit) {
case supportFunctionsFeatureBit.passageMode:
const {passageMode, startTime, endTime, isAllDay, weekDay, autoUnlock} = params.data
const startTimeBytes = convertTimeToBytes(startTime);
const endTimeBytes = convertTimeToBytes(endTime);
const weekDayBit = parseInt(String(convertWeekdayArrayToBit(weekDay)), 2);
params.data = [
passageMode,
...startTimeBytes,
...endTimeBytes,
isAllDay,
weekDayBit,
autoUnlock
]
break;
default:
params.data = [params.data]
break;
}
console.log('转换后的参数:', params.data)
} catch (e) {
return new Result(Result.NotMoreData, null, `参数转换时异常,请检查参数格式: ${e}`);
}
}
// 设置执行账号
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
}
let {featureBit, data, withParams, featureEnable} = params
const uid = this.accountInfo.uid.toString()
const keyId = this.lockInfo.keyId.toString()
// 确保data是数组形式
let dataArray = Array.isArray(data) ? data : [data]
let length = 2 + 1 + 1 + 40 + 20 + 4 + 1 + 16
if (withParams) {
length += 2 + dataArray.length
} else {
length += 2
}
const headArray = this.createPackageHeader(3, length)
const contentArray = new Uint8Array(length)
contentArray[0] = cmdIds.expandCmd / 256
contentArray[1] = cmdIds.expandCmd % 256
contentArray[2] = withParams ? subCmdIds.supportFunctionsWithParams : subCmdIds.supportFunctions
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] = featureBit
if (withParams) {
contentArray[65] = dataArray.length
contentArray.set(new Uint8Array(dataArray), 66)
} else {
contentArray[65] = featureEnable
}
contentArray.set(
this.lockInfo.token || new Uint8Array([0, 0, 0, 0]),
withParams ? 66 + dataArray.length : 66
)
contentArray[withParams ? 70 + dataArray.length : 70] = 16
const md5Array = md5Encrypt(
keyId + uid,
this.lockInfo.token || new Uint8Array([0, 0, 0, 0]),
this.lockInfo.bluetooth.signKey
)
contentArray.set(md5Array, withParams ? 71 + dataArray.length : 71)
console.log('加密前:', Array.from(contentArray))
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)
return this.getWriteResult(this.updateSupportFunctionsWithParams, params)
}
/**
* 读取支持功能项设置
* @param params
* @param {Number} params.lockId 锁id 必填
* @returns {Promise<void>}
*/
export async function readSupportFunctionsSetting(params){
return await getLockSettingRequest(params)
}
/** /**
* 获取Ic卡列表 * 获取Ic卡列表
* @param params.lockId 锁id 必填 * @param params.lockId 锁id 必填

View File

@ -2,7 +2,7 @@ import { sm4 } from 'sm-crypto'
import {cmdIds, Result} from '../constant' import {cmdIds, Result} from '../constant'
import {searchAndConnectDevice, writeBLECharacteristicValue} from '../uni/basic' import {searchAndConnectDevice, writeBLECharacteristicValue} from '../uni/basic'
import {createPackageEnd, md5Encrypt, timestampToArray} from '../format' import {createPackageEnd, md5Encrypt, timestampToArray} from '../format'
import { getLockDetailRequest, getLockSettingDataRequest } from '../api' import {getLockDetailRequest, getLockSettingDataRequest, remoteUnLockRequest} from '../api'
import {getStorage, setStorage} from '../export' import {getStorage, setStorage} from '../export'
import log from '../log' import log from '../log'
@ -363,3 +363,21 @@ export async function getLockSupportFeatures(params) {
} }
return new Result(code, data, message) return new Result(code, data, message)
} }
/**
* 远程开锁
* @param params
* @param {Number} params.lockId Id
* @returns {Promise<void>}
*/
export async function remoteUnLock(params) {
// 设置执行账号
const result = await this.login(params.uid)
if (result.code !== Result.Success.code) {
return result
}
return await remoteUnLockRequest({
lockId: params.lockId,
})
}

View File

@ -5,6 +5,8 @@ import { createPackageEnd, md5Encrypt, timestampToArray } from '../format'
import {checkPasswordRequest, getOfflinePasswordRequest} from '../api' import {checkPasswordRequest, getOfflinePasswordRequest} from '../api'
import {getConfig} from "../common.js"; import {getConfig} from "../common.js";
import StarCloud from "../star-cloud.js"; import StarCloud from "../star-cloud.js";
import {checkRequiredFields} from "../common.js";
/** /**
* 离线密码 * 离线密码
@ -61,6 +63,31 @@ export async function getOfflinePassword(params) {
* @returns {Promise<Result>} * @returns {Promise<Result>}
*/ */
export async function customPassword(params) { export async function customPassword(params) {
const baseRequiredFields = [
'keyboardPwdName',
'keyboardPwdType',
'keyboardPwd',
'addType',
'isCoerced',
'startDate',
'endDate',
'operate',
'pwdRight',
'lockId'
];
// 根据operate值动态添加必填字段
let cardRequiredFields = [...baseRequiredFields];
if (params.password && (params.password.operate === 1 || params.password.operate === 2)) {
cardRequiredFields.push('pwdNo', 'keyboardPwdId');
}
const missingField = checkRequiredFields(params.password, cardRequiredFields);
if (missingField) {
return new Result(Result.NotMoreData, null, `参数信息不完整: ${missingField}`);
}
const {password} = params const {password} = params
// 设置执行账号 // 设置执行账号
const result = await this.login(params.uid) const result = await this.login(params.uid)
@ -196,6 +223,19 @@ export async function customPassword(params) {
* @returns {Promise<Result>} * @returns {Promise<Result>}
*/ */
export async function updateAdminPassword(params) { export async function updateAdminPassword(params) {
// 需要校验的参数
const baseRequiredFields = [
'adminPwd',
];
// 根据operate值动态添加必填字段
let cardRequiredFields = [...baseRequiredFields];
const missingField = checkRequiredFields(params, cardRequiredFields);
if (missingField) {
return new Result(Result.NotMoreData, null, `参数信息不完整: ${missingField}`);
}
const {adminPwd} = params const {adminPwd} = params
// 设置执行账号 // 设置执行账号

View File

@ -1,7 +1,5 @@
import starCloudInstance from '../star-cloud' import starCloudInstance from '../star-cloud'
import { Result } from '../constant' import {Result, supportFunctionsFeatureBit} from '../constant'
import {getPalmVeinListRequest, getRemoteListRequest} from "../api.js";
export {Result} export {Result}
/** /**
@ -265,7 +263,6 @@ export const refreshHotWaterInfo = async params => {
} }
/** /**
* 注册扩展产品(卡片指纹人脸遥控掌静脉等) * 注册扩展产品(卡片指纹人脸遥控掌静脉等)
* *
@ -328,6 +325,26 @@ export const registerExtendedProductsCancel = async params => {
return await starCloudInstance.registerExtendedProductsCancel(params) return await starCloudInstance.registerExtendedProductsCancel(params)
} }
/**
* 更新支持功能项设置带参数
* @param params
* @returns {Promise<*>}
*/
export const updateSupportFunctionsWithParams = async params => {
return await starCloudInstance.updateSupportFunctionsWithParams(params)
}
/**
* 读取支持功能项设置
* @param params
* @returns {Promise<*>}
*/
export const readSupportFunctionsSetting = async params => {
return await starCloudInstance.readSupportFunctionsSetting(params)
}
/** /**
* 获取Ic卡列表 * 获取Ic卡列表
@ -379,3 +396,12 @@ export const getPalmVeinList = async params => {
export const getRemoteList = async params => { export const getRemoteList = async params => {
return await starCloudInstance.getRemoteList(params) return await starCloudInstance.getRemoteList(params)
} }
/**
* 远程开锁
* @param params
* @returns {Promise<*>}
*/
export const remoteUnLock = async params => {
return await starCloudInstance.remoteUnLock(params)
}