@jiabaida/tools 1.0.2 → 1.0.6
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/BleCmdDD.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/Transfer.js +1 -1
- package/dist/cjs/core/commonfun.js +1 -1
- package/dist/cjs/core/dataJson/baseParamsJson.js +1 -1
- 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/BleCmdDD.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/Transfer.js +1 -1
- package/dist/esm/core/commonfun.js +1 -1
- package/dist/esm/core/dataJson/baseParamsJson.js +1 -1
- package/dist/esm/index.js +1 -1
- package/package.json +1 -1
- package/src/core/BleApiManager.js +126 -80
- package/src/core/BleCmdAnalysis/BaseParamProtocol.js +35 -6
- package/src/core/BleCmdAnalysis/BleCmdDD.js +254 -6
- package/src/core/BleCmdAnalysis/BleCmdDDA4.js +761 -761
- package/src/core/BleCmdAnalysis/readAndSetParam.js +9 -7
- package/src/core/BleDataProcess.js +40 -0
- package/src/core/OtaUpgrade.js +16 -4
- package/src/core/Transfer.js +1 -1
- package/src/core/commonfun.js +2 -1
- package/src/core/dataJson/baseParamsJson.js +135 -33
- package/dist/cjs/core/BleCmdAnalysis.js +0 -1
- package/dist/esm/core/BleCmdAnalysis.js +0 -1
|
@@ -1,14 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { ab2decimalArr } from './BleDataProcess';
|
|
3
|
-
import {
|
|
1
|
+
import { ref } from 'vue';
|
|
2
|
+
import { ab2decimalArr, hexToDecimal } from './BleDataProcess';
|
|
3
|
+
import { eventBus, getOS } from './commonfun'; // 导入eventBus
|
|
4
4
|
const serviceId = '0000FF00-0000-1000-8000-00805F9B34FB';
|
|
5
5
|
const UUID_READ = '0000FF01-0000-1000-8000-00805F9B34FB';
|
|
6
6
|
const UUID_WRITE = '0000FF02-0000-1000-8000-00805F9B34FB';
|
|
7
|
-
|
|
7
|
+
const { isAndroid, isIOS } = getOS();
|
|
8
8
|
const bluetoothAdapterState = ref({
|
|
9
9
|
available: false,
|
|
10
10
|
discovering: false,
|
|
11
11
|
});
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
export var isInit = false;
|
|
15
|
+
|
|
12
16
|
// #region 处理广播的设备信息
|
|
13
17
|
/**
|
|
14
18
|
* 处理广播的设备信息
|
|
@@ -31,92 +35,127 @@ const enhanceDevice = (device) => {
|
|
|
31
35
|
macAddr = arr.join(':');
|
|
32
36
|
device['hasFound'] = true;
|
|
33
37
|
const moduleType = advHex.slice(12, 16);
|
|
34
|
-
const
|
|
38
|
+
const socHex = advHex.slice(16, 18);
|
|
39
|
+
const soc = socHex || socHex == 0 ? hexToDecimal(socHex) : '';
|
|
35
40
|
const productType = advHex.slice(18, 20);
|
|
36
|
-
|
|
41
|
+
let protocolVersion = advHex.slice(20, 22);
|
|
42
|
+
if (protocolVersion) {
|
|
43
|
+
const v = hexToDecimal(protocolVersion)
|
|
44
|
+
if (macAddr.startsWith("A5:C2") && v <= 0x23) {
|
|
45
|
+
protocolVersion = '01';
|
|
46
|
+
}
|
|
47
|
+
}
|
|
37
48
|
const appkeyStatus = advHex.slice(22, 24);
|
|
49
|
+
const tempVoltage = advHex.slice(24, 26);
|
|
50
|
+
const voltage = tempVoltage || tempVoltage == 0 ? hexToDecimal(tempVoltage) : '';
|
|
51
|
+
const tempCurrent = advHex.slice(26, 28);
|
|
52
|
+
const current = tempCurrent || tempCurrent == 0 ? hexToDecimal(tempCurrent) : '';
|
|
38
53
|
const broadcastLen = advHex.length / 2;
|
|
39
54
|
const isNewAppKey = advHex.length >= 24 //内容长度大于24位则是新appkey蓝牙设备
|
|
40
|
-
device = { ...device, macAddr, moduleType, soc, productType, advHex, protocolVersion, appkeyStatus, broadcastLen, isNewAppKey };
|
|
55
|
+
device = { ...device, macAddr, moduleType, soc, productType, advHex, protocolVersion, appkeyStatus, broadcastLen, isNewAppKey, voltage, current };
|
|
41
56
|
}
|
|
42
57
|
return device;
|
|
43
58
|
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
// 创建超时Promise
|
|
74
|
-
const timeoutPromise = new Promise((resolve, reject) => {
|
|
75
|
-
setTimeout(() => {
|
|
76
|
-
reject(new Error('网络信号差或连接异常,请检查网络情况'));
|
|
77
|
-
}, 10000); // 10秒超时
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* 状态码:
|
|
62
|
+
* 101:网络信号差或连接异常,请检查网络情况 --- 打开定位开关
|
|
63
|
+
* 102:当前手机蓝牙不可用,请检查手机蓝牙状态 --- 打开蓝牙开关 openSystemBluetoothSetting
|
|
64
|
+
* 103:请授权小程序位置信息权限, 并重启小程序。--- 打开小程序设置页面 openSetting
|
|
65
|
+
* 104:请授权微信位置信息权限, 并重启小程序。 --- 打开手机内微信权限设置页面 openAppAuthorizeSetting
|
|
66
|
+
* 105:请授权微信位置信息和蓝牙权限 --- 打开手机内微信权限设置页面 openAppAuthorizeSetting
|
|
67
|
+
* 106:请授权蓝牙和位置权限,并重启小程序 --- 打开小程序设置页面 openSetting
|
|
68
|
+
*/
|
|
69
|
+
export const checkBluetoothStatus = async (successCallback = () => {}) => {
|
|
70
|
+
return new Promise((resolve, reject) => {
|
|
71
|
+
uni.openBluetoothAdapter({
|
|
72
|
+
success: async (res) => {
|
|
73
|
+
if (successCallback) {
|
|
74
|
+
successCallback(res);
|
|
75
|
+
}
|
|
76
|
+
resolve(res);
|
|
77
|
+
},
|
|
78
|
+
fail: (err) => {
|
|
79
|
+
console.log('openBluetoothAdapter fail4-----', err);
|
|
80
|
+
if (err && err?.errno == 3) {
|
|
81
|
+
reject({ code: 105, message: '请授权微信位置信息和蓝牙权限' });
|
|
82
|
+
}
|
|
83
|
+
if (err && err?.errno == 103) {
|
|
84
|
+
reject({ code: 106, message: '请授权蓝牙和位置权限,并重启小程序' });
|
|
85
|
+
}
|
|
86
|
+
reject({ code: 102, message: '当前手机蓝牙不可用,请检查手机蓝牙状态' });
|
|
87
|
+
},
|
|
78
88
|
});
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export const checkLocationStatus = async (successCallback = () => {}) => {
|
|
93
|
+
// 创建超时Promise
|
|
94
|
+
const timeoutPromise = new Promise((resolve, reject) => {
|
|
95
|
+
setTimeout(() => {
|
|
96
|
+
reject({ code: 101, message: '网络信号差或连接异常,请检查网络情况' });
|
|
97
|
+
}, 10000); // 10秒超时
|
|
98
|
+
});
|
|
99
|
+
// 创建位置获取Promise
|
|
100
|
+
const locationPromise = new Promise((resolve, reject) => {
|
|
101
|
+
uni.getLocation({
|
|
102
|
+
type: 'wgs84',
|
|
103
|
+
success: (res) => {
|
|
104
|
+
console.log('位置信息-----------', res);
|
|
105
|
+
resolve(res);
|
|
106
|
+
},
|
|
107
|
+
fail: (err) => {
|
|
108
|
+
console.log('位置信息err', err);
|
|
109
|
+
if (err && err?.errno == 103) {
|
|
110
|
+
reject({ code: 103, message: '请授权小程序位置信息权限, 并重启小程序。' });
|
|
111
|
+
}
|
|
112
|
+
if (err && err?.errCode == 2) {
|
|
113
|
+
reject({ code: 101, message: '网络信号差或连接异常,请检查网络情况' });
|
|
114
|
+
}
|
|
115
|
+
reject({ code: 104, message: '请授权微信位置信息权限, 并重启小程序。' });
|
|
116
|
+
},
|
|
92
117
|
});
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
// message: '请检查手机位置是否开启',
|
|
104
|
-
});
|
|
105
|
-
});
|
|
106
|
-
};
|
|
118
|
+
});
|
|
119
|
+
// 使用Promise.race实现超时控制
|
|
120
|
+
return Promise.race([locationPromise, timeoutPromise])
|
|
121
|
+
.then(async (res) => {
|
|
122
|
+
// 成功获取位置信息
|
|
123
|
+
return await checkBluetoothStatus(successCallback);
|
|
124
|
+
})
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export const getBluetoothPermission = async (successCallback = () => {}) => {
|
|
107
128
|
try {
|
|
108
|
-
const { isAndroid } = getOS();
|
|
109
129
|
if (isAndroid) {
|
|
110
|
-
checkLocationStatus();
|
|
130
|
+
return await checkLocationStatus(successCallback);
|
|
111
131
|
} else {
|
|
112
|
-
checkBluetoothStatus();
|
|
132
|
+
return await checkBluetoothStatus(successCallback);
|
|
113
133
|
}
|
|
114
134
|
} catch (error) {
|
|
115
135
|
console.error('初始化蓝牙失败:', error);
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
136
|
+
throw (error);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// #region 初始化蓝牙
|
|
141
|
+
/** 初始化蓝牙
|
|
142
|
+
* 错误码:
|
|
143
|
+
* 101:网络信号差或连接异常,请检查网络情况
|
|
144
|
+
* 102:当前手机蓝牙不可用,请检查手机蓝牙状态
|
|
145
|
+
*/
|
|
146
|
+
export const initBle = async () => {
|
|
147
|
+
const initBluetoothSuccessCb = () => {
|
|
148
|
+
try {
|
|
149
|
+
onBluetoothDeviceFound();
|
|
150
|
+
onBLECharacteristicValueChange();
|
|
151
|
+
onBLEConnectionStateChange();
|
|
152
|
+
onBluetoothAdapterStateChange()
|
|
153
|
+
isInit = true;
|
|
154
|
+
} catch (error) {
|
|
155
|
+
throw error;
|
|
156
|
+
}
|
|
119
157
|
}
|
|
158
|
+
return await getBluetoothPermission(initBluetoothSuccessCb);
|
|
120
159
|
};
|
|
121
160
|
// #region 获取蓝牙适配器状态
|
|
122
161
|
/** 获取蓝牙适配器状态 */
|
|
@@ -166,6 +205,10 @@ export const startDevicesDiscovery = async (allowDuplicatesKey = true) => {
|
|
|
166
205
|
// #region 停止搜索蓝牙设备
|
|
167
206
|
/**停止搜索蓝牙设备 */
|
|
168
207
|
export const stopBluetoothDevicesDiscovery = async () => {
|
|
208
|
+
bluetoothAdapterState.value = {
|
|
209
|
+
available: bluetoothAdapterState.value.available,
|
|
210
|
+
discovering: false,
|
|
211
|
+
}
|
|
169
212
|
return new Promise((resolve, reject) => {
|
|
170
213
|
uni.stopBluetoothDevicesDiscovery({
|
|
171
214
|
success: (res) => {
|
|
@@ -392,7 +435,7 @@ export const connectAsync = async (deviceId, timeout = 10000) => {
|
|
|
392
435
|
/**
|
|
393
436
|
* 安卓扫码直连,苹果广播5秒
|
|
394
437
|
*/
|
|
395
|
-
export const scanHandle = (historyConnectedList = [], connectFn = (device) => { }) => {
|
|
438
|
+
export const scanHandle = (historyConnectedList = [], connectFn = (device) => { }, failScanFn = (err) => { }) => {
|
|
396
439
|
// 调起条码扫描
|
|
397
440
|
uni.scanCode({
|
|
398
441
|
scanType: ['barCode', 'qrCode'],
|
|
@@ -430,8 +473,6 @@ export const scanHandle = (historyConnectedList = [], connectFn = (device) => {
|
|
|
430
473
|
isMac = true;
|
|
431
474
|
}
|
|
432
475
|
}
|
|
433
|
-
|
|
434
|
-
const { isAndroid } = getOS();
|
|
435
476
|
// 检查历史连接列表是否已包含该设备
|
|
436
477
|
const matchedHistoryDevice = historyConnectedList.find((item) => item.macAddr == searchKey);
|
|
437
478
|
if (matchedHistoryDevice) {
|
|
@@ -452,12 +493,18 @@ export const scanHandle = (historyConnectedList = [], connectFn = (device) => {
|
|
|
452
493
|
console.log(error);
|
|
453
494
|
}
|
|
454
495
|
},
|
|
496
|
+
complete: (err) => {
|
|
497
|
+
},
|
|
498
|
+
fail: (err) => {
|
|
499
|
+
console.log('scanCode err', err);
|
|
500
|
+
failScanFn(err)
|
|
501
|
+
}
|
|
455
502
|
});
|
|
456
503
|
};
|
|
457
504
|
// #region 广播5秒
|
|
458
505
|
export const foundScanDevice = async (result, connectFn) => {
|
|
459
506
|
const deviceList = [];
|
|
460
|
-
await startDevicesDiscovery();
|
|
507
|
+
await startDevicesDiscovery(isIOS);
|
|
461
508
|
onFoundDevice((device) => {
|
|
462
509
|
deviceList.push(device)
|
|
463
510
|
const findDevice = device.macAddr === result || device.name === result;
|
|
@@ -476,8 +523,6 @@ export const foundScanDevice = async (result, connectFn) => {
|
|
|
476
523
|
try {
|
|
477
524
|
// 五秒后停止搜索且关闭轮询器
|
|
478
525
|
console.log('stopBluetoothDevicesDiscovery', deviceList);
|
|
479
|
-
clearInterval(scanTimer);
|
|
480
|
-
scanTimer = null;
|
|
481
526
|
uni.stopBluetoothDevicesDiscovery();
|
|
482
527
|
const findDevice = deviceList.find((device) => device.macAddr === result || device.name === result);
|
|
483
528
|
connectFn(findDevice);
|
|
@@ -485,3 +530,4 @@ export const foundScanDevice = async (result, connectFn) => {
|
|
|
485
530
|
}
|
|
486
531
|
}, 5000);
|
|
487
532
|
};
|
|
533
|
+
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
|
|
2
1
|
import { getSysParamCmd } from './readAndSetParam'
|
|
3
2
|
import { decimalToHex, hexToDecimal } from '../BleDataProcess';
|
|
4
|
-
import { batteryInfoJson, capInfoJson, voltageInfoJson,
|
|
3
|
+
import { batteryInfoJson, capInfoJson, voltageInfoJson,currentInfoJson, tempInfoJson, equalizerFunJson, capVolInfoJson, funcJson, tempFuncJson, systemJson, funcAndTempFuncJson } from '../dataJson/baseParamsJson.js';
|
|
5
4
|
import { readExistFactory, getProtectCountCmd, enterFactory } from './BleCmdDD.js'
|
|
5
|
+
|
|
6
6
|
/**
|
|
7
7
|
*
|
|
8
8
|
* @param {*} value 原始十进制值字数组
|
|
@@ -111,7 +111,7 @@ export const getBaseParams = async (chipType, deviceData, index, paramObj) => {
|
|
|
111
111
|
switch (index) {
|
|
112
112
|
case 1:
|
|
113
113
|
let datasInfo1 = {};
|
|
114
|
-
await sendCmdSeq(datasInfo1, chipType, deviceId, batteryInfoJson)
|
|
114
|
+
await sendCmdSeq(datasInfo1, chipType, deviceId, batteryInfoJson(crsDivisor))
|
|
115
115
|
dataInfo = getBaseInfo(datasInfo1)
|
|
116
116
|
return dataInfo
|
|
117
117
|
case 2:
|
|
@@ -188,9 +188,11 @@ export const getBaseParams = async (chipType, deviceData, index, paramObj) => {
|
|
|
188
188
|
if (chipType) {
|
|
189
189
|
let tindex = tempInfoJson.findIndex((el) => el.paramNo == 8)
|
|
190
190
|
let tindex1 = tempInfoJson.findIndex((el) => el.paramNo == 44)
|
|
191
|
+
let tindex2 = tempInfoJson.findIndex((el) => el.paramNo == 202)
|
|
191
192
|
const tempData = await getSysParamCmd(chipType, deviceId, { ...tempInfoJson[tindex], paramLength: 16 })
|
|
192
193
|
const tempData1 = await getSysParamCmd(chipType, deviceId, { ...tempInfoJson[tindex1], paramLength: 8 })
|
|
193
|
-
|
|
194
|
+
const tempData2 = await getSysParamCmd(chipType, deviceId, { ...tempInfoJson[tindex2], paramLength: 4 })
|
|
195
|
+
console.log('tempData: ', tempData, tempData2);
|
|
194
196
|
datasInfo5['chargeHightempProtect'] = tempData?.slice(0, 2)
|
|
195
197
|
datasInfo5['chargeHightempRecover'] = tempData?.slice(2, 4)
|
|
196
198
|
datasInfo5['chargeLowtempProtect'] = tempData?.slice(4, 6)
|
|
@@ -203,6 +205,8 @@ export const getBaseParams = async (chipType, deviceData, index, paramObj) => {
|
|
|
203
205
|
datasInfo5['chargeHightempDelay'] = tempData1?.slice(2, 4)
|
|
204
206
|
datasInfo5['dischargingLowtempDelay'] = tempData1?.slice(4, 6)
|
|
205
207
|
datasInfo5['dischargingHightempDelay'] = tempData1?.slice(6, 8)
|
|
208
|
+
datasInfo5['overtempProtect'] = tempData2?.slice(0, 2)
|
|
209
|
+
datasInfo5['overtempRecover'] = tempData2?.slice(2, 4)
|
|
206
210
|
} else {
|
|
207
211
|
await sendCmdSeq(datasInfo5, chipType, deviceId, tempInfoJson)
|
|
208
212
|
}
|
|
@@ -433,7 +437,7 @@ const getCurrentInfo = async (datas, chipType) => {
|
|
|
433
437
|
console.log('datas: ', datas);
|
|
434
438
|
const occhg = format(datas.occhg, 0.01, 0, 3)
|
|
435
439
|
// 采用补码形式传送
|
|
436
|
-
const dischargeOvercurrentProtect = (datas.dischargeOvercurrentProtect || datas.dischargeOvercurrentProtect == 0) && (format(datas.dischargeOvercurrentProtect, 1, 0, 3) - 0x10000) * 0.01
|
|
440
|
+
const dischargeOvercurrentProtect = (datas.dischargeOvercurrentProtect || datas.dischargeOvercurrentProtect == 0) && Number(((format(datas.dischargeOvercurrentProtect, 1, 0, 3) - 0x10000) * 0.01).toFixed(3))
|
|
437
441
|
|
|
438
442
|
let chargeOvercurrentDelay = null
|
|
439
443
|
let chargeOvercurrentRecoverDelay = null
|
|
@@ -546,6 +550,8 @@ const getTempInfo = (datas, chipType) => {
|
|
|
546
550
|
const dischargingHightempRecover = formatTemp(datas.dischargingHightempRecover)
|
|
547
551
|
const dischargingLowtempProtect = formatTemp(datas.dischargingLowtempProtect)
|
|
548
552
|
const dischargingLowtempRecover = formatTemp(datas.dischargingLowtempRecover)
|
|
553
|
+
const overtempProtect = formatTemp(datas.overtempProtect)
|
|
554
|
+
const overtempRecover = formatTemp(datas.overtempRecover)
|
|
549
555
|
let chargeHightempDelay = null
|
|
550
556
|
let chargeLowtempDelay = null
|
|
551
557
|
let dischargingHightempDelay = null
|
|
@@ -573,7 +579,9 @@ const getTempInfo = (datas, chipType) => {
|
|
|
573
579
|
chargeHightempDelay,
|
|
574
580
|
chargeLowtempDelay,
|
|
575
581
|
dischargingHightempDelay,
|
|
576
|
-
dischargingLowtempDelay
|
|
582
|
+
dischargingLowtempDelay,
|
|
583
|
+
overtempProtect,
|
|
584
|
+
overtempRecover
|
|
577
585
|
}
|
|
578
586
|
}
|
|
579
587
|
|
|
@@ -631,11 +639,26 @@ const getFuncAndTempFuncInfo = (datas) => {
|
|
|
631
639
|
})
|
|
632
640
|
return { func, tempFunc }
|
|
633
641
|
}
|
|
642
|
+
|
|
643
|
+
const splitNumberTo1Byte = (combined = 0) => {
|
|
644
|
+
combined = Number(combined);
|
|
645
|
+
return {
|
|
646
|
+
val1: combined & 0xFF,
|
|
647
|
+
val2: (combined >> 8) & 0xFF
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
|
|
634
651
|
const getSystemInfo = (datas) => {
|
|
635
652
|
const serialNumber = format(datas.serialNumber, 1)
|
|
636
653
|
const cycleCount = format(datas.cycleCount, 1)
|
|
637
654
|
const strCount = format(datas.strCount, 1)
|
|
638
655
|
const rsnsValue = format(datas.rsnsValue, crsDivisor, 0, 2)
|
|
656
|
+
const param1911 = splitNumberTo1Byte(format(datas.param1911)).val1
|
|
657
|
+
const param1912 = splitNumberTo1Byte(format(datas.param1911)).val2
|
|
658
|
+
const param1981 = splitNumberTo1Byte(format(datas.param1981)).val1
|
|
659
|
+
const param1982 = splitNumberTo1Byte(format(datas.param1981)).val2
|
|
660
|
+
const param1951 = splitNumberTo1Byte(format(datas.param1951)).val1
|
|
661
|
+
const param1952 = splitNumberTo1Byte(format(datas.param1951)).val2
|
|
639
662
|
// const identifyCurrent = format(datas.identifyCurrent, 1)
|
|
640
663
|
// const sleepTime = format(datas.sleepTime, 1)
|
|
641
664
|
// const capacityInterval = format(datas.capacityInterval, 1)
|
|
@@ -644,6 +667,12 @@ const getSystemInfo = (datas) => {
|
|
|
644
667
|
cycleCount,
|
|
645
668
|
strCount,
|
|
646
669
|
rsnsValue,
|
|
670
|
+
param1911,
|
|
671
|
+
param1912,
|
|
672
|
+
param1951,
|
|
673
|
+
param1952,
|
|
674
|
+
param1981,
|
|
675
|
+
param1982,
|
|
647
676
|
// identifyCurrent,
|
|
648
677
|
// sleepTime,
|
|
649
678
|
// capacityInterval
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { decimalToHex, fromBCD, generateCrc16modbusCheck, generateCrcCheckSum, hex2string, hexArr2Assic, hexArr2string, hexToDecimal, isWithin30Minutes, sleep, stringToTwoHexArray, toBCD } from '../BleDataProcess';
|
|
2
|
+
import { getData } from './BleCmdAnalysis.js';
|
|
3
3
|
import { getFFAA80Async, resolveFFAA80 } from './BleCmdFFAA.js';
|
|
4
|
+
|
|
4
5
|
// #region 进出工厂
|
|
5
6
|
/**进工厂 */
|
|
6
7
|
export const enterFactory = async (deviceId) => {
|
|
@@ -243,9 +244,21 @@ export const resolveDDA503 = (data) => {
|
|
|
243
244
|
|
|
244
245
|
const binArr = data[24].toString(2).padStart(8, '0').split('').reverse();
|
|
245
246
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
)
|
|
247
|
+
|
|
248
|
+
// 获取16-19索引的4个字节
|
|
249
|
+
const BC1 = (data[16] << 8 | data[17])
|
|
250
|
+
.toString(2)
|
|
251
|
+
.padStart(16, "0")
|
|
252
|
+
.split("")
|
|
253
|
+
.reverse();
|
|
254
|
+
console.log('BC1: ', BC1);
|
|
255
|
+
const BC2 = (data[18] << 8 | data[19])
|
|
256
|
+
.toString(2)
|
|
257
|
+
.padStart(16, "0")
|
|
258
|
+
.split("")
|
|
259
|
+
.reverse();
|
|
260
|
+
const BC = BC1.concat(BC2);
|
|
261
|
+
const balances = BC;
|
|
249
262
|
console.warn("BC: ---------------", balances);
|
|
250
263
|
const fet = data[24];
|
|
251
264
|
/**充电开关 */
|
|
@@ -658,6 +671,23 @@ export const getDD5A0AAsync = async (deviceId, value) => {
|
|
|
658
671
|
);
|
|
659
672
|
}
|
|
660
673
|
|
|
674
|
+
export const resolveDD5A0A = (data) => {
|
|
675
|
+
if (!data) return null;
|
|
676
|
+
// 示例回复: DD 0A 00 00 00 00 77
|
|
677
|
+
const dataStr = hexArr2string(data);
|
|
678
|
+
const statusDec = data[2];
|
|
679
|
+
const len = data[3];
|
|
680
|
+
const succeeded = statusDec === 0x00; // 0 成功, 其它失败/异常
|
|
681
|
+
// 校验位为最后倒数第三、倒数第二字节, 这里可按其他DD指令算法校验 (长度极短可忽略)
|
|
682
|
+
return {
|
|
683
|
+
dataStr,
|
|
684
|
+
status: hex2string(statusDec),
|
|
685
|
+
len,
|
|
686
|
+
succeeded,
|
|
687
|
+
message: succeeded ? 'CMD_EXEC_SUCCESS' : 'CMD_EXEC_FAIL',
|
|
688
|
+
};
|
|
689
|
+
}
|
|
690
|
+
|
|
661
691
|
// #region 设置满充容量
|
|
662
692
|
/**设置满充容量
|
|
663
693
|
*
|
|
@@ -1211,4 +1241,222 @@ export const get3B3CInfo = ({ deviceId, macAddr, moduleType, productType }) => {
|
|
|
1211
1241
|
reject(error);
|
|
1212
1242
|
}
|
|
1213
1243
|
});
|
|
1214
|
-
}
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1246
|
+
// #region 发送设备激活指令
|
|
1247
|
+
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 };
|
|
1260
|
+
}
|
|
1261
|
+
|
|
1262
|
+
// #region 获取均衡线电阻 DC 指令
|
|
1263
|
+
/** 获取均衡线电阻 DC 指令
|
|
1264
|
+
* 协议: 主机发送 DD A5 DC 00 CS1 CS2 77, BMS响应: DD DC STATUS LEN Data.. CS1 CS2 77
|
|
1265
|
+
* Data: 每个电芯占2字节, 小端(uint16), 单位 mΩ
|
|
1266
|
+
* @param {*} deviceId
|
|
1267
|
+
* @returns Promise<number[]|null>
|
|
1268
|
+
*/
|
|
1269
|
+
export const getDDA5DCAsync = (deviceId) => {
|
|
1270
|
+
// 组成指令: 帧头0xDD 0xA5, 命令码0xDC, 数据长度0x00, 校验和(命令码+长度), 结束位0x77
|
|
1271
|
+
const _command = ['0xDE', '0x00'];
|
|
1272
|
+
const checks = generateCrcCheckSum(_command); // 计算校验和
|
|
1273
|
+
const command = ['0xDD', '0xA5', ..._command, ...checks, '0x77'];
|
|
1274
|
+
return getData(
|
|
1275
|
+
deviceId,
|
|
1276
|
+
{
|
|
1277
|
+
command,
|
|
1278
|
+
commandVerifyHandler: (hexArr) => ({ verified: hexArr[0] == 0xdd && hexArr[1] == 0xde, pkgLen: hexArr[3] + 7 }),
|
|
1279
|
+
pkgVerifyHandler: (pkg) => {
|
|
1280
|
+
const len = pkg.length;
|
|
1281
|
+
// 校验范围: status(索引2) ~ data 末尾
|
|
1282
|
+
const [c1, c2] = generateCrcCheckSum(pkg.slice(2, len - 3));
|
|
1283
|
+
const [_c1, _c2] = [pkg[len - 3], pkg[len - 2]];
|
|
1284
|
+
return { verified: c1 == _c1 && c2 == _c2 };
|
|
1285
|
+
},
|
|
1286
|
+
},
|
|
1287
|
+
'DDA5_DC'
|
|
1288
|
+
);
|
|
1289
|
+
}
|
|
1290
|
+
/** 解析均衡线电阻 DC 指令
|
|
1291
|
+
* @param {number[]} data 响应数据
|
|
1292
|
+
* @returns {Object|null}
|
|
1293
|
+
*/
|
|
1294
|
+
export const resolveDDA5DC = (data) => {
|
|
1295
|
+
if (!data) return null;
|
|
1296
|
+
const dataStr = hexArr2string(data);
|
|
1297
|
+
const status = hex2string(data[2]);
|
|
1298
|
+
const len = data[3] & 0xff;
|
|
1299
|
+
// 大端: 高字节在前, 低字节在后
|
|
1300
|
+
const resistances_milliohm = [];
|
|
1301
|
+
for (let i = 4; i < 4 + len; i += 2) {
|
|
1302
|
+
const high = data[i] & 0xff;
|
|
1303
|
+
const low = data[i + 1] & 0xff;
|
|
1304
|
+
const value = (high << 8) + low; // uint16 mΩ
|
|
1305
|
+
resistances_milliohm.push(value);
|
|
1306
|
+
}
|
|
1307
|
+
console.log('均衡线电阻(mΩ): ', resistances_milliohm, data);
|
|
1308
|
+
let maxResistance = null, minResistance = null, avgResistance = null;
|
|
1309
|
+
if (resistances_milliohm.length) {
|
|
1310
|
+
maxResistance = Math.max(...resistances_milliohm);
|
|
1311
|
+
minResistance = Math.min(...resistances_milliohm);
|
|
1312
|
+
avgResistance = resistances_milliohm.reduce((a, c) => a + c, 0) / resistances_milliohm.length;
|
|
1313
|
+
}
|
|
1314
|
+
const resistances_ohm = resistances_milliohm.map(v => Number((v / 1000).toFixed(3)));
|
|
1315
|
+
const resistancesSeries = resistances_ohm.map((v, idx) => ({ name: idx + 1, value: v }));
|
|
1316
|
+
return {
|
|
1317
|
+
dataStr,
|
|
1318
|
+
status,
|
|
1319
|
+
len,
|
|
1320
|
+
resistances_milliohm,
|
|
1321
|
+
resistances_ohm,
|
|
1322
|
+
maxResistance_milliohm: maxResistance,
|
|
1323
|
+
minResistance_milliohm: minResistance,
|
|
1324
|
+
avgResistance_milliohm: avgResistance,
|
|
1325
|
+
maxResistance_ohm: maxResistance != null ? Number((maxResistance / 1000).toFixed(3)) : null,
|
|
1326
|
+
minResistance_ohm: minResistance != null ? Number((minResistance / 1000).toFixed(3)) : null,
|
|
1327
|
+
avgResistance_ohm: avgResistance != null ? Number((avgResistance / 1000).toFixed(3)) : null,
|
|
1328
|
+
resistancesSeries,
|
|
1329
|
+
};
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1332
|
+
/**重置容量
|
|
1333
|
+
*/
|
|
1334
|
+
export const resetCapacity = (deviceId) => {
|
|
1335
|
+
const command = ['0xDD', '0x5A', '0x0A', '0x02', '0x01', '0x00', '0xFF', '0xF3', '0x77'];
|
|
1336
|
+
return getData(
|
|
1337
|
+
deviceId,
|
|
1338
|
+
{
|
|
1339
|
+
command,
|
|
1340
|
+
commandVerifyHandler: (hexArr) => ({ verified: hexArr[0] == 0xdd && hexArr[1] == 0x0A, pkgLen: hexArr[3] + 7 }),
|
|
1341
|
+
pkgVerifyHandler: (pkg) => {
|
|
1342
|
+
return { verified: true };
|
|
1343
|
+
},
|
|
1344
|
+
},
|
|
1345
|
+
'DD5A_0A'
|
|
1346
|
+
);
|
|
1347
|
+
}
|
|
1348
|
+
|
|
1349
|
+
/**读取BMS系统时间*/
|
|
1350
|
+
export const getDDA506Async = async (deviceId) => {
|
|
1351
|
+
const command = ['0xdd', '0xa5', '0x06', '0x00', '0xff', '0xfa', '0x77'];
|
|
1352
|
+
const response = '';
|
|
1353
|
+
return getData(
|
|
1354
|
+
deviceId,
|
|
1355
|
+
{
|
|
1356
|
+
command,
|
|
1357
|
+
commandVerifyHandler: (hexArr) => ({ verified: hexArr[0] == 0xdd && hexArr[1] == 0x06, pkgLen: hexArr[3] + 7 }),
|
|
1358
|
+
pkgVerifyHandler: (pkg) => {
|
|
1359
|
+
const len = pkg.length;
|
|
1360
|
+
const [c1, c2] = generateCrcCheckSum(pkg.slice(2, len - 3));
|
|
1361
|
+
const [_c1, _c2] = [pkg[len - 3], pkg[len - 2]];
|
|
1362
|
+
return { verified: c1 == _c1 && c2 == _c2 };
|
|
1363
|
+
},
|
|
1364
|
+
},
|
|
1365
|
+
'DDA5_06'
|
|
1366
|
+
);
|
|
1367
|
+
}
|
|
1368
|
+
|
|
1369
|
+
/**解析BMS系统时间*/
|
|
1370
|
+
export const resolveDDA506 = (data) => {
|
|
1371
|
+
if (!data) return null;
|
|
1372
|
+
if (data[1] == 6 && data[2] == 0 && data[3] == 6) {
|
|
1373
|
+
//解析各字段
|
|
1374
|
+
const seconds = fromBCD(data[4]);
|
|
1375
|
+
const minutes = fromBCD(data[5]);
|
|
1376
|
+
const hours = fromBCD(data[6]);
|
|
1377
|
+
const day = fromBCD(data[7]);
|
|
1378
|
+
const month = fromBCD(data[8]);
|
|
1379
|
+
const year = 2000 + fromBCD(data[9]);
|
|
1380
|
+
const timeStr = `${year}-${String(month).padStart(2, 0)}-${String(day).padStart(2, 0)} ${String(hours).padStart(2, 0)}:${String(minutes).padStart(2, 0)}:${String(seconds).padStart(2, 0)}`;
|
|
1381
|
+
console.log('timeStr: ', timeStr, isWithin30Minutes(timeStr));
|
|
1382
|
+
return isWithin30Minutes(timeStr);
|
|
1383
|
+
} else {
|
|
1384
|
+
return false;
|
|
1385
|
+
}
|
|
1386
|
+
}
|
|
1387
|
+
|
|
1388
|
+
/**设置BMS系统时间*/
|
|
1389
|
+
//verified: hexArr[0] ->响应指令头 hexArr[1] ->指令码 pkgLen -> 响应指令长度
|
|
1390
|
+
export const setDD5AE3sync = async (deviceId) => {
|
|
1391
|
+
const header = ['0xDD', '0x5A']
|
|
1392
|
+
const now = new Date();
|
|
1393
|
+
const year = now.getFullYear();
|
|
1394
|
+
const month = now.getMonth() + 1;
|
|
1395
|
+
const day = now.getDate();
|
|
1396
|
+
const hours = now.getHours();
|
|
1397
|
+
const minutes = now.getMinutes();
|
|
1398
|
+
const seconds = now.getSeconds();
|
|
1399
|
+
|
|
1400
|
+
const values = [toBCD(seconds), toBCD(minutes), toBCD(hours) | 0x80, toBCD(day), toBCD(month), toBCD(year - 2000)].map(b => '0x' + b.toString(16).padStart(2, '0'));
|
|
1401
|
+
const content = ['0xE3', '0x07', '0x06', ...values];
|
|
1402
|
+
const checks = generateCrcCheckSum(content);
|
|
1403
|
+
const command = [...header, ...content, ...checks, '0x77'];
|
|
1404
|
+
console.log('command: ', command);
|
|
1405
|
+
return getData(
|
|
1406
|
+
deviceId,
|
|
1407
|
+
{
|
|
1408
|
+
command,
|
|
1409
|
+
commandVerifyHandler: (hexArr) => ({ verified: hexArr[0] == 0xdd && hexArr[1] == 0xe3, pkgLen: hexArr[3] + 7 }),
|
|
1410
|
+
pkgVerifyHandler: (pkg) => {
|
|
1411
|
+
return { verified: true };
|
|
1412
|
+
},
|
|
1413
|
+
},
|
|
1414
|
+
'SET_DDA5_E3'
|
|
1415
|
+
);
|
|
1416
|
+
}
|
|
1417
|
+
|
|
1418
|
+
/** 读取BMS运行时长 */
|
|
1419
|
+
export const getDDA4F0Async = async (deviceId) => {
|
|
1420
|
+
// 指令:DD A4 F0 00 FF 0B 77
|
|
1421
|
+
const command = ['0xDD', '0xA4', '0xF0', '0x00'];
|
|
1422
|
+
const checks = generateCrcCheckSum(command.slice(2)); // 只对命令码和长度做校验
|
|
1423
|
+
const fullCommand = [...command, ...checks, '0x77'];
|
|
1424
|
+
|
|
1425
|
+
return getData(
|
|
1426
|
+
deviceId,
|
|
1427
|
+
{
|
|
1428
|
+
command: fullCommand,
|
|
1429
|
+
commandVerifyHandler: (hexArr) => ({
|
|
1430
|
+
verified: hexArr[0] == 0xDD && hexArr[1] == 0xF0,
|
|
1431
|
+
pkgLen: hexArr[3] + 7
|
|
1432
|
+
}),
|
|
1433
|
+
pkgVerifyHandler: (pkg) => {
|
|
1434
|
+
const len = pkg.length;
|
|
1435
|
+
const [c1, c2] = generateCrcCheckSum(pkg.slice(2, len - 3));
|
|
1436
|
+
const [_c1, _c2] = [pkg[len - 3], pkg[len - 2]];
|
|
1437
|
+
return { verified: c1 == _c1 && c2 == _c2 };
|
|
1438
|
+
},
|
|
1439
|
+
},
|
|
1440
|
+
'DDA4_F0'
|
|
1441
|
+
);
|
|
1442
|
+
}
|
|
1443
|
+
|
|
1444
|
+
/** 解析BMS运行时长 */
|
|
1445
|
+
export const resolveDDA4F0 = (data) => {
|
|
1446
|
+
if (!data) return null;
|
|
1447
|
+
// 响应格式:DD F0 状态 长度 运行时长[4字节] 校验 0x77
|
|
1448
|
+
if (data[1] == 0xF0 && data[3] == 4) {
|
|
1449
|
+
// 运行时长为4字节,单位一般为秒(具体以协议为准)
|
|
1450
|
+
const runTime =
|
|
1451
|
+
(data[4] << 24) |
|
|
1452
|
+
(data[5] << 16) |
|
|
1453
|
+
(data[6] << 8) |
|
|
1454
|
+
data[7];
|
|
1455
|
+
return {
|
|
1456
|
+
runTime, // 运行时长(秒)
|
|
1457
|
+
runTimeHour: (runTime / 3600).toFixed(2), // 转为小时
|
|
1458
|
+
raw: hexArr2string(data)
|
|
1459
|
+
};
|
|
1460
|
+
}
|
|
1461
|
+
return null;
|
|
1462
|
+
}
|