@jiabaida/tools 1.0.7 → 1.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/core/BleApiManager.js +1 -1
- package/dist/cjs/core/BleCmdAnalysis/BaseParamProtocol.js +1 -1
- package/dist/cjs/core/BleCmdAnalysis/BleCmdAnalysis.js +1 -1
- package/dist/cjs/core/BleCmdAnalysis/BleCmdDD.js +1 -1
- package/dist/cjs/core/BleCmdAnalysis/BleCmdDDA4.js +1 -1
- package/dist/cjs/core/BleCmdAnalysis/BleCmdFFAA.js +1 -1
- package/dist/cjs/core/BleCmdAnalysis/readAndSetParam.js +1 -1
- package/dist/cjs/core/BleDataProcess.js +1 -1
- package/dist/cjs/core/OtaUpgrade.js +1 -1
- package/dist/cjs/core/Queue.js +1 -0
- package/dist/cjs/core/mqttServer.js +1 -1
- package/dist/cjs/core/tcpServer.js +1 -0
- package/dist/cjs/index.js +1 -1
- package/dist/esm/core/BleApiManager.js +1 -1
- package/dist/esm/core/BleCmdAnalysis/BaseParamProtocol.js +1 -1
- package/dist/esm/core/BleCmdAnalysis/BleCmdAnalysis.js +1 -1
- package/dist/esm/core/BleCmdAnalysis/BleCmdDD.js +1 -1
- package/dist/esm/core/BleCmdAnalysis/BleCmdDDA4.js +1 -1
- package/dist/esm/core/BleCmdAnalysis/BleCmdFFAA.js +1 -1
- package/dist/esm/core/BleCmdAnalysis/BleCmdHVES.js +1 -1
- package/dist/esm/core/BleCmdAnalysis/readAndSetParam.js +1 -1
- package/dist/esm/core/BleDataProcess.js +1 -1
- package/dist/esm/core/OtaUpgrade.js +1 -1
- package/dist/esm/core/Queue.js +1 -0
- package/dist/esm/core/mqttServer.js +1 -1
- package/dist/esm/core/tcpServer.js +1 -0
- package/dist/esm/index.js +1 -1
- package/package.json +1 -1
- package/src/core/BleApiManager.js +33 -15
- package/src/core/BleCmdAnalysis/BaseParamProtocol.js +116 -32
- package/src/core/BleCmdAnalysis/BleCmdAnalysis.js +58 -2
- package/src/core/BleCmdAnalysis/BleCmdDD.js +88 -19
- package/src/core/BleCmdAnalysis/BleCmdDDA4.js +154 -227
- package/src/core/BleCmdAnalysis/BleCmdFFAA.js +1 -0
- package/src/core/BleCmdAnalysis/readAndSetParam.js +133 -16
- package/src/core/BleDataProcess.js +15 -11
- package/src/core/OtaUpgrade.js +356 -350
- package/src/core/Queue.js +34 -0
- package/src/core/mqttServer.js +75 -5
- package/src/core/tcpServer.js +341 -0
- package/src/index.js +1 -0
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { ref } from 'vue';
|
|
2
2
|
import { ab2decimalArr, hexToDecimal } from './BleDataProcess';
|
|
3
3
|
import { eventBus, getOS } from './commonfun'; // 导入eventBus
|
|
4
|
+
// #ifdef MP-WEIXIN
|
|
5
|
+
import { tcpServer } from './tcpServer.js';
|
|
6
|
+
// #endif
|
|
7
|
+
// #ifdef APP-PLUS
|
|
8
|
+
import { mqttServer } from './mqttServer.js';
|
|
9
|
+
// #endif
|
|
4
10
|
const serviceId = '0000FF00-0000-1000-8000-00805F9B34FB';
|
|
5
11
|
const UUID_READ = '0000FF01-0000-1000-8000-00805F9B34FB';
|
|
6
12
|
const UUID_WRITE = '0000FF02-0000-1000-8000-00805F9B34FB';
|
|
@@ -40,11 +46,11 @@ export const enhanceDevice = (device) => {
|
|
|
40
46
|
const productType = advHex.slice(18, 20);
|
|
41
47
|
let protocolVersion = advHex.slice(20, 22);
|
|
42
48
|
if (protocolVersion) {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
49
|
+
const v = hexToDecimal(protocolVersion)
|
|
50
|
+
if (macAddr.startsWith("A5:C2") && v <= 0x23) {
|
|
51
|
+
protocolVersion = '01';
|
|
47
52
|
}
|
|
53
|
+
}
|
|
48
54
|
const appkeyStatus = advHex.slice(22, 24);
|
|
49
55
|
const tempVoltage = advHex.slice(24, 26);
|
|
50
56
|
const voltage = tempVoltage || tempVoltage == 0 ? hexToDecimal(tempVoltage) : '';
|
|
@@ -66,7 +72,7 @@ export const enhanceDevice = (device) => {
|
|
|
66
72
|
* 105:请授权微信位置信息和蓝牙权限 --- 打开手机内微信权限设置页面 openAppAuthorizeSetting
|
|
67
73
|
* 106:请授权蓝牙和位置权限,并重启小程序 --- 打开小程序设置页面 openSetting
|
|
68
74
|
*/
|
|
69
|
-
export const checkBluetoothStatus = async (successCallback = () => {}) => {
|
|
75
|
+
export const checkBluetoothStatus = async (successCallback = () => { }) => {
|
|
70
76
|
return new Promise((resolve, reject) => {
|
|
71
77
|
uni.openBluetoothAdapter({
|
|
72
78
|
success: async (res) => {
|
|
@@ -89,7 +95,7 @@ export const checkBluetoothStatus = async (successCallback = () => {}) => {
|
|
|
89
95
|
});
|
|
90
96
|
}
|
|
91
97
|
|
|
92
|
-
export const checkLocationStatus = async (successCallback = () => {}) => {
|
|
98
|
+
export const checkLocationStatus = async (successCallback = () => { }) => {
|
|
93
99
|
// 创建超时Promise
|
|
94
100
|
const timeoutPromise = new Promise((resolve, reject) => {
|
|
95
101
|
setTimeout(() => {
|
|
@@ -124,7 +130,7 @@ export const checkLocationStatus = async (successCallback = () => {}) => {
|
|
|
124
130
|
})
|
|
125
131
|
}
|
|
126
132
|
|
|
127
|
-
export const getBluetoothPermission = async (successCallback = () => {}) => {
|
|
133
|
+
export const getBluetoothPermission = async (successCallback = () => { }) => {
|
|
128
134
|
try {
|
|
129
135
|
if (isAndroid) {
|
|
130
136
|
return await checkLocationStatus(successCallback);
|
|
@@ -147,13 +153,13 @@ export const initBle = async () => {
|
|
|
147
153
|
const initBluetoothSuccessCb = () => {
|
|
148
154
|
console.log('初始化蓝牙成功initBluetoothSuccessCb1');
|
|
149
155
|
try {
|
|
150
|
-
if(isInit) return;
|
|
156
|
+
if (isInit) return;
|
|
151
157
|
onBluetoothDeviceFound();
|
|
152
158
|
onBLECharacteristicValueChange();
|
|
153
159
|
onBLEConnectionStateChange();
|
|
154
160
|
onBluetoothAdapterStateChange()
|
|
155
161
|
isInit = true;
|
|
156
|
-
} catch (error) {
|
|
162
|
+
} catch (error) {
|
|
157
163
|
throw error;
|
|
158
164
|
}
|
|
159
165
|
}
|
|
@@ -274,6 +280,15 @@ export const onBLEConnectionStateChange = async () => {
|
|
|
274
280
|
console.log('onBLEConnectionStateChange', characteristic);
|
|
275
281
|
// 触发事件总线事件
|
|
276
282
|
eventBus.emit('setBleChangedConnectionState', characteristic);
|
|
283
|
+
if (!characteristic.connected) {
|
|
284
|
+
// #ifdef APP-PLUS
|
|
285
|
+
mqttServer.closeMqttByDeviceId(characteristic.deviceId)
|
|
286
|
+
// #endif
|
|
287
|
+
// #ifdef MP-WEIXIN
|
|
288
|
+
// 连接失败
|
|
289
|
+
tcpServer.closeTcpSocket(characteristic.deviceId);
|
|
290
|
+
// #endif
|
|
291
|
+
}
|
|
277
292
|
});
|
|
278
293
|
};
|
|
279
294
|
|
|
@@ -351,10 +366,10 @@ export const getBLEDeviceServices = (deviceId) => {
|
|
|
351
366
|
await getBLEDeviceCharacteristics(deviceId);
|
|
352
367
|
return res.services;
|
|
353
368
|
},
|
|
354
|
-
|
|
355
|
-
|
|
369
|
+
10, // 最大重试次数(减少到10次)
|
|
370
|
+
300, // 重试间隔增加到300ms
|
|
356
371
|
'获取蓝牙服务'
|
|
357
|
-
);
|
|
372
|
+
);
|
|
358
373
|
};
|
|
359
374
|
// #region 获取蓝牙特征值
|
|
360
375
|
/** 获取蓝牙特征值 */
|
|
@@ -374,10 +389,10 @@ export const getBLEDeviceCharacteristics = async (deviceId) => {
|
|
|
374
389
|
console.log('获取特征值成功:', res);
|
|
375
390
|
return res.characteristics;
|
|
376
391
|
},
|
|
377
|
-
|
|
378
|
-
|
|
392
|
+
10, // 最大重试次数(减少到10次)
|
|
393
|
+
300, // 重试间隔增加到300ms
|
|
379
394
|
'获取蓝牙特征值'
|
|
380
|
-
);
|
|
395
|
+
);
|
|
381
396
|
};
|
|
382
397
|
// #region 订阅特征值
|
|
383
398
|
/** 订阅特征值 */
|
|
@@ -423,6 +438,8 @@ export const connectAsync = async (deviceId, timeout = 10000) => {
|
|
|
423
438
|
return new Promise(async (resolve, reject) => {
|
|
424
439
|
try {
|
|
425
440
|
await createBLEConnection(deviceId, timeout);
|
|
441
|
+
// 连接成功后等待设备准备服务(关键修复)
|
|
442
|
+
await new Promise(resolve => setTimeout(resolve, 800));
|
|
426
443
|
await getBLEDeviceServices(deviceId);
|
|
427
444
|
await notify(deviceId);
|
|
428
445
|
resolve(true);
|
|
@@ -441,6 +458,7 @@ export const scanHandle = (historyConnectedList = [], connectFn = (device) => {
|
|
|
441
458
|
// 调起条码扫描
|
|
442
459
|
uni.scanCode({
|
|
443
460
|
scanType: ['barCode', 'qrCode'],
|
|
461
|
+
autoZoom: false,
|
|
444
462
|
success: async ({ result }) => {
|
|
445
463
|
console.log('扫描内容: ' + result);
|
|
446
464
|
let searchKey = result;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { getSysParamCmd } from './readAndSetParam'
|
|
2
1
|
import { decimalToHex, hexToDecimal } from '../BleDataProcess';
|
|
3
|
-
import { batteryInfoJson, capInfoJson,
|
|
4
|
-
import {
|
|
2
|
+
import { batteryInfoJson, capInfoJson, capVolInfoJson, currentInfoJson, equalizerFunJson, funcAndTempFuncJson, funcJson, systemJson, tempFuncJson, tempInfoJson, voltageInfoJson } from '../dataJson/baseParamsJson.js';
|
|
3
|
+
import { enterFactory, getProtectCountCmd, readExistFactory } from './BleCmdDD.js';
|
|
4
|
+
import { getSysParamCmd } from './readAndSetParam';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
*
|
|
@@ -55,31 +55,43 @@ function formatBinary(arr) {
|
|
|
55
55
|
return resultArray
|
|
56
56
|
}
|
|
57
57
|
/**
|
|
58
|
-
*
|
|
59
|
-
* @param {Object} datasInfo
|
|
60
|
-
* @param {string} chipType 芯片类型
|
|
61
|
-
* @param {string} deviceId 设备ID
|
|
62
|
-
* @param {Array
|
|
58
|
+
* 批量串行读取设备参数
|
|
59
|
+
* @param {Object} datasInfo - 结果存储对象
|
|
60
|
+
* @param {string|null} chipType - 芯片类型
|
|
61
|
+
* @param {string} deviceId - 设备 ID
|
|
62
|
+
* @param {Array} params - 参数列表
|
|
63
63
|
*/
|
|
64
64
|
const sendCmdSeq = async (datasInfo, chipType, deviceId, params) => {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
65
|
+
// 基础参数校验
|
|
66
|
+
if (!datasInfo || !deviceId || !Array.isArray(params)) {
|
|
67
|
+
console.error('sendCmdSeq 参数异常');
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// 无芯片类型 → 进入工厂模式
|
|
72
|
+
if (!chipType) {
|
|
73
|
+
await enterFactory(deviceId);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// 串行读取所有参数(失败不中断)
|
|
77
|
+
for (const item of params) {
|
|
78
|
+
if (!item?.key) continue; // 跳过无效项
|
|
79
|
+
|
|
70
80
|
try {
|
|
71
|
-
const
|
|
72
|
-
datasInfo[item.key] =
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
// 可以选择继续执行下一个,或者中断执行
|
|
77
|
-
// break; // 如果要在失败时中断
|
|
78
|
-
index++; // 如果希望失败时也继续下一个
|
|
81
|
+
const baseData = await getSysParamCmd(chipType, deviceId, item, false);
|
|
82
|
+
datasInfo[item.key] = baseData;
|
|
83
|
+
} catch (err) {
|
|
84
|
+
console.error(`获取参数失败 [${item.key}]:`, err);
|
|
85
|
+
// 失败不重试、不中断,继续下一个
|
|
79
86
|
}
|
|
80
87
|
}
|
|
81
|
-
|
|
82
|
-
|
|
88
|
+
|
|
89
|
+
// 无芯片类型 → 退出工厂模式
|
|
90
|
+
if (!chipType) {
|
|
91
|
+
await readExistFactory(deviceId);
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
|
|
83
95
|
let crsDivisor = 0.1;
|
|
84
96
|
/**
|
|
85
97
|
* 解析FA基础参数
|
|
@@ -116,14 +128,36 @@ export const getBaseParams = async (chipType, deviceData, index, paramObj) => {
|
|
|
116
128
|
return dataInfo
|
|
117
129
|
case 2:
|
|
118
130
|
let datasInfo2 = {}
|
|
131
|
+
// 11 为主动均衡 需取高位
|
|
132
|
+
const productType = deviceData.productType;
|
|
133
|
+
const isBalanceDevice = productType === "12"
|
|
134
|
+
console.log('productType', productType, isBalanceDevice)
|
|
119
135
|
if (chipType) {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
136
|
+
if (!isBalanceDevice) {
|
|
137
|
+
/**连续读两个参数 */
|
|
138
|
+
const capData = await getSysParamCmd(chipType, deviceId, { ...capInfoJson[0], paramLength: 4 })
|
|
139
|
+
console.warn('capData: ', capData);
|
|
140
|
+
datasInfo2['normCap'] = capData?.slice(0, 2)
|
|
141
|
+
datasInfo2['cycleCap'] = capData?.slice(2, 4)
|
|
142
|
+
const capData2 = await getSysParamCmd(chipType, deviceId, capInfoJson[2])
|
|
143
|
+
datasInfo2['fullCap'] = capData2?.slice(0, 2)
|
|
144
|
+
} else {
|
|
145
|
+
/**读取标称容量:需要读取paramNo 0(低16位)和155(高16位) */
|
|
146
|
+
const normCapLow = await getSysParamCmd(chipType, deviceId, { paramNo: 0, paramLength: 2 })
|
|
147
|
+
const normCapHigh = await getSysParamCmd(chipType, deviceId, { paramNo: 155, paramLength: 2 })
|
|
148
|
+
console.log('normCapLow: ', normCapLow, 'normCapHigh: ', normCapHigh);
|
|
149
|
+
// 合并高低位,每个都只取前2个字节
|
|
150
|
+
datasInfo2['normCap'] = [...(normCapLow?.slice(0, 2) || []), ...(normCapHigh?.slice(0, 2) || [])]
|
|
151
|
+
|
|
152
|
+
const cycleCapData = await getSysParamCmd(chipType, deviceId, capInfoJson[1])
|
|
153
|
+
datasInfo2['cycleCap'] = cycleCapData?.slice(0, 2)
|
|
154
|
+
|
|
155
|
+
/**读取满充容量:需要读取paramNo 112(低16位)和156(高16位) */
|
|
156
|
+
const fullCapLow = await getSysParamCmd(chipType, deviceId, { paramNo: 112, paramLength: 2 })
|
|
157
|
+
const fullCapHigh = await getSysParamCmd(chipType, deviceId, { paramNo: 156, paramLength: 2 })
|
|
158
|
+
console.log('fullCapLow: ', fullCapLow, 'fullCapHigh: ', fullCapHigh);
|
|
159
|
+
datasInfo2['fullCap'] = [...(fullCapLow?.slice(0, 2) || []), ...(fullCapHigh?.slice(0, 2) || [])]
|
|
160
|
+
}
|
|
127
161
|
} else {
|
|
128
162
|
await sendCmdSeq(datasInfo2, chipType, deviceId, capInfoJson)
|
|
129
163
|
}
|
|
@@ -378,9 +412,59 @@ function toHexString(arr) {
|
|
|
378
412
|
}
|
|
379
413
|
const getCapInfo = async (datas) => {
|
|
380
414
|
console.log('datas: ', datas);
|
|
381
|
-
|
|
415
|
+
// 标称容量:低16位(前2字节)+ 高16位(后2字节),单位是0.01AH
|
|
416
|
+
let normCap = null;
|
|
417
|
+
if (datas.normCap && datas.normCap.length >= 4) {
|
|
418
|
+
console.log('normCap原始数据: ', datas.normCap);
|
|
419
|
+
// 读取低16位(前两个字节)- 大端序
|
|
420
|
+
const lowBytes = datas.normCap.slice(0, 2);
|
|
421
|
+
const lowValue = (lowBytes[0] << 8) | lowBytes[1];
|
|
422
|
+
console.log('normCap lowValue: ', lowValue);
|
|
423
|
+
|
|
424
|
+
// 读取高16位(后两个字节)- 大端序
|
|
425
|
+
const highBytes = datas.normCap.slice(2, 4);
|
|
426
|
+
const highValue = (highBytes[0] << 8) | highBytes[1];
|
|
427
|
+
console.log('normCap highValue: ', highValue);
|
|
428
|
+
|
|
429
|
+
// 合并高低位:(高位 << 16) | 低位
|
|
430
|
+
const totalValue = (highValue << 16) | lowValue;
|
|
431
|
+
console.log('normCap totalValue: ', totalValue);
|
|
432
|
+
normCap = Number((totalValue * 0.01).toFixed(2));
|
|
433
|
+
console.log('normCap最终值: ', normCap);
|
|
434
|
+
} else if (datas.normCap && datas.normCap.length >= 2) {
|
|
435
|
+
// 兼容旧协议,只有低16位 - 大端序
|
|
436
|
+
const lowBytes = datas.normCap.slice(0, 2);
|
|
437
|
+
const lowValue = (lowBytes[0] << 8) | lowBytes[1];
|
|
438
|
+
normCap = Number((lowValue * 0.01).toFixed(2));
|
|
439
|
+
}
|
|
440
|
+
|
|
382
441
|
const cycleCap = format(datas.cycleCap, 0.01, 0, 2)
|
|
383
|
-
|
|
442
|
+
|
|
443
|
+
// 满充容量:低16位(前2字节)+ 高16位(后2字节),单位是0.01AH
|
|
444
|
+
let fullCap = null;
|
|
445
|
+
if (datas.fullCap && datas.fullCap.length >= 4) {
|
|
446
|
+
console.log('fullCap原始数据: ', datas.fullCap);
|
|
447
|
+
// 读取低16位(前两个字节)- 大端序
|
|
448
|
+
const lowBytes = datas.fullCap.slice(0, 2);
|
|
449
|
+
const lowValue = (lowBytes[0] << 8) | lowBytes[1];
|
|
450
|
+
console.log('fullCap lowValue: ', lowValue);
|
|
451
|
+
|
|
452
|
+
// 读取高16位(后两个字节)- 大端序
|
|
453
|
+
const highBytes = datas.fullCap.slice(2, 4);
|
|
454
|
+
const highValue = (highBytes[0] << 8) | highBytes[1];
|
|
455
|
+
console.log('fullCap highValue: ', highValue);
|
|
456
|
+
|
|
457
|
+
// 合并高低位:(高位 << 16) | 低位
|
|
458
|
+
const totalValue = (highValue << 16) | lowValue;
|
|
459
|
+
console.log('fullCap totalValue: ', totalValue);
|
|
460
|
+
fullCap = Number((totalValue * 0.01).toFixed(2));
|
|
461
|
+
console.log('fullCap最终值: ', fullCap);
|
|
462
|
+
} else if (datas.fullCap && datas.fullCap.length >= 2) {
|
|
463
|
+
// 兼容旧协议,只有低16位 - 大端序
|
|
464
|
+
const lowBytes = datas.fullCap.slice(0, 2);
|
|
465
|
+
const lowValue = (lowBytes[0] << 8) | lowBytes[1];
|
|
466
|
+
fullCap = Number((lowValue * 0.01).toFixed(2));
|
|
467
|
+
}
|
|
384
468
|
return {
|
|
385
469
|
normCap,
|
|
386
470
|
cycleCap,
|
|
@@ -1,11 +1,57 @@
|
|
|
1
1
|
import { ab2decimalArr, hexArr2ab, hexArr2string, sleep } from '../BleDataProcess';
|
|
2
2
|
import { eventBus, getOS, getPlatform } from '../commonfun';
|
|
3
|
+
// #ifdef APP-PLUS
|
|
4
|
+
import { mqttServer } from '../mqttServer';
|
|
5
|
+
// #endif
|
|
3
6
|
|
|
4
7
|
const BLE_RESPONSE_TIMEOUT = 300; // 蓝牙指令响应超时
|
|
5
8
|
const STORE_MUTATION_NAME = 'setBleChangedCharacteristicValue';
|
|
6
9
|
const serviceId = '0000FF00-0000-1000-8000-00805F9B34FB';
|
|
7
10
|
const UUID_READ = '0000FF01-0000-1000-8000-00805F9B34FB';
|
|
8
11
|
const characteristicId = '0000FF02-0000-1000-8000-00805F9B34FB';
|
|
12
|
+
|
|
13
|
+
// 按设备维度串行执行蓝牙指令,避免并发写入导致回包串线
|
|
14
|
+
const BLE_COMMAND_QUEUE = new Map();
|
|
15
|
+
const BLE_COMMAND_RUNNING = new Set();
|
|
16
|
+
|
|
17
|
+
const runNextBleCommand = async (queueKey) => {
|
|
18
|
+
if (BLE_COMMAND_RUNNING.has(queueKey)) return;
|
|
19
|
+
const queue = BLE_COMMAND_QUEUE.get(queueKey) || [];
|
|
20
|
+
if (queue.length === 0) {
|
|
21
|
+
BLE_COMMAND_QUEUE.delete(queueKey);
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
BLE_COMMAND_RUNNING.add(queueKey);
|
|
26
|
+
const currentTask = queue[0];
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
const result = await currentTask.task();
|
|
30
|
+
currentTask.resolve(result);
|
|
31
|
+
} catch (error) {
|
|
32
|
+
currentTask.reject(error);
|
|
33
|
+
} finally {
|
|
34
|
+
const currentQueue = BLE_COMMAND_QUEUE.get(queueKey) || [];
|
|
35
|
+
currentQueue.shift();
|
|
36
|
+
BLE_COMMAND_RUNNING.delete(queueKey);
|
|
37
|
+
|
|
38
|
+
if (currentQueue.length === 0) {
|
|
39
|
+
BLE_COMMAND_QUEUE.delete(queueKey);
|
|
40
|
+
} else {
|
|
41
|
+
runNextBleCommand(queueKey);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const enqueueBleCommand = (deviceId, task) => {
|
|
47
|
+
const queueKey = deviceId || '__default__';
|
|
48
|
+
return new Promise((resolve, reject) => {
|
|
49
|
+
const queue = BLE_COMMAND_QUEUE.get(queueKey) || [];
|
|
50
|
+
queue.push({ task, resolve, reject });
|
|
51
|
+
BLE_COMMAND_QUEUE.set(queueKey, queue);
|
|
52
|
+
runNextBleCommand(queueKey);
|
|
53
|
+
});
|
|
54
|
+
};
|
|
9
55
|
// #region 发送写入指令
|
|
10
56
|
/** 向蓝牙设备写入特征值 发送指令
|
|
11
57
|
* @param {string} deviceId - 设备ID
|
|
@@ -88,7 +134,7 @@ export const getData = async (deviceId, {
|
|
|
88
134
|
if (!deviceId) throw new Error('deviceId is required');
|
|
89
135
|
if (!command || command.length <= 0) throw new Error('command is required');
|
|
90
136
|
|
|
91
|
-
return new Promise((resolve, reject) => {
|
|
137
|
+
return enqueueBleCommand(deviceId, () => new Promise((resolve, reject) => {
|
|
92
138
|
let isCompleted = false;
|
|
93
139
|
let timeoutId = null;
|
|
94
140
|
let responsed = false;
|
|
@@ -135,6 +181,16 @@ export const getData = async (deviceId, {
|
|
|
135
181
|
if (verified) {
|
|
136
182
|
responsed = true;
|
|
137
183
|
cleanup();
|
|
184
|
+
// #ifdef APP-PLUS
|
|
185
|
+
const value = [...pkg].map((o) => `00${o.toString(16)}`.slice(-2)).join('');
|
|
186
|
+
const cmdCode = mqttServer.currentCommand
|
|
187
|
+
if (value && cmdCode) {
|
|
188
|
+
if (mqttServer.setPassthroughType === 0) {
|
|
189
|
+
mqttServer.publishPassthroughHandle({ value, cmdCode }, deviceId)
|
|
190
|
+
}
|
|
191
|
+
mqttServer.setPassthroughType = 0
|
|
192
|
+
}
|
|
193
|
+
// #endif
|
|
138
194
|
resolve([...pkg]);
|
|
139
195
|
} else {
|
|
140
196
|
// 验证失败,重置状态
|
|
@@ -197,7 +253,7 @@ export const getData = async (deviceId, {
|
|
|
197
253
|
cleanup();
|
|
198
254
|
reject(error);
|
|
199
255
|
});
|
|
200
|
-
});
|
|
256
|
+
}));
|
|
201
257
|
}
|
|
202
258
|
// #region 设置Android MTU 最大传输单元
|
|
203
259
|
/** 设置Android MTU
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { decimalToHex, fromBCD, generateCrc16modbusCheck, generateCrcCheckSum, hex2string, hexArr2Assic, hexArr2string, hexToDecimal, isWithin30Minutes, sleep, stringToTwoHexArray, toBCD } from '../BleDataProcess';
|
|
1
|
+
import { decimalToHex, fromBCD, generateCrc16modbusCheck, generateCrcCheckSum, hex2string, hexArr2Assic, hexArr2string, hexToDecimal, isWithin30Minutes, sleep, stringToTwoHexArray, toBCD, decimalToHex0x } from '../BleDataProcess';
|
|
2
2
|
import { getData } from './BleCmdAnalysis.js';
|
|
3
3
|
import { getFFAA80Async, resolveFFAA80 } from './BleCmdFFAA.js';
|
|
4
|
-
|
|
4
|
+
import { controlSwitch } from './readAndSetParam.js';
|
|
5
|
+
|
|
5
6
|
// #region 进出工厂
|
|
6
7
|
/**进工厂 */
|
|
7
8
|
export const enterFactory = async (deviceId) => {
|
|
@@ -147,7 +148,16 @@ export const resolve3B3C = (data) => {
|
|
|
147
148
|
const content = data.slice(12, data.length - 3);
|
|
148
149
|
const CONTENT = [/*产品类型-TYPE*/ '01', /*产品类型标识长度*/ '04', /*产品类型表示*/ '00', /*前端类型标识*/ '02', /*协议版本标识*/ '01', /*层级关系架构*/ '00', /*硬件版本号-TYPE*/ '02', /*硬件版本号长度*/ '00', /*软件版本号-TYPE*/ '03', /*软件版本号长度*/ '0a', /*软件版本号内容ASCII*/ '44', /*软件版本号内容ASCII*/ '48', /*软件版本号内容ASCII*/ '30', /*软件版本号内容ASCII*/ '34', /*软件版本号内容ASCII*/ '2e', /*软件版本号内容ASCII*/ '31', /*软件版本号内容ASCII*/ '2e', /*软件版本号内容ASCII*/ '34', /*软件版本号内容ASCII*/ '2e', /*软件版本号内容ASCII*/ '37', /*PCB-TYPE*/ '04', /*PCB内容长度*/ '00'];
|
|
149
150
|
while (content.length > 0) {
|
|
150
|
-
|
|
151
|
+
if (content.length < 2) {
|
|
152
|
+
console.warn('Content too short to parse, remaining:', content);
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
const len = Math.min(content[1] + 2, content.length);
|
|
156
|
+
const [v1, v2, ...v] = content.splice(0, len);
|
|
157
|
+
if (v.length !== v2) {
|
|
158
|
+
console.warn(`Data length mismatch for type ${v1}: expected ${v2}, got ${v.length}`);
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
151
161
|
if (v1 == 0x01) {
|
|
152
162
|
result['productFlag'] = hex2string(v1);
|
|
153
163
|
result['productLen'] = v2;
|
|
@@ -358,6 +368,9 @@ export const resolveDDA503 = (data) => {
|
|
|
358
368
|
name: index + 1,
|
|
359
369
|
value: item,
|
|
360
370
|
}));
|
|
371
|
+
const hasProtocol =
|
|
372
|
+
data[3] + 7 >= humidityIndex + 11 + 3 + 1;
|
|
373
|
+
const protocolVersion = data[humidityIndex + 11];
|
|
361
374
|
return {
|
|
362
375
|
cmdResp03,
|
|
363
376
|
status: hex2string(data[2]),
|
|
@@ -383,6 +396,7 @@ export const resolveDDA503 = (data) => {
|
|
|
383
396
|
heatingState,
|
|
384
397
|
heatingCurrent,
|
|
385
398
|
equilibriumCurrent,
|
|
399
|
+
eqCurr: equilibriumCurrent,
|
|
386
400
|
isFactoryMode,
|
|
387
401
|
protVal,
|
|
388
402
|
alarmsState,
|
|
@@ -391,6 +405,8 @@ export const resolveDDA503 = (data) => {
|
|
|
391
405
|
fahTempList,
|
|
392
406
|
fet,
|
|
393
407
|
seriesNum,
|
|
408
|
+
hasProtocol,
|
|
409
|
+
protocolVersion
|
|
394
410
|
};
|
|
395
411
|
}
|
|
396
412
|
|
|
@@ -765,7 +781,7 @@ export const resolveDDA505 = (data) => {
|
|
|
765
781
|
export const getDDA5FAAsync = async (deviceId, paramNo, length) => {
|
|
766
782
|
const header = ['0xDD', '0xA5']
|
|
767
783
|
const _values = [...paramNo, length];
|
|
768
|
-
const lengthHex =
|
|
784
|
+
const lengthHex = decimalToHex0x(_values.length)
|
|
769
785
|
const _command = ['0xFA', lengthHex, ..._values];
|
|
770
786
|
const checks = generateCrcCheckSum(_command);
|
|
771
787
|
const command = [...header, ..._command, ...checks, '0x77'];
|
|
@@ -1206,9 +1222,8 @@ export const get3B3CInfo = ({ deviceId, macAddr, moduleType, productType }) => {
|
|
|
1206
1222
|
try {
|
|
1207
1223
|
if (!deviceId) throw new Error('deviceId required');
|
|
1208
1224
|
// 发送FFAA_80
|
|
1209
|
-
const
|
|
1210
|
-
_ffaa_80
|
|
1211
|
-
console.warn('Report-3B3C _ffaa_80 ', { _ffaa_80_hex, _ffaa_80 });
|
|
1225
|
+
const _ffaa_80 = await getFFAA80Async(deviceId, 'AT^VERSION?');
|
|
1226
|
+
console.warn('Report-3B3C _ffaa_80 ', { _ffaa_80 });
|
|
1212
1227
|
if (_ffaa_80) reportData['moduleVersion'] = _ffaa_80?.moduleVersion;
|
|
1213
1228
|
|
|
1214
1229
|
// 发送3B3C
|
|
@@ -1217,6 +1232,7 @@ export const get3B3CInfo = ({ deviceId, macAddr, moduleType, productType }) => {
|
|
|
1217
1232
|
console.warn('Report-3B3C _3b3c ', { _3b3c_hex, _3b3c });
|
|
1218
1233
|
if (_3b3c) {
|
|
1219
1234
|
reportData['cmdContent'] = _3b3c?.dataStr;
|
|
1235
|
+
reportData['bmsVersion'] = _3b3c?.sofewareV;
|
|
1220
1236
|
} /*3B3C超时 or 不支持3B3C*/ else {
|
|
1221
1237
|
// 发送DDA5_03
|
|
1222
1238
|
const _dda5_03_hex = await getDDA503Async(deviceId);
|
|
@@ -1245,18 +1261,71 @@ export const get3B3CInfo = ({ deviceId, macAddr, moduleType, productType }) => {
|
|
|
1245
1261
|
|
|
1246
1262
|
// #region 发送设备激活指令
|
|
1247
1263
|
export const activateAsync = async (deviceId) => {
|
|
1248
|
-
const startTime = +new Date();
|
|
1249
|
-
const disChargMOSHex = await getDD5AFBAsync(deviceId, '0x00', '0x00');
|
|
1250
|
-
const disChargMOSRes = resolveBaseDD(disChargMOSHex)?.dataStr;
|
|
1251
|
-
const disChargEndTime = +new Date();
|
|
1252
|
-
const activeHex = await getDD5AFBAsync(deviceId, '0x05', '0x01');
|
|
1253
|
-
const activeRes = resolveBaseDD(disChargMOSHex)?.dataStr;
|
|
1254
|
-
let baseInfo = null
|
|
1255
|
-
const endTime = +new Date();
|
|
1256
|
-
await sleep(300)
|
|
1257
|
-
baseInfo = await getDDA503Async(deviceId);
|
|
1258
|
-
const voltageInfo = await getDDA504Async(deviceId);
|
|
1259
|
-
return { disChargMOSHex, disChargMOSRes, activeHex, activeRes, baseInfo, voltageInfo, startTime, disChargEndTime, endTime };
|
|
1264
|
+
// const startTime = +new Date();
|
|
1265
|
+
// const disChargMOSHex = await getDD5AFBAsync(deviceId, '0x00', '0x00');
|
|
1266
|
+
// const disChargMOSRes = resolveBaseDD(disChargMOSHex)?.dataStr;
|
|
1267
|
+
// const disChargEndTime = +new Date();
|
|
1268
|
+
// const activeHex = await getDD5AFBAsync(deviceId, '0x05', '0x01');
|
|
1269
|
+
// const activeRes = resolveBaseDD(disChargMOSHex)?.dataStr;
|
|
1270
|
+
// let baseInfo = null
|
|
1271
|
+
// const endTime = +new Date();
|
|
1272
|
+
// await sleep(300)
|
|
1273
|
+
// baseInfo = await getDDA503Async(deviceId);
|
|
1274
|
+
// const voltageInfo = await getDDA504Async(deviceId);
|
|
1275
|
+
// return { disChargMOSHex, disChargMOSRes, activeHex, activeRes, baseInfo, voltageInfo, startTime, disChargEndTime, endTime };
|
|
1276
|
+
try {
|
|
1277
|
+
const startTime = +new Date();
|
|
1278
|
+
let acStatus = false // 激活结果
|
|
1279
|
+
// 发送打开放电MOS指令
|
|
1280
|
+
const mosRes = await controlSwitch(
|
|
1281
|
+
deviceId,
|
|
1282
|
+
'0x00',
|
|
1283
|
+
true,
|
|
1284
|
+
true,
|
|
1285
|
+
);
|
|
1286
|
+
const disChargMOSRes = mosRes?.dataStr;
|
|
1287
|
+
const disChargEndTime = +new Date();
|
|
1288
|
+
// 发送激活指令
|
|
1289
|
+
const activeHex = await getDD5AFBAsync(deviceId, '0x05', '0x01');
|
|
1290
|
+
const activeResult = resolveBaseDD(activeHex);
|
|
1291
|
+
console.log('激活指令结果: ', { activeHex, activeResult });
|
|
1292
|
+
const activeRes = activeResult?.dataStr;
|
|
1293
|
+
let endTime = +new Date();
|
|
1294
|
+
let baseInfo = null
|
|
1295
|
+
let voltageInfo = null
|
|
1296
|
+
let steps = []
|
|
1297
|
+
if (activeResult?.status == '00') {
|
|
1298
|
+
steps.push(4)
|
|
1299
|
+
acStatus = true
|
|
1300
|
+
} else if (activeResult?.status == '81' || activeResult?.status == '84') {//不支持激活指令,判断开关执行结果
|
|
1301
|
+
if (mosRes?.status == '00') {
|
|
1302
|
+
acStatus = true
|
|
1303
|
+
steps.push(5)
|
|
1304
|
+
} else {
|
|
1305
|
+
acStatus = false
|
|
1306
|
+
steps.push(10)
|
|
1307
|
+
}
|
|
1308
|
+
} else if (activeResult?.status == '82' || activeResult?.status == '83') { // 激活指令执行失败
|
|
1309
|
+
acStatus = false
|
|
1310
|
+
steps.push(6)
|
|
1311
|
+
} else if (!activeResult || activeResult == null) { //激活无响应
|
|
1312
|
+
await sleep(300)
|
|
1313
|
+
const baseInfo = await getDDA503Async(deviceId);
|
|
1314
|
+
// 读取03指令后判断放电MOS是否打开,若打开则激活成功
|
|
1315
|
+
if (baseInfo?.dischargeSwitch) {
|
|
1316
|
+
acStatus = true
|
|
1317
|
+
steps.push(7)
|
|
1318
|
+
} else {
|
|
1319
|
+
acStatus = false
|
|
1320
|
+
steps.push(8)
|
|
1321
|
+
}
|
|
1322
|
+
endTime = +new Date()
|
|
1323
|
+
}
|
|
1324
|
+
return { disChargMOSRes, activeHex, activeRes, baseInfo, voltageInfo, startTime, disChargEndTime, endTime, acStatus, steps };
|
|
1325
|
+
} catch (error) {
|
|
1326
|
+
console.log("🚀 ~ BleApiManager ~ activateAsync ~ error:", error)
|
|
1327
|
+
return null
|
|
1328
|
+
}
|
|
1260
1329
|
}
|
|
1261
1330
|
|
|
1262
1331
|
// #region 获取均衡线电阻 DC 指令
|