From cbf8505bae1e80cf2d9c92148f1ddbf8419f1197 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8C=83=E9=B9=8F?= Date: Sat, 12 Oct 2024 14:35:58 +0800 Subject: [PATCH 01/25] init --- .gitignore | 1 + README.md | 6 + api.js | 91 +++++ basic.js | 442 ++++++++++++++++++++++ env.js | 24 ++ format.js | 83 +++++ request.js | 104 ++++++ starCloud.js | 1013 ++++++++++++++++++++++++++++++++++++++++++++++++++ storage.js | 18 + 9 files changed, 1782 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 api.js create mode 100644 basic.js create mode 100644 env.js create mode 100644 format.js create mode 100644 request.js create mode 100644 starCloud.js create mode 100644 storage.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..485dee6 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea diff --git a/README.md b/README.md new file mode 100644 index 0000000..e2ef19a --- /dev/null +++ b/README.md @@ -0,0 +1,6 @@ +## 星云SDK + +### 1. 安装 + +### 2. 需安装的npm包 +`npm install buffer crc js-md5 pinia sm-crypto` diff --git a/api.js b/api.js new file mode 100644 index 0000000..d3a7b6b --- /dev/null +++ b/api.js @@ -0,0 +1,91 @@ +import request from '@/starCloud/request' + +// 创建账号 +export function starCloudCreateUser(data) { + return request({ + url: '/createUser', + method: 'POST', + data + }) +} + +// 获取访问令牌 +export function getStarCloudToken(data) { + return request({ + url: '/oauth2/token', + method: 'POST', + data + }) +} + +// 更新锁用户 +export function updateLockUserNoRequest(data) { + return request({ + url: '/v1/key/updateLockUserNo', + method: 'POST', + data + }) +} + +// 获取所有锁用户 +export function getUserNoListRequest(data) { + return request({ + url: '/v1/key/getUserNoList', + method: 'POST', + data + }) +} + +// 获取手机联网token +export function getLockNetTokenRequest(data) { + return request({ + url: '/v1/lock/getLockNetToken', + method: 'POST', + data + }) +} + +// 获取服务器时间 +export function getServerDatetime(data) { + return request({ + url: '/v1/lock/queryDate', + method: 'POST', + data + }) +} + +// 获取锁详情 +export function getLockDetail(data) { + return request({ + url: '/v1/lock/detail', + method: 'POST', + data + }) +} + +// 获取离线密码 +export function getOfflinePassword(data) { + return request({ + url: '/v1/keyboardPwd/get', + method: 'POST', + data + }) +} + +// 添加自定义密码 +export function addCustomPassword(data) { + return request({ + url: '/v1/keyboardPwd/add', + method: 'POST', + data + }) +} + +// 更新密码 +export function updatePassword(data) { + return request({ + url: '/v1/keyboardPwd/update', + method: 'POST', + data + }) +} diff --git a/basic.js b/basic.js new file mode 100644 index 0000000..6a0032f --- /dev/null +++ b/basic.js @@ -0,0 +1,442 @@ +export class Result { + static codes = { + Success: 0, + Fail: -1, + + NotAvailableBluetooth: -20, + NotAvailableBluetoothPermission: -21, + NotAvailableWeChatNearbyDevicesPermission: -22, + NotAvailableWeChatLocationPermission: -23, + NotAvailableWeChatNearbyDevicesEmpty: -24, + DeviceHasBeenReset: -30, + + NotRegisteredLock: 4, + NotTokenLock: 6, + NotMoreKeyLock: 12, + ReadyHasKeyLock: 15, + } + + static resultsMap = new Map([ + [Result.codes.Success, { message: '成功', data: {} }], + [Result.codes.Fail, { message: '失败', data: {} }], + + [Result.codes.NotAvailableBluetooth, { message: '蓝牙未开启', data: {} }], + [Result.codes.NotAvailableBluetoothPermission, { message: '小程序蓝牙权限被禁用', data: {} }], + [Result.codes.NotAvailableWeChatNearbyDevicesPermission, { message: '微信附近的设备权限被禁用', data: {} }], + [Result.codes.NotAvailableWeChatLocationPermission, { message: '微信定位权限被禁用', data: {} }], + [Result.codes.NotAvailableWeChatNearbyDevicesEmpty, { message: '微信附近的设备权限无法使用', data: {} }], + [Result.codes.DeviceHasBeenReset, { message: '设备已被重置', data: {} }], + + [Result.codes.NotRegisteredLock, { message: '用户在锁端未注册', data: {} }], + [Result.codes.NotTokenLock, { message: '用户在锁端token失效', data: {} }], + [Result.codes.NotMoreKeyLock, { message: '锁端钥匙数量已达上限', data: {} }], + [Result.codes.ReadyHasKeyLock, { message: '用户已是锁端用户', data: {} }], + ]) + + constructor(code, data, message) { + const result = Result.resultsMap.get(code) + if (result) { + this.code = code + this.message = message || result.message + this.data = data || result.data + } else { + this.code = code + this.message = message || '' + this.data = data || {} + } + } + + // 成功 + static get Success() { + return new Result(Result.codes.Success) + } + + // 失败(默认错误) + static get Fail() { + return new Result(Result.codes.Fail) + } + + // 蓝牙未开启 + static get NotAvailableBluetooth() { + return new Result(Result.codes.NotAvailableBluetooth) + } + + // 小程序蓝牙权限被禁用 + static get NotAvailableBluetoothPermission() { + return new Result(Result.codes.NotAvailableBluetoothPermission) + } + + // 微信附近的设备权限被禁用 + static get NotAvailableWeChatNearbyDevicesPermission() { + return new Result(Result.codes.NotAvailableWeChatNearbyDevicesPermission) + } + + // 微信定位权限被禁用 + static get NotAvailableWeChatLocationPermission() { + return new Result(Result.codes.NotAvailableWeChatLocationPermission) + } + + // 微信附近的设备权限无法使用(针对小米空白通行证,鸿蒙系统隐私中的定位服务) + static get NotAvailableWeChatNearbyDevicesEmpty() { + return new Result(Result.codes.NotAvailableWeChatNearbyDevicesEmpty) + } + + // 设备已被重置 + static get DeviceHasBeenReset() { + return new Result(Result.codes.DeviceHasBeenReset) + } + + // 用户在锁端未注册 + static get NotRegisteredLock() { + return new Result(Result.codes.NotRegisteredLock) + } + + // 用户在锁端token失效 + static get NotTokenLock() { + return new Result(Result.codes.NotTokenLock) + } + + // 锁端钥匙数量已达上限 + static get NotMoreKeyLock() { + return new Result(Result.codes.NotMoreKeyLock) + } + + // 锁端钥匙数量已达上限 + static get ReadyHasKeyLock() { + return new Result(Result.codes.ReadyHasKeyLock) + } +} + + +/** + * @typedef {Object} err + * @property {number} errno - 错误代码 + * @property {number} errCode - 错误代码 + * @property {String} errMsg - 错误信息 + */ + +// 查找设备并连接 +export function searchAndConnectDevice(name) { + // 循环查找设备 + let timer + // 超时计时器 + let timeoutTimer + + return new Promise(async (resolve) => { + const result = await startBluetoothDevicesDiscovery() + if(result.code === Result.Success.code) { + let searchFlag = false + timeoutTimer = setTimeout(async () => { + await stopBluetoothDevicesDiscovery() + clearInterval(timer) + if (!searchFlag) { + resolve(Result.NotAvailableWeChatNearbyDevicesEmpty) + } else { + resolve(Result.Fail) + } + }, 10500) + timer = setInterval(async () => { + const queryResult = await getBluetoothDevices() + if(queryResult.code === Result.Success.code) { + const deviceList = queryResult.data + if (searchFlag === false && deviceList.length > 0) { + searchFlag = true + } + for (let i = 0; i < deviceList.length; i++) { + if (deviceList[i]?.name === name) { + const uuid = deviceList[i]?.advertisServiceUUIDs[0] + if(uuid && uuid.slice(2, 8) === '758824') { + await stopBluetoothDevicesDiscovery() + clearTimeout(timeoutTimer) + clearInterval(timer) + if(uuid.slice(30, 32) === '00') { + resolve(Result.DeviceHasBeenReset) + } else if (uuid.slice(30, 32) === '01') { + const connectResult = await createBLEConnection(deviceList[i].deviceId) + resolve(connectResult) + } else { + resolve(Result.Fail) + } + break + } + } + } + } else { + resolve(queryResult) + } + }, 1000) + } else { + resolve(result) + } + }) +} + +// 蓝牙操作报错处理 +async function handleError (err, event) { + if (err.errCode === 10000) { + const result = await openBluetoothAdapter() + if (result.code === Result.Success.code) { + return await event() + } else { + return result + } + } else if (err.errCode === 10001) { + return Result.NotAvailableBluetooth + } else if (err.errno === 3) { + return Result.NotAvailableWeChatNearbyDevicesPermission + } else if (err.errno === 103) { + return Result.NotAvailableBluetoothPermission + } else if (err.errno === 1509008) { + return Result.NotAvailableWeChatLocationPermission + } else if (err.errMsg === 'openBluetoothAdapter:fail already opened') { + return Result.Success + } else { + return Result.Fail + } +} + +// 初始化蓝牙模块 +function openBluetoothAdapter() { + return new Promise((resolve) => { + uni.openBluetoothAdapter({ + success() { + resolve(Result.Success) + }, + async fail (err) { + resolve(await handleError(err)) + } + }) + }) +} + +// 关闭蓝牙模块 +function closeBluetoothAdapter() { + return new Promise((resolve) => { + uni.closeBluetoothAdapter({ + success() { + resolve(Result.Success) + }, + async fail (err) { + resolve(await handleError(err)) + } + }) + }) +} + +// 移除蓝牙适配器的全部监听 +function offBluetoothAdapterStateChange() { + uni.offBluetoothAdapterStateChange() +} + +// 监听蓝牙特征值改变 +export function onBLECharacteristicValueChange(callback) { + uni.onBLECharacteristicValueChange((res) => { + callback(res) + }) +} + +// 开始搜索附近的蓝牙设备 +function startBluetoothDevicesDiscovery() { + return new Promise((resolve) => { + uni.startBluetoothDevicesDiscovery({ + success() { + resolve(Result.Success) + }, + async fail (err) { + resolve(await handleError(err, startBluetoothDevicesDiscovery)) + } + }) + }) +} + +// 获取所有已发现的蓝牙设备 +function getBluetoothDevices() { + return new Promise((resolve) => { + uni.getBluetoothDevices({ + success(res) { + resolve(new Result(Result.Success.code, res.devices)) + }, + async fail () { + resolve(await handleError(err, getBluetoothDevices)) + } + }) + }) +} + +// 停止搜索附近的蓝牙设备 +function stopBluetoothDevicesDiscovery() { + return new Promise((resolve) => { + uni.stopBluetoothDevicesDiscovery({ + success() { + resolve(Result.Success) + }, + async fail () { + resolve(await handleError(err)) + } + }) + }) +} + +// 连接低功耗蓝牙设备 +function createBLEConnection(deviceId, reconnectNumber = 0) { + return new Promise((resolve) => { + uni.createBLEConnection({ + deviceId, + timeout: 10000, + async success () { + const res = await getBLEDeviceServicesAndCharacteristics(deviceId) + await notifyBLECharacteristicValueChange(deviceId, res.data.serviceId, res.data.notifyCharacteristicId) + resolve(res) + }, + async fail (err) { + if (err.errno === 1509007) { + const res = await getBLEDeviceServicesAndCharacteristics(deviceId) + await notifyBLECharacteristicValueChange(deviceId, res.data.serviceId, res.data.notifyCharacteristicId) + resolve(res) + } else if (err.errno === 1509001 && reconnectNumber < 1) { + resolve(Result.Fail) + } else if (reconnectNumber < 1) { + resolve(await createBLEConnection(deviceId, reconnectNumber + 1)) + } else { + resolve(Result.Fail) + } + } + }) + }) +} + +// 获取服务及对应特征值 +async function getBLEDeviceServicesAndCharacteristics (deviceId) { + const { code, data } = await getBLEDeviceServices(deviceId) + if (code === Result.Success.code) { + const { serviceId } = data + const { + code, + data: { notifyCharacteristicId, writeCharacteristicId } + } = await getBLEDeviceCharacteristics(deviceId, serviceId) + if (code === Result.Success.code) { + return new Result(Result.Success.code, { deviceId, serviceId, notifyCharacteristicId, writeCharacteristicId }) + } else { + return Result.Fail + } + } else { + return Result.Fail + } +} + +// 获取设备的服务 +function getBLEDeviceServices(deviceId) { + return new Promise((resolve) => { + uni.getBLEDeviceServices({ + deviceId, + success(res) { + let serviceId + for(let i = 0; i < res.services.length; i++) { + if(res.services[i].uuid.indexOf('FFF0') !== -1) { + serviceId = res.services[i].uuid + } + } + if(!serviceId) { + resolve(Result.Fail) + return + } + resolve(new Result(Result.Success.code, { serviceId })) + }, + fail() { + resolve(Result.Fail) + } + }) + }) +} + +// 获取服务的特征值 +function getBLEDeviceCharacteristics(deviceId, serviceId) { + return new Promise((resolve) => { + uni.getBLEDeviceCharacteristics({ + deviceId, + serviceId, + success(res) { + let notifyCharacteristicId + let writeCharacteristicId + for(let i = 0; i < res.characteristics.length; i++) { + const characteristic = res.characteristics[i] + if(characteristic.properties.notify) { + notifyCharacteristicId = characteristic.uuid + } + if(characteristic.properties.write) { + writeCharacteristicId = characteristic.uuid + } + } + if(notifyCharacteristicId && writeCharacteristicId) { + resolve(new Result(Result.Success.code, { notifyCharacteristicId, writeCharacteristicId })) + } else { + resolve(Result.Fail) + } + }, + fail() { + resolve(Result.Fail) + } + }) + }) +} + +// 订阅特征值 +function notifyBLECharacteristicValueChange(deviceId, serviceId, characteristicId) { + return new Promise((resolve) => { + uni.notifyBLECharacteristicValueChange({ + deviceId, + serviceId, + characteristicId, + state: true, + success() { + resolve(Result.Success) + }, + fail() { + resolve(Result.Fail) + } + }) + }) +} + +// 断开与低功耗蓝牙设备的连接 +export function closeBLEConnection(deviceId) { + return new Promise((resolve) => { + uni.closeBLEConnection({ + deviceId, + success() { + console.log('断开连接成功') + resolve(Result.Success) + }, + fail() { + console.log('断开连接失败') + resolve(Result.Fail) + } + }) + }) +} + +// 写入特征值 +export function writeBLECharacteristicValue(deviceId, serviceId, characteristicId, binaryData) { + return new Promise((resolve) => { + const count = Math.ceil(binaryData.length / 20) + let successCount = 0 + for(let i = 0; i < count; i++) { + const writeData = binaryData.slice(i * 20, i === (count - 1) ? binaryData.length : (i + 1) * 20) + uni.writeBLECharacteristicValue({ + deviceId, + serviceId, + characteristicId, + value: writeData.buffer, + success() { + successCount++ + if(successCount === count) { + resolve(Result.Success) + } + }, + fail() { + resolve(Result.Fail) + } + }) + } + }) +} diff --git a/env.js b/env.js new file mode 100644 index 0000000..47435d6 --- /dev/null +++ b/env.js @@ -0,0 +1,24 @@ +// 版本号 +export const version = '1.0.0' +// 构建号 +export const buildNumber = 1 + +// 环境配置 +export const configs = { + DEV: { + name: 'DEV', + baseUrl: 'https://dev.cloud.star-lock.cn/sdk' + }, + PRE: { + name: 'PRE', + baseUrl: 'https://pre.cloud.star-lock.cn' + }, + XHJ: { + name: 'XHJ', + baseUrl: 'https://cloud.star-lock.cn' + }, + SKY: { + name: 'SKY', + baseUrl: 'https://cloud.star-lock.cn' + } +} diff --git a/format.js b/format.js new file mode 100644 index 0000000..3bd8313 --- /dev/null +++ b/format.js @@ -0,0 +1,83 @@ +import { + md5 +} from 'js-md5' +import crc from 'crc' + +// 周数组转换 +export function convertWeekdaysToNumber(weekDay) { + let weekStr = '00000000' + + for (const day of weekDay) { + const index = day % 7 // 将周日的索引转换为0 + weekStr = weekStr.substring(0, index) + '1' + weekStr.substring(index + 1) + } + + // 倒序 weekStr + weekStr = weekStr.split('') + .reverse() + .join('') + + return parseInt(weekStr, 2) +} + +// 时间戳转二进制 +export function timestampToArray(timestamp) { + const array = new Uint8Array(4) + array[0] = (timestamp & 0xff000000) >> 24 + array[1] = (timestamp & 0xff0000) >> 16 + array[2] = (timestamp & 0xff00) >> 8 + array[3] = (timestamp & 0xff) + return array +} + +// md5加密 +export function md5Encrypt(text, token, key) { + const length = text.length + 4 + 16 + const md5Array = new Uint8Array(length) + + for (let i = 0; i < text.length; i++) { + md5Array[i] = text.charCodeAt(i) + } + + md5Array.set(token, text.length) + md5Array.set(key, text.length + 4) + + const md5Text = md5(md5Array) + return new Uint8Array(md5Text.match(/.{1,2}/g) + .map(byte => parseInt(byte, 16))) +} + +// 生成包尾 头部数据+内容数据 +export function createPackageEnd(headArray, contentArray) { + // 拼接头部和内容 + let mergerArray = new Uint8Array(headArray.length + contentArray.length) + mergerArray.set(headArray) + mergerArray.set(contentArray, headArray.length) + + // crc加密 + const crcResult = crc.crc16kermit(mergerArray) + + // 拼接crc + let newArray = new Uint8Array(mergerArray.length + 2) + newArray.set(mergerArray) + newArray.set([crcResult / 256, crcResult % 256], mergerArray.length) + + return newArray +} + +// 二进制转时间戳 +export function arrayToTimestamp(array) { + const timestamp = (array[0] << 24) | (array[1] << 16) | (array[2] << 8) | array[3] + return timestamp >>> 0 +} + +// 二进制转字符串 +export function uint8ArrayToString(uint8Array) { + let str = '' + for (let i = 0; i < uint8Array.length; i++) { + if (uint8Array[i] !== 0) { + str += String.fromCharCode(uint8Array[i]) + } + } + return str +} diff --git a/request.js b/request.js new file mode 100644 index 0000000..3f436de --- /dev/null +++ b/request.js @@ -0,0 +1,104 @@ +import { getStorage, removeStorage } from '@/starCloud/storage' +import { useStarCloudStore } from '@/starCloud/starCloud' +import { Result } from '@/starCloud/basic' + +/* +* config +* baseUrl: 请求域名 +* url: 请求路径 +* method: 请求方法 +* header: 请求头 +* token: 请求token +* data: 请求参数 +* */ + +const request = (config) => { + const starCloud = useStarCloudStore() + let timer + return new Promise(async (resolve) => { + const baseConfig = starCloud.getConfig() + + const token = config?.token ? config.token : getStorage('starCloudToken') + // 请求地址 + const URL = config.baseUrl ? config.baseUrl + config.url : baseConfig.baseUrl + config.url + + // 默认请求头 + const headerDefault = { + version: baseConfig.version + '+' + baseConfig.buildNumber + } + const header = { + ...headerDefault, + ...config.header + } + const method = config.method || 'POST' + const data = { + ...config.data, + accessToken: token, + clientId: starCloud.clientId + } + const timestamp = new Date().getTime() + + // 超时处理 + timer = setTimeout(() => { + resolve(new Result(Result.Fail.code, {},'网络访问失败,请检查网络是否正常')) + }, 3200) + + uni.request({ + url: URL, + method, + header, + data, + timeout: 3000, + async success (res) { + const { statusCode, data } = res + if (timer) { + clearTimeout(timer) + } + if (statusCode === 200) { + const code = data.errcode + const message = data.errmsg + if (code === 10003) { + removeStorage('starCloudToken') + removeStorage('starCloudUser') + const { code } = await starCloud.login( + starCloud.accountInfo.username, + starCloud.accountInfo.password + ) + if(code === Result.Success.code) { + resolve(await request(config)) + } + } else { + resolve({ + code, + data: data.data, + message + }) + } + } else { + resolve(new Result(Result.Fail.code, {},'网络访问失败,请检查网络是否正常')) + } + }, + async fail (res) { + console.log('网络访问失败', res) + if (timer) { + clearTimeout(timer) + } + resolve(new Result(Result.Fail.code, {},'网络访问失败,请检查网络是否正常')) + }, + async complete (res) { + console.log(URL.substring(baseConfig.baseUrl.length + 1), { + env: baseConfig.name, + url: URL.substring(baseConfig.baseUrl.length + 1), + req: config?.data || {}, + code: res?.data?.errcode, + res: res?.data?.data, + token: header?.authorization || '', + message: res?.data?.errmsg, + duration: new Date().getTime() - timestamp + }) + } + }) + }) +} + +export default request diff --git a/starCloud.js b/starCloud.js new file mode 100644 index 0000000..2257827 --- /dev/null +++ b/starCloud.js @@ -0,0 +1,1013 @@ +import { defineStore } from 'pinia' +import { buildNumber, configs, version } from '@/starCloud/env' +import { + addCustomPassword, + getLockDetail, + getLockNetTokenRequest, + getOfflinePassword, + getServerDatetime, + getStarCloudToken, + getUserNoListRequest, + starCloudCreateUser, + updateLockUserNoRequest, updatePassword +} from '@/starCloud/api' +import { getStorage, setStorage } from '@/starCloud/storage' +import { + closeBLEConnection, + onBLECharacteristicValueChange, + Result, + searchAndConnectDevice, + writeBLECharacteristicValue +} from '@/starCloud/basic' +import { + arrayToTimestamp, + convertWeekdaysToNumber, + createPackageEnd, + md5Encrypt, + timestampToArray, + uint8ArrayToString +} from '@/starCloud/format' +import { sm4 } from 'sm-crypto' + +/** + * 锁信息 + * @typedef {Object} lockInfo + * @property {Number} keyId - 钥匙ID + * @property {Number} lockId - 锁ID + * @property {String} lockName - 锁名称 + * @property {String} lockAlias - 锁别名 + * @property {Number} electricQuantity - 电量 + * @property {Number} electricQuantityStandby - 备用电量 + * @property {Number} electricQuantityDate - 电量更新时间 + * @property {String} fwVersion - 固件版本 + * @property {String} hwVersion - 硬件版本 + * @property {Number} keyType - 钥匙类型 + * @property {Number} passageMode - 常开模式 + * @property {Number} userType - 用户类型 + * @property {Number} startDate - 有效期开始时间 + * @property {Number} endDate - 有效期结束时间 + * @property {Object} weekDays - 循环周期 + * @property {Number} remoteEnable - 是否支持远程开锁:0-未知,1-是,2-否 + * @property {Number} faceAuthentication - 是否实名认证:0-未知,1-是,2-否 + * @property {Number} lastFaceValidateTime - 最后一次人脸验证时间 + * @property {Number} nextFaceValidateTime - 下次人脸验证时间 + * @property {Number} keyRight - 是否授权管理员钥匙: 0-未知,1-是,2-否 + * @property {Number} keyStatus - 钥匙状态 + * @property {Object} bluetooth - 蓝牙 + * @property {Number} sendDate - 发送时间 + * @property {Number} isLockOwner - 是否是锁主 + * @property {Object} lockFeature - 锁特征 + * @property {Object} lockSetting - 锁设置 + * @property {Number} lockUserNo - 用户编号 + * @property {Number} senderUserId - 发送者用户ID + * @property {Number} isOnlyManageSelf - 如果是授权管理员此字段区分是否仅管理自己发的钥匙 + * @property {Number} restoreCount - 重置次数 + * @property {String} model - 模式 + */ + +/** + * 锁蓝牙信息 + * @typedef {Object} bluetooth + * @property {String} bluetoothDeviceId - 设备ID + * @property {String} bluetoothDeviceName - 设备名称 + * @property {String} publicKey - 公钥 + * @property {String} privateKey - 私钥 + * @property {String} signKey - 签名密钥 + * @property {String} passwordKey - 密码密钥 + */ + +/** + * 锁设置信息 + * @typedef {Object} lockSetting + * @property {Number} appUnlockOnline - 开门是否需要联网 + */ + +/** + * 请求返回数据 + * @typedef {Object} requestData + * @property {String} userNos - 设备ID + */ + +// 命令ID +const cmdIds = { + // 获取公钥 + getPublicKey: 0x3090, + // 获取私钥 + getCommKey: 0x3091, + // 获取锁状态 + getLockStatus: 0x3040, + // 新增用户 + addUser: 0x3001, + // 开门 + openDoor: 0x3005, + // 重置设备 + resetDevice: 0x3004, + // 清理用户 + cleanUser: 0x300C, + // 扩展命令 + expandCmd: 0x3030 +} + +// 子命令ID +const subCmdIds = { + // 设置开锁密码 + setLockPassword: 3, + // 重置开锁密码 + resetLockPassword: 19 +} + +// 特性值回调 +let characteristicValueCallback = null +// 完整数据 +let completeArray +// 完整内容数据长度 +let length +// 请求参数 +let requestParams = null + +export const useStarCloudStore = defineStore('starCloud', { + state() { + return { + // 环境 + env: null, + // 客户端Id + clientId: null, + // 客户端密码 + clientSecret: null, + // 星云是否登录 + loginStarCloud: false, + // 星云用户信息 + userInfo: null, + // 账户信息 + accountInfo: null, + // 锁信息 + lockInfo: null, + // 消息序号 + messageCount: 1, + // 服务器时间 + serverTimestamp: 0, + // 时间差 + timeDifference: 0, + // 小程序环境 + envVersion: '' + } + }, + actions: { + // 初始化星云 + initStarCloud(clientId, clientSecret, env = 'XHJ') { + const appInfo = uni.getAccountInfoSync() + this.envVersion = appInfo.miniProgram.envVersion + + this.env = env + this.clientId = clientId + this.clientSecret = clientSecret + // 监听特性值变化 + onBLECharacteristicValueChange(this.listenCharacteristicValue) + }, + // 注册星云 + async register() { + const { + code, + data, + message + } = await starCloudCreateUser({ + clientId: this.clientId, + clientSecret: this.clientSecret + }) + return new Result(code, data, message) + }, + // 登录星云 + async login(username, password) { + this.accountInfo = { + username, + password + } + setStorage('starCloudUser', {"username":"vridg_Hgn3uuO1Sh36Hc2oI","access_token":"Bh7fBK8gIIsHPmZJG6Jpr4ka0tNHbAVJ3i43v69a","uid":650,"refresh_token":"TguBYKgPu9T0b5V96opXzk0gGaj3hMTpHANVsc1y","scope":"user,key,room","token_type":"Bearer","expires_in":7349225}) + setStorage('starCloudToken', 'Bh7fBK8gIIsHPmZJG6Jpr4ka0tNHbAVJ3i43v69a') + + const token = getStorage('starCloudToken') + if (token) { + this.userInfo = getStorage('starCloudUser') + this.loginStarCloud = true + // 获取服务器时间 + this.getServerTimestamp() + .then(() => {}) + return Result.Success + } + console.log('登录星云', username, password) + const { + code, + data: userInfo, + message + } = await getStarCloudToken({ + username: username, + password: password, + clientId: this.clientId, + clientSecret: this.clientSecret + }) + if (code === Result.Success.code) { + this.userInfo = userInfo + setStorage('starCloudToken', userInfo.access_token) + setStorage('starCloudUser', userInfo) + this.loginStarCloud = true + // 获取服务器时间 + this.getServerTimestamp() + .then(() => {}) + } + return new Result(code, {}, message) + }, + // 选择锁 + async selectLock(lockId) { + const { + code, + data, + message + } = await getLockDetail({ + lockId + }) + if (code === Result.Success.code) { + const lockList = getStorage('lockList') + if(lockList) { + const index = lockList.findIndex(item => item.lockId === lockId) + if (index === -1) { + lockList.push(data) + } else { + lockList[index] = data + } + setStorage('lockList', lockList) + } else { + setStorage('lockList', [data]) + } + this.lockInfo = data + } else { + const lockList = getStorage('lockList') + console.log('锁列表', lockList) + if(lockList) { + const index = lockList.findIndex(item => item.lockId === lockId) + if (index !== -1) { + this.lockInfo = lockList[index] + return new Result(Result.Success.code, this.lockInfo) + } + } + } + return new Result(code, data, message) + }, + // 清理用户 + async cleanLockUser(disconnect = false) { + // 确认设备连接正常 + const searchResult = await searchAndConnectDevice(this.lockInfo.bluetooth.bluetoothDeviceName) + if (searchResult.code !== Result.Success.code) { + return searchResult + } + this.updateLockInfo(searchResult.data) + + // 获取并处理锁信息 + let { + uid: authUid, + keyId, + token, + bluetooth + } = this.lockInfo + let { uid } = this.userInfo + authUid = authUid.toString() + uid = uid.toString() + keyId = keyId.toString() + const name = bluetooth.bluetoothDeviceName + + // 获取用户列表 + const { + code: requestCode, + data: requestData + } = await getUserNoListRequest({ + lockId: this.lockInfo.lockId + }) + console.log('获取用户列表请求结果', requestCode, requestData) + if (requestCode !== 0) return Result.Fail + const userNoList = requestData.userNos + + // 组装发送数据 + const length = 2 + 40 + 20 + 40 + 20 + 2 + userNoList.length + 4 + 1 + 16 + + const headArray = this.createPackageHeader(3, length) + const contentArray = new Uint8Array(length) + + contentArray[0] = cmdIds.cleanUser / 256 + contentArray[1] = cmdIds.cleanUser % 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) + } + + for (let i = 0; i < keyId.length; i++) { + contentArray[i + 62] = keyId.charCodeAt(i) + } + + for (let i = 0; i < uid.length; i++) { + contentArray[i + 102] = uid.charCodeAt(i) + } + + contentArray[122] = userNoList.length / 256 + contentArray[123] = userNoList.length % 256 + + for (let i = 0; i < userNoList.length; i++) { + contentArray[i + 124] = userNoList[i] + } + + contentArray.set(token || new Uint8Array([0, 0, 0, 0]), 124 + userNoList.length) + + contentArray[128 + userNoList.length] = 16 + + const md5Array = md5Encrypt(authUid + keyId, token || new Uint8Array([0, 0, 0, 0]), bluetooth.publicKey) + + contentArray.set(md5Array, 129 + userNoList.length) + + const cebArray = sm4.encrypt(contentArray, 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.cleanLockUser, disconnect) + }, + // 开门 + async openDoor(type = 'open', disconnect) { + // 确认设备连接正常 + 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 onlineToken = '' + if (this.lockInfo.lockSetting.appUnlockOnline) { + const result = await this.getNetToken() + if (result.code === Result.Success.code) { + onlineToken = result.data.token + } else { + return result + } + } + + // 开门方式 + 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.userInfo.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) + + 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.openDoor, disconnect) + }, + // 获取离线密码 + async getOfflinePassword(password) { + return await getOfflinePassword({ + ...password, + lockId: this.lockInfo.lockId + }) + }, + // 自定义密码 + async customPassword(password, disconnect) { + // 确认设备连接正常 + 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 + } + + requestParams = password + let { pwdNo, operate, keyboardPwd, startDate, endDate, pwdRight } = password + + const uid = this.userInfo.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, disconnect, password) + }, + + + + // 获取联网token + async getNetToken() { + const { + code, + data, + message + } = await getLockNetTokenRequest({ + lockId: this.lockInfo.lockId + }) + return new Result(code, data, message) + }, + // 获取服务器时间 + async getServerTimestamp() { + const { + code, + data, + message + } = await getServerDatetime({}) + if (code === Result.Success.code) { + this.serverTimestamp = Math.ceil(data.date / 1000) + this.timeDifference = Math.ceil((data.date - new Date() + .getTime()) / 1000) + } + return new Result(code, data, message) + }, + // 添加用户 + async addLockUser(data, disconnect = false) { + // 确认设备连接正常 + const searchResult = await searchAndConnectDevice(this.lockInfo.bluetooth.bluetoothDeviceName) + if (searchResult.code !== Result.Success.code) { + return searchResult + } + this.updateLockInfo(searchResult.data) + + const { + name, + authUid, + uid, + keyId, + openMode, + keyType, + startDate, + expireDate, + useCountLimit, + isRound, + weekRound, + startHour, + startMin, + endHour, + endMin, + role, + password + } = data + + const length = 2 + 40 + 20 + 40 + 20 + 1 + 1 + 4 + 4 + 2 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 20 + 4 + + 1 + 16 + const headArray = this.createPackageHeader(3, length) + const contentArray = new Uint8Array(length) + + contentArray[0] = cmdIds.addUser / 256 + contentArray[1] = cmdIds.addUser % 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) + } + + for (let i = 0; i < keyId.length; i++) { + contentArray[i + 62] = keyId.charCodeAt(i) + } + + for (let i = 0; i < uid.length; i++) { + contentArray[i + 102] = uid.charCodeAt(i) + } + + contentArray[122] = openMode + contentArray[123] = keyType + + contentArray.set(timestampToArray(startDate), 124) + contentArray.set(timestampToArray(expireDate), 128) + + contentArray[132] = useCountLimit / 256 + contentArray[133] = useCountLimit % 256 + + contentArray[134] = isRound + contentArray[135] = weekRound + contentArray[136] = startHour + contentArray[137] = startMin + contentArray[138] = endHour + contentArray[139] = endMin + contentArray[140] = role + + for (let i = 0; i < password.length; i++) { + contentArray[i + 141] = password.charCodeAt(i) + } + + contentArray.set(this.lockInfo.token || timestampToArray(startDate), 161) + + contentArray[165] = 16 + + const md5Array = md5Encrypt(authUid + keyId, this.lockInfo.token || timestampToArray(startDate), + this.lockInfo.bluetooth.publicKey) + + contentArray.set(md5Array, 166) + + 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.addLockUser, disconnect, data) + }, + // 获取写入结果 + getWriteResult(request, disconnect = false, params) { + return new Promise(resolve => { + const getWriteResultTimer = setTimeout(() => { + resolve(Result.Fail) + }, 20000) + characteristicValueCallback = async (data) => { + // code 6 token过期,重新获取 + if (data.code === Result.NotTokenLock.code) { + resolve(await request(params)) + } else if (data.code === Result.NotRegisteredLock.code) { + const checkResult = await this.checkLockUser(true) + if (checkResult.code === Result.Success.code) { + resolve(await request(params)) + } else { + clearTimeout(getWriteResultTimer) + resolve(checkResult) + } + } else { + clearTimeout(getWriteResultTimer) + if(disconnect) { + await this.disconnectDevice() + } + console.log('写入结果', data, request, params) + resolve(data) + } + } + }) + }, + // 检查是否已添加为用户 + async checkLockUser(forceAdd = false) { + if (this.lockInfo.lockUserNo === 0 || forceAdd) { + const timestamp = Math.floor(new Date() + .getTime() / 1000) + const password = (Math.floor(Math.random() * 900000) + 100000) + .toString() + console.log('用户未添加,开始添加用户') + const addUserParams = { + name: this.lockInfo.bluetooth.bluetoothDeviceName, + keyId: this.lockInfo.keyId.toString(), + authUid: this.lockInfo.uid.toString(), + uid: this.userInfo.uid.toString(), + openMode: 1, + keyType: 0, + startDate: this.lockInfo.startDate === 0 ? timestamp : Math.floor(this.lockInfo.startDate / + 1000), + expireDate: this.lockInfo.endDate === 0 ? 0xffffffff : Math.floor(this.lockInfo.endDate / + 1000), + useCountLimit: this.lockInfo.keyType === 3 ? 1 : 0xffff, + isRound: this.lockInfo.keyType === 4 ? 1 : 0, + weekRound: this.lockInfo.keyType === 4 ? convertWeekdaysToNumber(this.lockInfo.weekDays) : + 0, + startHour: this.lockInfo.keyType === 4 ? new Date(this.lockInfo.startDate) + .getHours() : 0, + startMin: this.lockInfo.keyType === 4 ? new Date(this.lockInfo.startDate) + .getMinutes() : 0, + endHour: this.lockInfo.keyType === 4 ? new Date(this.lockInfo.endDate) + .getHours() : 0, + endMin: this.lockInfo.keyType === 4 ? new Date(this.lockInfo.endDate) + .getMinutes() : 0, + role: 0, + password + } + const addUserResult = await this.addLockUser(addUserParams) + console.log('添加用户蓝牙结果', addUserResult) + if (addUserResult.code === Result.Success.code) { + const { + code + } = await updateLockUserNoRequest({ + keyId: this.lockInfo.keyId, + lockUserNo: this.lockInfo.lockUserNo + }) + console.log('添加用户请求结果', code) + return Result.Success + } else if (addUserResult.code === Result.NotMoreKeyLock.code) { + console.log('用户达上限,开始清理用户') + const { + code: cleanCode + } = await this.cleanLockUser() + console.log('清理用户蓝牙结果', cleanCode) + if (cleanCode === Result.Success.code) { + return await this.checkLockUser() + } else { + return Result.Fail + } + } else if (addUserResult.code === Result.ReadyHasKeyLock.code) { + return Result.Success + } else { + return Result.Fail + } + } else { + return Result.Success + } + }, + // 更新锁信息 + updateLockInfo(lockInfo) { + this.lockInfo = { + ...this.lockInfo, + ...lockInfo + } + }, + // 特征值变化回调 + listenCharacteristicValue(res) { + if (res.deviceId === this.lockInfo.deviceId) { + let binaryData = new Uint8Array(res.value) + if (binaryData[0] === 0xEF && binaryData[1] === 0x01 && binaryData[2] === 0xEE && binaryData[3] === + 0x02) { + length = binaryData[8] * 256 + binaryData[9] + if (length + 14 > binaryData.length) { + completeArray = binaryData + } else { + this.parsingCharacteristicValue(binaryData).then(() => {}) + } + } else { + if (completeArray) { + const combinedArray = new Uint8Array(completeArray.length + binaryData.length) + combinedArray.set(completeArray, 0) + combinedArray.set(binaryData, completeArray.length) + completeArray = combinedArray + if (length + 14 === completeArray.length) { + this.parsingCharacteristicValue(completeArray).then(() => {}) + completeArray = null + } + } + } + } + }, + // 解析特征值 + async parsingCharacteristicValue (binaryData) { + // 0x20 明文 0x22 SM4(事先约定密钥) 0x23 SM4(设备指定密钥) + if (binaryData[7] === 0x20) { + if (binaryData[12] * 256 + binaryData[13] === cmdIds.getPublicKey) { + if (binaryData[14] === Result.Success.code) { + this.updateLockInfo({ + bluetooth: { + ...this.lockInfo.bluetooth, + publicKey: [...binaryData.slice(15, 31)] + } + }) + } + characteristicValueCallback(new Result(binaryData[14])) + } + } else if (binaryData[7] === 0x22) { + // 截取入参 + const cebBinaryData = binaryData.slice(12, binaryData.length - 2) + // 解密 + const key = new Uint8Array(16) + for (let i = 0; i < this.lockInfo.bluetooth.bluetoothDeviceName.length; i++) { + key[i] = this.lockInfo.bluetooth.bluetoothDeviceName.charCodeAt(i) + } + const decrypted = sm4.decrypt(cebBinaryData, key, { + mode: 'ecb', + output: 'array' + }) + console.log('ecb解密后的数据', decrypted) + + if (decrypted[0] * 256 + decrypted[1] === cmdIds.getCommKey) { + if (decrypted[2] === Result.Success.code) { + this.updateLockInfo({ + bluetooth: { + ...this.lockInfo.bluetooth, + privateKey: decrypted.slice(3, 19), + signKey: decrypted.slice(19, 35), + pwdTimestamp: arrayToTimestamp(decrypted.slice(35, 39)) * 1000 + } + }) + console.log('privateKey', Array.from(this.lockInfo.bluetooth.privateKey)) + console.log('signKey', Array.from(this.lockInfo.signKey)) + } + characteristicValueCallback(new Result(decrypted[2])) + } + } else { + const cebBinaryData = binaryData.slice(12, binaryData.length - 2) + + const decrypted = sm4.decrypt(cebBinaryData, this.lockInfo.bluetooth.privateKey, { + mode: 'ecb', + output: 'array' + }) + console.log('ecb解密后的数据', decrypted) + + const cmdId = decrypted[0] * 256 + decrypted[1] + + switch (cmdId) { + case cmdIds.getLockStatus: + if (decrypted[2] === Result.Success.code) { + const lockConfig = { + vendor: uint8ArrayToString(decrypted.slice(3, 23)), + product: decrypted[23], + model: uint8ArrayToString(decrypted.slice(24, 44)), + fwVersion: uint8ArrayToString(decrypted.slice(44, 64)), + hwVersion: uint8ArrayToString(decrypted.slice(64, 84)), + serialNum0: uint8ArrayToString(decrypted.slice(84, 100)), + serialNum1: uint8ArrayToString(decrypted.slice(100, 116)), + btDeviceName: uint8ArrayToString(decrypted.slice(116, 132)), + electricQuantity: decrypted[132], + electricQuantityStandby: decrypted[133], + restoreCount: decrypted[134] * 256 + decrypted[135], + restoreDate: arrayToTimestamp(decrypted.slice(136, 140)), + icPartNo: uint8ArrayToString(decrypted.slice(140, 150)), + indate: arrayToTimestamp(decrypted.slice(150, 154)), + mac: uint8ArrayToString(decrypted.slice(154, 174)), + timezoneOffset: new Date() + .getTimezoneOffset() * 60 + } + this.updateLockInfo({ + featureValue: uint8ArrayToString(decrypted.slice(175, 175 + decrypted[ + 174])), + featureSettingValue: uint8ArrayToString(decrypted.slice(176 + decrypted[ + 174], 176 + decrypted[174] + decrypted[175 + decrypted[ + 174]])), + featureSettingParams: Array.from(decrypted.slice(176 + decrypted[174] + + decrypted[175 + decrypted[174]])), + lockConfig + }) + console.log('获取锁状态成功', this.lockInfo.lockConfig) + } + characteristicValueCallback(new Result(decrypted[2])) + break + case cmdIds.addUser: + this.updateLockInfo({ + token: decrypted.slice(42, 46) + }) + if (decrypted[46] === Result.Success.code) { + this.updateLockInfo({ + lockUserNo: decrypted[47] * 256 + decrypted[48] + }) + } + console.log('添加用户结果', decrypted[46], this.lockInfo.token) + characteristicValueCallback(new Result(decrypted[46])) + break + case cmdIds.expandCmd: + const subCmdId = decrypted[3] + switch (subCmdId) { + case subCmdIds.resetLockPassword: + this.updateLockInfo({ + token: decrypted.slice(5, 9) + }) + characteristicValueCallback(new Result(decrypted[4])) + break + case subCmdIds.setLockPassword: + this.updateLockInfo({ + token: decrypted.slice(5, 9) + }) + if (decrypted[2] === Result.Success.code) { + if(decrypted[11] === Result.Success.code) { + const pwdNo = decrypted[9] * 256 + decrypted[10] + if (requestParams.operate === 0) { + const addResult = await addCustomPassword({ + ...requestParams, + pwdUserNo: pwdNo, + lockId: this.lockInfo.lockId + }) + if (addResult.code === Result.Success.code) { + characteristicValueCallback(new Result(addResult.code, { + pwdNo: pwdNo, + keyboardPwdId: addResult.data.keyboardPwdId, + keyboardPwd: addResult.data.keyboardPwd + })) + } else { + characteristicValueCallback(new Result(addResult.code, addResult.data, addResult.message)) + } + } else if (requestParams.operate === 1) { + const updateResult = await updatePassword({ + ...requestParams, + keyboardPwdId: this.lockInfo.keyboardPwdId + }) + if (updateResult.code === Result.Success.code) { + characteristicValueCallback(new Result(updateResult.code)) + } else { + characteristicValueCallback(new Result(updateResult.code, updateResult.data, updateResult.message)) + } + } + } else { + characteristicValueCallback(new Result(decrypted[11])) + } + } else { + characteristicValueCallback(new Result(decrypted[2])) + } + break + } + break + case cmdIds.openDoor: + this.updateLockInfo({ + token: decrypted.slice(2, 6) + }) + console.log('开门', decrypted[6], this.lockInfo.token) + characteristicValueCallback(new Result(decrypted[6])) + break + default: + this.updateLockInfo({ + token: decrypted.slice(2, 6) + }) + console.log('默认结果', decrypted[6], this.lockInfo.token) + characteristicValueCallback(new Result(decrypted[6])) + break + } + } + }, + // 获取配置 + getConfig() { + let config = configs[this.env] + return { + ...config, + version, + buildNumber + } + }, + /* + * 生成包头 + * encryptionType 加密类型 0:明文,1:AES128,2:SM4(事先约定密钥),3:SM4(设备指定密钥) + * originalLength 原始数据长度 + * */ + createPackageHeader(encryptionType, originalLength) { + // 头部数据 + let headArray = new Uint8Array(12) + + // 固定包头 + headArray[0] = 0xEF + headArray[1] = 0x01 + headArray[2] = 0xEE + headArray[3] = 0x02 + + // 包类型 发送 + headArray[4] = 0x01 + + // 包序号 + headArray[5] = this.messageCount / 256 + headArray[6] = this.messageCount % 256 + this.messageCount++ + + // 包标识 + if (encryptionType === 0) { + headArray[7] = 0x20 + } else if (encryptionType === 2) { + headArray[7] = 0x22 + } else { + headArray[7] = 0x23 + } + + // 数据长度 + if (encryptionType === 0) { + headArray[8] = originalLength / 256 + headArray[9] = originalLength % 256 + } else { + const length = Math.ceil(originalLength / 16) * 16 + headArray[8] = length / 256 + headArray[9] = length % 256 + } + headArray[10] = originalLength / 256 + headArray[11] = originalLength % 256 + + return headArray + }, + // 断开与设备的连接 + async disconnectDevice() { + return await closeBLEConnection(this.lockInfo.deviceId) + }, + } +}) diff --git a/storage.js b/storage.js new file mode 100644 index 0000000..b6a8fe9 --- /dev/null +++ b/storage.js @@ -0,0 +1,18 @@ +import { useStarCloudStore } from '@/starCloud/starCloud' + +export function setStorage(key, value) { + return uni.setStorageSync(getPrefix() + key, value) +} + +export function getStorage(key) { + return uni.getStorageSync(getPrefix() + key) +} + +export function removeStorage(key) { + return uni.removeStorageSync(getPrefix() + key) +} + +function getPrefix() { + const starCloud = useStarCloudStore() + return `${ starCloud.envVersion }:` +} From 464f57925b19c33ed6b0b17e98b26037988a096b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8C=83=E9=B9=8F?= Date: Sat, 12 Oct 2024 15:23:54 +0800 Subject: [PATCH 02/25] =?UTF-8?q?feat:=20=E5=B0=8F=E7=A8=8B=E5=BA=8F?= =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 98 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e2ef19a..f5266a6 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,103 @@ ## 星云SDK ### 1. 安装 - +在需要引用的项目中执行命令 +`git fetch git@code.star-lock.cn:xhj/starcloud-sdk-uniapp.git master` ### 2. 需安装的npm包 `npm install buffer crc js-md5 pinia sm-crypto` +### 3. 使用 +```javascript +import { useStarCloudStore } from '@/starCloud/starCloud' +const $starCloud = useStarCloudStore() + +/** + * 初始化SDK + * @property {String} clientId - 客户端Id + * @property {String} clientSecret - 客户端密码 + * @property {String} env - 环境('DEV', 'PRE', 'XHJ', 'SKY) + */ +$starCloud.initStarCloud(clientId, clientSecret, env) + +// 注册,后续所有方法调用返回值均为code, data, message +// code对应报错码有三部分组合构成,锁端报错码+星云服务端报错码+自定义报错码 +// Result类定义了所有自定义报错码,具体报错码请查看Result类 +const { code, data, message } = await $starCloud.register() +if(code === Result.Success.code) { + // 逻辑代码 +} else { + // 错误处理 +} + +/** + * 登录 + * @property {String} username - 用户名 + * @property {String} password - 密码 + */ +const { code, data, message } = await $starCloud.login(username, password) + +/** + * 选择锁 + * @property {Number} lockId - 锁Id + */ +const { code, data, message } = await $starCloud.selectLock(lockId) + +/** + * 开门 + * @property {String} type - 开门或关门类型('open', 'close') + * @property {Boolean} disconnect - 操作完成后是否断开连接 + */ +const { code, data, message } = await $starCloud.openDoor(type, disconnect) + +/** + * 清理用户 + * @property {Boolean} disconnect - 操作完成后是否断开连接 + */ +const { code, data, message } = await $starCloud.cleanLockUser(disconnect) + +/** + * 获取离线密码 + * 该功能无需蓝牙交互直接请求服务端,详细参数说明请看星云接口文档 + * @typedef {Object} password + * @property {String} keyboardPwdName - 密码名称 + * @property {Number} keyboardPwdType - 密码类型 + * @property {Number} isCoerced - 胁迫 1:胁迫 2:非胁迫 + * @property {Number} startDate - 开始时间 + * @property {Number} endDate - 结束时间 + * @property {Number} hoursStart - 开始小时 + * @property {Number} hoursEnd - 结束小时 + */ +const data = await $starCloud.getOfflinePassword({ + keyboardPwdName: `租客端单次密码${new Date().getTime()}`, + keyboardPwdType: 1, + isCoerced: 2, + startDate: 0, + endDate: 0, + hoursStart: 0, + hoursEnd: 0 +}) + +/** + * 自定义密码 + * @typedef {Object} password + * @property {String} keyboardPwdName - 密码名称 + * @property {Number} keyboardPwdType - 密码类型 + * @property {Number} isCoerced - 胁迫 1:胁迫 2:非胁迫 + * @property {Number} startDate - 开始时间 + * @property {Number} endDate - 结束时间 + * @property {Number} keyboardPwd - 密码 + * @property {Number} addType - 添加方式,当前仅支持1 1:蓝牙 2:网关 + * @property {Number} operate - 操作类型,0:注册 1:修改 + * @property {Number} pwdRight - 是否是管理员密码,0:否 1:是 + */ +const data = await $starCloud.customPassword({ + keyboardPwdName: `租客端自定义密码`, + keyboardPwdType: 3, + keyboardPwd: 111111, + addType: 1, + isCoerced: 2, + startDate: 1728698137000, + endDate: 1735574400000, + operate: 0, + pwdRight: 0 +}, true) +``` From 077f4315831cf30bbe17a579f27adb42cb2e3476 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8C=83=E9=B9=8F?= Date: Sat, 12 Oct 2024 15:26:50 +0800 Subject: [PATCH 03/25] =?UTF-8?q?feat:=20=E5=B0=8F=E7=A8=8B=E5=BA=8F?= =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 +++- starCloud.js | 2 -- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f5266a6..d654027 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,9 @@ ### 1. 安装 在需要引用的项目中执行命令 -`git fetch git@code.star-lock.cn:xhj/starcloud-sdk-uniapp.git master` +`git subtree add --prefix=starCloud git@code.star-lock.cn:xhj/starcloud-sdk-uniapp.git master` +更新 +`git subtree pull --prefix=starCloud git@code.star-lock.cn:xhj/starcloud-sdk-uniapp.git master` ### 2. 需安装的npm包 `npm install buffer crc js-md5 pinia sm-crypto` ### 3. 使用 diff --git a/starCloud.js b/starCloud.js index 2257827..be154ae 100644 --- a/starCloud.js +++ b/starCloud.js @@ -182,8 +182,6 @@ export const useStarCloudStore = defineStore('starCloud', { username, password } - setStorage('starCloudUser', {"username":"vridg_Hgn3uuO1Sh36Hc2oI","access_token":"Bh7fBK8gIIsHPmZJG6Jpr4ka0tNHbAVJ3i43v69a","uid":650,"refresh_token":"TguBYKgPu9T0b5V96opXzk0gGaj3hMTpHANVsc1y","scope":"user,key,room","token_type":"Bearer","expires_in":7349225}) - setStorage('starCloudToken', 'Bh7fBK8gIIsHPmZJG6Jpr4ka0tNHbAVJ3i43v69a') const token = getStorage('starCloudToken') if (token) { From f5358fea62a9aa0ed7416f615c95b5deacab2f44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8C=83=E9=B9=8F?= Date: Sat, 12 Oct 2024 15:30:25 +0800 Subject: [PATCH 04/25] =?UTF-8?q?feat:=20=E6=9B=B4=E6=96=B0sdk=E8=AF=B4?= =?UTF-8?q?=E6=98=8E=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index d654027..f87dac4 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,13 @@ `git subtree pull --prefix=starCloud git@code.star-lock.cn:xhj/starcloud-sdk-uniapp.git master` ### 2. 需安装的npm包 `npm install buffer crc js-md5 pinia sm-crypto` + +pinia是全局状态管理工具,需在main.js中引入 +```javascript +import * as Pinia from 'pinia' +const store = Pinia.createPinia() +app.use(store) +``` ### 3. 使用 ```javascript import { useStarCloudStore } from '@/starCloud/starCloud' From 8dbabbb073fefa4d9231a75375380321f8a9b58c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8C=83=E9=B9=8F?= Date: Mon, 21 Oct 2024 09:58:17 +0800 Subject: [PATCH 05/25] =?UTF-8?q?feat:=201.=20=E6=B7=BB=E5=8A=A0lint?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- basic.js | 150 ++++++++++++++++------------ format.js | 16 ++- request.js | 34 +++---- starCloud.js | 270 ++++++++++++++++++++++++++------------------------- storage.js | 2 +- 5 files changed, 248 insertions(+), 224 deletions(-) diff --git a/basic.js b/basic.js index 6a0032f..9fabfde 100644 --- a/basic.js +++ b/basic.js @@ -13,7 +13,7 @@ export class Result { NotRegisteredLock: 4, NotTokenLock: 6, NotMoreKeyLock: 12, - ReadyHasKeyLock: 15, + ReadyHasKeyLock: 15 } static resultsMap = new Map([ @@ -22,15 +22,24 @@ export class Result { [Result.codes.NotAvailableBluetooth, { message: '蓝牙未开启', data: {} }], [Result.codes.NotAvailableBluetoothPermission, { message: '小程序蓝牙权限被禁用', data: {} }], - [Result.codes.NotAvailableWeChatNearbyDevicesPermission, { message: '微信附近的设备权限被禁用', data: {} }], - [Result.codes.NotAvailableWeChatLocationPermission, { message: '微信定位权限被禁用', data: {} }], - [Result.codes.NotAvailableWeChatNearbyDevicesEmpty, { message: '微信附近的设备权限无法使用', data: {} }], + [ + Result.codes.NotAvailableWeChatNearbyDevicesPermission, + { message: '微信附近的设备权限被禁用', data: {} } + ], + [ + Result.codes.NotAvailableWeChatLocationPermission, + { message: '微信定位权限被禁用', data: {} } + ], + [ + Result.codes.NotAvailableWeChatNearbyDevicesEmpty, + { message: '微信附近的设备权限无法使用', data: {} } + ], [Result.codes.DeviceHasBeenReset, { message: '设备已被重置', data: {} }], [Result.codes.NotRegisteredLock, { message: '用户在锁端未注册', data: {} }], [Result.codes.NotTokenLock, { message: '用户在锁端token失效', data: {} }], [Result.codes.NotMoreKeyLock, { message: '锁端钥匙数量已达上限', data: {} }], - [Result.codes.ReadyHasKeyLock, { message: '用户已是锁端用户', data: {} }], + [Result.codes.ReadyHasKeyLock, { message: '用户已是锁端用户', data: {} }] ]) constructor(code, data, message) { @@ -107,7 +116,6 @@ export class Result { } } - /** * @typedef {Object} err * @property {number} errno - 错误代码 @@ -122,9 +130,9 @@ export function searchAndConnectDevice(name) { // 超时计时器 let timeoutTimer - return new Promise(async (resolve) => { + return new Promise(async resolve => { const result = await startBluetoothDevicesDiscovery() - if(result.code === Result.Success.code) { + if (result.code === Result.Success.code) { let searchFlag = false timeoutTimer = setTimeout(async () => { await stopBluetoothDevicesDiscovery() @@ -137,7 +145,7 @@ export function searchAndConnectDevice(name) { }, 10500) timer = setInterval(async () => { const queryResult = await getBluetoothDevices() - if(queryResult.code === Result.Success.code) { + if (queryResult.code === Result.Success.code) { const deviceList = queryResult.data if (searchFlag === false && deviceList.length > 0) { searchFlag = true @@ -145,11 +153,11 @@ export function searchAndConnectDevice(name) { for (let i = 0; i < deviceList.length; i++) { if (deviceList[i]?.name === name) { const uuid = deviceList[i]?.advertisServiceUUIDs[0] - if(uuid && uuid.slice(2, 8) === '758824') { + if (uuid && uuid.slice(2, 8) === '758824') { await stopBluetoothDevicesDiscovery() clearTimeout(timeoutTimer) clearInterval(timer) - if(uuid.slice(30, 32) === '00') { + if (uuid.slice(30, 32) === '00') { resolve(Result.DeviceHasBeenReset) } else if (uuid.slice(30, 32) === '01') { const connectResult = await createBLEConnection(deviceList[i].deviceId) @@ -172,37 +180,40 @@ export function searchAndConnectDevice(name) { } // 蓝牙操作报错处理 -async function handleError (err, event) { +async function handleError(err, event) { if (err.errCode === 10000) { const result = await openBluetoothAdapter() if (result.code === Result.Success.code) { return await event() - } else { - return result } - } else if (err.errCode === 10001) { - return Result.NotAvailableBluetooth - } else if (err.errno === 3) { - return Result.NotAvailableWeChatNearbyDevicesPermission - } else if (err.errno === 103) { - return Result.NotAvailableBluetoothPermission - } else if (err.errno === 1509008) { - return Result.NotAvailableWeChatLocationPermission - } else if (err.errMsg === 'openBluetoothAdapter:fail already opened') { - return Result.Success - } else { - return Result.Fail + return result } + if (err.errCode === 10001) { + return Result.NotAvailableBluetooth + } + if (err.errno === 3) { + return Result.NotAvailableWeChatNearbyDevicesPermission + } + if (err.errno === 103) { + return Result.NotAvailableBluetoothPermission + } + if (err.errno === 1509008) { + return Result.NotAvailableWeChatLocationPermission + } + if (err.errMsg === 'openBluetoothAdapter:fail already opened') { + return Result.Success + } + return Result.Fail } // 初始化蓝牙模块 function openBluetoothAdapter() { - return new Promise((resolve) => { + return new Promise(resolve => { uni.openBluetoothAdapter({ success() { resolve(Result.Success) }, - async fail (err) { + async fail(err) { resolve(await handleError(err)) } }) @@ -211,12 +222,12 @@ function openBluetoothAdapter() { // 关闭蓝牙模块 function closeBluetoothAdapter() { - return new Promise((resolve) => { + return new Promise(resolve => { uni.closeBluetoothAdapter({ success() { resolve(Result.Success) }, - async fail (err) { + async fail(err) { resolve(await handleError(err)) } }) @@ -230,19 +241,19 @@ function offBluetoothAdapterStateChange() { // 监听蓝牙特征值改变 export function onBLECharacteristicValueChange(callback) { - uni.onBLECharacteristicValueChange((res) => { + uni.onBLECharacteristicValueChange(res => { callback(res) }) } // 开始搜索附近的蓝牙设备 function startBluetoothDevicesDiscovery() { - return new Promise((resolve) => { + return new Promise(resolve => { uni.startBluetoothDevicesDiscovery({ success() { resolve(Result.Success) }, - async fail (err) { + async fail(err) { resolve(await handleError(err, startBluetoothDevicesDiscovery)) } }) @@ -251,12 +262,12 @@ function startBluetoothDevicesDiscovery() { // 获取所有已发现的蓝牙设备 function getBluetoothDevices() { - return new Promise((resolve) => { + return new Promise(resolve => { uni.getBluetoothDevices({ success(res) { resolve(new Result(Result.Success.code, res.devices)) }, - async fail () { + async fail(err) { resolve(await handleError(err, getBluetoothDevices)) } }) @@ -265,12 +276,12 @@ function getBluetoothDevices() { // 停止搜索附近的蓝牙设备 function stopBluetoothDevicesDiscovery() { - return new Promise((resolve) => { + return new Promise(resolve => { uni.stopBluetoothDevicesDiscovery({ success() { resolve(Result.Success) }, - async fail () { + async fail(err) { resolve(await handleError(err)) } }) @@ -279,19 +290,27 @@ function stopBluetoothDevicesDiscovery() { // 连接低功耗蓝牙设备 function createBLEConnection(deviceId, reconnectNumber = 0) { - return new Promise((resolve) => { + return new Promise(resolve => { uni.createBLEConnection({ deviceId, timeout: 10000, - async success () { + async success() { const res = await getBLEDeviceServicesAndCharacteristics(deviceId) - await notifyBLECharacteristicValueChange(deviceId, res.data.serviceId, res.data.notifyCharacteristicId) + await notifyBLECharacteristicValueChange( + deviceId, + res.data.serviceId, + res.data.notifyCharacteristicId + ) resolve(res) }, - async fail (err) { + async fail(err) { if (err.errno === 1509007) { const res = await getBLEDeviceServicesAndCharacteristics(deviceId) - await notifyBLECharacteristicValueChange(deviceId, res.data.serviceId, res.data.notifyCharacteristicId) + await notifyBLECharacteristicValueChange( + deviceId, + res.data.serviceId, + res.data.notifyCharacteristicId + ) resolve(res) } else if (err.errno === 1509001 && reconnectNumber < 1) { resolve(Result.Fail) @@ -306,7 +325,7 @@ function createBLEConnection(deviceId, reconnectNumber = 0) { } // 获取服务及对应特征值 -async function getBLEDeviceServicesAndCharacteristics (deviceId) { +async function getBLEDeviceServicesAndCharacteristics(deviceId) { const { code, data } = await getBLEDeviceServices(deviceId) if (code === Result.Success.code) { const { serviceId } = data @@ -315,28 +334,31 @@ async function getBLEDeviceServicesAndCharacteristics (deviceId) { data: { notifyCharacteristicId, writeCharacteristicId } } = await getBLEDeviceCharacteristics(deviceId, serviceId) if (code === Result.Success.code) { - return new Result(Result.Success.code, { deviceId, serviceId, notifyCharacteristicId, writeCharacteristicId }) - } else { - return Result.Fail + return new Result(Result.Success.code, { + deviceId, + serviceId, + notifyCharacteristicId, + writeCharacteristicId + }) } - } else { return Result.Fail } + return Result.Fail } // 获取设备的服务 function getBLEDeviceServices(deviceId) { - return new Promise((resolve) => { + return new Promise(resolve => { uni.getBLEDeviceServices({ deviceId, success(res) { let serviceId - for(let i = 0; i < res.services.length; i++) { - if(res.services[i].uuid.indexOf('FFF0') !== -1) { + for (let i = 0; i < res.services.length; i++) { + if (res.services[i].uuid.indexOf('FFF0') !== -1) { serviceId = res.services[i].uuid } } - if(!serviceId) { + if (!serviceId) { resolve(Result.Fail) return } @@ -351,24 +373,26 @@ function getBLEDeviceServices(deviceId) { // 获取服务的特征值 function getBLEDeviceCharacteristics(deviceId, serviceId) { - return new Promise((resolve) => { + return new Promise(resolve => { uni.getBLEDeviceCharacteristics({ deviceId, serviceId, success(res) { let notifyCharacteristicId let writeCharacteristicId - for(let i = 0; i < res.characteristics.length; i++) { + for (let i = 0; i < res.characteristics.length; i++) { const characteristic = res.characteristics[i] - if(characteristic.properties.notify) { + if (characteristic.properties.notify) { notifyCharacteristicId = characteristic.uuid } - if(characteristic.properties.write) { + if (characteristic.properties.write) { writeCharacteristicId = characteristic.uuid } } - if(notifyCharacteristicId && writeCharacteristicId) { - resolve(new Result(Result.Success.code, { notifyCharacteristicId, writeCharacteristicId })) + if (notifyCharacteristicId && writeCharacteristicId) { + resolve( + new Result(Result.Success.code, { notifyCharacteristicId, writeCharacteristicId }) + ) } else { resolve(Result.Fail) } @@ -382,7 +406,7 @@ function getBLEDeviceCharacteristics(deviceId, serviceId) { // 订阅特征值 function notifyBLECharacteristicValueChange(deviceId, serviceId, characteristicId) { - return new Promise((resolve) => { + return new Promise(resolve => { uni.notifyBLECharacteristicValueChange({ deviceId, serviceId, @@ -400,7 +424,7 @@ function notifyBLECharacteristicValueChange(deviceId, serviceId, characteristicI // 断开与低功耗蓝牙设备的连接 export function closeBLEConnection(deviceId) { - return new Promise((resolve) => { + return new Promise(resolve => { uni.closeBLEConnection({ deviceId, success() { @@ -417,11 +441,11 @@ export function closeBLEConnection(deviceId) { // 写入特征值 export function writeBLECharacteristicValue(deviceId, serviceId, characteristicId, binaryData) { - return new Promise((resolve) => { + return new Promise(resolve => { const count = Math.ceil(binaryData.length / 20) let successCount = 0 - for(let i = 0; i < count; i++) { - const writeData = binaryData.slice(i * 20, i === (count - 1) ? binaryData.length : (i + 1) * 20) + for (let i = 0; i < count; i++) { + const writeData = binaryData.slice(i * 20, i === count - 1 ? binaryData.length : (i + 1) * 20) uni.writeBLECharacteristicValue({ deviceId, serviceId, @@ -429,7 +453,7 @@ export function writeBLECharacteristicValue(deviceId, serviceId, characteristicI value: writeData.buffer, success() { successCount++ - if(successCount === count) { + if (successCount === count) { resolve(Result.Success) } }, diff --git a/format.js b/format.js index 3bd8313..b5afceb 100644 --- a/format.js +++ b/format.js @@ -1,21 +1,18 @@ -import { - md5 -} from 'js-md5' +import { md5 } from 'js-md5' import crc from 'crc' // 周数组转换 export function convertWeekdaysToNumber(weekDay) { let weekStr = '00000000' + // eslint-disable-next-line no-restricted-syntax for (const day of weekDay) { - const index = day % 7 // 将周日的索引转换为0 + const index = day % 7 weekStr = weekStr.substring(0, index) + '1' + weekStr.substring(index + 1) } // 倒序 weekStr - weekStr = weekStr.split('') - .reverse() - .join('') + weekStr = weekStr.split('').reverse().join('') return parseInt(weekStr, 2) } @@ -26,7 +23,7 @@ export function timestampToArray(timestamp) { array[0] = (timestamp & 0xff000000) >> 24 array[1] = (timestamp & 0xff0000) >> 16 array[2] = (timestamp & 0xff00) >> 8 - array[3] = (timestamp & 0xff) + array[3] = timestamp & 0xff return array } @@ -43,8 +40,7 @@ export function md5Encrypt(text, token, key) { md5Array.set(key, text.length + 4) const md5Text = md5(md5Array) - return new Uint8Array(md5Text.match(/.{1,2}/g) - .map(byte => parseInt(byte, 16))) + return new Uint8Array(md5Text.match(/.{1,2}/g).map(byte => parseInt(byte, 16))) } // 生成包尾 头部数据+内容数据 diff --git a/request.js b/request.js index 3f436de..f596ac0 100644 --- a/request.js +++ b/request.js @@ -3,19 +3,19 @@ import { useStarCloudStore } from '@/starCloud/starCloud' import { Result } from '@/starCloud/basic' /* -* config -* baseUrl: 请求域名 -* url: 请求路径 -* method: 请求方法 -* header: 请求头 -* token: 请求token -* data: 请求参数 -* */ + * config + * baseUrl: 请求域名 + * url: 请求路径 + * method: 请求方法 + * header: 请求头 + * token: 请求token + * data: 请求参数 + * */ -const request = (config) => { +const request = config => { const starCloud = useStarCloudStore() let timer - return new Promise(async (resolve) => { + return new Promise(async resolve => { const baseConfig = starCloud.getConfig() const token = config?.token ? config.token : getStorage('starCloudToken') @@ -40,7 +40,7 @@ const request = (config) => { // 超时处理 timer = setTimeout(() => { - resolve(new Result(Result.Fail.code, {},'网络访问失败,请检查网络是否正常')) + resolve(new Result(Result.Fail.code, {}, '网络访问失败,请检查网络是否正常')) }, 3200) uni.request({ @@ -49,7 +49,7 @@ const request = (config) => { header, data, timeout: 3000, - async success (res) { + async success(res) { const { statusCode, data } = res if (timer) { clearTimeout(timer) @@ -64,7 +64,7 @@ const request = (config) => { starCloud.accountInfo.username, starCloud.accountInfo.password ) - if(code === Result.Success.code) { + if (code === Result.Success.code) { resolve(await request(config)) } } else { @@ -75,17 +75,17 @@ const request = (config) => { }) } } else { - resolve(new Result(Result.Fail.code, {},'网络访问失败,请检查网络是否正常')) + resolve(new Result(Result.Fail.code, {}, '网络访问失败,请检查网络是否正常')) } }, - async fail (res) { + async fail(res) { console.log('网络访问失败', res) if (timer) { clearTimeout(timer) } - resolve(new Result(Result.Fail.code, {},'网络访问失败,请检查网络是否正常')) + resolve(new Result(Result.Fail.code, {}, '网络访问失败,请检查网络是否正常')) }, - async complete (res) { + async complete(res) { console.log(URL.substring(baseConfig.baseUrl.length + 1), { env: baseConfig.name, url: URL.substring(baseConfig.baseUrl.length + 1), diff --git a/starCloud.js b/starCloud.js index be154ae..2d8f38a 100644 --- a/starCloud.js +++ b/starCloud.js @@ -1,4 +1,5 @@ import { defineStore } from 'pinia' +import { sm4 } from 'sm-crypto' import { buildNumber, configs, version } from '@/starCloud/env' import { addCustomPassword, @@ -9,7 +10,8 @@ import { getStarCloudToken, getUserNoListRequest, starCloudCreateUser, - updateLockUserNoRequest, updatePassword + updateLockUserNoRequest, + updatePassword } from '@/starCloud/api' import { getStorage, setStorage } from '@/starCloud/storage' import { @@ -27,7 +29,6 @@ import { timestampToArray, uint8ArrayToString } from '@/starCloud/format' -import { sm4 } from 'sm-crypto' /** * 锁信息 @@ -103,7 +104,7 @@ const cmdIds = { // 重置设备 resetDevice: 0x3004, // 清理用户 - cleanUser: 0x300C, + cleanUser: 0x300c, // 扩展命令 expandCmd: 0x3030 } @@ -166,11 +167,7 @@ export const useStarCloudStore = defineStore('starCloud', { }, // 注册星云 async register() { - const { - code, - data, - message - } = await starCloudCreateUser({ + const { code, data, message } = await starCloudCreateUser({ clientId: this.clientId, clientSecret: this.clientSecret }) @@ -188,8 +185,7 @@ export const useStarCloudStore = defineStore('starCloud', { this.userInfo = getStorage('starCloudUser') this.loginStarCloud = true // 获取服务器时间 - this.getServerTimestamp() - .then(() => {}) + this.getServerTimestamp().then(() => {}) return Result.Success } console.log('登录星云', username, password) @@ -198,8 +194,8 @@ export const useStarCloudStore = defineStore('starCloud', { data: userInfo, message } = await getStarCloudToken({ - username: username, - password: password, + username, + password, clientId: this.clientId, clientSecret: this.clientSecret }) @@ -209,23 +205,18 @@ export const useStarCloudStore = defineStore('starCloud', { setStorage('starCloudUser', userInfo) this.loginStarCloud = true // 获取服务器时间 - this.getServerTimestamp() - .then(() => {}) + this.getServerTimestamp().then(() => {}) } return new Result(code, {}, message) }, // 选择锁 async selectLock(lockId) { - const { - code, - data, - message - } = await getLockDetail({ + const { code, data, message } = await getLockDetail({ lockId }) if (code === Result.Success.code) { const lockList = getStorage('lockList') - if(lockList) { + if (lockList) { const index = lockList.findIndex(item => item.lockId === lockId) if (index === -1) { lockList.push(data) @@ -240,7 +231,7 @@ export const useStarCloudStore = defineStore('starCloud', { } else { const lockList = getStorage('lockList') console.log('锁列表', lockList) - if(lockList) { + if (lockList) { const index = lockList.findIndex(item => item.lockId === lockId) if (index !== -1) { this.lockInfo = lockList[index] @@ -260,12 +251,7 @@ export const useStarCloudStore = defineStore('starCloud', { this.updateLockInfo(searchResult.data) // 获取并处理锁信息 - let { - uid: authUid, - keyId, - token, - bluetooth - } = this.lockInfo + let { uid: authUid, keyId, token, bluetooth } = this.lockInfo let { uid } = this.userInfo authUid = authUid.toString() uid = uid.toString() @@ -273,10 +259,7 @@ export const useStarCloudStore = defineStore('starCloud', { const name = bluetooth.bluetoothDeviceName // 获取用户列表 - const { - code: requestCode, - data: requestData - } = await getUserNoListRequest({ + const { code: requestCode, data: requestData } = await getUserNoListRequest({ lockId: this.lockInfo.lockId }) console.log('获取用户列表请求结果', requestCode, requestData) @@ -319,7 +302,11 @@ export const useStarCloudStore = defineStore('starCloud', { contentArray[128 + userNoList.length] = 16 - const md5Array = md5Encrypt(authUid + keyId, token || new Uint8Array([0, 0, 0, 0]), bluetooth.publicKey) + const md5Array = md5Encrypt( + authUid + keyId, + token || new Uint8Array([0, 0, 0, 0]), + bluetooth.publicKey + ) contentArray.set(md5Array, 129 + userNoList.length) @@ -330,8 +317,12 @@ export const useStarCloudStore = defineStore('starCloud', { 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 } @@ -339,6 +330,7 @@ export const useStarCloudStore = defineStore('starCloud', { return this.getWriteResult(this.cleanLockUser, disconnect) }, // 开门 + // eslint-disable-next-line default-param-last async openDoor(type = 'open', disconnect) { // 确认设备连接正常 const searchResult = await searchAndConnectDevice(this.lockInfo.bluetooth.bluetoothDeviceName) @@ -374,8 +366,7 @@ export const useStarCloudStore = defineStore('starCloud', { const name = this.lockInfo.bluetooth.bluetoothDeviceName const uid = this.userInfo.uid.toString() - const openTime = Math.ceil(new Date() - .getTime() / 1000) + this.timeDifference + 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) @@ -402,8 +393,11 @@ export const useStarCloudStore = defineStore('starCloud', { contentArray[71] = 16 - const md5Array = md5Encrypt(name + uid, this.lockInfo.token || timestampToArray(openTime), - this.lockInfo.bluetooth.signKey) + const md5Array = md5Encrypt( + name + uid, + this.lockInfo.token || timestampToArray(openTime), + this.lockInfo.bluetooth.signKey + ) contentArray.set(md5Array, 72) @@ -418,8 +412,12 @@ export const useStarCloudStore = defineStore('starCloud', { 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 @@ -455,12 +453,12 @@ export const useStarCloudStore = defineStore('starCloud', { const uid = this.userInfo.uid.toString() const keyId = this.lockInfo.keyId.toString() const isAdmin = pwdRight - const userCountLimit = 0xFFFF + const userCountLimit = 0xffff startDate = Math.floor(startDate / 1000) endDate = Math.floor(endDate / 1000) keyboardPwd = keyboardPwd.toString() - if(!pwdNo) { + if (!pwdNo) { pwdNo = 0 } @@ -504,8 +502,11 @@ export const useStarCloudStore = defineStore('starCloud', { contentArray[102] = 16 - const md5Array = md5Encrypt(keyId + uid, this.lockInfo.token || new Uint8Array([0, 0, 0, 0]), - this.lockInfo.bluetooth.signKey) + const md5Array = md5Encrypt( + keyId + uid, + this.lockInfo.token || new Uint8Array([0, 0, 0, 0]), + this.lockInfo.bluetooth.signKey + ) contentArray.set(md5Array, 103) @@ -516,8 +517,12 @@ export const useStarCloudStore = defineStore('starCloud', { 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 @@ -526,30 +531,19 @@ export const useStarCloudStore = defineStore('starCloud', { return this.getWriteResult(this.customPassword, disconnect, password) }, - - // 获取联网token async getNetToken() { - const { - code, - data, - message - } = await getLockNetTokenRequest({ + const { code, data, message } = await getLockNetTokenRequest({ lockId: this.lockInfo.lockId }) return new Result(code, data, message) }, // 获取服务器时间 async getServerTimestamp() { - const { - code, - data, - message - } = await getServerDatetime({}) + const { code, data, message } = await getServerDatetime({}) if (code === Result.Success.code) { this.serverTimestamp = Math.ceil(data.date / 1000) - this.timeDifference = Math.ceil((data.date - new Date() - .getTime()) / 1000) + this.timeDifference = Math.ceil((data.date - new Date().getTime()) / 1000) } return new Result(code, data, message) }, @@ -582,8 +576,8 @@ export const useStarCloudStore = defineStore('starCloud', { password } = data - const length = 2 + 40 + 20 + 40 + 20 + 1 + 1 + 4 + 4 + 2 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 20 + 4 + - 1 + 16 + const length = + 2 + 40 + 20 + 40 + 20 + 1 + 1 + 4 + 4 + 2 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 20 + 4 + 1 + 16 const headArray = this.createPackageHeader(3, length) const contentArray = new Uint8Array(length) @@ -631,8 +625,11 @@ export const useStarCloudStore = defineStore('starCloud', { contentArray[165] = 16 - const md5Array = md5Encrypt(authUid + keyId, this.lockInfo.token || timestampToArray(startDate), - this.lockInfo.bluetooth.publicKey) + const md5Array = md5Encrypt( + authUid + keyId, + this.lockInfo.token || timestampToArray(startDate), + this.lockInfo.bluetooth.publicKey + ) contentArray.set(md5Array, 166) @@ -642,8 +639,12 @@ export const useStarCloudStore = defineStore('starCloud', { }) 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 @@ -651,12 +652,13 @@ export const useStarCloudStore = defineStore('starCloud', { return this.getWriteResult(this.addLockUser, disconnect, data) }, // 获取写入结果 + // eslint-disable-next-line default-param-last getWriteResult(request, disconnect = false, params) { return new Promise(resolve => { const getWriteResultTimer = setTimeout(() => { resolve(Result.Fail) }, 20000) - characteristicValueCallback = async (data) => { + characteristicValueCallback = async data => { // code 6 token过期,重新获取 if (data.code === Result.NotTokenLock.code) { resolve(await request(params)) @@ -670,7 +672,7 @@ export const useStarCloudStore = defineStore('starCloud', { } } else { clearTimeout(getWriteResultTimer) - if(disconnect) { + if (disconnect) { await this.disconnectDevice() } console.log('写入结果', data, request, params) @@ -682,10 +684,8 @@ export const useStarCloudStore = defineStore('starCloud', { // 检查是否已添加为用户 async checkLockUser(forceAdd = false) { if (this.lockInfo.lockUserNo === 0 || forceAdd) { - const timestamp = Math.floor(new Date() - .getTime() / 1000) - const password = (Math.floor(Math.random() * 900000) + 100000) - .toString() + const timestamp = Math.floor(new Date().getTime() / 1000) + const password = (Math.floor(Math.random() * 900000) + 100000).toString() console.log('用户未添加,开始添加用户') const addUserParams = { name: this.lockInfo.bluetooth.bluetoothDeviceName, @@ -694,55 +694,47 @@ export const useStarCloudStore = defineStore('starCloud', { uid: this.userInfo.uid.toString(), openMode: 1, keyType: 0, - startDate: this.lockInfo.startDate === 0 ? timestamp : Math.floor(this.lockInfo.startDate / - 1000), - expireDate: this.lockInfo.endDate === 0 ? 0xffffffff : Math.floor(this.lockInfo.endDate / - 1000), + startDate: + this.lockInfo.startDate === 0 ? timestamp : Math.floor(this.lockInfo.startDate / 1000), + expireDate: + this.lockInfo.endDate === 0 ? 0xffffffff : Math.floor(this.lockInfo.endDate / 1000), useCountLimit: this.lockInfo.keyType === 3 ? 1 : 0xffff, isRound: this.lockInfo.keyType === 4 ? 1 : 0, - weekRound: this.lockInfo.keyType === 4 ? convertWeekdaysToNumber(this.lockInfo.weekDays) : - 0, - startHour: this.lockInfo.keyType === 4 ? new Date(this.lockInfo.startDate) - .getHours() : 0, - startMin: this.lockInfo.keyType === 4 ? new Date(this.lockInfo.startDate) - .getMinutes() : 0, - endHour: this.lockInfo.keyType === 4 ? new Date(this.lockInfo.endDate) - .getHours() : 0, - endMin: this.lockInfo.keyType === 4 ? new Date(this.lockInfo.endDate) - .getMinutes() : 0, + weekRound: + this.lockInfo.keyType === 4 ? convertWeekdaysToNumber(this.lockInfo.weekDays) : 0, + startHour: this.lockInfo.keyType === 4 ? new Date(this.lockInfo.startDate).getHours() : 0, + startMin: + this.lockInfo.keyType === 4 ? new Date(this.lockInfo.startDate).getMinutes() : 0, + endHour: this.lockInfo.keyType === 4 ? new Date(this.lockInfo.endDate).getHours() : 0, + endMin: this.lockInfo.keyType === 4 ? new Date(this.lockInfo.endDate).getMinutes() : 0, role: 0, password } const addUserResult = await this.addLockUser(addUserParams) console.log('添加用户蓝牙结果', addUserResult) if (addUserResult.code === Result.Success.code) { - const { - code - } = await updateLockUserNoRequest({ + const { code } = await updateLockUserNoRequest({ keyId: this.lockInfo.keyId, lockUserNo: this.lockInfo.lockUserNo }) console.log('添加用户请求结果', code) return Result.Success - } else if (addUserResult.code === Result.NotMoreKeyLock.code) { + } + if (addUserResult.code === Result.NotMoreKeyLock.code) { console.log('用户达上限,开始清理用户') - const { - code: cleanCode - } = await this.cleanLockUser() + const { code: cleanCode } = await this.cleanLockUser() console.log('清理用户蓝牙结果', cleanCode) if (cleanCode === Result.Success.code) { return await this.checkLockUser() - } else { - return Result.Fail } - } else if (addUserResult.code === Result.ReadyHasKeyLock.code) { - return Result.Success - } else { return Result.Fail } - } else { - return Result.Success + if (addUserResult.code === Result.ReadyHasKeyLock.code) { + return Result.Success + } + return Result.Fail } + return Result.Success }, // 更新锁信息 updateLockInfo(lockInfo) { @@ -755,30 +747,32 @@ export const useStarCloudStore = defineStore('starCloud', { listenCharacteristicValue(res) { if (res.deviceId === this.lockInfo.deviceId) { let binaryData = new Uint8Array(res.value) - if (binaryData[0] === 0xEF && binaryData[1] === 0x01 && binaryData[2] === 0xEE && binaryData[3] === - 0x02) { + if ( + binaryData[0] === 0xef && + binaryData[1] === 0x01 && + binaryData[2] === 0xee && + binaryData[3] === 0x02 + ) { length = binaryData[8] * 256 + binaryData[9] if (length + 14 > binaryData.length) { completeArray = binaryData } else { this.parsingCharacteristicValue(binaryData).then(() => {}) } - } else { - if (completeArray) { - const combinedArray = new Uint8Array(completeArray.length + binaryData.length) - combinedArray.set(completeArray, 0) - combinedArray.set(binaryData, completeArray.length) - completeArray = combinedArray - if (length + 14 === completeArray.length) { - this.parsingCharacteristicValue(completeArray).then(() => {}) - completeArray = null - } + } else if (completeArray) { + const combinedArray = new Uint8Array(completeArray.length + binaryData.length) + combinedArray.set(completeArray, 0) + combinedArray.set(binaryData, completeArray.length) + completeArray = combinedArray + if (length + 14 === completeArray.length) { + this.parsingCharacteristicValue(completeArray).then(() => {}) + completeArray = null } } } }, // 解析特征值 - async parsingCharacteristicValue (binaryData) { + async parsingCharacteristicValue(binaryData) { // 0x20 明文 0x22 SM4(事先约定密钥) 0x23 SM4(设备指定密钥) if (binaryData[7] === 0x20) { if (binaryData[12] * 256 + binaryData[13] === cmdIds.getPublicKey) { @@ -851,17 +845,19 @@ export const useStarCloudStore = defineStore('starCloud', { icPartNo: uint8ArrayToString(decrypted.slice(140, 150)), indate: arrayToTimestamp(decrypted.slice(150, 154)), mac: uint8ArrayToString(decrypted.slice(154, 174)), - timezoneOffset: new Date() - .getTimezoneOffset() * 60 + timezoneOffset: new Date().getTimezoneOffset() * 60 } this.updateLockInfo({ - featureValue: uint8ArrayToString(decrypted.slice(175, 175 + decrypted[ - 174])), - featureSettingValue: uint8ArrayToString(decrypted.slice(176 + decrypted[ - 174], 176 + decrypted[174] + decrypted[175 + decrypted[ - 174]])), - featureSettingParams: Array.from(decrypted.slice(176 + decrypted[174] + - decrypted[175 + decrypted[174]])), + featureValue: uint8ArrayToString(decrypted.slice(175, 175 + decrypted[174])), + featureSettingValue: uint8ArrayToString( + decrypted.slice( + 176 + decrypted[174], + 176 + decrypted[174] + decrypted[175 + decrypted[174]] + ) + ), + featureSettingParams: Array.from( + decrypted.slice(176 + decrypted[174] + decrypted[175 + decrypted[174]]) + ), lockConfig }) console.log('获取锁状态成功', this.lockInfo.lockConfig) @@ -894,7 +890,7 @@ export const useStarCloudStore = defineStore('starCloud', { token: decrypted.slice(5, 9) }) if (decrypted[2] === Result.Success.code) { - if(decrypted[11] === Result.Success.code) { + if (decrypted[11] === Result.Success.code) { const pwdNo = decrypted[9] * 256 + decrypted[10] if (requestParams.operate === 0) { const addResult = await addCustomPassword({ @@ -903,13 +899,17 @@ export const useStarCloudStore = defineStore('starCloud', { lockId: this.lockInfo.lockId }) if (addResult.code === Result.Success.code) { - characteristicValueCallback(new Result(addResult.code, { - pwdNo: pwdNo, - keyboardPwdId: addResult.data.keyboardPwdId, - keyboardPwd: addResult.data.keyboardPwd - })) + characteristicValueCallback( + new Result(addResult.code, { + pwdNo, + keyboardPwdId: addResult.data.keyboardPwdId, + keyboardPwd: addResult.data.keyboardPwd + }) + ) } else { - characteristicValueCallback(new Result(addResult.code, addResult.data, addResult.message)) + characteristicValueCallback( + new Result(addResult.code, addResult.data, addResult.message) + ) } } else if (requestParams.operate === 1) { const updateResult = await updatePassword({ @@ -919,7 +919,9 @@ export const useStarCloudStore = defineStore('starCloud', { if (updateResult.code === Result.Success.code) { characteristicValueCallback(new Result(updateResult.code)) } else { - characteristicValueCallback(new Result(updateResult.code, updateResult.data, updateResult.message)) + characteristicValueCallback( + new Result(updateResult.code, updateResult.data, updateResult.message) + ) } } } else { @@ -929,6 +931,8 @@ export const useStarCloudStore = defineStore('starCloud', { characteristicValueCallback(new Result(decrypted[2])) } break + default: + break } break case cmdIds.openDoor: @@ -967,9 +971,9 @@ export const useStarCloudStore = defineStore('starCloud', { let headArray = new Uint8Array(12) // 固定包头 - headArray[0] = 0xEF + headArray[0] = 0xef headArray[1] = 0x01 - headArray[2] = 0xEE + headArray[2] = 0xee headArray[3] = 0x02 // 包类型 发送 @@ -1006,6 +1010,6 @@ export const useStarCloudStore = defineStore('starCloud', { // 断开与设备的连接 async disconnectDevice() { return await closeBLEConnection(this.lockInfo.deviceId) - }, + } } }) diff --git a/storage.js b/storage.js index b6a8fe9..febe265 100644 --- a/storage.js +++ b/storage.js @@ -14,5 +14,5 @@ export function removeStorage(key) { function getPrefix() { const starCloud = useStarCloudStore() - return `${ starCloud.envVersion }:` + return `${starCloud.envVersion}:` } From bd3de787755830c71fcab451ebc440f0102bfe59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8C=83=E9=B9=8F?= Date: Wed, 23 Oct 2024 18:26:07 +0800 Subject: [PATCH 06/25] =?UTF-8?q?feat:=201.=E5=AE=8C=E6=88=90=E9=99=A4?= =?UTF-8?q?=E4=B8=80=E9=94=AE=E7=99=BB=E5=BD=95=E5=A4=96=E7=9A=84=E8=B4=A6?= =?UTF-8?q?=E5=8F=B7=E5=8A=9F=E8=83=BD=202.=E5=AE=8C=E6=88=90=E5=90=88?= =?UTF-8?q?=E5=90=8C=E7=9B=B8=E5=85=B3=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- basic.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/basic.js b/basic.js index 9fabfde..8463313 100644 --- a/basic.js +++ b/basic.js @@ -3,6 +3,8 @@ export class Result { Success: 0, Fail: -1, + NotMoreData: -10, + NotAvailableBluetooth: -20, NotAvailableBluetoothPermission: -21, NotAvailableWeChatNearbyDevicesPermission: -22, @@ -20,6 +22,8 @@ export class Result { [Result.codes.Success, { message: '成功', data: {} }], [Result.codes.Fail, { message: '失败', data: {} }], + [Result.codes.NotMoreData, { message: '没有更多数据', data: {} }], + [Result.codes.NotAvailableBluetooth, { message: '蓝牙未开启', data: {} }], [Result.codes.NotAvailableBluetoothPermission, { message: '小程序蓝牙权限被禁用', data: {} }], [ @@ -65,6 +69,11 @@ export class Result { return new Result(Result.codes.Fail) } + // 没有更多数据 + static get NotMoreData() { + return new Result(Result.codes.NotMoreData) + } + // 蓝牙未开启 static get NotAvailableBluetooth() { return new Result(Result.codes.NotAvailableBluetooth) From 64beacd03582129c5a9f232dffa6ed9badb5d66d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8C=83=E9=B9=8F?= Date: Wed, 30 Oct 2024 14:09:02 +0800 Subject: [PATCH 07/25] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E7=BB=91?= =?UTF-8?q?=E5=AE=9A=E9=94=81=E7=9B=B8=E5=85=B3=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 29 ++++- api.js | 19 +++- basic.js | 21 ++-- starCloud.js | 310 ++++++++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 347 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index f87dac4..7dac3f5 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,30 @@ ## 星云SDK ### 1. 安装 + 在需要引用的项目中执行命令 `git subtree add --prefix=starCloud git@code.star-lock.cn:xhj/starcloud-sdk-uniapp.git master` 更新 `git subtree pull --prefix=starCloud git@code.star-lock.cn:xhj/starcloud-sdk-uniapp.git master` + ### 2. 需安装的npm包 + `npm install buffer crc js-md5 pinia sm-crypto` pinia是全局状态管理工具,需在main.js中引入 + ```javascript import * as Pinia from 'pinia' + const store = Pinia.createPinia() app.use(store) ``` + ### 3. 使用 + ```javascript import { useStarCloudStore } from '@/starCloud/starCloud' + const $starCloud = useStarCloudStore() /** @@ -31,7 +39,7 @@ $starCloud.initStarCloud(clientId, clientSecret, env) // code对应报错码有三部分组合构成,锁端报错码+星云服务端报错码+自定义报错码 // Result类定义了所有自定义报错码,具体报错码请查看Result类 const { code, data, message } = await $starCloud.register() -if(code === Result.Success.code) { +if (code === Result.Success.code) { // 逻辑代码 } else { // 错误处理 @@ -48,6 +56,7 @@ const { code, data, message } = await $starCloud.login(username, password) * 选择锁 * @property {Number} lockId - 锁Id */ +// 所需信息data中会返回,如data中没有可通过$starCloud.lockInfo获取 const { code, data, message } = await $starCloud.selectLock(lockId) /** @@ -109,4 +118,22 @@ const data = await $starCloud.customPassword({ operate: 0, pwdRight: 0 }, true) + +/** + * 搜索蓝牙设备 + */ +await $starCloud.searchDevice(searchDevice) +const searchDevice = async result => { +} + +/** + * 停止搜索 + */ +await $starCloud.stopSearchDevice() + +/** + * 连接蓝牙设备 + * @property {String} name - 设备名称 + */ +const data = await $starCloud.bindDevice(name) ``` diff --git a/api.js b/api.js index d3a7b6b..2be80c1 100644 --- a/api.js +++ b/api.js @@ -46,7 +46,7 @@ export function getLockNetTokenRequest(data) { } // 获取服务器时间 -export function getServerDatetime(data) { +export function getServerDatetimeRequest(data) { return request({ url: '/v1/lock/queryDate', method: 'POST', @@ -55,7 +55,7 @@ export function getServerDatetime(data) { } // 获取锁详情 -export function getLockDetail(data) { +export function getLockDetailRequest(data) { return request({ url: '/v1/lock/detail', method: 'POST', @@ -64,7 +64,7 @@ export function getLockDetail(data) { } // 获取离线密码 -export function getOfflinePassword(data) { +export function getOfflinePasswordRequest(data) { return request({ url: '/v1/keyboardPwd/get', method: 'POST', @@ -73,7 +73,7 @@ export function getOfflinePassword(data) { } // 添加自定义密码 -export function addCustomPassword(data) { +export function addCustomPasswordRequest(data) { return request({ url: '/v1/keyboardPwd/add', method: 'POST', @@ -82,10 +82,19 @@ export function addCustomPassword(data) { } // 更新密码 -export function updatePassword(data) { +export function updatePasswordRequest(data) { return request({ url: '/v1/keyboardPwd/update', method: 'POST', data }) } + +// 绑定智能锁 +export function bindLockRequest(data) { + return request({ + url: '/v1/lock/initialize', + method: 'POST', + data + }) +} diff --git a/basic.js b/basic.js index 8463313..95be775 100644 --- a/basic.js +++ b/basic.js @@ -36,7 +36,10 @@ export class Result { ], [ Result.codes.NotAvailableWeChatNearbyDevicesEmpty, - { message: '微信附近的设备权限无法使用', data: {} } + { + message: '手机定位服务被关闭', + data: {} + } ], [Result.codes.DeviceHasBeenReset, { message: '设备已被重置', data: {} }], @@ -133,7 +136,7 @@ export class Result { */ // 查找设备并连接 -export function searchAndConnectDevice(name) { +export function searchAndConnectDevice(name, reset = true) { // 循环查找设备 let timer // 超时计时器 @@ -166,13 +169,11 @@ export function searchAndConnectDevice(name) { await stopBluetoothDevicesDiscovery() clearTimeout(timeoutTimer) clearInterval(timer) - if (uuid.slice(30, 32) === '00') { + if (uuid.slice(30, 32) === '00' && reset) { resolve(Result.DeviceHasBeenReset) - } else if (uuid.slice(30, 32) === '01') { + } else { const connectResult = await createBLEConnection(deviceList[i].deviceId) resolve(connectResult) - } else { - resolve(Result.Fail) } break } @@ -256,7 +257,7 @@ export function onBLECharacteristicValueChange(callback) { } // 开始搜索附近的蓝牙设备 -function startBluetoothDevicesDiscovery() { +export function startBluetoothDevicesDiscovery() { return new Promise(resolve => { uni.startBluetoothDevicesDiscovery({ success() { @@ -270,7 +271,7 @@ function startBluetoothDevicesDiscovery() { } // 获取所有已发现的蓝牙设备 -function getBluetoothDevices() { +export function getBluetoothDevices() { return new Promise(resolve => { uni.getBluetoothDevices({ success(res) { @@ -284,7 +285,7 @@ function getBluetoothDevices() { } // 停止搜索附近的蓝牙设备 -function stopBluetoothDevicesDiscovery() { +export function stopBluetoothDevicesDiscovery() { return new Promise(resolve => { uni.stopBluetoothDevicesDiscovery({ success() { @@ -298,7 +299,7 @@ function stopBluetoothDevicesDiscovery() { } // 连接低功耗蓝牙设备 -function createBLEConnection(deviceId, reconnectNumber = 0) { +export function createBLEConnection(deviceId, reconnectNumber = 0) { return new Promise(resolve => { uni.createBLEConnection({ deviceId, diff --git a/starCloud.js b/starCloud.js index 2d8f38a..6bd215b 100644 --- a/starCloud.js +++ b/starCloud.js @@ -2,23 +2,28 @@ import { defineStore } from 'pinia' import { sm4 } from 'sm-crypto' import { buildNumber, configs, version } from '@/starCloud/env' import { - addCustomPassword, - getLockDetail, + addCustomPasswordRequest, + bindLockRequest, + getLockDetailRequest, getLockNetTokenRequest, - getOfflinePassword, - getServerDatetime, + getOfflinePasswordRequest, + getServerDatetimeRequest, getStarCloudToken, getUserNoListRequest, starCloudCreateUser, updateLockUserNoRequest, - updatePassword + updatePasswordRequest } from '@/starCloud/api' import { getStorage, setStorage } from '@/starCloud/storage' import { closeBLEConnection, + createBLEConnection, + getBluetoothDevices, onBLECharacteristicValueChange, Result, searchAndConnectDevice, + startBluetoothDevicesDiscovery, + stopBluetoothDevicesDiscovery, writeBLECharacteristicValue } from '@/starCloud/basic' import { @@ -125,6 +130,8 @@ let completeArray let length // 请求参数 let requestParams = null +// 计时器 +let timer export const useStarCloudStore = defineStore('starCloud', { state() { @@ -150,7 +157,9 @@ export const useStarCloudStore = defineStore('starCloud', { // 时间差 timeDifference: 0, // 小程序环境 - envVersion: '' + envVersion: '', + // 搜索设备列表 + searchDeviceList: [] } }, actions: { @@ -211,7 +220,7 @@ export const useStarCloudStore = defineStore('starCloud', { }, // 选择锁 async selectLock(lockId) { - const { code, data, message } = await getLockDetail({ + const { code, data, message } = await getLockDetailRequest({ lockId }) if (code === Result.Success.code) { @@ -427,7 +436,7 @@ export const useStarCloudStore = defineStore('starCloud', { }, // 获取离线密码 async getOfflinePassword(password) { - return await getOfflinePassword({ + return await getOfflinePasswordRequest({ ...password, lockId: this.lockInfo.lockId }) @@ -531,6 +540,272 @@ export const useStarCloudStore = defineStore('starCloud', { return this.getWriteResult(this.customPassword, disconnect, password) }, + // 搜索设备 + async searchDevice(callback) { + const result = await startBluetoothDevicesDiscovery() + if (result.code === Result.Success.code) { + const timestamp = new Date().getTime() + let queryFlag = false + timer = setInterval(async () => { + const queryResult = await getBluetoothDevices() + if (queryResult.code === Result.Success.code) { + const deviceList = queryResult.data + if (queryFlag === false && deviceList.length > 0) { + queryFlag = true + } + if (new Date().getTime() - timestamp > 10000 && !queryFlag) { + if (timer) { + clearInterval(timer) + } + callback(Result.NotAvailableWeChatNearbyDevicesEmpty) + } + + const list = [] + + for (let i = 0; i < deviceList.length; i++) { + if (deviceList[i]?.advertisServiceUUIDs) { + const uuid = deviceList[i]?.advertisServiceUUIDs[0] + if (uuid && uuid.slice(2, 8) === '758824' && uuid.slice(30, 32) === '00') { + list.push(deviceList[i]) + } + } + } + + this.searchDeviceList = list + callback( + new Result(Result.Success, { + list + }) + ) + } else { + callback(queryResult) + } + }, 1000) + } else { + callback(result) + } + }, + + // 停止搜索 + async stopSearchDevice() { + console.log('停止搜索') + if (timer) { + clearInterval(timer) + } + + return await stopBluetoothDevicesDiscovery() + }, + + // 绑定设备 + async bindDevice(name) { + const device = this.searchDeviceList.find(item => item.name === name) + const connectResult = await createBLEConnection(device.deviceId) + if (connectResult.code === Result.Success.code) { + this.updateLockInfo({ + ...connectResult.data, + bluetooth: { + bluetoothDeviceId: device.deviceId, + bluetoothDeviceName: device.name + } + }) + const publicKeyResult = await this.getPublicKey() + if (publicKeyResult.code !== Result.Success.code) { + return publicKeyResult + } + const commKeyResult = await this.getCommKey() + if (commKeyResult.code !== Result.Success.code) { + return commKeyResult + } + const lockStatusResult = await this.getLockStatus() + if (lockStatusResult.code !== Result.Success.code) { + return lockStatusResult + } + const timestamp = Math.ceil(new Date().getTime() / 1000) + const password = (Math.floor(Math.random() * 900000) + 100000).toString() + const addUserResult = await this.addLockUser( + { + name: this.lockInfo.bluetooth.bluetoothDeviceName, + keyId: '0', + authUid: this.userInfo.uid.toString(), + uid: this.userInfo.uid.toString(), + openMode: 1, + keyType: 0, + startDate: timestamp, + expireDate: 0xffffffff, + useCountLimit: 0xffff, + isRound: 0, + weekRound: 0, + startHour: 0, + startMin: 0, + endHour: 0, + endMin: 0, + role: 0xff, + password + }, + true + ) + if (addUserResult.code !== Result.Success.code) { + return addUserResult + } + const params = { + lockAlias: this.lockInfo.bluetooth.bluetoothDeviceName, + lockInfo: { + ...this.lockInfo.lockConfig, + adminPwd: password + }, + bluetooth: this.lockInfo.bluetooth, + lockUserNo: this.lockInfo.lockUserNo, + pwdTimestamp: this.lockInfo.pwdTimestamp, + featureValue: this.lockInfo.featureValue, + featureSettingValue: this.lockInfo.featureSettingValue, + featureSettingParams: this.lockInfo.featureSettingParams + } + const bindLockResult = await bindLockRequest(params) + if (bindLockResult.code === Result.Success.code) { + this.updateLockInfo({ + lockId: bindLockResult.data.lockId, + keyId: bindLockResult.data.keyId + }) + } + return bindLockResult + } + return connectResult + }, + + // 获取公钥 + async getPublicKey() { + const headArray = this.createPackageHeader(0, 42) + + const contentArray = new Uint8Array(42) + + contentArray[0] = cmdIds.getPublicKey / 256 + contentArray[1] = cmdIds.getPublicKey % 256 + + const name = this.lockInfo.bluetooth.bluetoothDeviceName + + for (let i = 0; i < name.length; i++) { + contentArray[i + 2] = name.charCodeAt(i) + } + + const packageArray = createPackageEnd(headArray, contentArray) + + 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.getPublicKey, false) + }, + // 获取私钥 + async getCommKey() { + const length = 2 + 40 + 40 + 20 + 4 + 1 + 16 + const headArray = this.createPackageHeader(2, length) + const contentArray = new Uint8Array(length) + + contentArray[0] = cmdIds.getCommKey / 256 + contentArray[1] = cmdIds.getCommKey % 256 + + const name = this.lockInfo.bluetooth.bluetoothDeviceName + const keyId = '0' + const authUid = this.userInfo.uid.toString() + await this.getServerTimestamp() + const nowTime = this.serverTimestamp + + for (let i = 0; i < name.length; i++) { + contentArray[i + 2] = name.charCodeAt(i) + } + + for (let i = 0; i < keyId.length; i++) { + contentArray[i + 42] = keyId.charCodeAt(i) + } + + for (let i = 0; i < authUid.length; i++) { + contentArray[i + 82] = authUid.charCodeAt(i) + } + + contentArray.set(timestampToArray(nowTime), 102) + + contentArray[106] = 16 + + const md5Array = md5Encrypt( + authUid + keyId, + contentArray.slice(102, 106), + this.lockInfo.bluetooth.publicKey + ) + + contentArray.set(md5Array, 107) + + const cebArray = sm4.encrypt(contentArray, contentArray.slice(2, 18), { + 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.getCommKey, false) + }, + // 获取锁状态 + async getLockStatus() { + const length = 2 + 40 + 20 + 4 + 4 + const headArray = this.createPackageHeader(3, length) + + const contentArray = new Uint8Array(length) + contentArray[0] = cmdIds.getLockStatus / 256 + contentArray[1] = cmdIds.getLockStatus % 256 + + const name = this.lockInfo.bluetooth.bluetoothDeviceName + const uid = this.userInfo.uid.toString() + await this.getServerTimestamp() + const nowTime = this.serverTimestamp + const date = new Date() + const localTime = Math.floor(date.getTime() / 1000) - date.getTimezoneOffset() * 60 + + 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.set(timestampToArray(nowTime), 62) + contentArray.set(timestampToArray(localTime), 66) + + 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.getLockStatus, false) + }, // 获取联网token async getNetToken() { const { code, data, message } = await getLockNetTokenRequest({ @@ -540,7 +815,7 @@ export const useStarCloudStore = defineStore('starCloud', { }, // 获取服务器时间 async getServerTimestamp() { - const { code, data, message } = await getServerDatetime({}) + const { code, data, message } = await getServerDatetimeRequest({}) if (code === Result.Success.code) { this.serverTimestamp = Math.ceil(data.date / 1000) this.timeDifference = Math.ceil((data.date - new Date().getTime()) / 1000) @@ -550,7 +825,10 @@ export const useStarCloudStore = defineStore('starCloud', { // 添加用户 async addLockUser(data, disconnect = false) { // 确认设备连接正常 - const searchResult = await searchAndConnectDevice(this.lockInfo.bluetooth.bluetoothDeviceName) + const searchResult = await searchAndConnectDevice( + this.lockInfo.bluetooth.bluetoothDeviceName, + data.role !== 0xff + ) if (searchResult.code !== Result.Success.code) { return searchResult } @@ -806,12 +1084,12 @@ export const useStarCloudStore = defineStore('starCloud', { bluetooth: { ...this.lockInfo.bluetooth, privateKey: decrypted.slice(3, 19), - signKey: decrypted.slice(19, 35), - pwdTimestamp: arrayToTimestamp(decrypted.slice(35, 39)) * 1000 - } + signKey: decrypted.slice(19, 35) + }, + pwdTimestamp: arrayToTimestamp(decrypted.slice(35, 39)) * 1000 }) console.log('privateKey', Array.from(this.lockInfo.bluetooth.privateKey)) - console.log('signKey', Array.from(this.lockInfo.signKey)) + console.log('signKey', Array.from(this.lockInfo.bluetooth.signKey)) } characteristicValueCallback(new Result(decrypted[2])) } @@ -893,7 +1171,7 @@ export const useStarCloudStore = defineStore('starCloud', { if (decrypted[11] === Result.Success.code) { const pwdNo = decrypted[9] * 256 + decrypted[10] if (requestParams.operate === 0) { - const addResult = await addCustomPassword({ + const addResult = await addCustomPasswordRequest({ ...requestParams, pwdUserNo: pwdNo, lockId: this.lockInfo.lockId @@ -912,7 +1190,7 @@ export const useStarCloudStore = defineStore('starCloud', { ) } } else if (requestParams.operate === 1) { - const updateResult = await updatePassword({ + const updateResult = await updatePasswordRequest({ ...requestParams, keyboardPwdId: this.lockInfo.keyboardPwdId }) From ef5be48f4b33a7a90d57721f3392378a97fb0659 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8C=83=E9=B9=8F?= Date: Thu, 31 Oct 2024 18:41:21 +0800 Subject: [PATCH 08/25] =?UTF-8?q?feat:=201.=20=E9=94=81=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=202.=E4=B8=80=E9=94=AE=E7=99=BB=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 5 +++++ basic.js | 31 +++++++++++++++++++++++++------ starCloud.js | 13 ++++++++++++- 3 files changed, 42 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 7dac3f5..7415b4a 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,11 @@ if (code === Result.Success.code) { */ const { code, data, message } = await $starCloud.login(username, password) +/** + * 退出登录(未做请求,实际上不会失败) + */ +const { code, data, message } = await $starCloud.logout() + /** * 选择锁 * @property {Number} lockId - 锁Id diff --git a/basic.js b/basic.js index 95be775..e942dff 100644 --- a/basic.js +++ b/basic.js @@ -10,6 +10,7 @@ export class Result { NotAvailableWeChatNearbyDevicesPermission: -22, NotAvailableWeChatLocationPermission: -23, NotAvailableWeChatNearbyDevicesEmpty: -24, + NotAvailableWeChatBluetoothPermission: -25, DeviceHasBeenReset: -30, NotRegisteredLock: 4, @@ -24,20 +25,30 @@ export class Result { [Result.codes.NotMoreData, { message: '没有更多数据', data: {} }], - [Result.codes.NotAvailableBluetooth, { message: '蓝牙未开启', data: {} }], - [Result.codes.NotAvailableBluetoothPermission, { message: '小程序蓝牙权限被禁用', data: {} }], + [Result.codes.NotAvailableBluetooth, { message: '蓝牙尚未打开,请先打开蓝牙', data: {} }], + [ + Result.codes.NotAvailableBluetoothPermission, + { message: '小程序蓝牙功能被禁用,请打开小程序蓝牙权限', data: {} } + ], [ Result.codes.NotAvailableWeChatNearbyDevicesPermission, - { message: '微信附近的设备权限被禁用', data: {} } + { message: '蓝牙功能需要附近设备权限,请前往设置开启微信的附近设备权限后再试', data: {} } ], [ Result.codes.NotAvailableWeChatLocationPermission, - { message: '微信定位权限被禁用', data: {} } + { message: '蓝牙功能需要定位权限,请前往设置开启微信的定位权限后再试', data: {} } ], [ Result.codes.NotAvailableWeChatNearbyDevicesEmpty, { - message: '手机定位服务被关闭', + message: '蓝牙功能需要定位服务,请前往设置开启定位服务后再试', + data: {} + } + ], + [ + Result.codes.NotAvailableWeChatBluetoothPermission, + { + message: '微信的蓝牙权限被禁用,请前往设置开启微信的蓝牙权限后再试', data: {} } ], @@ -97,11 +108,16 @@ export class Result { return new Result(Result.codes.NotAvailableWeChatLocationPermission) } - // 微信附近的设备权限无法使用(针对小米空白通行证,鸿蒙系统隐私中的定位服务) + // 手机定位服务被关闭 static get NotAvailableWeChatNearbyDevicesEmpty() { return new Result(Result.codes.NotAvailableWeChatNearbyDevicesEmpty) } + // 微信的蓝牙权限被禁用 + static get NotAvailableWeChatBluetoothPermission() { + return new Result(Result.codes.NotAvailableWeChatBluetoothPermission) + } + // 设备已被重置 static get DeviceHasBeenReset() { return new Result(Result.codes.DeviceHasBeenReset) @@ -199,6 +215,9 @@ async function handleError(err, event) { return result } if (err.errCode === 10001) { + if (err.state === 3) { + return Result.NotAvailableWeChatBluetoothPermission + } return Result.NotAvailableBluetooth } if (err.errno === 3) { diff --git a/starCloud.js b/starCloud.js index 6bd215b..0f062d9 100644 --- a/starCloud.js +++ b/starCloud.js @@ -14,7 +14,7 @@ import { updateLockUserNoRequest, updatePasswordRequest } from '@/starCloud/api' -import { getStorage, setStorage } from '@/starCloud/storage' +import { getStorage, removeStorage, setStorage } from '@/starCloud/storage' import { closeBLEConnection, createBLEConnection, @@ -218,6 +218,17 @@ export const useStarCloudStore = defineStore('starCloud', { } return new Result(code, {}, message) }, + // 退出登录 + logout() { + this.loginStarCloud = false + this.userInfo = null + this.accountInfo = null + removeStorage('starCloudToken') + removeStorage('starCloudUser') + removeStorage('lockList') + + return Result.Success + }, // 选择锁 async selectLock(lockId) { const { code, data, message } = await getLockDetailRequest({ From b1b75c9300227c16e082427b6d7fe235f50ac887 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8C=83=E9=B9=8F?= Date: Mon, 4 Nov 2024 15:30:44 +0800 Subject: [PATCH 09/25] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E6=98=9F?= =?UTF-8?q?=E4=BA=91=E8=AF=B7=E6=B1=82=E5=9C=B0=E5=9D=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- env.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/env.js b/env.js index 47435d6..70335df 100644 --- a/env.js +++ b/env.js @@ -11,14 +11,14 @@ export const configs = { }, PRE: { name: 'PRE', - baseUrl: 'https://pre.cloud.star-lock.cn' + baseUrl: 'https://pre.cloud.star-lock.cn/sdk' }, XHJ: { name: 'XHJ', - baseUrl: 'https://cloud.star-lock.cn' + baseUrl: 'https://cloud.star-lock.cn/sdk' }, SKY: { name: 'SKY', - baseUrl: 'https://cloud.star-lock.cn' + baseUrl: 'https://cloud.star-lock.cn/sdk' } } From ae2aab74f17278978d9c5e726ed9db84d92f0823 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8C=83=E9=B9=8F?= Date: Tue, 5 Nov 2024 15:35:30 +0800 Subject: [PATCH 10/25] =?UTF-8?q?feat:=201.=20=E5=AE=8C=E6=88=90=E6=B0=B4?= =?UTF-8?q?=E7=94=B5=E8=A1=A8=E8=AE=B0=E5=BD=95=E5=88=97=E8=A1=A8=202.=20?= =?UTF-8?q?=E5=AE=8C=E6=88=90=E9=83=A8=E5=88=86=E5=AF=86=E7=A0=81=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api.js | 9 +++++++++ env.js | 4 ++-- starCloud.js | 19 +++++++++++++++++-- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/api.js b/api.js index 2be80c1..8110415 100644 --- a/api.js +++ b/api.js @@ -90,6 +90,15 @@ export function updatePasswordRequest(data) { }) } +// 删除密码 +export function deletePasswordRequest(data) { + return request({ + url: '/v1/keyboardPwd/delete', + method: 'POST', + data + }) +} + // 绑定智能锁 export function bindLockRequest(data) { return request({ diff --git a/env.js b/env.js index 70335df..34fc8ea 100644 --- a/env.js +++ b/env.js @@ -15,10 +15,10 @@ export const configs = { }, XHJ: { name: 'XHJ', - baseUrl: 'https://cloud.star-lock.cn/sdk' + baseUrl: 'https://cloud.xhjcn.ltd/sdk' }, SKY: { name: 'SKY', - baseUrl: 'https://cloud.star-lock.cn/sdk' + baseUrl: 'https://cloud.skychip.top/sdk' } } diff --git a/starCloud.js b/starCloud.js index 0f062d9..a6762e6 100644 --- a/starCloud.js +++ b/starCloud.js @@ -4,6 +4,7 @@ import { buildNumber, configs, version } from '@/starCloud/env' import { addCustomPasswordRequest, bindLockRequest, + deletePasswordRequest, getLockDetailRequest, getLockNetTokenRequest, getOfflinePasswordRequest, @@ -1162,7 +1163,7 @@ export const useStarCloudStore = defineStore('starCloud', { lockUserNo: decrypted[47] * 256 + decrypted[48] }) } - console.log('添加用户结果', decrypted[46], this.lockInfo.token) + console.log('添加用户结果', decrypted[46], this.lockInfo.lockUserNo) characteristicValueCallback(new Result(decrypted[46])) break case cmdIds.expandCmd: @@ -1192,7 +1193,9 @@ export const useStarCloudStore = defineStore('starCloud', { new Result(addResult.code, { pwdNo, keyboardPwdId: addResult.data.keyboardPwdId, - keyboardPwd: addResult.data.keyboardPwd + keyboardPwd: addResult.data.keyboardPwd, + keyboardPwdStatus: addResult.data.keyboardPwdStatus, + pwdUserNo: pwdNo }) ) } else { @@ -1212,6 +1215,18 @@ export const useStarCloudStore = defineStore('starCloud', { new Result(updateResult.code, updateResult.data, updateResult.message) ) } + } else if (requestParams.operate === 3) { + const deleteResult = await deletePasswordRequest({ + ...requestParams, + keyboardPwdId: this.lockInfo.keyboardPwdId + }) + if (deleteResult.code === Result.Success.code) { + characteristicValueCallback(new Result(deleteResult.code)) + } else { + characteristicValueCallback( + new Result(deleteResult.code, deleteResult.data, deleteResult.message) + ) + } } } else { characteristicValueCallback(new Result(decrypted[11])) From 904c0bf2475044774ba9b0494718d7bf69b96edb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8C=83=E9=B9=8F?= Date: Fri, 8 Nov 2024 18:22:17 +0800 Subject: [PATCH 11/25] =?UTF-8?q?feat:=20=E5=AE=8C=E6=88=90=E5=AF=86?= =?UTF-8?q?=E7=A0=81=E7=9B=B8=E5=85=B3=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- basic.js | 11 +++++++++-- starCloud.js | 10 ++-------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/basic.js b/basic.js index e942dff..bc745bf 100644 --- a/basic.js +++ b/basic.js @@ -16,7 +16,8 @@ export class Result { NotRegisteredLock: 4, NotTokenLock: 6, NotMoreKeyLock: 12, - ReadyHasKeyLock: 15 + ReadyHasKeyLock: 15, + ReadyHasPassword: 251 } static resultsMap = new Map([ @@ -57,7 +58,8 @@ export class Result { [Result.codes.NotRegisteredLock, { message: '用户在锁端未注册', data: {} }], [Result.codes.NotTokenLock, { message: '用户在锁端token失效', data: {} }], [Result.codes.NotMoreKeyLock, { message: '锁端钥匙数量已达上限', data: {} }], - [Result.codes.ReadyHasKeyLock, { message: '用户已是锁端用户', data: {} }] + [Result.codes.ReadyHasKeyLock, { message: '用户已是锁端用户', data: {} }], + [Result.codes.ReadyHasPassword, { message: '该密码已存在', data: {} }] ]) constructor(code, data, message) { @@ -142,6 +144,11 @@ export class Result { static get ReadyHasKeyLock() { return new Result(Result.codes.ReadyHasKeyLock) } + + // 密码已存在 + static get ReadyHasPassword() { + return new Result(Result.codes.ReadyHasPassword) + } } /** diff --git a/starCloud.js b/starCloud.js index a6762e6..0fc6bb2 100644 --- a/starCloud.js +++ b/starCloud.js @@ -1204,10 +1204,7 @@ export const useStarCloudStore = defineStore('starCloud', { ) } } else if (requestParams.operate === 1) { - const updateResult = await updatePasswordRequest({ - ...requestParams, - keyboardPwdId: this.lockInfo.keyboardPwdId - }) + const updateResult = await updatePasswordRequest(requestParams) if (updateResult.code === Result.Success.code) { characteristicValueCallback(new Result(updateResult.code)) } else { @@ -1216,10 +1213,7 @@ export const useStarCloudStore = defineStore('starCloud', { ) } } else if (requestParams.operate === 3) { - const deleteResult = await deletePasswordRequest({ - ...requestParams, - keyboardPwdId: this.lockInfo.keyboardPwdId - }) + const deleteResult = await deletePasswordRequest(requestParams) if (deleteResult.code === Result.Success.code) { characteristicValueCallback(new Result(deleteResult.code)) } else { From a254039d5ed07df8cd62b132405042955f56f27d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8C=83=E9=B9=8F?= Date: Wed, 13 Nov 2024 14:36:51 +0800 Subject: [PATCH 12/25] =?UTF-8?q?feat:=20=E5=AE=8C=E6=88=90=E6=B0=B4?= =?UTF-8?q?=E7=94=B5=E5=85=85=E5=80=BC=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- basic.js | 15 +++------------ starCloud.js | 6 ++++++ 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/basic.js b/basic.js index bc745bf..37ced86 100644 --- a/basic.js +++ b/basic.js @@ -257,21 +257,12 @@ function openBluetoothAdapter() { } // 关闭蓝牙模块 -function closeBluetoothAdapter() { - return new Promise(resolve => { - uni.closeBluetoothAdapter({ - success() { - resolve(Result.Success) - }, - async fail(err) { - resolve(await handleError(err)) - } - }) - }) +export function closeBluetoothAdapter() { + uni.closeBluetoothAdapter() } // 移除蓝牙适配器的全部监听 -function offBluetoothAdapterStateChange() { +export function offBluetoothAdapterStateChange() { uni.offBluetoothAdapterStateChange() } diff --git a/starCloud.js b/starCloud.js index 0fc6bb2..fbfd96b 100644 --- a/starCloud.js +++ b/starCloud.js @@ -18,8 +18,10 @@ import { import { getStorage, removeStorage, setStorage } from '@/starCloud/storage' import { closeBLEConnection, + closeBluetoothAdapter, createBLEConnection, getBluetoothDevices, + offBluetoothAdapterStateChange, onBLECharacteristicValueChange, Result, searchAndConnectDevice, @@ -659,6 +661,10 @@ export const useStarCloudStore = defineStore('starCloud', { if (addUserResult.code !== Result.Success.code) { return addUserResult } + + offBluetoothAdapterStateChange() + closeBluetoothAdapter() + const params = { lockAlias: this.lockInfo.bluetooth.bluetoothDeviceName, lockInfo: { From c7a594b451d1729797343020ccbe34741092e6f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8C=83=E9=B9=8F?= Date: Sat, 16 Nov 2024 18:21:16 +0800 Subject: [PATCH 13/25] =?UTF-8?q?feat:=201.=E5=AE=8C=E6=88=90=E7=A9=BA?= =?UTF-8?q?=E5=88=97=E8=A1=A8UI=202.=E4=BF=AE=E6=94=B9=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E7=AA=97=E5=8F=A3=E4=BF=A1=E6=81=AF=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7415b4a..031f750 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,11 @@ ### 1. 安装 在需要引用的项目中执行命令 -`git subtree add --prefix=starCloud git@code.star-lock.cn:xhj/starcloud-sdk-uniapp.git master` +`git subtree add --prefix=starCloud git@code.star-lock.cn:StarlockTeam/starcloud-sdk-uniapp.git master` 更新 -`git subtree pull --prefix=starCloud git@code.star-lock.cn:xhj/starcloud-sdk-uniapp.git master` +`git subtree pull --prefix=starCloud git@code.star-lock.cn:StarlockTeam/starcloud-sdk-uniapp.git master` +推送 +`git subtree push --prefix=starCloud git@code.star-lock.cn:StarlockTeam/starcloud-sdk-uniapp.git master` ### 2. 需安装的npm包 From 806ec1b7779de0de38b632a646cacbd91fdfc984 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8C=83=E9=B9=8F?= Date: Mon, 18 Nov 2024 14:45:33 +0800 Subject: [PATCH 14/25] =?UTF-8?q?feat:=20=E6=98=9F=E4=BA=91SDK=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E5=A4=9A=E8=B4=A6=E5=8F=B7=E5=90=8C=E6=97=B6=E4=BD=BF?= =?UTF-8?q?=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 105 ++---- request.js | 9 +- starCloud.js | 967 +++++++++++++++++++++++++++++---------------------- 3 files changed, 595 insertions(+), 486 deletions(-) diff --git a/README.md b/README.md index 031f750..cb5075f 100644 --- a/README.md +++ b/README.md @@ -30,12 +30,13 @@ import { useStarCloudStore } from '@/starCloud/starCloud' const $starCloud = useStarCloudStore() /** - * 初始化SDK - * @property {String} clientId - 客户端Id - * @property {String} clientSecret - 客户端密码 - * @property {String} env - 环境('DEV', 'PRE', 'XHJ', 'SKY) + * 初始化星云 + * @param params + * @param {String} params.clientId 客户端Id + * @param {String} params.clientSecret 客户端密码 + * @param {String} params.env 环境 */ -$starCloud.initStarCloud(clientId, clientSecret, env) +$starCloud.initStarCloud(params) // 注册,后续所有方法调用返回值均为code, data, message // code对应报错码有三部分组合构成,锁端报错码+星云服务端报错码+自定义报错码 @@ -48,83 +49,48 @@ if (code === Result.Success.code) { } /** - * 登录 - * @property {String} username - 用户名 - * @property {String} password - 密码 + * 退出登录 + * @param params + * @param {Number} params.uid 用户ID */ -const { code, data, message } = await $starCloud.login(username, password) - -/** - * 退出登录(未做请求,实际上不会失败) - */ -const { code, data, message } = await $starCloud.logout() +const { code, data, message } = await $starCloud.logout(params) /** * 选择锁 - * @property {Number} lockId - 锁Id + * @param params + * @param {AccountInfo} params.accountInfo 账号信息 + * @param {Number} params.lockId 锁ID + * @returns {Promise} */ -// 所需信息data中会返回,如data中没有可通过$starCloud.lockInfo获取 -const { code, data, message } = await $starCloud.selectLock(lockId) +const { code, data, message } = await $starCloud.selectLock(params) /** * 开门 - * @property {String} type - 开门或关门类型('open', 'close') - * @property {Boolean} disconnect - 操作完成后是否断开连接 + * @param params + * @param {AccountInfo} params.accountInfo 账号信息 + * @param {String} params.type 开门方式 close: 关门 open: 开门 + * @param {Boolean} params.disconnect 操作后是否断开连接 + * @returns {Promise} */ -const { code, data, message } = await $starCloud.openDoor(type, disconnect) - -/** - * 清理用户 - * @property {Boolean} disconnect - 操作完成后是否断开连接 - */ -const { code, data, message } = await $starCloud.cleanLockUser(disconnect) +const { code, data, message } = await $starCloud.openDoor(params) /** * 获取离线密码 - * 该功能无需蓝牙交互直接请求服务端,详细参数说明请看星云接口文档 - * @typedef {Object} password - * @property {String} keyboardPwdName - 密码名称 - * @property {Number} keyboardPwdType - 密码类型 - * @property {Number} isCoerced - 胁迫 1:胁迫 2:非胁迫 - * @property {Number} startDate - 开始时间 - * @property {Number} endDate - 结束时间 - * @property {Number} hoursStart - 开始小时 - * @property {Number} hoursEnd - 结束小时 + * @param {AccountInfo} accountInfo 账号信息 + * @param {OfflinePassword} password 密码信息 + * @returns {Promise} */ -const data = await $starCloud.getOfflinePassword({ - keyboardPwdName: `租客端单次密码${new Date().getTime()}`, - keyboardPwdType: 1, - isCoerced: 2, - startDate: 0, - endDate: 0, - hoursStart: 0, - hoursEnd: 0 -}) +const data = await $starCloud.getOfflinePassword(accountInfo, password) /** * 自定义密码 - * @typedef {Object} password - * @property {String} keyboardPwdName - 密码名称 - * @property {Number} keyboardPwdType - 密码类型 - * @property {Number} isCoerced - 胁迫 1:胁迫 2:非胁迫 - * @property {Number} startDate - 开始时间 - * @property {Number} endDate - 结束时间 - * @property {Number} keyboardPwd - 密码 - * @property {Number} addType - 添加方式,当前仅支持1 1:蓝牙 2:网关 - * @property {Number} operate - 操作类型,0:注册 1:修改 - * @property {Number} pwdRight - 是否是管理员密码,0:否 1:是 + * @param params + * @param {AccountInfo} params.accountInfo 账号信息 + * @param {CustomPassword} params.password 密码信息 + * @param {Boolean} params.disconnect 操作后是否断开连接 + * @returns {Promise} */ -const data = await $starCloud.customPassword({ - keyboardPwdName: `租客端自定义密码`, - keyboardPwdType: 3, - keyboardPwd: 111111, - addType: 1, - isCoerced: 2, - startDate: 1728698137000, - endDate: 1735574400000, - operate: 0, - pwdRight: 0 -}, true) +const data = await $starCloud.customPassword(params) /** * 搜索蓝牙设备 @@ -139,8 +105,11 @@ const searchDevice = async result => { await $starCloud.stopSearchDevice() /** - * 连接蓝牙设备 - * @property {String} name - 设备名称 + * 绑定设备 + * @param params + * @param {AccountInfo} params.accountInfo 账号信息 + * @param {String} params.name 设备名称 + * @returns {Promise} */ -const data = await $starCloud.bindDevice(name) +const data = await $starCloud.bindDevice(params) ``` diff --git a/request.js b/request.js index f596ac0..58b2073 100644 --- a/request.js +++ b/request.js @@ -60,10 +60,11 @@ const request = config => { if (code === 10003) { removeStorage('starCloudToken') removeStorage('starCloudUser') - const { code } = await starCloud.login( - starCloud.accountInfo.username, - starCloud.accountInfo.password - ) + const { code } = await starCloud.login({ + username: starCloud.starCloudAccountInfo.username, + password: starCloud.starCloudAccountInfo.password, + uid: starCloud.starCloudAccountInfo.uid + }) if (code === Result.Success.code) { resolve(await request(config)) } diff --git a/starCloud.js b/starCloud.js index fbfd96b..8eba676 100644 --- a/starCloud.js +++ b/starCloud.js @@ -38,6 +38,42 @@ import { uint8ArrayToString } from '@/starCloud/format' +/** + * 离线密码 + * 该功能无需蓝牙交互直接请求服务端,详细参数说明请看星云接口文档 + * @typedef {Object} OfflinePassword + * @property {String} keyboardPwdName - 密码名称 + * @property {Number} keyboardPwdType - 密码类型 + * @property {Number} isCoerced - 胁迫 1:胁迫 2:非胁迫 + * @property {Number} startDate - 开始时间 + * @property {Number} endDate - 结束时间 + * @property {Number} hoursStart - 开始小时 + * @property {Number} hoursEnd - 结束小时 + */ + +/** + * 自定义密码 + * @typedef {Object} CustomPassword + * @property {String} keyboardPwdName - 密码名称 + * @property {Number} keyboardPwdType - 密码类型 + * @property {Number} isCoerced - 胁迫 1:胁迫 2:非胁迫 + * @property {Number} startDate - 开始时间 + * @property {Number} endDate - 结束时间 + * @property {Number} keyboardPwd - 密码 + * @property {Number} addType - 添加方式,当前仅支持1 1:蓝牙 2:网关 + * @property {Number} operate - 操作类型,0:注册 1:修改 + * @property {Number} pwdRight - 是否是管理员密码,0:否 1:是 + */ + +/** + * 账户信息信息 + * @typedef {Object} AccountInfo + * @property {Number} uid 用户ID + * @property {String} username 用户名 + * @property {String} password 密码 + * @property {String} token token 非必填 + */ + /** * 锁信息 * @typedef {Object} lockInfo @@ -145,39 +181,47 @@ export const useStarCloudStore = defineStore('starCloud', { clientId: null, // 客户端密码 clientSecret: null, - // 星云是否登录 - loginStarCloud: false, - // 星云用户信息 - userInfo: null, - // 账户信息 - accountInfo: null, + // 小程序环境 + envVersion: '', // 锁信息 lockInfo: null, - // 消息序号 - messageCount: 1, // 服务器时间 serverTimestamp: 0, // 时间差 timeDifference: 0, - // 小程序环境 - envVersion: '', // 搜索设备列表 - searchDeviceList: [] + searchDeviceList: [], + // 星云用户信息 + userInfo: null, + // 账户信息 + accountInfo: null, + // 消息序号 + messageCount: 1 } }, actions: { - // 初始化星云 - initStarCloud(clientId, clientSecret, env = 'XHJ') { + /** + * 初始化星云 + * @param params + * @param {String} params.clientId 客户端Id + * @param {String} params.clientSecret 客户端密码 + * @param {String} params.env 环境 + */ + initStarCloud(params) { + const { clientId, clientSecret, env } = params const appInfo = uni.getAccountInfoSync() this.envVersion = appInfo.miniProgram.envVersion - this.env = env + this.env = env || 'XHJ' this.clientId = clientId this.clientSecret = clientSecret // 监听特性值变化 onBLECharacteristicValueChange(this.listenCharacteristicValue) }, - // 注册星云 + /** + * 注册星云 + * @returns {Promise} + */ async register() { const { code, data, message } = await starCloudCreateUser({ clientId: this.clientId, @@ -185,87 +229,456 @@ export const useStarCloudStore = defineStore('starCloud', { }) return new Result(code, data, message) }, - // 登录星云 - async login(username, password) { - this.accountInfo = { - username, - password + /** + * 退出登录 + * @param params + * @param {Number} params.uid 用户ID + */ + logout(params) { + const { uid } = params + if (this.accountInfo.uid === uid) { + this.userInfo = null + this.accountInfo = null + this.lockInfo = null + removeStorage('starCloudToken') + } + }, + /** + * 选择锁 + * @param params + * @param {AccountInfo} params.accountInfo 账号信息 + * @param {Number} params.lockId 锁ID + * @returns {Promise} + */ + async selectLock(params) { + const { accountInfo, lockId } = params + const result = await this.login(accountInfo) + if (result.code !== Result.Success.code) { + return result } - const token = getStorage('starCloudToken') - if (token) { - this.userInfo = getStorage('starCloudUser') - this.loginStarCloud = true - // 获取服务器时间 - this.getServerTimestamp().then(() => {}) - return Result.Success - } - console.log('登录星云', username, password) - const { - code, - data: userInfo, - message - } = await getStarCloudToken({ - username, - password, - clientId: this.clientId, - clientSecret: this.clientSecret - }) - if (code === Result.Success.code) { - this.userInfo = userInfo - setStorage('starCloudToken', userInfo.access_token) - setStorage('starCloudUser', userInfo) - this.loginStarCloud = true - // 获取服务器时间 - this.getServerTimestamp().then(() => {}) - } - return new Result(code, {}, message) - }, - // 退出登录 - logout() { - this.loginStarCloud = false - this.userInfo = null - this.accountInfo = null - removeStorage('starCloudToken') - removeStorage('starCloudUser') - removeStorage('lockList') - - return Result.Success - }, - // 选择锁 - async selectLock(lockId) { const { code, data, message } = await getLockDetailRequest({ lockId }) if (code === Result.Success.code) { - const lockList = getStorage('lockList') - if (lockList) { - const index = lockList.findIndex(item => item.lockId === lockId) + let lockList = getStorage('lockList') + if (!lockList) { + lockList = {} + } + if (lockList[accountInfo.uid]) { + const index = lockList[accountInfo.uid].findIndex(item => item.lockId === lockId) if (index === -1) { - lockList.push(data) + lockList[accountInfo.uid].push(data) } else { - lockList[index] = data + lockList[accountInfo.uid][index] = data } setStorage('lockList', lockList) } else { - setStorage('lockList', [data]) + lockList[accountInfo.uid] = [data] + setStorage('lockList', lockList) } this.lockInfo = data } else { const lockList = getStorage('lockList') - console.log('锁列表', lockList) - if (lockList) { - const index = lockList.findIndex(item => item.lockId === lockId) + if (lockList[accountInfo.uid]) { + const index = lockList[accountInfo.uid].findIndex(item => item.lockId === lockId) if (index !== -1) { - this.lockInfo = lockList[index] + this.lockInfo = lockList[accountInfo.uid][index] return new Result(Result.Success.code, this.lockInfo) } } } return new Result(code, data, message) }, - // 清理用户 - async cleanLockUser(disconnect = false) { + /** + * 开门 + * @param params + * @param {AccountInfo} params.accountInfo 账号信息 + * @param {String} params.type 开门方式 close: 关门 open: 开门 + * @param {Boolean} params.disconnect 操作后是否断开连接 + * @returns {Promise} + */ + async openDoor(params) { + const { accountInfo, type } = params + // 设置执行账号 + const result = await this.login(accountInfo) + if (result.code !== Result.Success.code) { + return result + } + + // 确认设备连接正常 + 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 onlineToken = '' + if (this.lockInfo.lockSetting.appUnlockOnline) { + const result = await this.getNetToken() + if (result.code === Result.Success.code) { + onlineToken = result.data.token + } else { + return result + } + } + + // 开门方式 + 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) + + 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.openDoor, params) + }, + /** + * 获取离线密码 + * @param {AccountInfo} accountInfo 账号信息 + * @param {OfflinePassword} password 密码信息 + * @returns {Promise} + */ + async getOfflinePassword(accountInfo, password) { + // 设置执行账号 + const result = await this.login(accountInfo) + if (result.code !== Result.Success.code) { + return result + } + return await getOfflinePasswordRequest({ + ...password, + lockId: this.lockInfo.lockId + }) + }, + /** + * 自定义密码 + * @param params + * @param {AccountInfo} params.accountInfo 账号信息 + * @param {CustomPassword} params.password 密码信息 + * @param {Boolean} params.disconnect 操作后是否断开连接 + * @returns {Promise} + */ + async customPassword(params) { + const { accountInfo, password } = params + // 设置执行账号 + const result = await this.login(accountInfo) + if (result.code !== Result.Success.code) { + return result + } + // 确认设备连接正常 + 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 + } + + requestParams = password + let { pwdNo, operate, keyboardPwd, startDate, endDate, pwdRight } = password + + 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) + }, + + // 搜索设备 + async searchDevice(callback) { + const result = await startBluetoothDevicesDiscovery() + if (result.code === Result.Success.code) { + const timestamp = new Date().getTime() + let queryFlag = false + timer = setInterval(async () => { + const queryResult = await getBluetoothDevices() + if (queryResult.code === Result.Success.code) { + const deviceList = queryResult.data + if (queryFlag === false && deviceList.length > 0) { + queryFlag = true + } + if (new Date().getTime() - timestamp > 10000 && !queryFlag) { + if (timer) { + clearInterval(timer) + } + callback(Result.NotAvailableWeChatNearbyDevicesEmpty) + } + + const list = [] + + for (let i = 0; i < deviceList.length; i++) { + if (deviceList[i]?.advertisServiceUUIDs) { + const uuid = deviceList[i]?.advertisServiceUUIDs[0] + if (uuid && uuid.slice(2, 8) === '758824' && uuid.slice(30, 32) === '00') { + list.push(deviceList[i]) + } + } + } + + this.searchDeviceList = list + callback( + new Result(Result.Success, { + list + }) + ) + } else { + callback(queryResult) + } + }, 1000) + } else { + callback(result) + } + }, + // 停止搜索 + async stopSearchDevice() { + console.log('停止搜索') + if (timer) { + clearInterval(timer) + } + + return await stopBluetoothDevicesDiscovery() + }, + /** + * 绑定设备 + * @param params + * @param {AccountInfo} params.accountInfo 账号信息 + * @param {String} params.name 设备名称 + * @returns {Promise} + */ + async bindDevice(params) { + const { accountInfo, name } = params + // 设置执行账号 + const result = await this.login(accountInfo) + if (result.code !== Result.Success.code) { + return result + } + const device = this.searchDeviceList.find(item => item.name === name) + const connectResult = await createBLEConnection(device.deviceId) + if (connectResult.code === Result.Success.code) { + this.updateLockInfo({ + ...connectResult.data, + bluetooth: { + bluetoothDeviceId: device.deviceId, + bluetoothDeviceName: device.name + } + }) + const publicKeyResult = await this.getPublicKey() + if (publicKeyResult.code !== Result.Success.code) { + return publicKeyResult + } + const commKeyResult = await this.getCommKey() + if (commKeyResult.code !== Result.Success.code) { + return commKeyResult + } + const lockStatusResult = await this.getLockStatus() + if (lockStatusResult.code !== Result.Success.code) { + return lockStatusResult + } + const timestamp = Math.ceil(new Date().getTime() / 1000) + const password = (Math.floor(Math.random() * 900000) + 100000).toString() + const addUserResult = await this.addLockUser({ + params: { + name: this.lockInfo.bluetooth.bluetoothDeviceName, + keyId: '0', + authUid: this.accountInfo.uid.toString(), + uid: this.accountInfo.uid.toString(), + openMode: 1, + keyType: 0, + startDate: timestamp, + expireDate: 0xffffffff, + useCountLimit: 0xffff, + isRound: 0, + weekRound: 0, + startHour: 0, + startMin: 0, + endHour: 0, + endMin: 0, + role: 0xff, + password + }, + disconnect: true + }) + if (addUserResult.code !== Result.Success.code) { + return addUserResult + } + + offBluetoothAdapterStateChange() + closeBluetoothAdapter() + + const params = { + lockAlias: this.lockInfo.bluetooth.bluetoothDeviceName, + lockInfo: { + ...this.lockInfo.lockConfig, + adminPwd: password + }, + bluetooth: this.lockInfo.bluetooth, + lockUserNo: this.lockInfo.lockUserNo, + pwdTimestamp: this.lockInfo.pwdTimestamp, + featureValue: this.lockInfo.featureValue, + featureSettingValue: this.lockInfo.featureSettingValue, + featureSettingParams: this.lockInfo.featureSettingParams + } + const bindLockResult = await bindLockRequest(params) + if (bindLockResult.code === Result.Success.code) { + this.updateLockInfo({ + lockId: bindLockResult.data.lockId, + keyId: bindLockResult.data.keyId + }) + } + return bindLockResult + } + return connectResult + }, + + /** + * 清理用户 + * @returns {Promise} + */ + async cleanLockUser() { // 确认设备连接正常 const searchResult = await searchAndConnectDevice(this.lockInfo.bluetooth.bluetoothDeviceName) if (searchResult.code !== Result.Success.code) { @@ -350,346 +763,69 @@ export const useStarCloudStore = defineStore('starCloud', { return writeResult } - return this.getWriteResult(this.cleanLockUser, disconnect) + return this.getWriteResult(this.cleanLockUser, { disconnect: false }) }, - // 开门 - // eslint-disable-next-line default-param-last - async openDoor(type = 'open', disconnect) { - // 确认设备连接正常 - const searchResult = await searchAndConnectDevice(this.lockInfo.bluetooth.bluetoothDeviceName) - if (searchResult.code !== Result.Success.code) { - return searchResult + /** + * 登录星云 + * @param {Object} accountInfo + * @returns {Promise} + */ + async login(accountInfo) { + let accounts = getStorage('starCloudAccount') + let userInfos = getStorage('starCloudUser') + if (!accounts) { + accounts = {} } - this.updateLockInfo(searchResult.data) - - // 检查是否已添加为用户 - const checkResult = await this.checkLockUser() - if (checkResult.code !== Result.Success.code) { - return checkResult + if (!userInfos) { + userInfos = {} } - // 是否需要联网 - 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 - } + this.accountInfo = accounts[accountInfo.uid] + if (this.accountInfo && this.accountInfo.token) { + this.userInfo = userInfos[accountInfo.uid] + + setStorage('starCloudToken', this.accountInfo.token) + + this.getServerTimestamp().then(() => {}) + return Result.Success } - // 开门方式 - 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.userInfo.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 { + code, + data: userInfo, + message + } = await getStarCloudToken({ + username: accountInfo.username, + password: accountInfo.password, + clientId: this.clientId, + clientSecret: this.clientSecret }) - - 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.openDoor, disconnect) - }, - // 获取离线密码 - async getOfflinePassword(password) { - return await getOfflinePasswordRequest({ - ...password, - lockId: this.lockInfo.lockId - }) - }, - // 自定义密码 - async customPassword(password, disconnect) { - // 确认设备连接正常 - 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 - } - - requestParams = password - let { pwdNo, operate, keyboardPwd, startDate, endDate, pwdRight } = password - - const uid = this.userInfo.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, disconnect, password) - }, - - // 搜索设备 - async searchDevice(callback) { - const result = await startBluetoothDevicesDiscovery() - if (result.code === Result.Success.code) { - const timestamp = new Date().getTime() - let queryFlag = false - timer = setInterval(async () => { - const queryResult = await getBluetoothDevices() - if (queryResult.code === Result.Success.code) { - const deviceList = queryResult.data - if (queryFlag === false && deviceList.length > 0) { - queryFlag = true - } - if (new Date().getTime() - timestamp > 10000 && !queryFlag) { - if (timer) { - clearInterval(timer) - } - callback(Result.NotAvailableWeChatNearbyDevicesEmpty) - } - - const list = [] - - for (let i = 0; i < deviceList.length; i++) { - if (deviceList[i]?.advertisServiceUUIDs) { - const uuid = deviceList[i]?.advertisServiceUUIDs[0] - if (uuid && uuid.slice(2, 8) === '758824' && uuid.slice(30, 32) === '00') { - list.push(deviceList[i]) - } - } - } - - this.searchDeviceList = list - callback( - new Result(Result.Success, { - list - }) - ) - } else { - callback(queryResult) - } - }, 1000) - } else { - callback(result) - } - }, - - // 停止搜索 - async stopSearchDevice() { - console.log('停止搜索') - if (timer) { - clearInterval(timer) - } - - return await stopBluetoothDevicesDiscovery() - }, - - // 绑定设备 - async bindDevice(name) { - const device = this.searchDeviceList.find(item => item.name === name) - const connectResult = await createBLEConnection(device.deviceId) - if (connectResult.code === Result.Success.code) { - this.updateLockInfo({ - ...connectResult.data, - bluetooth: { - bluetoothDeviceId: device.deviceId, - bluetoothDeviceName: device.name - } - }) - const publicKeyResult = await this.getPublicKey() - if (publicKeyResult.code !== Result.Success.code) { - return publicKeyResult - } - const commKeyResult = await this.getCommKey() - if (commKeyResult.code !== Result.Success.code) { - return commKeyResult - } - const lockStatusResult = await this.getLockStatus() - if (lockStatusResult.code !== Result.Success.code) { - return lockStatusResult - } - const timestamp = Math.ceil(new Date().getTime() / 1000) - const password = (Math.floor(Math.random() * 900000) + 100000).toString() - const addUserResult = await this.addLockUser( - { - name: this.lockInfo.bluetooth.bluetoothDeviceName, - keyId: '0', - authUid: this.userInfo.uid.toString(), - uid: this.userInfo.uid.toString(), - openMode: 1, - keyType: 0, - startDate: timestamp, - expireDate: 0xffffffff, - useCountLimit: 0xffff, - isRound: 0, - weekRound: 0, - startHour: 0, - startMin: 0, - endHour: 0, - endMin: 0, - role: 0xff, - password - }, - true - ) - if (addUserResult.code !== Result.Success.code) { - return addUserResult + if (code === Result.Success.code) { + this.userInfo = userInfo + this.accountInfo = { + username: accountInfo.username, + password: accountInfo.password, + token: userInfo.access_token, + uid: userInfo.cloudUid } + setStorage('starCloudToken', userInfo.access_token) - offBluetoothAdapterStateChange() - closeBluetoothAdapter() + accounts[userInfo.cloudUid] = { + uid: userInfo.cloudUid, + username: accountInfo.username, + password: accountInfo.password, + token: userInfo.access_token + } + setStorage('starCloudAccount', accounts) - const params = { - lockAlias: this.lockInfo.bluetooth.bluetoothDeviceName, - lockInfo: { - ...this.lockInfo.lockConfig, - adminPwd: password - }, - bluetooth: this.lockInfo.bluetooth, - lockUserNo: this.lockInfo.lockUserNo, - pwdTimestamp: this.lockInfo.pwdTimestamp, - featureValue: this.lockInfo.featureValue, - featureSettingValue: this.lockInfo.featureSettingValue, - featureSettingParams: this.lockInfo.featureSettingParams - } - const bindLockResult = await bindLockRequest(params) - if (bindLockResult.code === Result.Success.code) { - this.updateLockInfo({ - lockId: bindLockResult.data.lockId, - keyId: bindLockResult.data.keyId - }) - } - return bindLockResult + userInfos[userInfo.cloudUid] = userInfo + setStorage('starCloudUser', userInfo) + + // 获取服务器时间 + this.getServerTimestamp().then(() => {}) } - return connectResult + return new Result(code, {}, message) }, - // 获取公钥 async getPublicKey() { const headArray = this.createPackageHeader(0, 42) @@ -718,7 +854,7 @@ export const useStarCloudStore = defineStore('starCloud', { return writeResult } - return this.getWriteResult(this.getPublicKey, false) + return this.getWriteResult(this.getPublicKey, { disconnect: false }) }, // 获取私钥 async getCommKey() { @@ -731,7 +867,7 @@ export const useStarCloudStore = defineStore('starCloud', { const name = this.lockInfo.bluetooth.bluetoothDeviceName const keyId = '0' - const authUid = this.userInfo.uid.toString() + const authUid = this.accountInfo.uid.toString() await this.getServerTimestamp() const nowTime = this.serverTimestamp @@ -777,7 +913,7 @@ export const useStarCloudStore = defineStore('starCloud', { return writeResult } - return this.getWriteResult(this.getCommKey, false) + return this.getWriteResult(this.getCommKey, { disconnect: false }) }, // 获取锁状态 async getLockStatus() { @@ -789,7 +925,7 @@ export const useStarCloudStore = defineStore('starCloud', { contentArray[1] = cmdIds.getLockStatus % 256 const name = this.lockInfo.bluetooth.bluetoothDeviceName - const uid = this.userInfo.uid.toString() + const uid = this.accountInfo.uid.toString() await this.getServerTimestamp() const nowTime = this.serverTimestamp const date = new Date() @@ -822,7 +958,7 @@ export const useStarCloudStore = defineStore('starCloud', { return writeResult } - return this.getWriteResult(this.getLockStatus, false) + return this.getWriteResult(this.getLockStatus, { disconnect: false }) }, // 获取联网token async getNetToken() { @@ -841,7 +977,8 @@ export const useStarCloudStore = defineStore('starCloud', { return new Result(code, data, message) }, // 添加用户 - async addLockUser(data, disconnect = false) { + async addLockUser(params) { + const { params: data } = params // 确认设备连接正常 const searchResult = await searchAndConnectDevice( this.lockInfo.bluetooth.bluetoothDeviceName, @@ -945,11 +1082,10 @@ export const useStarCloudStore = defineStore('starCloud', { if (writeResult.code !== Result.Success.code) { return writeResult } - return this.getWriteResult(this.addLockUser, disconnect, data) + return this.getWriteResult(this.addLockUser, params) }, // 获取写入结果 - // eslint-disable-next-line default-param-last - getWriteResult(request, disconnect = false, params) { + getWriteResult(request, params) { return new Promise(resolve => { const getWriteResultTimer = setTimeout(() => { resolve(Result.Fail) @@ -968,7 +1104,7 @@ export const useStarCloudStore = defineStore('starCloud', { } } else { clearTimeout(getWriteResultTimer) - if (disconnect) { + if (params.disconnect) { await this.disconnectDevice() } console.log('写入结果', data, request, params) @@ -987,7 +1123,7 @@ export const useStarCloudStore = defineStore('starCloud', { name: this.lockInfo.bluetooth.bluetoothDeviceName, keyId: this.lockInfo.keyId.toString(), authUid: this.lockInfo.uid.toString(), - uid: this.userInfo.uid.toString(), + uid: this.accountInfo.uid.toString(), openMode: 1, keyType: 0, startDate: @@ -1006,7 +1142,10 @@ export const useStarCloudStore = defineStore('starCloud', { role: 0, password } - const addUserResult = await this.addLockUser(addUserParams) + const addUserResult = await this.addLockUser({ + params: addUserParams, + disconnect: false + }) console.log('添加用户蓝牙结果', addUserResult) if (addUserResult.code === Result.Success.code) { const { code } = await updateLockUserNoRequest({ From d4d7f9e89fc591ab9e80010ff68de8a3a33d791f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8C=83=E9=B9=8F?= Date: Tue, 19 Nov 2024 15:17:48 +0800 Subject: [PATCH 15/25] =?UTF-8?q?feat:=201.=20=E5=AE=8C=E6=88=90=E8=B4=A6?= =?UTF-8?q?=E5=8F=B7=E7=9B=B8=E5=85=B3=E5=8A=9F=E8=83=BD=202.=E5=AE=8C?= =?UTF-8?q?=E6=88=90=E9=A6=96=E9=A1=B5UI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- starCloud.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/starCloud.js b/starCloud.js index 8eba676..08d961b 100644 --- a/starCloud.js +++ b/starCloud.js @@ -236,7 +236,7 @@ export const useStarCloudStore = defineStore('starCloud', { */ logout(params) { const { uid } = params - if (this.accountInfo.uid === uid) { + if (this.accountInfo?.uid === uid) { this.userInfo = null this.accountInfo = null this.lockInfo = null From fff16d121315d341856e8c9a3023ca5286000048 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8C=83=E9=B9=8F?= Date: Thu, 21 Nov 2024 14:50:43 +0800 Subject: [PATCH 16/25] =?UTF-8?q?feat:=201.=20=E5=AE=8C=E6=88=90=E9=94=81?= =?UTF-8?q?=E5=88=97=E8=A1=A8=E7=9B=B8=E5=85=B3=E5=8A=9F=E8=83=BD=202.=20?= =?UTF-8?q?=E5=AE=8C=E6=88=90=E7=BB=91=E5=AE=9A=E9=94=81=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- starCloud.js | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/starCloud.js b/starCloud.js index 08d961b..5195bb4 100644 --- a/starCloud.js +++ b/starCloud.js @@ -561,7 +561,7 @@ export const useStarCloudStore = defineStore('starCloud', { this.searchDeviceList = list callback( - new Result(Result.Success, { + new Result(Result.Success.code, { list }) ) @@ -666,10 +666,17 @@ export const useStarCloudStore = defineStore('starCloud', { if (bindLockResult.code === Result.Success.code) { this.updateLockInfo({ lockId: bindLockResult.data.lockId, - keyId: bindLockResult.data.keyId + keyId: bindLockResult.data.keyId, + adminPwd: password }) } - return bindLockResult + return new Result( + bindLockResult.code, + { + lock: this.lockInfo + }, + bindLockResult.message + ) } return connectResult }, @@ -806,19 +813,19 @@ export const useStarCloudStore = defineStore('starCloud', { username: accountInfo.username, password: accountInfo.password, token: userInfo.access_token, - uid: userInfo.cloudUid + uid: userInfo.uid } setStorage('starCloudToken', userInfo.access_token) - accounts[userInfo.cloudUid] = { - uid: userInfo.cloudUid, + accounts[userInfo.uid] = { + uid: userInfo.uid, username: accountInfo.username, password: accountInfo.password, token: userInfo.access_token } setStorage('starCloudAccount', accounts) - userInfos[userInfo.cloudUid] = userInfo + userInfos[userInfo.uid] = userInfo setStorage('starCloudUser', userInfo) // 获取服务器时间 @@ -929,7 +936,7 @@ export const useStarCloudStore = defineStore('starCloud', { await this.getServerTimestamp() const nowTime = this.serverTimestamp const date = new Date() - const localTime = Math.floor(date.getTime() / 1000) - date.getTimezoneOffset() * 60 + const localTime = this.serverTimestamp - date.getTimezoneOffset() * 60 for (let i = 0; i < name.length; i++) { contentArray[i + 2] = name.charCodeAt(i) From 6cd5311190865aee4281f7461c2c5c4d2f3a280d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8C=83=E9=B9=8F?= Date: Fri, 22 Nov 2024 14:07:50 +0800 Subject: [PATCH 17/25] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9starCloud?= =?UTF-8?q?=E7=9A=84readme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index cb5075f..53a46b7 100644 --- a/README.md +++ b/README.md @@ -3,11 +3,22 @@ ### 1. 安装 在需要引用的项目中执行命令 -`git subtree add --prefix=starCloud git@code.star-lock.cn:StarlockTeam/starcloud-sdk-uniapp.git master` + +```git +git subtree add --prefix=starCloud git@code.star-lock.cn:StarlockTeam/starcloud-sdk-uniapp.git master +``` + 更新 -`git subtree pull --prefix=starCloud git@code.star-lock.cn:StarlockTeam/starcloud-sdk-uniapp.git master` + +```git +git subtree pull --prefix=starCloud git@code.star-lock.cn:StarlockTeam/starcloud-sdk-uniapp.git master +``` + 推送 -`git subtree push --prefix=starCloud git@code.star-lock.cn:StarlockTeam/starcloud-sdk-uniapp.git master` + +```git +git subtree push --prefix=starCloud git@code.star-lock.cn:StarlockTeam/starcloud-sdk-uniapp.git master +``` ### 2. 需安装的npm包 From 778172cf7f0a8985c0c788fb4b2e89160c666c7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8C=83=E9=B9=8F?= Date: Mon, 25 Nov 2024 15:31:38 +0800 Subject: [PATCH 18/25] =?UTF-8?q?feat:=201.=20=E5=AE=8C=E6=88=90=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE=E7=9B=B8=E5=85=B3=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api.js | 18 +++++++ starCloud.js | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 150 insertions(+), 1 deletion(-) diff --git a/api.js b/api.js index 8110415..cecb405 100644 --- a/api.js +++ b/api.js @@ -107,3 +107,21 @@ export function bindLockRequest(data) { data }) } + +// 移除坏锁 +export function removeBadLockRequest(data) { + return request({ + url: '/v1/lock/removeBadLock', + method: 'POST', + data + }) +} + +// 删除锁 +export function deleteLockRequest(data) { + return request({ + url: '/v1/lock/delete', + method: 'POST', + data + }) +} diff --git a/starCloud.js b/starCloud.js index 5195bb4..e15f562 100644 --- a/starCloud.js +++ b/starCloud.js @@ -4,6 +4,7 @@ import { buildNumber, configs, version } from '@/starCloud/env' import { addCustomPasswordRequest, bindLockRequest, + deleteLockRequest, deletePasswordRequest, getLockDetailRequest, getLockNetTokenRequest, @@ -11,6 +12,7 @@ import { getServerDatetimeRequest, getStarCloudToken, getUserNoListRequest, + removeBadLockRequest, starCloudCreateUser, updateLockUserNoRequest, updatePasswordRequest @@ -527,7 +529,6 @@ export const useStarCloudStore = defineStore('starCloud', { return this.getWriteResult(this.customPassword, params) }, - // 搜索设备 async searchDevice(callback) { const result = await startBluetoothDevicesDiscovery() @@ -680,6 +681,111 @@ export const useStarCloudStore = defineStore('starCloud', { } return connectResult }, + /** + * 移除坏锁 + * @param params + * @param {AccountInfo} params.accountInfo 账号信息 + * @param {List[int]} params.lockIds 锁Id列表 + * @returns {Promise} + */ + async removeBadLock(params) { + const { accountInfo, lockIds } = params + // 设置执行账号 + const result = await this.login(accountInfo) + if (result.code !== Result.Success.code) { + return result + } + const { code, message } = await removeBadLockRequest({ + lockIds: params.lockIds + }) + if (code === Result.Success.code) { + const lockList = getStorage('lockList') + if (lockList[accountInfo.uid]) { + lockIds.forEach(lockId => { + const index = lockList[accountInfo.uid].findIndex(item => item.lockId === lockId) + if (index !== -1) { + lockList[accountInfo.uid].splice(index, 1) + } + }) + setStorage('lockList', lockList) + } + } + + return new Result(code, {}, message) + }, + /** + * 删除锁 + * @param params + * @param {AccountInfo} params.accountInfo 账号信息 + */ + async deleteLock(params) { + const { accountInfo } = params + // 设置执行账号 + const result = await this.login(accountInfo) + if (result.code !== Result.Success.code) { + return result + } + // 确认设备连接正常 + 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) + }, /** * 清理用户 @@ -1392,6 +1498,31 @@ export const useStarCloudStore = defineStore('starCloud', { console.log('开门', decrypted[6], this.lockInfo.token) characteristicValueCallback(new Result(decrypted[6])) break + case cmdIds.resetDevice: + this.updateLockInfo({ + token: decrypted.slice(2, 6) + }) + if (decrypted[6] === Result.Success.code) { + const { code, message } = await deleteLockRequest({ + lockId: this.lockInfo.lockId + }) + if (code === Result.Success.code) { + const lockList = getStorage('lockList') + if (lockList[this.accountInfo.uid]) { + const index = lockList[this.accountInfo.uid].findIndex( + item => item.lockId === this.lockInfo.lockId + ) + if (index !== -1) { + lockList[this.accountInfo.uid].splice(index, 1) + } + setStorage('lockList', lockList) + } + } + characteristicValueCallback(new Result(code, {}, message)) + } else { + characteristicValueCallback(new Result(decrypted[6])) + } + break default: this.updateLockInfo({ token: decrypted.slice(2, 6) From 1d00c0f535c062aa0cbfbd5a1c7bec71730c082c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8C=83=E9=B9=8F?= Date: Mon, 25 Nov 2024 18:08:19 +0800 Subject: [PATCH 19/25] =?UTF-8?q?feat:=201.=20=E5=AE=8C=E6=88=90=E5=BC=80?= =?UTF-8?q?=E9=97=A8=E7=94=B5=E9=87=8F=E4=B8=8A=E6=8A=A5=202.=20=E5=AE=8C?= =?UTF-8?q?=E6=88=90=E9=80=9A=E7=9F=A5=E5=88=97=E8=A1=A8=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 16 ++++++++++++++++ api.js | 9 +++++++++ starCloud.js | 15 ++++++++++++--- 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 53a46b7..02e5a99 100644 --- a/README.md +++ b/README.md @@ -123,4 +123,20 @@ await $starCloud.stopSearchDevice() * @returns {Promise} */ const data = await $starCloud.bindDevice(params) + +/** + * 移除坏锁 + * @param params + * @param {AccountInfo} params.accountInfo 账号信息 + * @param {List[int]} params.lockIds 锁Id列表 + * @returns {Promise} + */ +const data = await $starCloud.removeBadLock(params) + +/** + * 删除锁 + * @param params + * @param {AccountInfo} params.accountInfo 账号信息 + */ +const data = await $starCloud.deleteLock(params) ``` diff --git a/api.js b/api.js index cecb405..c9a1454 100644 --- a/api.js +++ b/api.js @@ -125,3 +125,12 @@ export function deleteLockRequest(data) { data }) } + +// 删除锁 +export function updateElectricQuantityRequest(data) { + return request({ + url: '/v1/lock/updateElectricQuantity', + method: 'POST', + data + }) +} diff --git a/starCloud.js b/starCloud.js index e15f562..21fd1fb 100644 --- a/starCloud.js +++ b/starCloud.js @@ -14,6 +14,7 @@ import { getUserNoListRequest, removeBadLockRequest, starCloudCreateUser, + updateElectricQuantityRequest, updateLockUserNoRequest, updatePasswordRequest } from '@/starCloud/api' @@ -1493,10 +1494,18 @@ export const useStarCloudStore = defineStore('starCloud', { break case cmdIds.openDoor: this.updateLockInfo({ - token: decrypted.slice(2, 6) + token: decrypted.slice(2, 6), + electricQuantity: decrypted[7], + electricQuantityStandby: decrypted[9] }) - console.log('开门', decrypted[6], this.lockInfo.token) - characteristicValueCallback(new Result(decrypted[6])) + if (decrypted[6] === Result.Success.code) { + updateElectricQuantityRequest({ + lockId: this.lockInfo.lockId, + electricQuantity: decrypted[7], + electricQuantityStandby: decrypted[9] + }) + } + characteristicValueCallback(new Result(decrypted[6], { lock: this.lockInfo })) break case cmdIds.resetDevice: this.updateLockInfo({ From 455687486a36ac1bc51499324a74efca9dab609d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8C=83=E9=B9=8F?= Date: Tue, 26 Nov 2024 10:16:28 +0800 Subject: [PATCH 20/25] =?UTF-8?q?feat:=20=E5=AE=8C=E6=88=90=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E7=AE=A1=E7=90=86=E5=91=98=E5=AF=86=E7=A0=81=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api.js | 9 ++++ starCloud.js | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 130 insertions(+) diff --git a/api.js b/api.js index c9a1454..0c262d3 100644 --- a/api.js +++ b/api.js @@ -134,3 +134,12 @@ export function updateElectricQuantityRequest(data) { data }) } + +// 修改管理员密码 +export function changeAdminKeyboardPwdRequest(data) { + return request({ + url: '/v1/lock/changeAdminKeyboardPwd', + method: 'POST', + data + }) +} diff --git a/starCloud.js b/starCloud.js index 21fd1fb..4eed516 100644 --- a/starCloud.js +++ b/starCloud.js @@ -4,6 +4,7 @@ import { buildNumber, configs, version } from '@/starCloud/env' import { addCustomPasswordRequest, bindLockRequest, + changeAdminKeyboardPwdRequest, deleteLockRequest, deletePasswordRequest, getLockDetailRequest, @@ -158,6 +159,8 @@ const cmdIds = { // 子命令ID const subCmdIds = { + // 修改管理员密码 + updateAdminPassword: 2, // 设置开锁密码 setLockPassword: 3, // 重置开锁密码 @@ -787,6 +790,110 @@ export const useStarCloudStore = defineStore('starCloud', { return this.getWriteResult(this.deleteLock, params) }, + /** + * 修改管理员密码 + * @param params + * @param {AccountInfo} params.accountInfo 账号信息 + * @param {String} params.adminPwd 管理员密码 + * @param {Boolean} params.disconnect 操作后是否断开连接 + * @returns {Promise} + */ + async updateAdminPassword(params) { + const { adminPwd, accountInfo } = params + + // 设置执行账号 + const result = await this.login(accountInfo) + if (result.code !== Result.Success.code) { + return result + } + + // 确认设备连接正常 + 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 + } + + requestParams = params + + const uid = this.lockInfo.uid.toString() + const keyId = this.lockInfo.keyId.toString() + const pwdNo = 1 + const userCountLimit = 0xff + const startDate = Math.floor(this.lockInfo.startDate / 1000) + const endDate = Math.floor(this.lockInfo.endDate / 1000) + + const length = 2 + 1 + 1 + 40 + 20 + 2 + 20 + 2 + 4 + 4 + 4 + 1 + 16 + const headArray = this.createPackageHeader(3, length) + + const contentArray = new Uint8Array(length) + contentArray[0] = cmdIds.expandCmd / 256 + contentArray[1] = cmdIds.expandCmd % 256 + + // 子命令 + contentArray[2] = subCmdIds.updateAdminPassword + + contentArray[3] = length - 3 + + for (let i = 0; i < keyId.length; i++) { + contentArray[i + 4] = keyId.charCodeAt(i) + } + + for (let i = 0; i < uid.length; i++) { + contentArray[i + 44] = uid.charCodeAt(i) + } + + contentArray[64] = pwdNo / 256 + contentArray[65] = pwdNo % 256 + + for (let i = 0; i < adminPwd.length; i++) { + contentArray[i + 66] = adminPwd.charCodeAt(i) + } + + contentArray[86] = userCountLimit / 256 + contentArray[87] = userCountLimit % 256 + + contentArray.set(this.lockInfo.token || new Uint8Array([0, 0, 0, 0]), 88) + + contentArray.set(timestampToArray(startDate), 92) + contentArray.set(timestampToArray(endDate), 96) + + contentArray[100] = 16 + + const md5Array = md5Encrypt( + keyId + uid, + this.lockInfo.token || new Uint8Array([0, 0, 0, 0]), + this.lockInfo.bluetooth.signKey + ) + + contentArray.set(md5Array, 101) + + const cebArray = sm4.encrypt(contentArray, this.lockInfo.bluetooth.privateKey, { + mode: 'ecb', + output: 'array' + }) + + const packageArray = createPackageEnd(headArray, cebArray) + + const writeResult = await writeBLECharacteristicValue( + this.lockInfo.deviceId, + this.lockInfo.serviceId, + this.lockInfo.writeCharacteristicId, + packageArray + ) + + if (writeResult.code !== Result.Success.code) { + return writeResult + } + + return this.getWriteResult(this.updateAdminPassword, params) + }, /** * 清理用户 @@ -1428,6 +1535,20 @@ export const useStarCloudStore = defineStore('starCloud', { case cmdIds.expandCmd: const subCmdId = decrypted[3] switch (subCmdId) { + case subCmdIds.updateAdminPassword: + this.updateLockInfo({ + token: decrypted.slice(5, 9) + }) + if (decrypted[2] === Result.Success.code) { + const result = await changeAdminKeyboardPwdRequest({ + password: requestParams.adminPwd, + lockId: this.lockInfo.lockId + }) + return characteristicValueCallback(new Result(result.code)) + } else { + characteristicValueCallback(new Result(decrypted[2])) + } + break case subCmdIds.resetLockPassword: this.updateLockInfo({ token: decrypted.slice(5, 9) From f92782e13764c10a4390652f96eda9b54f43f86b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8C=83=E9=B9=8F?= Date: Tue, 26 Nov 2024 17:39:56 +0800 Subject: [PATCH 21/25] =?UTF-8?q?feat:=20=E5=AE=8C=E6=88=90=E5=BC=80?= =?UTF-8?q?=E9=97=A8=E8=AE=B0=E5=BD=95=E7=9B=B8=E5=85=B3=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=EF=BC=88=E5=B7=AEUI=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 19 ++++++ api.js | 18 ++++++ starCloud.js | 178 ++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 213 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 02e5a99..0ffa075 100644 --- a/README.md +++ b/README.md @@ -139,4 +139,23 @@ const data = await $starCloud.removeBadLock(params) * @param {AccountInfo} params.accountInfo 账号信息 */ const data = await $starCloud.deleteLock(params) + +/** + * 修改管理员密码 + * @param params + * @param {AccountInfo} params.accountInfo 账号信息 + * @param {String} params.adminPwd 管理员密码 + * @param {Boolean} params.disconnect 操作后是否断开连接 + * @returns {Promise} + */ +const data = await $starCloud.updateAdminPassword(params) + +/** + * 同步全部开门记录 + * @param params + * @param {AccountInfo} params.accountInfo 账号信息 + * @param {Boolean} params.disconnect 操作后是否断开连接 + * @returns {Promise} + */ +const data = await $starCloud.syncAllOpenRecord(params) ``` diff --git a/api.js b/api.js index 0c262d3..4d31d43 100644 --- a/api.js +++ b/api.js @@ -143,3 +143,21 @@ export function changeAdminKeyboardPwdRequest(data) { data }) } + +// 获取操作记录的最后上传时间 +export function getLastRecordTimeRequest(data) { + return request({ + url: '/v1/lockRecord/getLastRecordTime', + method: 'POST', + data + }) +} + +// 上传操作记录 +export function uploadRecordRequest(data) { + return request({ + url: '/v1/lockRecord/upload', + method: 'POST', + data + }) +} diff --git a/starCloud.js b/starCloud.js index 4eed516..9e39b3b 100644 --- a/starCloud.js +++ b/starCloud.js @@ -7,6 +7,7 @@ import { changeAdminKeyboardPwdRequest, deleteLockRequest, deletePasswordRequest, + getLastRecordTimeRequest, getLockDetailRequest, getLockNetTokenRequest, getOfflinePasswordRequest, @@ -17,7 +18,8 @@ import { starCloudCreateUser, updateElectricQuantityRequest, updateLockUserNoRequest, - updatePasswordRequest + updatePasswordRequest, + uploadRecordRequest } from '@/starCloud/api' import { getStorage, removeStorage, setStorage } from '@/starCloud/storage' import { @@ -164,7 +166,9 @@ const subCmdIds = { // 设置开锁密码 setLockPassword: 3, // 重置开锁密码 - resetLockPassword: 19 + resetLockPassword: 19, + // 同步开门记录 + syncOpenRecord: 41 } // 特性值回调 @@ -895,6 +899,139 @@ export const useStarCloudStore = defineStore('starCloud', { return this.getWriteResult(this.updateAdminPassword, params) }, + /** + * 同步全部开门记录 + * @param params + * @param {AccountInfo} params.accountInfo 账号信息 + * @param {Boolean} params.disconnect 操作后是否断开连接 + * @returns {Promise} + */ + async syncAllOpenRecord(params) { + const { accountInfo, disconnect } = params + + const { code, data, message } = await this.syncOpenRecord({ + accountInfo, + disconnect: false + }) + + if (code === Result.Success.code) { + if (data.count === 10) { + return await this.syncAllOpenRecord({ + accountInfo, + disconnect + }) + } else { + if (disconnect) { + await this.disconnectDevice() + } + return new Result(code, data, message) + } + } else { + return new Result(code, data, message) + } + }, + + /** + * 同步开门记录 + * @param params + * @param {AccountInfo} params.accountInfo 账号信息 + * @param {Boolean} params.disconnect 操作后是否断开连接 + * @returns {Promise} + */ + async syncOpenRecord(params) { + const { accountInfo } = params + + // 设置执行账号 + const result = await this.login(accountInfo) + if (result.code !== Result.Success.code) { + return result + } + + // 确认设备连接正常 + 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.lockInfo.uid.toString() + const keyId = this.lockInfo.keyId.toString() + const logsCount = 10 + + const timeResult = await getLastRecordTimeRequest({ + lockId: this.lockInfo.lockId + }) + + if (timeResult.code !== Result.Success.code) { + return timeResult + } + + const operateDate = Math.ceil(timeResult.data.operateDate / 1000) + const currentDate = Math.ceil(timeResult.data.currentDate / 1000) + + const length = 2 + 1 + 1 + 40 + 20 + 2 + 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.syncOpenRecord + + 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] = logsCount / 256 + contentArray[65] = logsCount % 256 + + contentArray.set(timestampToArray(operateDate), 66) + contentArray.set(timestampToArray(currentDate), 70) + + contentArray[74] = 16 + + const md5Array = md5Encrypt( + uid + keyId, + this.lockInfo.token || new Uint8Array([0, 0, 0, 0]), + this.lockInfo.bluetooth.publicKey + ) + + contentArray.set(md5Array, 75) + + 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.syncOpenRecord, params) + }, + /** * 清理用户 * @returns {Promise} @@ -1609,6 +1746,43 @@ export const useStarCloudStore = defineStore('starCloud', { characteristicValueCallback(new Result(decrypted[2])) } break + case subCmdIds.syncOpenRecord: + if (decrypted[2] === Result.Success.code && decrypted[6] > 0) { + const records = [] + const count = decrypted[6] || 0 + for (let i = 0; i < count; i++) { + let password = decrypted.slice(14 + 17 * i, 14 + 17 * i + 10) + if (password.every(item => item === 0)) { + password = null + } else { + password = uint8ArrayToString(password) + } + const record = { + type: decrypted[7 + 17 * i], + user: decrypted[8 + 17 * i] * 256 + decrypted[9 + 17 * i], + date: arrayToTimestamp(decrypted.slice(10 + 17 * i, 14 + 17 * i)) * 1000, + success: 1, + password: password + } + records.push(record) + } + const { code, message } = await uploadRecordRequest({ + records, + lockId: this.lockInfo.lockId + }) + characteristicValueCallback( + new Result( + code, + { + count + }, + message + ) + ) + } else { + characteristicValueCallback(new Result(decrypted[2])) + } + break default: break } From a888ce74158aceca1ff08615b09857ab578e319c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8C=83=E9=B9=8F?= Date: Thu, 28 Nov 2024 13:45:45 +0800 Subject: [PATCH 22/25] =?UTF-8?q?fix:=20=E4=BC=98=E5=8C=96=E5=BC=80?= =?UTF-8?q?=E9=94=81=E9=80=9F=E5=BA=A6=EF=BC=8C=E6=B7=BB=E5=8A=A0=E5=BC=80?= =?UTF-8?q?=E9=94=81=E5=AE=9E=E6=97=B6=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 + log.js | 40 +++++++++ starCloud.js | 235 ++++++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 235 insertions(+), 41 deletions(-) create mode 100644 log.js diff --git a/README.md b/README.md index 0ffa075..82a110e 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,7 @@ const $starCloud = useStarCloudStore() * @param {String} params.clientId 客户端Id * @param {String} params.clientSecret 客户端密码 * @param {String} params.env 环境 + * @param {Boolean} params.isReportLog 是否上报日志 */ $starCloud.initStarCloud(params) diff --git a/log.js b/log.js new file mode 100644 index 0000000..ff8ab75 --- /dev/null +++ b/log.js @@ -0,0 +1,40 @@ +import { isReportLog } from '@/starCloud/starCloud' + +const log = wx.getRealtimeLogManager ? wx.getRealtimeLogManager() : null + +export default { + debug() { + if (!log) return + if (!isReportLog) return + log.debug.apply(log, arguments) + }, + info() { + if (!log) return + if (!isReportLog) return + log.info.apply(log, arguments) + }, + warn() { + if (!log) return + if (!isReportLog) return + log.warn.apply(log, arguments) + }, + error() { + if (!log) return + if (!isReportLog) return + log.error.apply(log, arguments) + }, + setFilterMsg(msg) { + // 从基础库2.7.3开始支持 + if (!log || !log.setFilterMsg) return + if (typeof msg !== 'string') return + if (!isReportLog) return + log.setFilterMsg(msg) + }, + addFilterMsg(msg) { + // 从基础库2.8.1开始支持 + if (!log || !log.addFilterMsg) return + if (typeof msg !== 'string') return + if (!isReportLog) return + log.addFilterMsg(msg) + } +} diff --git a/starCloud.js b/starCloud.js index 9e39b3b..ff3e707 100644 --- a/starCloud.js +++ b/starCloud.js @@ -43,6 +43,7 @@ import { timestampToArray, uint8ArrayToString } from '@/starCloud/format' +import log from '@/starCloud/log' /** * 离线密码 @@ -139,6 +140,9 @@ import { * @property {String} userNos - 设备ID */ +// 是否上报日志 +export const isReportLog = false + // 命令ID const cmdIds = { // 获取公钥 @@ -216,12 +220,15 @@ export const useStarCloudStore = defineStore('starCloud', { * @param {String} params.clientId 客户端Id * @param {String} params.clientSecret 客户端密码 * @param {String} params.env 环境 + * @param {Boolean} params.isReportLog 是否上报日志 */ initStarCloud(params) { const { clientId, clientSecret, env } = params const appInfo = uni.getAccountInfoSync() this.envVersion = appInfo.miniProgram.envVersion + isReportLog = params.isReportLog + this.env = env || 'XHJ' this.clientId = clientId this.clientSecret = clientSecret @@ -271,25 +278,26 @@ export const useStarCloudStore = defineStore('starCloud', { lockId }) if (code === Result.Success.code) { - let lockList = getStorage('lockList') + this.lockInfo = data + let lockList = getStorage('starLockList') if (!lockList) { lockList = {} } if (lockList[accountInfo.uid]) { const index = lockList[accountInfo.uid].findIndex(item => item.lockId === lockId) if (index === -1) { - lockList[accountInfo.uid].push(data) + lockList[accountInfo.uid].push(this.lockInfo) } else { - lockList[accountInfo.uid][index] = data + this.lockInfo.token = lockList[accountInfo.uid][index].token + lockList[accountInfo.uid][index] = this.lockInfo } - setStorage('lockList', lockList) + setStorage('starLockList', lockList) } else { - lockList[accountInfo.uid] = [data] - setStorage('lockList', lockList) + lockList[accountInfo.uid] = [this.lockInfo] + setStorage('starLockList', lockList) } - this.lockInfo = data } else { - const lockList = getStorage('lockList') + const lockList = getStorage('starLockList') if (lockList[accountInfo.uid]) { const index = lockList[accountInfo.uid].findIndex(item => item.lockId === lockId) if (index !== -1) { @@ -310,18 +318,61 @@ export const useStarCloudStore = defineStore('starCloud', { */ async openDoor(params) { const { accountInfo, type } = params + + log.info( + new Result( + Result.Success.code, + { + lockName: this.lockInfo.bluetooth.bluetoothDeviceName, + lockId: this.lockInfo.lockId, + uid: accountInfo.uid, + time: new Date().getTime() + }, + `开始开门` + ) + ) + // 设置执行账号 const result = await this.login(accountInfo) if (result.code !== Result.Success.code) { return result } + log.info( + new Result( + result.code, + { + lockName: this.lockInfo.bluetooth.bluetoothDeviceName, + lockId: this.lockInfo.lockId, + uid: accountInfo.uid, + time: new Date().getTime() + }, + `登录星云账号: ${result.message}` + ) + ) + // 确认设备连接正常 - const searchResult = await searchAndConnectDevice(this.lockInfo.bluetooth.bluetoothDeviceName) - if (searchResult.code !== Result.Success.code) { - return searchResult + 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: accountInfo.uid, + time: new Date().getTime() + }, + `连接设备: ${searchResult.message}` + ) + ) + if (searchResult.code !== Result.Success.code) { + return searchResult + } + this.updateLockInfo(searchResult.data) } - this.updateLockInfo(searchResult.data) // 检查是否已添加为用户 const checkResult = await this.checkLockUser() @@ -329,6 +380,19 @@ export const useStarCloudStore = defineStore('starCloud', { return checkResult } + log.info( + new Result( + checkResult.code, + { + lockName: this.lockInfo.bluetooth.bluetoothDeviceName, + lockId: this.lockInfo.lockId, + uid: accountInfo.uid, + time: new Date().getTime() + }, + `确认是否为锁用户: ${checkResult.message}` + ) + ) + // 是否需要联网 let onlineToken = '' if (this.lockInfo.lockSetting.appUnlockOnline) { @@ -340,6 +404,19 @@ export const useStarCloudStore = defineStore('starCloud', { } } + log.info( + new Result( + checkResult.code, + { + lockName: this.lockInfo.bluetooth.bluetoothDeviceName, + lockId: this.lockInfo.lockId, + uid: accountInfo.uid, + time: new Date().getTime() + }, + `判断是否需要联网token: ${this.lockInfo.lockSetting.appUnlockOnline}` + ) + ) + // 开门方式 let openMode if (type === 'close') { @@ -396,6 +473,19 @@ export const useStarCloudStore = defineStore('starCloud', { const packageArray = createPackageEnd(headArray, cebArray) + log.info( + new Result( + Result.Success.code, + { + lockName: this.lockInfo.bluetooth.bluetoothDeviceName, + lockId: this.lockInfo.lockId, + uid: accountInfo.uid, + time: new Date().getTime() + }, + `开始写入` + ) + ) + const writeResult = await writeBLECharacteristicValue( this.lockInfo.deviceId, this.lockInfo.serviceId, @@ -407,6 +497,19 @@ export const useStarCloudStore = defineStore('starCloud', { return writeResult } + log.info( + new Result( + writeResult.code, + { + lockName: this.lockInfo.bluetooth.bluetoothDeviceName, + lockId: this.lockInfo.lockId, + uid: accountInfo.uid, + time: new Date().getTime() + }, + `写入完成:${writeResult.message}` + ) + ) + return this.getWriteResult(this.openDoor, params) }, /** @@ -442,11 +545,15 @@ export const useStarCloudStore = defineStore('starCloud', { return result } // 确认设备连接正常 - const searchResult = await searchAndConnectDevice(this.lockInfo.bluetooth.bluetoothDeviceName) - if (searchResult.code !== Result.Success.code) { - return searchResult + 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() @@ -707,7 +814,7 @@ export const useStarCloudStore = defineStore('starCloud', { lockIds: params.lockIds }) if (code === Result.Success.code) { - const lockList = getStorage('lockList') + const lockList = getStorage('starLockList') if (lockList[accountInfo.uid]) { lockIds.forEach(lockId => { const index = lockList[accountInfo.uid].findIndex(item => item.lockId === lockId) @@ -715,7 +822,7 @@ export const useStarCloudStore = defineStore('starCloud', { lockList[accountInfo.uid].splice(index, 1) } }) - setStorage('lockList', lockList) + setStorage('starLockList', lockList) } } @@ -734,11 +841,15 @@ export const useStarCloudStore = defineStore('starCloud', { return result } // 确认设备连接正常 - const searchResult = await searchAndConnectDevice(this.lockInfo.bluetooth.bluetoothDeviceName) - if (searchResult.code !== Result.Success.code) { - return searchResult + 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() @@ -812,11 +923,15 @@ export const useStarCloudStore = defineStore('starCloud', { } // 确认设备连接正常 - const searchResult = await searchAndConnectDevice(this.lockInfo.bluetooth.bluetoothDeviceName) - if (searchResult.code !== Result.Success.code) { - return searchResult + 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() @@ -948,11 +1063,15 @@ export const useStarCloudStore = defineStore('starCloud', { } // 确认设备连接正常 - const searchResult = await searchAndConnectDevice(this.lockInfo.bluetooth.bluetoothDeviceName) - if (searchResult.code !== Result.Success.code) { - return searchResult + 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() @@ -1337,15 +1456,18 @@ export const useStarCloudStore = defineStore('starCloud', { // 添加用户 async addLockUser(params) { const { params: data } = params + // 确认设备连接正常 - const searchResult = await searchAndConnectDevice( - this.lockInfo.bluetooth.bluetoothDeviceName, - data.role !== 0xff - ) - if (searchResult.code !== Result.Success.code) { - return searchResult + if (!params.connected) { + const searchResult = await searchAndConnectDevice( + this.lockInfo.bluetooth.bluetoothDeviceName, + data.role !== 0xff + ) + if (searchResult.code !== Result.Success.code) { + return searchResult + } + this.updateLockInfo(searchResult.data) } - this.updateLockInfo(searchResult.data) const { name, @@ -1451,11 +1573,22 @@ export const useStarCloudStore = defineStore('starCloud', { characteristicValueCallback = async data => { // code 6 token过期,重新获取 if (data.code === Result.NotTokenLock.code) { - resolve(await request(params)) + log.info( + new Result( + data.code, + { + lockName: this.lockInfo.bluetooth.bluetoothDeviceName, + lockId: this.lockInfo.lockId, + time: new Date().getTime() + }, + `token过期:${data.message}` + ) + ) + resolve(await request({ ...params, connected: true })) } else if (data.code === Result.NotRegisteredLock.code) { const checkResult = await this.checkLockUser(true) if (checkResult.code === Result.Success.code) { - resolve(await request(params)) + resolve(await request({ ...params, connected: true })) } else { clearTimeout(getWriteResultTimer) resolve(checkResult) @@ -1466,6 +1599,17 @@ export const useStarCloudStore = defineStore('starCloud', { await this.disconnectDevice() } console.log('写入结果', data, request, params) + log.info( + new Result( + data.code, + { + lockName: this.lockInfo.bluetooth.bluetoothDeviceName, + lockId: this.lockInfo.lockId, + time: new Date().getTime() + }, + `开门结果:${data.message}` + ) + ) resolve(data) } } @@ -1535,6 +1679,15 @@ export const useStarCloudStore = defineStore('starCloud', { ...this.lockInfo, ...lockInfo } + + const lockList = getStorage('starLockList') + const index = lockList[this.accountInfo.uid].findIndex( + item => item.lockId === this.lockInfo.lockId + ) + if (index !== -1) { + lockList[this.accountInfo.uid][index] = this.lockInfo + } + setStorage('starLockList', lockList) }, // 特征值变化回调 listenCharacteristicValue(res) { @@ -1811,7 +1964,7 @@ export const useStarCloudStore = defineStore('starCloud', { lockId: this.lockInfo.lockId }) if (code === Result.Success.code) { - const lockList = getStorage('lockList') + const lockList = getStorage('starLockList') if (lockList[this.accountInfo.uid]) { const index = lockList[this.accountInfo.uid].findIndex( item => item.lockId === this.lockInfo.lockId @@ -1819,7 +1972,7 @@ export const useStarCloudStore = defineStore('starCloud', { if (index !== -1) { lockList[this.accountInfo.uid].splice(index, 1) } - setStorage('lockList', lockList) + setStorage('starLockList', lockList) } } characteristicValueCallback(new Result(code, {}, message)) From 2504826566feef0725e5505ce265daea45eebf92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8C=83=E9=B9=8F?= Date: Thu, 28 Nov 2024 16:35:19 +0800 Subject: [PATCH 23/25] =?UTF-8?q?fix:=20bug=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- env.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/env.js b/env.js index 34fc8ea..8c9fe3c 100644 --- a/env.js +++ b/env.js @@ -13,6 +13,10 @@ export const configs = { name: 'PRE', baseUrl: 'https://pre.cloud.star-lock.cn/sdk' }, + PRE_SKY: { + name: 'PRE_SKY', + baseUrl: 'https://pre.cloud.star-lock.cn/sdk' + }, XHJ: { name: 'XHJ', baseUrl: 'https://cloud.xhjcn.ltd/sdk' From a7d4cd28f2cdf884c3379bea4700d290781032da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8C=83=E9=B9=8F?= Date: Mon, 2 Dec 2024 10:22:21 +0800 Subject: [PATCH 24/25] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E6=98=9F?= =?UTF-8?q?=E4=BA=91sdk=E6=9B=B4=E6=96=B0=E9=94=81=E4=BF=A1=E6=81=AFbug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- starCloud.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/starCloud.js b/starCloud.js index ff3e707..7a94545 100644 --- a/starCloud.js +++ b/starCloud.js @@ -1681,13 +1681,15 @@ export const useStarCloudStore = defineStore('starCloud', { } const lockList = getStorage('starLockList') - const index = lockList[this.accountInfo.uid].findIndex( - item => item.lockId === this.lockInfo.lockId - ) - if (index !== -1) { - lockList[this.accountInfo.uid][index] = this.lockInfo + if (lockList[this.accountInfo.uid]) { + const index = lockList[this.accountInfo.uid].findIndex( + item => item.lockId === this.lockInfo.lockId + ) + if (index !== -1) { + lockList[this.accountInfo.uid][index] = this.lockInfo + } + setStorage('starLockList', lockList) } - setStorage('starLockList', lockList) }, // 特征值变化回调 listenCharacteristicValue(res) { From 758363cd101aa5e0a544a224b5871dab4d2f2f41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8C=83=E9=B9=8F?= Date: Tue, 3 Dec 2024 10:21:27 +0800 Subject: [PATCH 25/25] =?UTF-8?q?fix:=20=E6=B7=BB=E5=8A=A0=E9=94=81?= =?UTF-8?q?=E7=8A=B6=E6=80=81=E5=88=A4=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 ++++++ log.js | 24 +++++++++++++++++------- starCloud.js | 45 ++++++++++++++++++++------------------------- 3 files changed, 43 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index 82a110e..36e3797 100644 --- a/README.md +++ b/README.md @@ -159,4 +159,10 @@ const data = await $starCloud.updateAdminPassword(params) * @returns {Promise} */ const data = await $starCloud.syncAllOpenRecord(params) + +/** + * 获取服务器时间 + * @returns {Promise} + */ +const data = await $starCloud.getServerTimestamp() ``` diff --git a/log.js b/log.js index ff8ab75..684e025 100644 --- a/log.js +++ b/log.js @@ -1,40 +1,50 @@ -import { isReportLog } from '@/starCloud/starCloud' +import { useStarCloudStore } from '@/starCloud/starCloud' const log = wx.getRealtimeLogManager ? wx.getRealtimeLogManager() : null export default { debug() { if (!log) return - if (!isReportLog) return + const $starCloud = useStarCloudStore() + if (!$starCloud.isReportLog) return + // eslint-disable-next-line prefer-spread,prefer-rest-params log.debug.apply(log, arguments) }, info() { if (!log) return - if (!isReportLog) return + const $starCloud = useStarCloudStore() + if (!$starCloud.isReportLog) return + // eslint-disable-next-line prefer-spread,prefer-rest-params log.info.apply(log, arguments) }, warn() { if (!log) return - if (!isReportLog) return + const $starCloud = useStarCloudStore() + if (!$starCloud.isReportLog) return + // eslint-disable-next-line prefer-spread,prefer-rest-params log.warn.apply(log, arguments) }, error() { if (!log) return - if (!isReportLog) return + const $starCloud = useStarCloudStore() + if (!$starCloud.isReportLog) return + // eslint-disable-next-line prefer-spread,prefer-rest-params log.error.apply(log, arguments) }, setFilterMsg(msg) { // 从基础库2.7.3开始支持 if (!log || !log.setFilterMsg) return if (typeof msg !== 'string') return - if (!isReportLog) return + const $starCloud = useStarCloudStore() + if (!$starCloud.isReportLog) return log.setFilterMsg(msg) }, addFilterMsg(msg) { // 从基础库2.8.1开始支持 if (!log || !log.addFilterMsg) return if (typeof msg !== 'string') return - if (!isReportLog) return + const $starCloud = useStarCloudStore() + if (!$starCloud.isReportLog) return log.addFilterMsg(msg) } } diff --git a/starCloud.js b/starCloud.js index 7a94545..6977b39 100644 --- a/starCloud.js +++ b/starCloud.js @@ -140,9 +140,6 @@ import log from '@/starCloud/log' * @property {String} userNos - 设备ID */ -// 是否上报日志 -export const isReportLog = false - // 命令ID const cmdIds = { // 获取公钥 @@ -210,7 +207,9 @@ export const useStarCloudStore = defineStore('starCloud', { // 账户信息 accountInfo: null, // 消息序号 - messageCount: 1 + messageCount: 1, + // 是否上报日志 + isReportLog: false } }, actions: { @@ -227,7 +226,7 @@ export const useStarCloudStore = defineStore('starCloud', { const appInfo = uni.getAccountInfoSync() this.envVersion = appInfo.miniProgram.envVersion - isReportLog = params.isReportLog + this.isReportLog = params.isReportLog this.env = env || 'XHJ' this.clientId = clientId @@ -1013,7 +1012,6 @@ export const useStarCloudStore = defineStore('starCloud', { return this.getWriteResult(this.updateAdminPassword, params) }, - /** * 同步全部开门记录 * @param params @@ -1035,17 +1033,14 @@ export const useStarCloudStore = defineStore('starCloud', { accountInfo, disconnect }) - } else { - if (disconnect) { - await this.disconnectDevice() - } - return new Result(code, data, message) } - } else { + if (disconnect) { + await this.disconnectDevice() + } return new Result(code, data, message) } + return new Result(code, data, message) }, - /** * 同步开门记录 * @param params @@ -1150,6 +1145,15 @@ export const useStarCloudStore = defineStore('starCloud', { return this.getWriteResult(this.syncOpenRecord, params) }, + // 获取服务器时间 + async getServerTimestamp() { + const { code, data, message } = await getServerDatetimeRequest({}) + if (code === Result.Success.code) { + this.serverTimestamp = Math.ceil(data.date / 1000) + this.timeDifference = Math.ceil((data.date - new Date().getTime()) / 1000) + } + return new Result(code, data, message) + }, /** * 清理用户 @@ -1444,15 +1448,6 @@ export const useStarCloudStore = defineStore('starCloud', { }) return new Result(code, data, message) }, - // 获取服务器时间 - async getServerTimestamp() { - const { code, data, message } = await getServerDatetimeRequest({}) - if (code === Result.Success.code) { - this.serverTimestamp = Math.ceil(data.date / 1000) - this.timeDifference = Math.ceil((data.date - new Date().getTime()) / 1000) - } - return new Result(code, data, message) - }, // 添加用户 async addLockUser(params) { const { params: data } = params @@ -1837,9 +1832,9 @@ export const useStarCloudStore = defineStore('starCloud', { lockId: this.lockInfo.lockId }) return characteristicValueCallback(new Result(result.code)) - } else { - characteristicValueCallback(new Result(decrypted[2])) } + characteristicValueCallback(new Result(decrypted[2])) + break case subCmdIds.resetLockPassword: this.updateLockInfo({ @@ -1917,7 +1912,7 @@ export const useStarCloudStore = defineStore('starCloud', { user: decrypted[8 + 17 * i] * 256 + decrypted[9 + 17 * i], date: arrayToTimestamp(decrypted.slice(10 + 17 * i, 14 + 17 * i)) * 1000, success: 1, - password: password + password } records.push(record) }