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

@ -738,4 +738,44 @@ export function getRemoteListRequest(data) {
method: 'POST',
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
} from './format'
import {configs} from './env'
import {cmdIds, Result, subCmdIds} from './constant'
import {cmdIds, Result, subCmdIds, supportFunctionsFeatureBit} from './constant'
import {
closeBLEConnection,
searchAndConnectDevice,
@ -34,7 +34,7 @@ import {
updateElectricQuantityRequest,
updateFaceRequest,
updateFingerprintRequest,
updateIcCardRequest,
updateIcCardRequest, updateLockSettingRequest,
updateLockUserNoRequest, updatePalmVeinRequest,
updatePasswordRequest, updateRemoteRequest,
uploadRecordRequest
@ -788,7 +788,6 @@ export async function parsingCharacteristicValue(binaryData) {
const cmdId = decrypted[0] * 256 + decrypted[1]
switch (cmdId) {
case cmdIds.getLockStatus:
if (decrypted[2] === Result.Success.code) {
@ -992,6 +991,8 @@ export async function parsingCharacteristicValue(binaryData) {
this.characteristicValueCallback(new Result(decrypted[2]))
break;
}
} else {
this.characteristicValueCallback(new Result(decrypted[2]))
}
break;
case subCmdIds.registerCardConfirm:
@ -1018,6 +1019,8 @@ export async function parsingCharacteristicValue(binaryData) {
await this.disconnectDevice()
break;
}
} else {
this.characteristicValueCallback(new Result(decrypted[2]))
}
break;
case subCmdIds.registerFingerprint:
@ -1063,6 +1066,8 @@ export async function parsingCharacteristicValue(binaryData) {
this.characteristicValueCallback(new Result(decrypted[2]))
break;
}
} else {
this.characteristicValueCallback(new Result(decrypted[2]))
}
break;
case subCmdIds.registerFingerprintProcess:
@ -1092,6 +1097,8 @@ export async function parsingCharacteristicValue(binaryData) {
// 断开蓝牙连接
await this.disconnectDevice()
}
} else {
this.characteristicValueCallback(new Result(decrypted[2]))
}
break;
case subCmdIds.registerFace:
@ -1135,6 +1142,8 @@ export async function parsingCharacteristicValue(binaryData) {
this.characteristicValueCallback(new Result(decrypted[2]))
break;
}
} else {
this.characteristicValueCallback(new Result(decrypted[2]))
}
break;
case subCmdIds.registerFaceProcess:
@ -1161,6 +1170,8 @@ export async function parsingCharacteristicValue(binaryData) {
emitRegisterFaceConfirmEvent(addResult)
// 断开蓝牙连接
await this.disconnectDevice()
} else {
this.characteristicValueCallback(new Result(decrypted[2]))
}
break;
case subCmdIds.registerPalmVein:
@ -1202,6 +1213,8 @@ export async function parsingCharacteristicValue(binaryData) {
this.characteristicValueCallback(new Result(decrypted[2]))
break;
}
} else {
this.characteristicValueCallback(new Result(decrypted[2]))
}
break;
case subCmdIds.registerPalmVeinConfirm:
@ -1228,6 +1241,8 @@ export async function parsingCharacteristicValue(binaryData) {
await this.disconnectDevice()
break;
}
} else {
this.characteristicValueCallback(new Result(decrypted[2]))
}
break;
case subCmdIds.registerRemote:
@ -1267,6 +1282,8 @@ export async function parsingCharacteristicValue(binaryData) {
this.characteristicValueCallback(new Result(decrypted[2]))
break;
}
} else {
this.characteristicValueCallback(new Result(decrypted[2]))
}
break;
case subCmdIds.registerRemoteConfirm:
@ -1293,8 +1310,67 @@ export async function parsingCharacteristicValue(binaryData) {
await this.disconnectDevice()
break;
}
} else {
this.characteristicValueCallback(new Result(decrypted[2]))
}
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:
break
}
@ -1419,6 +1495,7 @@ export async function disconnectDevice() {
return await closeBLEConnection(this.lockInfo.deviceId)
}
/**
* 用于判断时间戳是否是秒级别的如果是的话则补充到毫秒级别
* @param timestamp 时间戳
@ -1428,4 +1505,64 @@ export async function disconnectDevice() {
export function _convertToMilliseconds(timestamp) {
if (!timestamp) return 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
import {updateAutomaticLocking, updateSupportFunctionsWithParams} from "./star-cloud/generalExtend.js";
export const cmdIds = {
// 获取公钥
getPublicKey: 0x3090,
@ -62,6 +64,24 @@ export const subCmdIds = {
registerPalmVeinConfirm: 43,
// 注册掌纹取消
registerPalmVeinCancel: 44,
// 设置支持功能(带参数)
supportFunctionsWithParams: 72,
// 设置支持功能
supportFunctions: 70,
}
// 支持项对于功能位
export const supportFunctionsFeatureBit = {
// 自动闭锁
automaticLocking: 29,
// 支持防撬开关配置(启用/禁用)
antiPrySwitch: 30,
// 支持重置键配置(启用/禁用)
resetSwitch: 30,
// 支持语音提示管理(音量大小/禁用)
lockSound: 33,
// 常开模式
passageMode: 50
}
// 回调事件key昵称

View File

@ -1,5 +1,5 @@
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 {sm4} from "sm-crypto";
import {
@ -11,26 +11,11 @@ import {
clearAllIcCard,
deleteIcCardRequest, getFaceListRequest,
getFingerprintListRequest,
getIcCardListRequest, getPalmVeinListRequest, getRemoteListRequest,
getIcCardListRequest, getLockSettingRequest, getPalmVeinListRequest, getRemoteListRequest,
updateIcCardRequest
} from "../api.js";
import {_convertToMilliseconds} 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;
}
import {_convertToMilliseconds, checkRequiredFields, convertTimeToBytes, convertWeekdayArrayToBit} from "../common.js";
/**
@ -45,7 +30,7 @@ function _checkRequiredFields(params, requiredFields) {
* @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 {array} params.weekDay - 循环周期数组Bit0 -- 6 置位分别代表周日 -- 周六例如循环星期一星期二星期四,对应为[124]
* @param {number} params.startDate - 生效日期时间戳永久则填0
* @param {number} params.endDate - 失效日期时间戳永久则填0
* @param {string} params.startTime - 生效时间字符串例如'00:00'
@ -81,7 +66,7 @@ function _checkRequiredFields(params, requiredFields) {
export async function registerExtendedProducts(params) {
const cardRequiredFields = ['type', 'keyId', 'uid', 'userCountLimit', 'operate', 'isAdmin', 'isForce', 'isRound', 'startDate', 'endDate'];
const missingField = _checkRequiredFields(params, cardRequiredFields);
const missingField = checkRequiredFields(params, cardRequiredFields);
if (missingField) {
return new Result(Result.NotMoreData, null, `参数信息不完整: ${missingField}`);
}
@ -91,7 +76,7 @@ export async function registerExtendedProducts(params) {
// 注册卡片时的参数校验
if (params.operate === 0) {
const cardRequiredFields = ['cardName', 'cardType', 'cardNumber'];
const missingField = _checkRequiredFields(params, cardRequiredFields);
const missingField = checkRequiredFields(params, cardRequiredFields);
if (missingField) {
return new Result(Result.NotMoreData, null, `卡片信息不完整: ${missingField}`);
}
@ -114,7 +99,7 @@ export async function registerExtendedProducts(params) {
if (params.operate === 2) {
cardRequiredFields.push('cardNumber')
}
const missingField = _checkRequiredFields(params, cardRequiredFields);
const missingField = checkRequiredFields(params, cardRequiredFields);
if (missingField) {
return new Result(Result.NotMoreData, null, `卡片信息不完整: ${missingField}`);
}
@ -125,7 +110,7 @@ export async function registerExtendedProducts(params) {
if (params.type === 'fingerprint') {
if (params.operate === 0) {
const cardRequiredFields = ['fingerprintName', 'fingerprintNumber', 'fingerprintType'];
const missingField = _checkRequiredFields(params, cardRequiredFields);
const missingField = checkRequiredFields(params, cardRequiredFields);
if (missingField) {
return new Result(Result.NotMoreData, null, `指纹信息不完整: ${missingField}`);
}
@ -149,7 +134,7 @@ export async function registerExtendedProducts(params) {
cardRequiredFields.push('deleteType')
cardRequiredFields.push('fingerprintNumber')
}
const missingField = _checkRequiredFields(params, cardRequiredFields);
const missingField = checkRequiredFields(params, cardRequiredFields);
if (missingField) {
return new Result(Result.NotMoreData, null, `指纹信息不完整: ${missingField}`);
}
@ -160,7 +145,7 @@ export async function registerExtendedProducts(params) {
if (params.type === 'face') {
if (params.operate === 0) {
const cardRequiredFields = ['faceName', 'faceNumber', 'faceType'];
const missingField = _checkRequiredFields(params, cardRequiredFields);
const missingField = checkRequiredFields(params, cardRequiredFields);
if (missingField) {
return new Result(Result.NotMoreData, null, `人脸信息不完整: ${missingField}`);
}
@ -183,7 +168,7 @@ export async function registerExtendedProducts(params) {
if (params.operate === 2) {
cardRequiredFields.push('faceNumber')
}
const missingField = _checkRequiredFields(params, cardRequiredFields);
const missingField = checkRequiredFields(params, cardRequiredFields);
if (missingField) {
return new Result(Result.NotMoreData, null, `人脸信息不完整: ${missingField}`);
}
@ -194,7 +179,7 @@ export async function registerExtendedProducts(params) {
if (params.type === 'palmVein') {
if (params.operate === 0) {
const cardRequiredFields = ['palmVeinName', 'palmVeinNumber', 'palmVeinType'];
const missingField = _checkRequiredFields(params, cardRequiredFields);
const missingField = checkRequiredFields(params, cardRequiredFields);
if (missingField) {
return new Result(Result.NotMoreData, null, `掌静脉信息不完整: ${missingField}`);
}
@ -217,7 +202,7 @@ export async function registerExtendedProducts(params) {
if (params.operate === 2) {
cardRequiredFields.push('palmVeinNumber')
}
const missingField = _checkRequiredFields(params, cardRequiredFields);
const missingField = checkRequiredFields(params, cardRequiredFields);
if (missingField) {
return new Result(Result.NotMoreData, null, `掌静脉信息不完整: ${missingField}`);
}
@ -228,7 +213,7 @@ export async function registerExtendedProducts(params) {
if (params.type === 'remote') {
if (params.operate === 0) {
const cardRequiredFields = ['remoteName', 'remoteNumber', 'remoteType'];
const missingField = _checkRequiredFields(params, cardRequiredFields);
const missingField = checkRequiredFields(params, cardRequiredFields);
if (missingField) {
return new Result(Result.NotMoreData, null, `遥控信息不完整: ${missingField}`);
}
@ -251,7 +236,7 @@ export async function registerExtendedProducts(params) {
if (params.operate === 2) {
cardRequiredFields.push('remoteNumber')
}
const missingField = _checkRequiredFields(params, cardRequiredFields);
const missingField = checkRequiredFields(params, cardRequiredFields);
if (missingField) {
return new Result(Result.NotMoreData, null, `遥控信息不完整: ${missingField}`);
}
@ -263,8 +248,6 @@ export async function registerExtendedProducts(params) {
// 操作后不断开蓝牙
params.disconnect = false;
console.log('params', params)
let {
type,
keyId,
@ -274,7 +257,7 @@ export async function registerExtendedProducts(params) {
userCountLimit,
isForce,
isRound,
weekDays,
weekDay,
startDate,
endDate,
startTime,
@ -381,7 +364,7 @@ export async function registerExtendedProducts(params) {
contentArray.set(this.lockInfo.token || new Uint8Array([0, 0, 0, 0]), 71)
contentArray[75] = isRound
contentArray[76] = convertWeekdaysToNumber(weekDays)
contentArray[76] = convertWeekdaysToNumber(weekDay)
contentArray.set(timestampToArray(startDate), 77)
contentArray.set(timestampToArray(endDate), 81)
@ -511,6 +494,195 @@ export async function registerExtendedProductsCancel(params) {
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卡列表
* @param params.lockId 锁id 必填

View File

@ -1,9 +1,9 @@
import { sm4 } from 'sm-crypto'
import { cmdIds, Result } from '../constant'
import { searchAndConnectDevice, writeBLECharacteristicValue } from '../uni/basic'
import { createPackageEnd, md5Encrypt, timestampToArray } from '../format'
import { getLockDetailRequest, getLockSettingDataRequest } from '../api'
import { getStorage, setStorage } from '../export'
import {sm4} from 'sm-crypto'
import {cmdIds, Result} from '../constant'
import {searchAndConnectDevice, writeBLECharacteristicValue} from '../uni/basic'
import {createPackageEnd, md5Encrypt, timestampToArray} from '../format'
import {getLockDetailRequest, getLockSettingDataRequest, remoteUnLockRequest} from '../api'
import {getStorage, setStorage} from '../export'
import log from '../log'
/**
@ -14,45 +14,45 @@ import log from '../log'
* @returns {Promise<Result>}
*/
export async function selectLock(params) {
const { lockId } = params
const result = await this.login(params.uid)
if (result.code !== Result.Success.code) {
return result
}
const {lockId} = params
const result = await this.login(params.uid)
if (result.code !== Result.Success.code) {
return result
}
const { code, data, message } = await getLockDetailRequest({
lockId
})
if (code === Result.Success.code) {
this.lockInfo = data
let lockList = getStorage('starLockList')
if (!lockList) {
lockList = {}
const {code, data, message} = await getLockDetailRequest({
lockId
})
if (code === Result.Success.code) {
this.lockInfo = data
let lockList = getStorage('starLockList')
if (!lockList) {
lockList = {}
}
if (lockList[this.accountInfo.uid]) {
const index = lockList[this.accountInfo.uid].findIndex(item => item.lockId === lockId)
if (index === -1) {
lockList[this.accountInfo.uid].push(this.lockInfo)
} else {
this.lockInfo.token = lockList[this.accountInfo.uid][index].token
lockList[this.accountInfo.uid][index] = this.lockInfo
}
setStorage('starLockList', lockList)
} else {
lockList[this.accountInfo.uid] = [this.lockInfo]
setStorage('starLockList', lockList)
}
} else if (code === Result.Fail.code) {
const lockList = getStorage('starLockList')
if (lockList[this.accountInfo.uid]) {
const index = lockList[this.accountInfo.uid].findIndex(item => item.lockId === lockId)
if (index !== -1) {
this.lockInfo = lockList[this.accountInfo.uid][index]
return new Result(Result.Success.code, this.lockInfo)
}
}
}
if (lockList[this.accountInfo.uid]) {
const index = lockList[this.accountInfo.uid].findIndex(item => item.lockId === lockId)
if (index === -1) {
lockList[this.accountInfo.uid].push(this.lockInfo)
} else {
this.lockInfo.token = lockList[this.accountInfo.uid][index].token
lockList[this.accountInfo.uid][index] = this.lockInfo
}
setStorage('starLockList', lockList)
} else {
lockList[this.accountInfo.uid] = [this.lockInfo]
setStorage('starLockList', lockList)
}
} else if (code === Result.Fail.code) {
const lockList = getStorage('starLockList')
if (lockList[this.accountInfo.uid]) {
const index = lockList[this.accountInfo.uid].findIndex(item => item.lockId === lockId)
if (index !== -1) {
this.lockInfo = lockList[this.accountInfo.uid][index]
return new Result(Result.Success.code, this.lockInfo)
}
}
}
return new Result(code, data, message)
return new Result(code, data, message)
}
/**
@ -64,204 +64,204 @@ export async function selectLock(params) {
* @returns {Promise<Result>}
*/
export async function openDoor(params) {
const { type } = params
log.info({
...new Result(
Result.Success.code,
{
lockName: this.lockInfo.bluetooth.bluetoothDeviceName,
lockId: this.lockInfo.lockId,
uid: params.uid,
time: new Date().getTime()
},
`开始开门`
),
name: 'openDoor'
})
// 设置执行账号
const result = await this.login(params.uid)
if (result.code !== Result.Success.code) {
return result
}
log.info({
...new Result(
result.code,
{
lockName: this.lockInfo.bluetooth.bluetoothDeviceName,
lockId: this.lockInfo.lockId,
uid: this.accountInfo.uid,
time: new Date().getTime()
},
`登录星云账号: ${result.message}`
),
name: 'openDoor'
})
// 确认设备连接正常
if (!params.connected) {
const searchResult = await searchAndConnectDevice(this.lockInfo.bluetooth.bluetoothDeviceName)
const {type} = params
log.info({
...new Result(
searchResult.code,
{
lockName: this.lockInfo.bluetooth.bluetoothDeviceName,
lockId: this.lockInfo.lockId,
uid: this.accountInfo.uid,
time: new Date().getTime()
},
`连接设备: ${searchResult.message}`
),
name: 'openDoor'
...new Result(
Result.Success.code,
{
lockName: this.lockInfo.bluetooth.bluetoothDeviceName,
lockId: this.lockInfo.lockId,
uid: params.uid,
time: new Date().getTime()
},
`开始开门`
),
name: 'openDoor'
})
if (searchResult.code !== Result.Success.code) {
return searchResult
// 设置执行账号
const result = await this.login(params.uid)
if (result.code !== Result.Success.code) {
return result
}
this.updateLockInfo(searchResult.data)
}
// 检查是否已添加为用户
const checkResult = await this.checkLockUser()
if (checkResult.code !== Result.Success.code) {
return checkResult
}
log.info({
...new Result(
result.code,
{
lockName: this.lockInfo.bluetooth.bluetoothDeviceName,
lockId: this.lockInfo.lockId,
uid: this.accountInfo.uid,
time: new Date().getTime()
},
`登录星云账号: ${result.message}`
),
name: 'openDoor'
})
log.info({
...new Result(
checkResult.code,
{
lockName: this.lockInfo.bluetooth.bluetoothDeviceName,
lockId: this.lockInfo.lockId,
uid: this.accountInfo.uid,
time: new Date().getTime()
},
`确认是否为锁用户: ${checkResult.message}`
),
name: 'openDoor'
})
// 确认设备连接正常
if (!params.connected) {
const searchResult = await searchAndConnectDevice(this.lockInfo.bluetooth.bluetoothDeviceName)
log.info({
...new Result(
searchResult.code,
{
lockName: this.lockInfo.bluetooth.bluetoothDeviceName,
lockId: this.lockInfo.lockId,
uid: this.accountInfo.uid,
time: new Date().getTime()
},
`连接设备: ${searchResult.message}`
),
name: 'openDoor'
})
if (searchResult.code !== Result.Success.code) {
return searchResult
}
this.updateLockInfo(searchResult.data)
}
// 是否需要联网
let onlineToken = ''
if (this.lockInfo.lockSetting.appUnlockOnline) {
const result = await this.getNetToken()
if (result.code === Result.Success.code) {
onlineToken = result.data.token
// 检查是否已添加为用户
const checkResult = await this.checkLockUser()
if (checkResult.code !== Result.Success.code) {
return checkResult
}
log.info({
...new Result(
checkResult.code,
{
lockName: this.lockInfo.bluetooth.bluetoothDeviceName,
lockId: this.lockInfo.lockId,
uid: this.accountInfo.uid,
time: new Date().getTime()
},
`确认是否为锁用户: ${checkResult.message}`
),
name: 'openDoor'
})
// 是否需要联网
let onlineToken = ''
if (this.lockInfo.lockSetting.appUnlockOnline) {
const result = await this.getNetToken()
if (result.code === Result.Success.code) {
onlineToken = result.data.token
} else {
return result
}
}
log.info({
...new Result(
checkResult.code,
{
lockName: this.lockInfo.bluetooth.bluetoothDeviceName,
lockId: this.lockInfo.lockId,
uid: this.accountInfo.uid,
time: new Date().getTime()
},
`判断是否需要联网token: ${this.lockInfo.lockSetting.appUnlockOnline}`
),
name: 'openDoor'
})
// 开门方式
let openMode
if (type === 'close') {
openMode = this.lockInfo.lockSetting.appUnlockOnline ? 33 : 32
} else {
return result
openMode = this.lockInfo.lockSetting.appUnlockOnline ? 1 : 0
}
}
log.info({
...new Result(
checkResult.code,
{
lockName: this.lockInfo.bluetooth.bluetoothDeviceName,
lockId: this.lockInfo.lockId,
uid: this.accountInfo.uid,
time: new Date().getTime()
},
`判断是否需要联网token: ${this.lockInfo.lockSetting.appUnlockOnline}`
),
name: 'openDoor'
})
const name = this.lockInfo.bluetooth.bluetoothDeviceName
const uid = this.accountInfo.uid.toString()
const openTime = Math.ceil(new Date().getTime() / 1000) + this.timeDifference
// 开门方式
let openMode
if (type === 'close') {
openMode = this.lockInfo.lockSetting.appUnlockOnline ? 33 : 32
} else {
openMode = this.lockInfo.lockSetting.appUnlockOnline ? 1 : 0
}
const length = 2 + 40 + 20 + 1 + 4 + 4 + 1 + 16 + 16
const headArray = this.createPackageHeader(3, length)
const name = this.lockInfo.bluetooth.bluetoothDeviceName
const uid = this.accountInfo.uid.toString()
const openTime = Math.ceil(new Date().getTime() / 1000) + this.timeDifference
const contentArray = new Uint8Array(length)
contentArray[0] = cmdIds.openDoor / 256
contentArray[1] = cmdIds.openDoor % 256
const length = 2 + 40 + 20 + 1 + 4 + 4 + 1 + 16 + 16
const headArray = this.createPackageHeader(3, length)
for (let i = 0; i < name.length; i++) {
contentArray[i + 2] = name.charCodeAt(i)
}
const contentArray = new Uint8Array(length)
contentArray[0] = cmdIds.openDoor / 256
contentArray[1] = cmdIds.openDoor % 256
for (let i = 0; i < uid.length; i++) {
contentArray[i + 42] = uid.charCodeAt(i)
}
for (let i = 0; i < name.length; i++) {
contentArray[i + 2] = name.charCodeAt(i)
}
contentArray[62] = openMode
for (let i = 0; i < uid.length; i++) {
contentArray[i + 42] = uid.charCodeAt(i)
}
contentArray.set(timestampToArray(openTime), 63)
contentArray[62] = openMode
console.log('开门时token', this.lockInfo.token)
contentArray.set(timestampToArray(openTime), 63)
contentArray.set(this.lockInfo.token || timestampToArray(openTime), 67)
console.log('开门时token', this.lockInfo.token)
contentArray[71] = 16
contentArray.set(this.lockInfo.token || timestampToArray(openTime), 67)
const md5Array = md5Encrypt(
name + uid,
this.lockInfo.token || timestampToArray(openTime),
this.lockInfo.bluetooth.signKey
)
contentArray[71] = 16
contentArray.set(md5Array, 72)
const md5Array = md5Encrypt(
name + uid,
this.lockInfo.token || timestampToArray(openTime),
this.lockInfo.bluetooth.signKey
)
for (let i = 0; i < onlineToken.length; i++) {
contentArray[i + 88] = onlineToken.charCodeAt(i)
}
contentArray.set(md5Array, 72)
const cebArray = sm4.encrypt(contentArray, this.lockInfo.bluetooth.privateKey, {
mode: 'ecb',
output: 'array'
})
for (let i = 0; i < onlineToken.length; i++) {
contentArray[i + 88] = onlineToken.charCodeAt(i)
}
const packageArray = createPackageEnd(headArray, cebArray)
const cebArray = sm4.encrypt(contentArray, this.lockInfo.bluetooth.privateKey, {
mode: 'ecb',
output: 'array'
})
log.info({
...new Result(
Result.Success.code,
{
lockName: this.lockInfo.bluetooth.bluetoothDeviceName,
lockId: this.lockInfo.lockId,
uid: this.accountInfo.uid,
time: new Date().getTime()
},
`开始写入`
),
name: 'openDoor'
})
const packageArray = createPackageEnd(headArray, cebArray)
const writeResult = await writeBLECharacteristicValue(
this.lockInfo.deviceId,
this.lockInfo.serviceId,
this.lockInfo.writeCharacteristicId,
packageArray
)
log.info({
...new Result(
Result.Success.code,
{
lockName: this.lockInfo.bluetooth.bluetoothDeviceName,
lockId: this.lockInfo.lockId,
uid: this.accountInfo.uid,
time: new Date().getTime()
},
`开始写入`
),
name: 'openDoor'
})
if (writeResult.code !== Result.Success.code) {
return writeResult
}
const writeResult = await writeBLECharacteristicValue(
this.lockInfo.deviceId,
this.lockInfo.serviceId,
this.lockInfo.writeCharacteristicId,
packageArray
)
log.info({
...new Result(
writeResult.code,
{
lockName: this.lockInfo.bluetooth.bluetoothDeviceName,
lockId: this.lockInfo.lockId,
uid: this.accountInfo.uid,
time: new Date().getTime()
},
`写入完成:${writeResult.message}`
),
name: 'openDoor'
})
if (writeResult.code !== Result.Success.code) {
return writeResult
}
log.info({
...new Result(
writeResult.code,
{
lockName: this.lockInfo.bluetooth.bluetoothDeviceName,
lockId: this.lockInfo.lockId,
uid: this.accountInfo.uid,
time: new Date().getTime()
},
`写入完成:${writeResult.message}`
),
name: 'openDoor'
})
return this.getWriteResult(this.openDoor, params)
return this.getWriteResult(this.openDoor, params)
}
/**
@ -270,73 +270,73 @@ export async function openDoor(params) {
* @param {Number} [params.uid] 用户ID
*/
export async function deleteLock(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
// 设置执行账号
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)
}
this.updateLockInfo(searchResult.data)
}
// 检查是否已添加为用户
const checkResult = await this.checkLockUser()
if (checkResult.code !== Result.Success.code) {
return checkResult
}
// 检查是否已添加为用户
const checkResult = await this.checkLockUser()
if (checkResult.code !== Result.Success.code) {
return checkResult
}
const {
token,
bluetooth: { publicKey, privateKey }
} = this.lockInfo
const {
token,
bluetooth: {publicKey, privateKey}
} = this.lockInfo
const authUid = this.lockInfo.uid.toString()
const name = this.lockInfo.bluetooth.bluetoothDeviceName
const authUid = this.lockInfo.uid.toString()
const name = this.lockInfo.bluetooth.bluetoothDeviceName
const length = 2 + 40 + 20 + 4 + 1 + 16
const headArray = this.createPackageHeader(3, length)
const contentArray = new Uint8Array(length)
const length = 2 + 40 + 20 + 4 + 1 + 16
const headArray = this.createPackageHeader(3, length)
const contentArray = new Uint8Array(length)
contentArray[0] = cmdIds.resetDevice / 256
contentArray[1] = cmdIds.resetDevice % 256
contentArray[0] = cmdIds.resetDevice / 256
contentArray[1] = cmdIds.resetDevice % 256
for (let i = 0; i < name.length; i++) {
contentArray[i + 2] = name.charCodeAt(i)
}
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)
}
contentArray.set(token || new Uint8Array([0, 0, 0, 0]), 62)
contentArray[66] = 16
for (let i = 0; i < authUid.length; i++) {
contentArray[i + 42] = authUid.charCodeAt(i)
}
contentArray.set(token || new Uint8Array([0, 0, 0, 0]), 62)
contentArray[66] = 16
const md5Array = md5Encrypt(name, token || new Uint8Array([0, 0, 0, 0]), publicKey)
contentArray.set(md5Array, 67)
const md5Array = md5Encrypt(name, token || new Uint8Array([0, 0, 0, 0]), publicKey)
contentArray.set(md5Array, 67)
const cebArray = sm4.encrypt(contentArray, privateKey, {
mode: 'ecb',
output: 'array'
})
const cebArray = sm4.encrypt(contentArray, privateKey, {
mode: 'ecb',
output: 'array'
})
const packageArray = createPackageEnd(headArray, cebArray)
const packageArray = createPackageEnd(headArray, cebArray)
const writeResult = await writeBLECharacteristicValue(
this.lockInfo.deviceId,
this.lockInfo.serviceId,
this.lockInfo.writeCharacteristicId,
packageArray
)
const writeResult = await writeBLECharacteristicValue(
this.lockInfo.deviceId,
this.lockInfo.serviceId,
this.lockInfo.writeCharacteristicId,
packageArray
)
if (writeResult.code !== Result.Success.code) {
return writeResult
}
if (writeResult.code !== Result.Success.code) {
return writeResult
}
return this.getWriteResult(this.deleteLock, params)
return this.getWriteResult(this.deleteLock, params)
}
/**
@ -347,19 +347,37 @@ export async function deleteLock(params) {
* @returns {Promise<Result>}
*/
export async function getLockSupportFeatures(params) {
const { lockId } = params
const {lockId} = params
// 设置执行账号
const result = await this.login(params.uid)
if (result.code !== Result.Success.code) {
return result
}
// 设置执行账号
const result = await this.login(params.uid)
if (result.code !== Result.Success.code) {
return result
}
const { code, data, message } = await getLockSettingDataRequest({
lockId
})
if (code === Result.Success.code) {
return new Result(code, { ...data.lockFeature }, message)
}
return new Result(code, data, message)
const {code, data, message} = await getLockSettingDataRequest({
lockId
})
if (code === Result.Success.code) {
return new Result(code, {...data.lockFeature}, 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

@ -1,10 +1,12 @@
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'
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'
import {getConfig} from "../common.js";
import StarCloud from "../star-cloud.js";
import {checkRequiredFields} from "../common.js";
/**
* 离线密码
@ -43,13 +45,13 @@ import StarCloud from "../star-cloud.js";
* @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)
const {password} = params
// 设置执行账号
const result = await this.login(params.uid)
if (result.code !== Result.Success.code) {
return result
}
return await getOfflinePasswordRequest(password)
}
/**
@ -61,130 +63,155 @@ export async function getOfflinePassword(params) {
* @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
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');
}
if (password.keyboardPwdId) {
checkPasswordParams.keyboardPwdId = password.keyboardPwdId
const missingField = checkRequiredFields(params.password, cardRequiredFields);
if (missingField) {
return new Result(Result.NotMoreData, null, `参数信息不完整: ${missingField}`);
}
const checkPasswordResult = await this.checkPassword({
uid:params.uid,
info:checkPasswordParams
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({
uid: params.uid,
info: 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'
})
if (checkPasswordResult.code === -3) {
return Result.ReadyHasPassword
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
}
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)
return this.getWriteResult(this.customPassword, params)
}
/**
@ -196,119 +223,132 @@ export async function customPassword(params) {
* @returns {Promise<Result>}
*/
export async function updateAdminPassword(params) {
const { adminPwd } = params
// 需要校验的参数
const baseRequiredFields = [
'adminPwd',
];
// 设置执行账号
const result = await this.login(params.uid)
if (result.code !== Result.Success.code) {
return result
}
// 根据operate值动态添加必填字段
let cardRequiredFields = [...baseRequiredFields];
// 确认设备连接正常
if (!params.connected) {
const searchResult = await searchAndConnectDevice(this.lockInfo.bluetooth.bluetoothDeviceName)
if (searchResult.code !== Result.Success.code) {
return searchResult
const missingField = checkRequiredFields(params, cardRequiredFields);
if (missingField) {
return new Result(Result.NotMoreData, null, `参数信息不完整: ${missingField}`);
}
this.updateLockInfo(searchResult.data)
}
// 检查是否已添加为用户
const checkResult = await this.checkLockUser()
if (checkResult.code !== Result.Success.code) {
return checkResult
}
const {adminPwd} = params
this.requestParams = params
// 设置执行账号
const result = await this.login(params.uid)
if (result.code !== Result.Success.code) {
return result
}
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)
// 确认设备连接正常
if (!params.connected) {
const searchResult = await searchAndConnectDevice(this.lockInfo.bluetooth.bluetoothDeviceName)
if (searchResult.code !== Result.Success.code) {
return searchResult
}
this.updateLockInfo(searchResult.data)
}
const length = 2 + 1 + 1 + 40 + 20 + 2 + 20 + 2 + 4 + 4 + 4 + 1 + 16
const headArray = this.createPackageHeader(3, length)
// 检查是否已添加为用户
const checkResult = await this.checkLockUser()
if (checkResult.code !== Result.Success.code) {
return checkResult
}
const contentArray = new Uint8Array(length)
contentArray[0] = cmdIds.expandCmd / 256
contentArray[1] = cmdIds.expandCmd % 256
this.requestParams = params
// 子命令
contentArray[2] = subCmdIds.updateAdminPassword
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)
contentArray[3] = length - 3
const length = 2 + 1 + 1 + 40 + 20 + 2 + 20 + 2 + 4 + 4 + 4 + 1 + 16
const headArray = this.createPackageHeader(3, length)
for (let i = 0; i < keyId.length; i++) {
contentArray[i + 4] = keyId.charCodeAt(i)
}
const contentArray = new Uint8Array(length)
contentArray[0] = cmdIds.expandCmd / 256
contentArray[1] = cmdIds.expandCmd % 256
for (let i = 0; i < uid.length; i++) {
contentArray[i + 44] = uid.charCodeAt(i)
}
// 子命令
contentArray[2] = subCmdIds.updateAdminPassword
if( StarCloud.env !== null &&
StarCloud.env !== undefined&&
StarCloud.env !=='' &&
StarCloud.env === 'SKY'){
contentArray[64] = Math.floor(pwdNo / 256) & 0xFF // 确保高字节为 0x00
contentArray[65] = pwdNo & 0xFF
}else{
contentArray[64] = pwdNo / 256
contentArray[65] = pwdNo % 256
}
contentArray[3] = length - 3
for (let i = 0; i < adminPwd.length; i++) {
contentArray[i + 66] = adminPwd.charCodeAt(i)
}
for (let i = 0; i < keyId.length; i++) {
contentArray[i + 4] = keyId.charCodeAt(i)
}
contentArray[86] = userCountLimit / 256
contentArray[87] = userCountLimit % 256
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]), 88)
if (StarCloud.env !== null &&
StarCloud.env !== undefined &&
StarCloud.env !== '' &&
StarCloud.env === 'SKY') {
contentArray[64] = Math.floor(pwdNo / 256) & 0xFF // 确保高字节为 0x00
contentArray[65] = pwdNo & 0xFF
} else {
contentArray[64] = pwdNo / 256
contentArray[65] = pwdNo % 256
}
contentArray.set(timestampToArray(startDate), 92)
contentArray.set(timestampToArray(endDate), 96)
for (let i = 0; i < adminPwd.length; i++) {
contentArray[i + 66] = adminPwd.charCodeAt(i)
}
contentArray[100] = 16
contentArray[86] = userCountLimit / 256
contentArray[87] = userCountLimit % 256
const md5Array = md5Encrypt(
keyId + uid,
this.lockInfo.token || new Uint8Array([0, 0, 0, 0]),
this.lockInfo.bluetooth.signKey
)
contentArray.set(this.lockInfo.token || new Uint8Array([0, 0, 0, 0]), 88)
contentArray.set(md5Array, 101)
contentArray.set(timestampToArray(startDate), 92)
contentArray.set(timestampToArray(endDate), 96)
const cebArray = sm4.encrypt(contentArray, this.lockInfo.bluetooth.privateKey, {
mode: 'ecb',
output: 'array'
})
contentArray[100] = 16
const packageArray = createPackageEnd(headArray, cebArray)
const md5Array = md5Encrypt(
keyId + uid,
this.lockInfo.token || new Uint8Array([0, 0, 0, 0]),
this.lockInfo.bluetooth.signKey
)
const writeResult = await writeBLECharacteristicValue(
this.lockInfo.deviceId,
this.lockInfo.serviceId,
this.lockInfo.writeCharacteristicId,
packageArray
)
contentArray.set(md5Array, 101)
if (writeResult.code !== Result.Success.code) {
return writeResult
}
const cebArray = sm4.encrypt(contentArray, this.lockInfo.bluetooth.privateKey, {
mode: 'ecb',
output: 'array'
})
return this.getWriteResult(this.updateAdminPassword, params)
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) {
const { info } = params
// 设置执行账号
const result = await this.login(params.uid)
if (result.code !== Result.Success.code) {
return result
}
return await checkPasswordRequest(info)
const {info} = params
// 设置执行账号
const result = await this.login(params.uid)
if (result.code !== Result.Success.code) {
return result
}
return await checkPasswordRequest(info)
}

