feat:增加配网功能接口

This commit is contained in:
liyi 2025-06-11 17:29:21 +08:00
parent a641d1f8ef
commit bcb7a9cfa1
11 changed files with 638 additions and 509 deletions

2
api.js
View File

@ -126,7 +126,7 @@ export function deleteLockRequest(data) {
}) })
} }
// 删除锁 // 更新锁电量
export function updateElectricQuantityRequest(data) { export function updateElectricQuantityRequest(data) {
return request({ return request({
url: '/v1/lock/updateElectricQuantity', url: '/v1/lock/updateElectricQuantity',

View File

@ -3,7 +3,7 @@ import {
arrayToTimestamp, arrayToTimestamp,
convertWeekdaysToNumber, convertWeekdaysToNumber,
createPackageEnd, createPackageEnd,
md5Encrypt, md5Encrypt, parseWifiList,
removeTrailingZeros, removeTrailingZeros,
timestampToArray, timestampToArray,
uint8ArrayToString uint8ArrayToString
@ -53,6 +53,7 @@ import {
version version
} from './export' } from './export'
import log from './log' import log from './log'
import {emitSearchWiFiResultEventUni} from "./uni/storage.js";
/** /**
* 同步开门记录 * 同步开门记录
@ -573,6 +574,7 @@ export function getWriteResult(request, params) {
return new Promise(resolve => { return new Promise(resolve => {
const getWriteResultTimer = setTimeout(() => { const getWriteResultTimer = setTimeout(() => {
resolve(Result.Fail) resolve(Result.Fail)
console.log("超时失败")
}, 20000) }, 20000)
this.characteristicValueCallback = async data => { this.characteristicValueCallback = async data => {
// code 6 token过期,重新获取 // code 6 token过期,重新获取
@ -733,7 +735,6 @@ export function listenCharacteristicValue(res) {
// 解析特征值 // 解析特征值
export async function parsingCharacteristicValue(binaryData) { export async function parsingCharacteristicValue(binaryData) {
// 0x20 明文 0x22 SM4事先约定密钥 0x23 SM4设备指定密钥 // 0x20 明文 0x22 SM4事先约定密钥 0x23 SM4设备指定密钥
if (binaryData[7] === 0x20) { if (binaryData[7] === 0x20) {
if (binaryData[12] * 256 + binaryData[13] === cmdIds.getPublicKey) { if (binaryData[12] * 256 + binaryData[13] === cmdIds.getPublicKey) {
@ -746,7 +747,16 @@ export async function parsingCharacteristicValue(binaryData) {
}) })
} }
this.characteristicValueCallback(new Result(binaryData[14])) this.characteristicValueCallback(new Result(binaryData[14]))
} else if (binaryData[12] * 256 + binaryData[13] === cmdIds.searchWiFi) {
this.characteristicValueCallback(new Result(binaryData[14]))
} }
// } else if (binaryData[12] * 256 + binaryData[13] === cmdIds.configureNetworkResult) {
// console.log("收到明文数据configureNetworkResult", Array.from(binaryData))
// this.characteristicValueCallback(new Result(binaryData[14]))
// } else if (binaryData[12] * 256 + binaryData[13] === cmdIds.configureNetwork) {
// console.log("收到明文数据configureNetwork", Array.from(binaryData))
// this.characteristicValueCallback(new Result(binaryData[14]))
// }
} else if (binaryData[7] === 0x22) { } else if (binaryData[7] === 0x22) {
// 截取入参 // 截取入参
const cebBinaryData = binaryData.slice(12, binaryData.length - 2) const cebBinaryData = binaryData.slice(12, binaryData.length - 2)
@ -759,7 +769,7 @@ export async function parsingCharacteristicValue(binaryData) {
mode: 'ecb', mode: 'ecb',
output: 'array' output: 'array'
}) })
console.log('ecb解密后的数据', decrypted) console.log('SM4事先约定密钥 ecb解密后的数据', decrypted)
if (decrypted[0] * 256 + decrypted[1] === cmdIds.getCommKey) { if (decrypted[0] * 256 + decrypted[1] === cmdIds.getCommKey) {
if (decrypted[2] === Result.Success.code) { if (decrypted[2] === Result.Success.code) {
@ -775,6 +785,9 @@ export async function parsingCharacteristicValue(binaryData) {
console.log('signKey', Array.from(this.lockInfo.bluetooth.signKey)) console.log('signKey', Array.from(this.lockInfo.bluetooth.signKey))
} }
this.characteristicValueCallback(new Result(decrypted[2])) this.characteristicValueCallback(new Result(decrypted[2]))
} else if (decrypted[0] * 256 + decrypted[1] === cmdIds.configureNetworkResult) {
console.log("SM4事先约定密钥 ecb解密后的数据configureNetworkResult", Array.from(binaryData))
this.characteristicValueCallback(new Result(binaryData[14]))
} }
} else { } else {
const cebBinaryData = binaryData.slice(12, binaryData.length - 2) const cebBinaryData = binaryData.slice(12, binaryData.length - 2)
@ -783,7 +796,7 @@ export async function parsingCharacteristicValue(binaryData) {
output: 'array', output: 'array',
padding: 'none' padding: 'none'
}) })
console.log('ecb解密后的数据', decrypted) console.log('SM4设备指定密钥 ecb解密后的数据', decrypted)
const cmdId = decrypted[0] * 256 + decrypted[1] const cmdId = decrypted[0] * 256 + decrypted[1]
@ -1091,7 +1104,6 @@ export async function parsingCharacteristicValue(binaryData) {
// 增加返回一个指纹序号 // 增加返回一个指纹序号
addResult.data.fingerprintNumber = decrypted[6] * 256 + decrypted[7]; addResult.data.fingerprintNumber = decrypted[6] * 256 + decrypted[7];
} }
console.log('registerFingerprintConfirm', decrypted)
// 触发指纹确认事件 // 触发指纹确认事件
emitRegisterFingerprintConfirmEvent(addResult) emitRegisterFingerprintConfirmEvent(addResult)
// 断开蓝牙连接 // 断开蓝牙连接
@ -1430,6 +1442,23 @@ export async function parsingCharacteristicValue(binaryData) {
this.characteristicValueCallback(new Result(decrypted[6])) this.characteristicValueCallback(new Result(decrypted[6]))
} }
break break
case cmdIds.searchWiFiResult:
if (decrypted[2] === Result.Success.code) {
const wifiInfoList = parseWifiList(decrypted);
emitSearchWiFiResultEventUni({
code: wifiInfoList.status,
numberOfSsid: wifiInfoList.numberOfSsid,
wifiList: wifiInfoList.wifiList,
})
}
break;
case cmdIds.configureNetworkResult:
if (decrypted[2] === Result.Success.code) {
this.characteristicValueCallback(new Result(decrypted[2], null, "配网成功"))
} else {
this.characteristicValueCallback(new Result(decrypted[2], null, "配网失败"))
}
break;
default: default:
this.updateLockInfo({ this.updateLockInfo({
token: decrypted.slice(2, 6) token: decrypted.slice(2, 6)

View File

@ -18,14 +18,14 @@ export const cmdIds = {
cleanUser: 0x300c, cleanUser: 0x300c,
// 扩展命令 // 扩展命令
expandCmd: 0x3030, expandCmd: 0x3030,
// 获取Wi-Fi列表 // 获取Wi-Fi
getWifiList: 0x30f6, searchWiFi: 0x30F6,
// Wi-Fi列表 // Wi-Fi列表
wifiList: 0x30f7, searchWiFiResult: 0x30F7,
// 配网 // 配网
distributionNetwork: 0x30f4, configureNetwork: 0x30F4,
// 配网结果 // 配网结果
distributionNetworkResult: 0x30f5 configureNetworkResult: 0x30F5
} }
// 子命令ID // 子命令ID

216
format.js
View File

@ -1,104 +1,105 @@
import { md5 } from 'js-md5' import {md5} from 'js-md5'
import crc from 'crc' import crc from 'crc'
// 周数组转换 // 周数组转换
export function convertWeekdaysToNumber(weekDay) { export function convertWeekdaysToNumber(weekDay) {
let weekStr = '00000000' let weekStr = '00000000'
// eslint-disable-next-line no-restricted-syntax // eslint-disable-next-line no-restricted-syntax
for (const day of weekDay) { for (const day of weekDay) {
const index = day % 7 const index = day % 7
weekStr = weekStr.substring(0, index) + '1' + weekStr.substring(index + 1) weekStr = weekStr.substring(0, index) + '1' + weekStr.substring(index + 1)
} }
// 倒序 weekStr // 倒序 weekStr
weekStr = weekStr.split('').reverse().join('') weekStr = weekStr.split('').reverse().join('')
return parseInt(weekStr, 2) return parseInt(weekStr, 2)
} }
// 时间戳转二进制 // 时间戳转二进制
export function timestampToArray(timestamp) { export function timestampToArray(timestamp) {
const array = new Uint8Array(4) const array = new Uint8Array(4)
array[0] = (timestamp & 0xff000000) >> 24 array[0] = (timestamp & 0xff000000) >> 24
array[1] = (timestamp & 0xff0000) >> 16 array[1] = (timestamp & 0xff0000) >> 16
array[2] = (timestamp & 0xff00) >> 8 array[2] = (timestamp & 0xff00) >> 8
array[3] = timestamp & 0xff array[3] = timestamp & 0xff
return array return array
} }
// 时分字符串转二进制 // 时分字符串转二进制
export function parseTimeToList(timeString) { export function parseTimeToList(timeString) {
let timeList = [0, 0, 0, 0] let timeList = [0, 0, 0, 0]
if (timeString.includes(':')) { if (timeString.includes(':')) {
let timeParts = timeString.split(':') let timeParts = timeString.split(':')
timeList[2] = parseInt(timeParts[0], 10) timeList[2] = parseInt(timeParts[0], 10)
timeList[3] = parseInt(timeParts[1], 10) timeList[3] = parseInt(timeParts[1], 10)
} }
return new Uint8Array(timeList) return new Uint8Array(timeList)
} }
// md5加密 // md5加密
export function md5Encrypt(text, token, key) { export function md5Encrypt(text, token, key) {
const length = text.length + 4 + 16 const length = text.length + 4 + 16
const md5Array = new Uint8Array(length) const md5Array = new Uint8Array(length)
for (let i = 0; i < text.length; i++) { for (let i = 0; i < text.length; i++) {
md5Array[i] = text.charCodeAt(i) md5Array[i] = text.charCodeAt(i)
} }
md5Array.set(token, text.length) md5Array.set(token, text.length)
md5Array.set(key, text.length + 4) md5Array.set(key, text.length + 4)
const md5Text = md5(md5Array) 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)))
} }
// 生成包尾 头部数据+内容数据 // 生成包尾 头部数据+内容数据
export function createPackageEnd(headArray, contentArray) { export function createPackageEnd(headArray, contentArray) {
// 拼接头部和内容 // 拼接头部和内容
let mergerArray = new Uint8Array(headArray.length + contentArray.length) let mergerArray = new Uint8Array(headArray.length + contentArray.length)
mergerArray.set(headArray) mergerArray.set(headArray)
mergerArray.set(contentArray, headArray.length) mergerArray.set(contentArray, headArray.length)
// crc加密 // crc加密
const crcResult = crc.crc16kermit(mergerArray) const crcResult = crc.crc16kermit(mergerArray)
// 拼接crc // 拼接crc
let newArray = new Uint8Array(mergerArray.length + 2) let newArray = new Uint8Array(mergerArray.length + 2)
newArray.set(mergerArray) newArray.set(mergerArray)
newArray.set([crcResult / 256, crcResult % 256], mergerArray.length) newArray.set([crcResult / 256, crcResult % 256], mergerArray.length)
return newArray return newArray
} }
// 二进制转时间戳 // 二进制转时间戳
export function arrayToTimestamp(array) { export function arrayToTimestamp(array) {
const timestamp = (array[0] << 24) | (array[1] << 16) | (array[2] << 8) | array[3] const timestamp = (array[0] << 24) | (array[1] << 16) | (array[2] << 8) | array[3]
return timestamp >>> 0 return timestamp >>> 0
} }
// 二进制转字符串 // 二进制转字符串
export function uint8ArrayToString(uint8Array) { export function uint8ArrayToString(uint8Array) {
let str = '' let str = ''
for (let i = 0; i < uint8Array.length; i++) { for (let i = 0; i < uint8Array.length; i++) {
if (uint8Array[i] !== 0) { if (uint8Array[i] !== 0) {
str += String.fromCharCode(uint8Array[i]) str += String.fromCharCode(uint8Array[i])
}
} }
} return str
return str
} }
// 去除特征值尾部0 // 去除特征值尾部0
export function removeTrailingZeros(data) { export function removeTrailingZeros(data) {
const featureCount = data[0] const featureCount = data[0]
let currentIndex = 1 let currentIndex = 1
for (let i = 0; i < featureCount; i++) { for (let i = 0; i < featureCount; i++) {
const length = data[currentIndex + 1] const length = data[currentIndex + 1]
currentIndex += 2 + length currentIndex += 2 + length
} }
return data.slice(0, currentIndex) return data.slice(0, currentIndex)
} }
@ -108,10 +109,10 @@ export function removeTrailingZeros(data) {
* @returns {(number|number)[]} * @returns {(number|number)[]}
*/ */
export function convertTimeToBytes(minutes) { export function convertTimeToBytes(minutes) {
return [ return [
Math.floor(minutes / 256), // 高字节 Math.floor(minutes / 256), // 高字节
minutes % 256 // 低字节 minutes % 256 // 低字节
]; ];
} }
/** /**
@ -121,14 +122,14 @@ export function convertTimeToBytes(minutes) {
* @returns {*[]} * @returns {*[]}
*/ */
export function convertWeekdayBitToArray(weekdayBit) { export function convertWeekdayBitToArray(weekdayBit) {
const weekdays = []; const weekdays = [];
const bits = weekdayBit.split(''); const bits = weekdayBit.split('');
bits.forEach((bit, index) => { bits.forEach((bit, index) => {
if (bit === '1') { if (bit === '1') {
weekdays.push(index); weekdays.push(index);
} }
}); });
return weekdays; return weekdays;
} }
/** /**
@ -138,15 +139,15 @@ export function convertWeekdayBitToArray(weekdayBit) {
* @returns {string} - 7位二进制字符串从右到左分别代表周一到周日 * @returns {string} - 7位二进制字符串从右到左分别代表周一到周日
*/ */
export function convertWeekdayArrayToBit(weekdays) { export function convertWeekdayArrayToBit(weekdays) {
const bits = new Array(7).fill('0'); const bits = new Array(7).fill('0');
weekdays.forEach(day => { weekdays.forEach(day => {
if (day >= 1 && day <= 7) { if (day >= 1 && day <= 7) {
// 将1-7转换为0-6的数组索引 // 将1-7转换为0-6的数组索引
const index = day === 7 ? 0 : day - 1; const index = day === 7 ? 0 : day - 1;
bits[index] = '1'; bits[index] = '1';
} }
}); });
return bits.join(''); return bits.join('');
} }
/** /**
@ -156,8 +157,8 @@ export function convertWeekdayArrayToBit(weekdays) {
* @private * @private
*/ */
export function _convertToMilliseconds(timestamp) { export function _convertToMilliseconds(timestamp) {
if (!timestamp) return timestamp; if (!timestamp) return timestamp;
return timestamp.toString().length === 10 ? timestamp * 1000 : timestamp; return timestamp.toString().length === 10 ? timestamp * 1000 : timestamp;
} }
/** /**
@ -167,10 +168,53 @@ export function _convertToMilliseconds(timestamp) {
* @returns {string | null} - 如果有字段为空则返回错误消息否则返回null * @returns {string | null} - 如果有字段为空则返回错误消息否则返回null
*/ */
export function checkRequiredFields(params, requiredFields) { export function checkRequiredFields(params, requiredFields) {
for (let field of requiredFields) { for (let field of requiredFields) {
if (params[field] === undefined || params[field] === null) { if (params[field] === undefined || params[field] === null) {
return `${field} 不能为空`; return `${field} 不能为空`;
}
} }
} return null;
return null; }
/**
* 转换解析wifi列表数据
* @param data
* @returns {{status: *, numberOfSsid: *, wifiList: *[]}}
*/
export function parseWifiList(data) {
// data: Array or Uint8Array
// 跳过前两位命令码
const status = data[2];
const numberOfSsid = data[3];
const wifiList = [];
let offset = 4;
for (let i = 0; i < numberOfSsid; i++) {
// 取32字节SSID
const ssidBytes = data.slice(offset, offset + 32);
// 用自定义函数转字符串并去除末尾0
const ssid = _bytesToString(ssidBytes).trim();
offset += 32;
// 取rssi
let rssi = data[offset];
// 通常rssi是无符号byte需转为有符号
if (rssi > 127) rssi = rssi - 256;
offset += 1;
// 过滤空名
if (ssid) {
wifiList.push({ssid, rssi});
}
}
return {status, numberOfSsid, wifiList};
}
function _bytesToString(bytes) {
// 只适用于ASCII和UTF-8无多字节字符的场景
let str = '';
for (let i = 0; i < bytes.length; i++) {
if (bytes[i] === 0) break; // 截断0
str += String.fromCharCode(bytes[i]);
}
return str;
} }

View File

@ -5,7 +5,11 @@ import ignore from 'ignore'
import { uniVersion } from './env.js' import { uniVersion } from './env.js'
// 获取当前目录和构建目标目录 // 获取当前目录和构建目标目录
const sourceDir = path.dirname(new URL(import.meta.url).pathname) const sourceDir = path.dirname(
process.platform === 'win32'
? new URL(import.meta.url).pathname.slice(1)
: new URL(import.meta.url).pathname
)
const distDir = path.join(sourceDir, 'dist') const distDir = path.join(sourceDir, 'dist')
const gitignorePath = path.join(sourceDir, '.gitignore') const gitignorePath = path.join(sourceDir, '.gitignore')

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{ {
"name": "star-cloud-uni", "name": "star-cloud-uni",
"version": "1.0.10", "version": "1.0.14",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "star-cloud-uni", "name": "star-cloud-uni",
"version": "1.0.10", "version": "1.0.14",
"dependencies": { "dependencies": {
"buffer": "^6.0.3", "buffer": "^6.0.3",
"crc": "^4.3.2", "crc": "^4.3.2",

View File

@ -10,6 +10,7 @@ import * as elec from './star-cloud/elec.js'
import * as coldWater from './star-cloud/coldWater.js' import * as coldWater from './star-cloud/coldWater.js'
import * as hotWater from './star-cloud/hotWater.js' import * as hotWater from './star-cloud/hotWater.js'
import * as generalExtend from './star-cloud/generalExtend.js' import * as generalExtend from './star-cloud/generalExtend.js'
import * as configureNetwork from './star-cloud/configureNetwork.js'
import { onBLECharacteristicValueChange } from './uni/basic' import { onBLECharacteristicValueChange } from './uni/basic'
/** /**
@ -141,7 +142,7 @@ class StarCloud {
* @param {Boolean} params.isReportLog 是否上报日志 * @param {Boolean} params.isReportLog 是否上报日志
*/ */
init(params) { init(params) {
Object.assign(StarCloud.prototype, device, lock, other, password, record, user, common, elec,coldWater, hotWater,generalExtend) Object.assign(StarCloud.prototype, device, lock, other, password, record, user, common, elec,coldWater, hotWater,generalExtend,configureNetwork)
const { clientId, clientSecret, env, platform, accounts,clientUrl } = params const { clientId, clientSecret, env, platform, accounts,clientUrl } = params
this.envVersion = 'release' this.envVersion = 'release'

View File

@ -1,20 +1,9 @@
import { import {
_convertToMilliseconds,
checkRequiredFields, checkRequiredFields,
convertWeekdaysToNumber, createPackageEnd, md5Encrypt, createPackageEnd,
parseTimeToList,
timestampToArray
} from "../format.js"; } from "../format.js";
import {cmdIds, Result, subCmdIds} from "../constant.js"; import {cmdIds, Result} from "../constant.js";
import {
checkRepeatCardName,
checkRepeatFaceName,
checkRepeatFingerprintName,
checkRepeatPalmVeinName,
checkRepeatRemoteName
} from "../api.js";
import {searchAndConnectDevice, writeBLECharacteristicValue} from "../uni/basic.js"; import {searchAndConnectDevice, writeBLECharacteristicValue} from "../uni/basic.js";
import {sm4} from "sm-crypto";
/** /**
* 开始搜索wifi * 开始搜索wifi
@ -23,7 +12,7 @@ import {sm4} from "sm-crypto";
export async function startSearchWiFi(params) { export async function startSearchWiFi(params) {
const uid = this.accountInfo.uid.toString() const uid = this.accountInfo.uid.toString()
// 设置执行账号 // 设置执行账号
const result = await this.login(uid) const result = await this.login(params.uid)
if (result.code !== Result.Success.code) { if (result.code !== Result.Success.code) {
return result return result
} }
@ -38,97 +27,26 @@ export async function startSearchWiFi(params) {
// 检查是否已添加为用户 // 检查是否已添加为用户
const checkResult = await this.checkLockUser() const checkResult = await this.checkLockUser()
if (!checkResult) { if (checkResult.code !== Result.Success.code) {
return { return checkResult
code: -1
}
} }
const length = 2 + 1 + 1 + 40 + 20 + 2 + 2 + 1 + 1 + 1 + 4 + 1 + 1 + 4 + 4 + 4 + 4 + 1 + 16 // 判断锁是否支持wifi功能
const headArray = this.createPackageHeader(3, length) if (!this.lockInfo.lockFeature || this.lockInfo.lockFeature.wifi !== 1) {
return new Result(Result.codes.Fail, null, '该锁不支持wifi配置');
}
const length = 2 + 20
const headArray = this.createPackageHeader(0, length)
const contentArray = new Uint8Array(length) const contentArray = new Uint8Array(length)
contentArray[0] = cmdIds.expandCmd / 256 contentArray[0] = cmdIds.searchWiFi / 256
contentArray[1] = cmdIds.expandCmd % 256 contentArray[1] = cmdIds.searchWiFi % 256
// 子命令
if (type === 'card') {
contentArray[2] = subCmdIds.registerCard
} else if (type === 'fingerprint') {
contentArray[2] = subCmdIds.registerFingerprint
} else if (type === 'face') {
contentArray[2] = subCmdIds.registerFace
} else if (type === 'remote') {
contentArray[2] = subCmdIds.registerRemote
} else if (type === 'palmVein') {
contentArray[2] = subCmdIds.registerPalmVein
}
contentArray[3] = length - 3
for (let i = 0; i < keyId.length; i++) {
contentArray[i + 4] = keyId.charCodeAt(i)
}
for (let i = 0; i < uid.length; i++) { for (let i = 0; i < uid.length; i++) {
contentArray[i + 44] = uid.charCodeAt(i) contentArray[i + 2] = i < uid.length ? uid.charCodeAt(i) : 0;
} }
const packageArray = createPackageEnd(headArray, contentArray)
// 子命令
if (type === 'card') {
contentArray[64] = (params.cardNumber || 0) / 256
contentArray[65] = (params.cardNumber || 0) % 256
} else if (type === 'fingerprint') {
contentArray[64] = (params.fingerprintNumber || 0) / 256
contentArray[65] = (params.fingerprintNumber || 0) % 256
} else if (type === 'face') {
contentArray[64] = (params.faceNumber || 0) / 256
contentArray[65] = (params.faceNumber || 0) % 256
} else if (type === 'remote') {
contentArray[64] = (params.remoteNumber || 0) / 256
contentArray[65] = (params.remoteNumber || 0) % 256
} else if (type === 'palmVein') {
contentArray[64] = (params.palmVeinNumber || 0) / 256
contentArray[65] = (params.palmVeinNumber || 0) % 256
}
contentArray[66] = (userCountLimit || 0xffff) / 256
contentArray[67] = (userCountLimit || 0xffff) % 256
contentArray[68] = operate
contentArray[69] = isAdmin || 0
contentArray[70] = isForce || 0
contentArray.set(this.lockInfo.token || new Uint8Array([0, 0, 0, 0]), 71)
contentArray[75] = isRound
contentArray[76] = convertWeekdaysToNumber(weekDay)
contentArray.set(timestampToArray(startDate), 77)
contentArray.set(timestampToArray(endDate), 81)
if (isRound) {
contentArray.set(parseTimeToList(startTime), 85)
contentArray.set(parseTimeToList(endTime), 89)
} else {
contentArray.set(new Uint8Array([0, 0, 0, 0]), 85)
contentArray.set(new Uint8Array([0, 0, 0, 0]), 89)
}
contentArray[93] = 16
const md5Array = md5Encrypt(
keyId + uid,
this.lockInfo.token || new Uint8Array([0, 0, 0, 0]),
this.lockInfo.bluetooth.signKey
)
contentArray.set(md5Array, 94)
console.log('加密前:', Array.from(contentArray))
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, const writeResult = await writeBLECharacteristicValue(this.lockInfo.deviceId,
this.lockInfo.serviceId, this.lockInfo.serviceId,
@ -137,6 +55,115 @@ export async function startSearchWiFi(params) {
if (writeResult.code !== Result.Success.code) { if (writeResult.code !== Result.Success.code) {
return writeResult return writeResult
} }
return this.getWriteResult(this.registerExtendedProducts, params) return this.getWriteResult(this.startSearchWiFi, params)
} }
/**
* 连接wifi
* @param params
* @returns {Promise<unknown>}
*/
export async function connectWiFi(params) {
const cardRequiredFields = ['ssid', 'password'];
const missingField = checkRequiredFields(params, cardRequiredFields);
if (missingField) {
return new Result(Result.codes.NotMoreData, null, `参数信息不完整: ${missingField}`);
}
let {
ssid,
password,
configureJson = JSON.stringify({
starcloudRpcPeerId: "6HnEcGnXMUcLQoE7rnC4aXMVJmojMnKAjqKHrt4TmN1U",
starcloudReportPeerId: "G3ehYz8djE35CTE2LWn5xe2nD51UpjC4hWd3vqVmXViE",
starcloudUrl: "http://cloud.skychip.top",
userPeerId: "C2HjHNy9LsjxW2QEmceiNDTN6XSXFDUZ3fYsnBigVQXA",
scdUrl: "http://scd.skychip.top:8710",
starlockPeerId: "0b3bd6327daafe2da24fdd0cae76c71477f32e3ef8ab",
clientId: "sBfWAwdMqVKIMBj4dPuRextHViC266aE",
secretKey: "zNn1AluC6sTVAtA4dX",
userPeerld: "zC2HjHNy9LsjxW2QEmceiNDTN6XSXFDUZ3fYsnBigVQX"
})
} = params
const uid = this.accountInfo.uid.toString()
// 设置执行账号
const result = await this.login(params.uid)
if (result.code !== Result.Success.code) {
return result
}
// 确认设备连接正常
if (!params.connected) {
const searchResult = await searchAndConnectDevice(this.lockInfo.bluetooth.bluetoothDeviceName)
if (searchResult.code !== Result.Success.code) {
return searchResult
}
this.updateLockInfo(searchResult.data)
}
// 检查是否已添加为用户
const checkResult = await this.checkLockUser()
if (checkResult.code !== Result.Success.code) {
return checkResult
}
// 判断锁是否支持wifi功能
if (!this.lockInfo.lockFeature || this.lockInfo.lockFeature.wifi !== 1) {
return new Result(Result.codes.Fail, null, '该锁不支持wifi配置');
}
// 处理 configureJson
let configureJsonBytes = [];
if (configureJson) {
for (let i = 0; i < configureJson.length; i++) {
const code = configureJson.charCodeAt(i);
if (code < 0x80) {
configureJsonBytes.push(code);
} else if (code < 0x800) {
configureJsonBytes.push(0xc0 | (code >> 6));
configureJsonBytes.push(0x80 | (code & 0x3f));
} else {
configureJsonBytes.push(0xe0 | (code >> 12));
configureJsonBytes.push(0x80 | ((code >> 6) & 0x3f));
configureJsonBytes.push(0x80 | (code & 0x3f));
}
}
}
const configureJsonLength = configureJsonBytes.length;
// 计算总长度
const length = 2 + 30 + 20 + 2 + configureJsonLength;
const headArray = this.createPackageHeader(0, length);
const contentArray = new Uint8Array(length);
contentArray[0] = cmdIds.configureNetwork / 256;
contentArray[1] = cmdIds.configureNetwork % 256;
// SSID: 30字节补0
for (let i = 0; i < 30; i++) {
contentArray[i + 2] = i < ssid.length ? ssid.charCodeAt(i) : 0;
}
// Password: 20字节补0
for (let i = 0; i < 20; i++) {
contentArray[i + 32] = i < password.length ? password.charCodeAt(i) : 0;
}
// configureJsonLength: 2字节大端序
contentArray[52] = (configureJsonLength >> 8) & 0xff;
contentArray[53] = configureJsonLength & 0xff;
// configureJson内容
for (let i = 0; i < configureJsonLength; i++) {
contentArray[54 + i] = configureJsonBytes[i];
}
console.log("配网命令:", Array.from(contentArray))
const packageArray = createPackageEnd(headArray, contentArray)
console.log("蓝牙包:", Array.from(packageArray))
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.connectWiFi, params)
}

62
uni.md
View File

@ -675,6 +675,38 @@ refreshHotWaterInfo(params)
**返回** **返回**
# 监听事件
**监听相关事件**
| 事件名 | 描述 | 返回值示例 |
|----------------------------|----------|-------------------------------------------------------|
| registerCardConfirm | 卡片注册成功 | {cardNumber:1,cardId:1} |
| registerFingerprintProcess | 指纹注册进度 | {status: 0,process: 0}**process总步数在上方统一`Result`中返回** |
| registerFingerprintConfirm | 指纹注册成功 | {fingerprintNumber:1,fingerprintId:1} |
| registerFaceProcess | 人脸注册进度 | {faceNumber:1,faceId:1} |
| registerFaceConfirm | 人脸注册成功 | {faceNumber:1,faceId:1} |
| registerPalmVeinConfirm | 掌静脉注册成功 | {palmVeinNumber:1,palmVeinId:1} |
| registerRemoteConfirm | 遥控注册成功 | {remoteNumber:1,remoteId:1} |
| searchWiFiResult | wifi搜索结果 | {status:0, numberOfSsid:7, wifiList:[Object]} |
**监听事件示例**
```js
// uniapp 监听注册卡片完成事件
uni.$on('registerCardConfirm', async data => {
// TODO
})
// uniapp 监听注册指纹进度
uni.$on('registerFingerprintProcess', async data => {
// TODO
})
// uniapp 指纹注册成功
uni.$on('registerFingerprintConfirm', async data => {
// TODO
})
```
# 扩展功能操作ic卡、指纹、人脸、遥控、掌静脉 # 扩展功能操作ic卡、指纹、人脸、遥控、掌静脉
## 注册、修改、删除、 删除全部 ## 注册、修改、删除、 删除全部
@ -736,36 +768,6 @@ registerExtendedProducts(params)
> >
> 收到锁版提示后,将卡片放置读卡器 > 收到锁版提示后,将卡片放置读卡器
**监听相关事件**
| 事件名 | 描述 | 返回值示例 |
|----------------------------|---------|-------------------------------------------------------|
| registerCardConfirm | 卡片注册成功 | {cardNumber:1,cardId:1} |
| registerFingerprintProcess | 指纹注册进度 | {status: 0,process: 0}**process总步数在上方统一`Result`中返回** |
| registerFingerprintConfirm | 指纹注册成功 | {fingerprintNumber:1,fingerprintId:1} |
| registerFaceProcess | 人脸注册进度 | {faceNumber:1,faceId:1} |
| registerFaceConfirm | 人脸注册成功 | {faceNumber:1,faceId:1} |
| registerPalmVeinConfirm | 掌静脉注册成功 | {palmVeinNumber:1,palmVeinId:1} |
| registerRemoteConfirm | 遥控注册成功 | {remoteNumber:1,remoteId:1} |
**监听事件示例**
```js
// uniapp 监听注册卡片完成事件
uni.$on('registerCardConfirm', async data => {
// TODO
})
// uniapp 监听注册指纹进度
uni.$on('registerFingerprintProcess', async data => {
// TODO
})
// uniapp 指纹注册成功
uni.$on('registerFingerprintConfirm', async data => {
// TODO
})
```
## 取消操作 ## 取消操作
**调用方法** **调用方法**

View File

@ -1,4 +1,4 @@
import { Result } from '../constant' import {Result} from '../constant'
/** /**
* @typedef {Object} err * @typedef {Object} err
@ -9,365 +9,367 @@ import { Result } from '../constant'
// 查找设备并连接 // 查找设备并连接
export function searchAndConnectDevice(name, reset = true) { export function searchAndConnectDevice(name, reset = true) {
// 循环查找设备 // 循环查找设备
let timer let timer
// 超时计时器 // 超时计时器
let timeoutTimer let timeoutTimer
return new Promise(async resolve => { return new Promise(async resolve => {
const result = await startBluetoothDevicesDiscovery() const result = await startBluetoothDevicesDiscovery()
if (result.code === Result.Success.code) { if (result.code === Result.Success.code) {
let searchFlag = false let searchFlag = false
timeoutTimer = setTimeout(async () => { 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() await stopBluetoothDevicesDiscovery()
clearTimeout(timeoutTimer)
clearInterval(timer) clearInterval(timer)
if (uuid.slice(30, 32) === '00' && reset) { if (!searchFlag) {
resolve(Result.DeviceHasBeenReset) resolve(Result.NotAvailableWeChatNearbyDevicesEmpty)
} else { } else {
const connectResult = await createBLEConnection(deviceList[i].deviceId) resolve(Result.Fail)
resolve(connectResult)
} }
break }, 10500)
} timer = setInterval(async () => {
if (uuid && uuid.slice(0, 2) === '75') { const queryResult = await getBluetoothDevices()
await stopBluetoothDevicesDiscovery() if (queryResult.code === Result.Success.code) {
clearTimeout(timeoutTimer) const deviceList = queryResult.data
clearInterval(timer) if (searchFlag === false && deviceList.length > 0) {
if (uuid.slice(4, 6) === '00' && reset) { searchFlag = true
resolve(Result.DeviceHasBeenReset) }
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' && reset) {
resolve(Result.DeviceHasBeenReset)
} else {
const connectResult = await createBLEConnection(deviceList[i].deviceId)
resolve(connectResult)
}
break
}
if (uuid && uuid.slice(0, 2) === '75') {
await stopBluetoothDevicesDiscovery()
clearTimeout(timeoutTimer)
clearInterval(timer)
if (uuid.slice(4, 6) === '00' && reset) {
resolve(Result.DeviceHasBeenReset)
} else {
const connectResult = await createBLEConnection(deviceList[i].deviceId)
resolve(connectResult)
}
break
}
}
}
} else { } else {
const connectResult = await createBLEConnection(deviceList[i].deviceId) resolve(queryResult)
resolve(connectResult)
} }
break }, 1000)
}
}
}
} else { } else {
resolve(queryResult) resolve(result)
} }
}, 1000) })
} else {
resolve(result)
}
})
} }
// 蓝牙操作报错处理 // 蓝牙操作报错处理
async function handleError(err, event) { async function handleError(err, event) {
if (err.errCode === 10000) { if (err.errCode === 10000) {
const result = await openBluetoothAdapter() const result = await openBluetoothAdapter()
if (result.code === Result.Success.code) { if (result.code === Result.Success.code) {
return await event() return await event()
}
return result
} }
return result if (err.errCode === 10001) {
} if (err.state === 3) {
if (err.errCode === 10001) { return Result.NotAvailableWeChatBluetoothPermission
if (err.state === 3) { }
return Result.NotAvailableWeChatBluetoothPermission return Result.NotAvailableBluetooth
} }
return Result.NotAvailableBluetooth if (err.errno === 3) {
} return Result.NotAvailableWeChatNearbyDevicesPermission
if (err.errno === 3) { }
return Result.NotAvailableWeChatNearbyDevicesPermission if (err.errno === 103) {
} return Result.NotAvailableBluetoothPermission
if (err.errno === 103) { }
return Result.NotAvailableBluetoothPermission if (err.errno === 1509008) {
} return Result.NotAvailableWeChatLocationPermission
if (err.errno === 1509008) { }
return Result.NotAvailableWeChatLocationPermission if (err.errMsg === 'openBluetoothAdapter:fail already opened') {
} return Result.Success
if (err.errMsg === 'openBluetoothAdapter:fail already opened') { }
return Result.Success return Result.Fail
}
return Result.Fail
} }
// 初始化蓝牙模块 // 初始化蓝牙模块
function openBluetoothAdapter() { function openBluetoothAdapter() {
return new Promise(resolve => { return new Promise(resolve => {
uni.openBluetoothAdapter({ uni.openBluetoothAdapter({
success() { success() {
resolve(Result.Success) resolve(Result.Success)
}, },
async fail(err) { async fail(err) {
resolve(await handleError(err)) resolve(await handleError(err))
} }
})
}) })
})
} }
// 关闭蓝牙模块 // 关闭蓝牙模块
export function closeBluetoothAdapter() { export function closeBluetoothAdapter() {
uni.closeBluetoothAdapter() uni.closeBluetoothAdapter()
} }
// 移除蓝牙适配器的全部监听 // 移除蓝牙适配器的全部监听
export function offBluetoothAdapterStateChange() { export function offBluetoothAdapterStateChange() {
uni.offBluetoothAdapterStateChange() uni.offBluetoothAdapterStateChange()
} }
// 监听蓝牙特征值改变 // 监听蓝牙特征值改变
export function onBLECharacteristicValueChange(callback) { export function onBLECharacteristicValueChange(callback) {
uni.onBLECharacteristicValueChange(res => { uni.onBLECharacteristicValueChange(res => {
callback(res) callback(res)
}) })
} }
// 开始搜索附近的蓝牙设备 // 开始搜索附近的蓝牙设备
export function startBluetoothDevicesDiscovery() { export function startBluetoothDevicesDiscovery() {
return new Promise(resolve => { return new Promise(resolve => {
uni.startBluetoothDevicesDiscovery({ uni.startBluetoothDevicesDiscovery({
success() { success() {
resolve(Result.Success) resolve(Result.Success)
}, },
async fail(err) { async fail(err) {
resolve(await handleError(err, startBluetoothDevicesDiscovery)) resolve(await handleError(err, startBluetoothDevicesDiscovery))
} }
})
}) })
})
} }
// 获取所有已发现的蓝牙设备 // 获取所有已发现的蓝牙设备
export function getBluetoothDevices() { export function getBluetoothDevices() {
return new Promise(resolve => { return new Promise(resolve => {
uni.getBluetoothDevices({ uni.getBluetoothDevices({
success(res) { success(res) {
resolve(new Result(Result.Success.code, res.devices)) resolve(new Result(Result.Success.code, res.devices))
}, },
async fail(err) { async fail(err) {
resolve(await handleError(err, getBluetoothDevices)) resolve(await handleError(err, getBluetoothDevices))
} }
})
}) })
})
} }
// 停止搜索附近的蓝牙设备 // 停止搜索附近的蓝牙设备
export function stopBluetoothDevicesDiscovery() { export function stopBluetoothDevicesDiscovery() {
return new Promise(resolve => { return new Promise(resolve => {
uni.stopBluetoothDevicesDiscovery({ uni.stopBluetoothDevicesDiscovery({
success() { success() {
resolve(Result.Success) resolve(Result.Success)
}, },
async fail(err) { async fail(err) {
resolve(await handleError(err)) resolve(await handleError(err))
} }
})
}) })
})
} }
// 连接低功耗蓝牙设备 // 连接低功耗蓝牙设备
export function createBLEConnection(deviceId, reconnectNumber = 0) { export function createBLEConnection(deviceId, reconnectNumber = 0) {
return new Promise(resolve => { return new Promise(resolve => {
uni.createBLEConnection({ uni.createBLEConnection({
deviceId,
timeout: 10000,
async success() {
const res = await getBLEDeviceServicesAndCharacteristics(deviceId)
await notifyBLECharacteristicValueChange(
deviceId,
res.data.serviceId,
res.data.notifyCharacteristicId
)
// 使用同步方法获取系统信息
const systemInfo = uni.getSystemInfoSync();
if (systemInfo.platform === 'android') {
// 如果是Android机型则设置BLE MTU
uni.setBLEMTU({
deviceId: deviceId,
mtu: 512,
fail: res => {
// console.log('mtu fail', res);
},
success: res => {
// console.log('mtu success', res);
}
});
} else {
// 对于非Android设备可以在这里添加其他逻辑或者直接忽略
// console.log('当前设备不是Android跳过设置BLE MTU');
}
resolve(res)
},
async fail(err) {
if (err.errno === 1509007) {
const res = await getBLEDeviceServicesAndCharacteristics(deviceId)
await notifyBLECharacteristicValueChange(
deviceId, deviceId,
res.data.serviceId, timeout: 10000,
res.data.notifyCharacteristicId async success() {
) const res = await getBLEDeviceServicesAndCharacteristics(deviceId)
resolve(res) await notifyBLECharacteristicValueChange(
} else if (err.errno === 1509001 && reconnectNumber < 1) { deviceId,
resolve(Result.Fail) res.data.serviceId,
} else if (reconnectNumber < 1) { res.data.notifyCharacteristicId
resolve(await createBLEConnection(deviceId, reconnectNumber + 1)) )
} else { // 使用同步方法获取系统信息
resolve(Result.Fail) const systemInfo = uni.getSystemInfoSync();
}
} if (systemInfo.platform === 'android') {
// 如果是Android机型则设置BLE MTU
uni.setBLEMTU({
deviceId: deviceId,
mtu: 512,
fail: res => {
// console.log('mtu fail', res);
},
success: res => {
// console.log('mtu success', res);
}
});
} else {
// 对于非Android设备可以在这里添加其他逻辑或者直接忽略
// console.log('当前设备不是Android跳过设置BLE MTU');
}
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) { async function getBLEDeviceServicesAndCharacteristics(deviceId) {
const { code, data } = await getBLEDeviceServices(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) { if (code === Result.Success.code) {
return new Result(Result.Success.code, { const {serviceId} = data
deviceId, const {
serviceId, code,
notifyCharacteristicId, data: {notifyCharacteristicId, writeCharacteristicId}
writeCharacteristicId } = await getBLEDeviceCharacteristics(deviceId, serviceId)
}) if (code === Result.Success.code) {
return new Result(Result.Success.code, {
deviceId,
serviceId,
notifyCharacteristicId,
writeCharacteristicId
})
}
return Result.Fail
} }
return Result.Fail return Result.Fail
}
return Result.Fail
} }
// 获取设备的服务 // 获取设备的服务
function getBLEDeviceServices(deviceId) { function getBLEDeviceServices(deviceId) {
return new Promise(resolve => { return new Promise(resolve => {
uni.getBLEDeviceServices({ uni.getBLEDeviceServices({
deviceId, deviceId,
success(res) { success(res) {
let serviceId let serviceId
for (let i = 0; i < res.services.length; i++) { for (let i = 0; i < res.services.length; i++) {
if (res.services[i].uuid.indexOf('FFF0') !== -1) { if (res.services[i].uuid.indexOf('FFF0') !== -1) {
serviceId = res.services[i].uuid serviceId = res.services[i].uuid
} }
} }
if (!serviceId) { if (!serviceId) {
resolve(Result.Fail) resolve(Result.Fail)
return return
} }
resolve(new Result(Result.Success.code, { serviceId })) resolve(new Result(Result.Success.code, {serviceId}))
}, },
fail() { fail() {
resolve(Result.Fail) resolve(Result.Fail)
} }
})
}) })
})
} }
// 获取服务的特征值 // 获取服务的特征值
function getBLEDeviceCharacteristics(deviceId, serviceId) { function getBLEDeviceCharacteristics(deviceId, serviceId) {
return new Promise(resolve => { return new Promise(resolve => {
uni.getBLEDeviceCharacteristics({ uni.getBLEDeviceCharacteristics({
deviceId, deviceId,
serviceId, serviceId,
success(res) { success(res) {
let notifyCharacteristicId let notifyCharacteristicId
let writeCharacteristicId 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] const characteristic = res.characteristics[i]
if (characteristic.properties.notify) { if (characteristic.properties.notify) {
notifyCharacteristicId = characteristic.uuid notifyCharacteristicId = characteristic.uuid
} }
if (characteristic.properties.write) { if (characteristic.properties.write) {
writeCharacteristicId = characteristic.uuid writeCharacteristicId = characteristic.uuid
} }
} }
if (notifyCharacteristicId && writeCharacteristicId) { if (notifyCharacteristicId && writeCharacteristicId) {
resolve( resolve(
new Result(Result.Success.code, { notifyCharacteristicId, writeCharacteristicId }) new Result(Result.Success.code, {notifyCharacteristicId, writeCharacteristicId})
) )
} else { } else {
resolve(Result.Fail) resolve(Result.Fail)
} }
}, },
fail() { fail() {
resolve(Result.Fail) resolve(Result.Fail)
} }
})
}) })
})
} }
// 订阅特征值 // 订阅特征值
function notifyBLECharacteristicValueChange(deviceId, serviceId, characteristicId) { function notifyBLECharacteristicValueChange(deviceId, serviceId, characteristicId) {
return new Promise(resolve => { return new Promise(resolve => {
uni.notifyBLECharacteristicValueChange({ uni.notifyBLECharacteristicValueChange({
deviceId, deviceId,
serviceId, serviceId,
characteristicId, characteristicId,
state: true, state: true,
success() { success() {
resolve(Result.Success) resolve(Result.Success)
}, },
fail() { fail() {
resolve(Result.Fail) resolve(Result.Fail)
} }
})
}) })
})
} }
// 断开与低功耗蓝牙设备的连接 // 断开与低功耗蓝牙设备的连接
export function closeBLEConnection(deviceId) { export function closeBLEConnection(deviceId) {
return new Promise(resolve => { return new Promise(resolve => {
uni.closeBLEConnection({ uni.closeBLEConnection({
deviceId, deviceId,
success() { success() {
console.log('断开连接成功') console.log('断开连接成功')
resolve(Result.Success) resolve(Result.Success)
}, },
fail() { fail() {
console.log('断开连接失败') console.log('断开连接失败')
resolve(Result.Fail) resolve(Result.Fail)
} }
})
}) })
})
} }
// 写入特征值 // 写入特征值
export function writeBLECharacteristicValue(deviceId, serviceId, characteristicId, binaryData) { export function writeBLECharacteristicValue(deviceId, serviceId, characteristicId, binaryData) {
return new Promise(resolve => { return new Promise(resolve => {
const count = Math.ceil(binaryData.length / 20) const count = Math.ceil(binaryData.length / 20)
let successCount = 0 let successCount = 0
for (let i = 0; i < count; i++) { for (let i = 0; i < count; i++) {
const writeData = binaryData.slice(i * 20, i === count - 1 ? binaryData.length : (i + 1) * 20) const writeData = binaryData.slice(i * 20, i === count - 1 ? binaryData.length : (i + 1) * 20)
uni.writeBLECharacteristicValue({ uni.writeBLECharacteristicValue({
deviceId, deviceId,
serviceId, serviceId,
characteristicId, characteristicId,
value: writeData.buffer, value: writeData.buffer,
success() { success(res) {
successCount++ successCount++
if (successCount === count) { if (successCount === count) {
resolve(Result.Success) resolve(Result.Success)
} }
}, console.log("writeBLECharacteristicValue res", res)
fail() { },
resolve(Result.Fail) fail(err) {
console.error("writeBLECharacteristicValue err", err)
resolve(Result.Fail)
}
})
} }
}) })
}
})
} }

View File

@ -1,5 +1,6 @@
import starCloudInstance from '../star-cloud' import starCloudInstance from '../star-cloud'
import {Result, supportFunctionsFeatureBit} from '../constant' import {Result, supportFunctionsFeatureBit} from '../constant'
export {Result} export {Result}
/** /**
@ -345,7 +346,6 @@ export const readSupportFunctionsSetting = async params => {
} }
/** /**
* 获取Ic卡列表 * 获取Ic卡列表
* @param params.lockId 锁id 必填 * @param params.lockId 锁id 必填
@ -414,3 +414,23 @@ export const remoteUnLock = async params => {
export const getLockList = async params => { export const getLockList = async params => {
return await starCloudInstance.getLockList(params) return await starCloudInstance.getLockList(params)
} }
/**
* 启动搜索wifi
* @param params
* @returns {Promise<*>}
*/
export const startSearchWiFi = async params => {
return await starCloudInstance.startSearchWiFi(params)
}
/**
* 连接wifi
* @param params.ssid wifi昵称
* @param params.password wifi密码
* @returns {Promise<*>}
*/
export const connectWiFi = async params => {
return await starCloudInstance.connectWiFi(params)
}