435 lines
13 KiB
JavaScript
435 lines
13 KiB
JavaScript
import {sm4} from 'sm-crypto'
|
|
import {cmdIds, Result} from '../constant'
|
|
import {searchAndConnectDevice, writeBLECharacteristicValue} from '../uni/basic'
|
|
import {createPackageEnd, md5Encrypt, timestampToArray,checkRequiredFields} from '../format'
|
|
import {getLockDetailRequest, getLockSettingDataRequest, remoteUnLockRequest} from '../api'
|
|
import {getStorage, setStorage} from '../export'
|
|
import log from '../log'
|
|
|
|
|
|
/**
|
|
* 选择锁
|
|
* @param params
|
|
* @param {Number} [params.uid] 用户ID
|
|
* @param {Number} params.lockId 锁ID
|
|
* @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 {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)
|
|
}
|
|
}
|
|
}
|
|
return new Result(code, data, message)
|
|
}
|
|
|
|
/**
|
|
* 开门
|
|
* @param params
|
|
* @param {Number} [params.uid] 用户ID
|
|
* @param {String} params.type 开门方式 close: 关门 open: 开门
|
|
* @param {Boolean} [params.disconnect] 操作后是否断开连接,默认断开
|
|
* @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)
|
|
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)
|
|
}
|
|
|
|
// 检查是否已添加为用户
|
|
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 {
|
|
openMode = this.lockInfo.lockSetting.appUnlockOnline ? 1 : 0
|
|
}
|
|
|
|
const name = this.lockInfo.bluetooth.bluetoothDeviceName
|
|
const uid = this.accountInfo.uid.toString()
|
|
const openTime = Math.ceil(new Date().getTime() / 1000) + this.timeDifference
|
|
|
|
const length = 2 + 40 + 20 + 1 + 4 + 4 + 1 + 16 + 16
|
|
const headArray = this.createPackageHeader(3, length)
|
|
|
|
const contentArray = new Uint8Array(length)
|
|
contentArray[0] = cmdIds.openDoor / 256
|
|
contentArray[1] = cmdIds.openDoor % 256
|
|
|
|
for (let i = 0; i < name.length; i++) {
|
|
contentArray[i + 2] = name.charCodeAt(i)
|
|
}
|
|
|
|
for (let i = 0; i < uid.length; i++) {
|
|
contentArray[i + 42] = uid.charCodeAt(i)
|
|
}
|
|
|
|
contentArray[62] = openMode
|
|
|
|
contentArray.set(timestampToArray(openTime), 63)
|
|
|
|
console.log('开门时token', this.lockInfo.token)
|
|
|
|
contentArray.set(this.lockInfo.token || timestampToArray(openTime), 67)
|
|
|
|
contentArray[71] = 16
|
|
|
|
const md5Array = md5Encrypt(
|
|
name + uid,
|
|
this.lockInfo.token || timestampToArray(openTime),
|
|
this.lockInfo.bluetooth.signKey
|
|
)
|
|
|
|
contentArray.set(md5Array, 72)
|
|
|
|
for (let i = 0; i < onlineToken.length; i++) {
|
|
contentArray[i + 88] = onlineToken.charCodeAt(i)
|
|
}
|
|
|
|
const cebArray = sm4.encrypt(contentArray, this.lockInfo.bluetooth.privateKey, {
|
|
mode: 'ecb',
|
|
output: 'array'
|
|
})
|
|
|
|
const packageArray = createPackageEnd(headArray, cebArray)
|
|
|
|
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 writeResult = await writeBLECharacteristicValue(
|
|
this.lockInfo.deviceId,
|
|
this.lockInfo.serviceId,
|
|
this.lockInfo.writeCharacteristicId,
|
|
packageArray
|
|
)
|
|
|
|
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)
|
|
}
|
|
|
|
/**
|
|
* 删除锁
|
|
* @param 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
|
|
}
|
|
this.updateLockInfo(searchResult.data)
|
|
}
|
|
|
|
// 检查是否已添加为用户
|
|
const checkResult = await this.checkLockUser()
|
|
if (checkResult.code !== Result.Success.code) {
|
|
return checkResult
|
|
}
|
|
|
|
const {
|
|
token,
|
|
bluetooth: {publicKey, privateKey}
|
|
} = this.lockInfo
|
|
|
|
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)
|
|
|
|
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 < 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 cebArray = sm4.encrypt(contentArray, 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.deleteLock, params)
|
|
}
|
|
|
|
/**
|
|
* 获取锁支持项
|
|
* @param params
|
|
* @param {Number} [params.uid] 用户ID
|
|
* @param {Number} params.lockId 锁 Id
|
|
* @returns {Promise<Result>}
|
|
*/
|
|
export async function getLockSupportFeatures(params) {
|
|
const {lockId} = params
|
|
|
|
// 设置执行账号
|
|
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)
|
|
}
|
|
|
|
/**
|
|
* 远程开锁
|
|
* @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,
|
|
})
|
|
}
|
|
|
|
/**
|
|
* 搜索wifi列表
|
|
* @param params
|
|
* @returns {Promise<void>}
|
|
*/
|
|
export async function searchWifiList(params) {
|
|
// 需要校验的参数
|
|
const baseRequiredFields = [
|
|
'uid',
|
|
];
|
|
const missingField = checkRequiredFields(params, baseRequiredFields);
|
|
if (missingField) {
|
|
return new Result(Result.NotMoreData, null, `参数信息不完整: ${missingField}`);
|
|
}
|
|
|
|
// 确认设备连接正常
|
|
if (!params.connected) {
|
|
const searchResult = await searchAndConnectDevice(this.lockInfo.bluetooth.bluetoothDeviceName)
|
|
if (searchResult.code !== Result.Success.code) {
|
|
return searchResult
|
|
}
|
|
this.updateLockInfo(searchResult.data)
|
|
}
|
|
|
|
const {uid} = params
|
|
const length = 2 + 20
|
|
const headArray = this.createPackageHeader(3, length)
|
|
|
|
const contentArray = new Uint8Array(length)
|
|
contentArray[0] = cmdIds.getWifiList / 256
|
|
contentArray[1] = cmdIds.getWifiList % 256
|
|
for (let i = 0; i < uid.length; i++) {
|
|
contentArray[i + 2] = uid.charCodeAt(i)
|
|
}
|
|
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.searchWifiList, params)
|
|
} |