View File

@ -1,8 +1,6 @@
import starCloudInstance from '../star-cloud'
import { Result } from '../constant'
import {getPalmVeinListRequest, getRemoteListRequest} from "../api.js";
export { Result }
import {Result, supportFunctionsFeatureBit} from '../constant'
export {Result}
/**
* 账户信息
@ -22,10 +20,10 @@ export { Result }
* @param {Boolean} params.isReportLog 是否上报日志
*/
export const init = params => {
starCloudInstance.init({
...params,
platform: 1
})
starCloudInstance.init({
...params,
platform: 1
})
}
/**
@ -33,7 +31,7 @@ export const init = params => {
* @returns Result
*/
export const register = async () => {
return await starCloudInstance.register()
return await starCloudInstance.register()
}
/**
@ -42,7 +40,7 @@ export const register = async () => {
* @param {Number} params.uid 用户ID
*/
export const logout = params => {
starCloudInstance.logout(params)
starCloudInstance.logout(params)
}
/**
@ -53,7 +51,7 @@ export const logout = params => {
* @returns Result
*/
export const selectLock = async params => {
return await starCloudInstance.selectLock(params)
return await starCloudInstance.selectLock(params)
}
/**
@ -65,7 +63,7 @@ export const selectLock = async params => {
* @returns Result
*/
export const openDoor = async params => {
return await starCloudInstance.openDoor(params)
return await starCloudInstance.openDoor(params)
}
/**
@ -89,7 +87,7 @@ export const openDoor = async params => {
* @returns Result
*/
export const getOfflinePassword = async params => {
return await starCloudInstance.getOfflinePassword(params)
return await starCloudInstance.getOfflinePassword(params)
}
/**
@ -109,7 +107,7 @@ export const getOfflinePassword = async params => {
* @returns Result
*/
export const checkPassword = async params => {
return await starCloudInstance.checkPassword(params)
return await starCloudInstance.checkPassword(params)
}
/**
@ -137,7 +135,7 @@ export const checkPassword = async params => {
* @returns Result
*/
export const customPassword = async params => {
return await starCloudInstance.customPassword(params)
return await starCloudInstance.customPassword(params)
}
/**
@ -146,7 +144,7 @@ export const customPassword = async params => {
* @returns Result
*/
export const searchDevice = async callback => {
return await starCloudInstance.searchDevice(callback)
return await starCloudInstance.searchDevice(callback)
}
/**
@ -154,7 +152,7 @@ export const searchDevice = async callback => {
* @returns Result
*/
export const stopSearchDevice = async () => {
return await starCloudInstance.stopSearchDevice()
return await starCloudInstance.stopSearchDevice()
}
/**
@ -165,7 +163,7 @@ export const stopSearchDevice = async () => {
* @returns Result
*/
export const bindDevice = async params => {
return await starCloudInstance.bindDevice(params)
return await starCloudInstance.bindDevice(params)
}
/**
@ -176,7 +174,7 @@ export const bindDevice = async params => {
* @returns Result
*/
export const removeBadLock = async params => {
return await starCloudInstance.removeBadLock(params)
return await starCloudInstance.removeBadLock(params)
}
/**
@ -185,7 +183,7 @@ export const removeBadLock = async params => {
* @param {Number} [params.uid] 用户ID
*/
export const deleteLock = async params => {
return await starCloudInstance.deleteLock(params)
return await starCloudInstance.deleteLock(params)
}
/**
@ -197,7 +195,7 @@ export const deleteLock = async params => {
* @returns Result
*/
export const updateAdminPassword = async params => {
return await starCloudInstance.updateAdminPassword(params)
return await starCloudInstance.updateAdminPassword(params)
}
/**
@ -208,7 +206,7 @@ export const updateAdminPassword = async params => {
* @returns Result
*/
export const syncOpenDoorRecord = async params => {
return await starCloudInstance.syncAllOpenRecord(params)
return await starCloudInstance.syncAllOpenRecord(params)
}
/**
@ -216,7 +214,7 @@ export const syncOpenDoorRecord = async params => {
* @returns Result
*/
export const getServerTime = async () => {
return await starCloudInstance.getServerTimestamp()
return await starCloudInstance.getServerTimestamp()
}
/**
@ -227,7 +225,7 @@ export const getServerTime = async () => {
* @returns Result
*/
export const getLockSupportFeatures = async params => {
return await starCloudInstance.getLockSupportFeatures(params)
return await starCloudInstance.getLockSupportFeatures(params)
}
/**
@ -238,7 +236,7 @@ export const getLockSupportFeatures = async params => {
* @returns Result
*/
export const refreshElecInfo = async params => {
return await starCloudInstance.refreshElecInfo(params)
return await starCloudInstance.refreshElecInfo(params)
}
/**
@ -249,7 +247,7 @@ export const refreshElecInfo = async params => {
* @returns Result
*/
export const refreshColdWaterInfo = async params => {
return await starCloudInstance.refreshColdWaterInfo(params)
return await starCloudInstance.refreshColdWaterInfo(params)
}
@ -261,11 +259,10 @@ export const refreshColdWaterInfo = async params => {
* @returns Result
*/
export const refreshHotWaterInfo = async params => {
return await starCloudInstance.refreshHotWaterInfo(params)
return await starCloudInstance.refreshHotWaterInfo(params)
}
/**
* 注册扩展产品(卡片指纹人脸遥控掌静脉等)
*
@ -325,9 +322,29 @@ export const registerExtendedProducts = async params => {
* @param {string} params.uid - 用户 ID
*/
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卡列表
@ -336,7 +353,7 @@ export const registerExtendedProductsCancel = async params => {
* @param params.pageSize 每页显示数选填
*/
export const getIcCardList = async params => {
return await starCloudInstance.getIcCardList(params)
return await starCloudInstance.getIcCardList(params)
}
@ -347,7 +364,7 @@ export const getIcCardList = async params => {
* @param params.pageSize 每页显示数选填
*/
export const getFingerprintList = async params => {
return await starCloudInstance.getFingerprintList(params)
return await starCloudInstance.getFingerprintList(params)
}
/**
@ -357,7 +374,7 @@ export const getFingerprintList = async params => {
* @param params.pageSize 每页显示数选填
*/
export const getFaceList = async params => {
return await starCloudInstance.getFaceList(params)
return await starCloudInstance.getFaceList(params)
}
/**
@ -367,7 +384,7 @@ export const getFaceList = async params => {
* @param params.pageSize 每页显示数选填
*/
export const getPalmVeinList = async params => {
return await starCloudInstance.getPalmVeinList(params)
return await starCloudInstance.getPalmVeinList(params)
}
/**
@ -377,5 +394,14 @@ export const getPalmVeinList = async params => {
* @param params.pageSize 每页显示数选填
*/
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)
}