@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.
Files changed (41) hide show
  1. package/dist/cjs/core/BleApiManager.js +1 -1
  2. package/dist/cjs/core/BleCmdAnalysis/BaseParamProtocol.js +1 -1
  3. package/dist/cjs/core/BleCmdAnalysis/BleCmdAnalysis.js +1 -1
  4. package/dist/cjs/core/BleCmdAnalysis/BleCmdDD.js +1 -1
  5. package/dist/cjs/core/BleCmdAnalysis/BleCmdDDA4.js +1 -1
  6. package/dist/cjs/core/BleCmdAnalysis/BleCmdFFAA.js +1 -1
  7. package/dist/cjs/core/BleCmdAnalysis/readAndSetParam.js +1 -1
  8. package/dist/cjs/core/BleDataProcess.js +1 -1
  9. package/dist/cjs/core/OtaUpgrade.js +1 -1
  10. package/dist/cjs/core/Queue.js +1 -0
  11. package/dist/cjs/core/mqttServer.js +1 -1
  12. package/dist/cjs/core/tcpServer.js +1 -0
  13. package/dist/cjs/index.js +1 -1
  14. package/dist/esm/core/BleApiManager.js +1 -1
  15. package/dist/esm/core/BleCmdAnalysis/BaseParamProtocol.js +1 -1
  16. package/dist/esm/core/BleCmdAnalysis/BleCmdAnalysis.js +1 -1
  17. package/dist/esm/core/BleCmdAnalysis/BleCmdDD.js +1 -1
  18. package/dist/esm/core/BleCmdAnalysis/BleCmdDDA4.js +1 -1
  19. package/dist/esm/core/BleCmdAnalysis/BleCmdFFAA.js +1 -1
  20. package/dist/esm/core/BleCmdAnalysis/BleCmdHVES.js +1 -1
  21. package/dist/esm/core/BleCmdAnalysis/readAndSetParam.js +1 -1
  22. package/dist/esm/core/BleDataProcess.js +1 -1
  23. package/dist/esm/core/OtaUpgrade.js +1 -1
  24. package/dist/esm/core/Queue.js +1 -0
  25. package/dist/esm/core/mqttServer.js +1 -1
  26. package/dist/esm/core/tcpServer.js +1 -0
  27. package/dist/esm/index.js +1 -1
  28. package/package.json +1 -1
  29. package/src/core/BleApiManager.js +33 -15
  30. package/src/core/BleCmdAnalysis/BaseParamProtocol.js +116 -32
  31. package/src/core/BleCmdAnalysis/BleCmdAnalysis.js +58 -2
  32. package/src/core/BleCmdAnalysis/BleCmdDD.js +88 -19
  33. package/src/core/BleCmdAnalysis/BleCmdDDA4.js +154 -227
  34. package/src/core/BleCmdAnalysis/BleCmdFFAA.js +1 -0
  35. package/src/core/BleCmdAnalysis/readAndSetParam.js +133 -16
  36. package/src/core/BleDataProcess.js +15 -11
  37. package/src/core/OtaUpgrade.js +356 -350
  38. package/src/core/Queue.js +34 -0
  39. package/src/core/mqttServer.js +75 -5
  40. package/src/core/tcpServer.js +341 -0
  41. package/src/index.js +1 -0
@@ -20,7 +20,8 @@ export const getDDA420Async = async (deviceId) => {
20
20
  return { verified: c1 == _c1 && c2 == _c2 };
21
21
  },
22
22
  },
23
- 'DDA420'
23
+ 'DDA420',
24
+ 1500
24
25
  );
25
26
  }
26
27
 
@@ -85,10 +86,11 @@ export const getDDA420Async = async (deviceId) => {
85
86
  );
86
87
 
87
88
  // 6. 充电器温度(2字节)
88
- const chargeTemperature = hexToDecimal(
89
+ const tempChargeTemperature = hexToDecimal(
89
90
  decimalToHex(data[n++]) +
90
91
  decimalToHex(data[n++])
91
- ) / 10;
92
+ );
93
+ const chargeTemperature = tempChargeTemperature > 32768 ? (tempChargeTemperature - 65536) / 10 : tempChargeTemperature / 10;
92
94
 
93
95
  // 7. 已充电量(4字节)
94
96
  const chargeCapacity = hexToDecimal(
@@ -231,7 +233,7 @@ export const getDDA420Async = async (deviceId) => {
231
233
  const checks = generateCrcCheckSum(_command);
232
234
  const command = ['0xdd', '0xa4', ..._command, ...checks, '0x77'];
233
235
 
234
- return this.getData(
236
+ return getData(
235
237
  deviceId,
236
238
  {
237
239
  command,
@@ -243,7 +245,8 @@ export const getDDA420Async = async (deviceId) => {
243
245
  return { verified: c1 == _c1 && c2 == _c2 };
244
246
  },
245
247
  },
246
- 'DDA421'
248
+ 'DDA421',
249
+ 1500
247
250
  );
248
251
  }
249
252
  /** 解析充电电池信息21指令
@@ -271,7 +274,8 @@ export const getDDA420Async = async (deviceId) => {
271
274
  const batterySOC = data[18]; // %
272
275
  // 电池温度 2BYTE [19,20]
273
276
  const batteryTempHex = decimalToHex(data[19]) + decimalToHex(data[20]);
274
- const batteryTemperature = hexToDecimal(batteryTempHex) / 10; // 0.1摄氏度
277
+ const tempBatteryTemperature = hexToDecimal(batteryTempHex);
278
+ const batteryTemperature = tempBatteryTemperature > 32768 ? (tempBatteryTemperature - 65536) / 10 : tempBatteryTemperature / 10; // 0.1摄氏度
275
279
  // const batteryTemperature = [data[19] ?? 0, [data[20] ?? 0]] // 摄氏度,保留一位小数
276
280
  // 加热状态 1BYTE [21]
277
281
  const heatingStatus = data[21]; // 0未加热 1加热中
@@ -332,7 +336,8 @@ export const getDDA420Async = async (deviceId) => {
332
336
  return { verified: true };
333
337
  },
334
338
  },
335
- 'DDA425'
339
+ 'DDA425',
340
+ 1500
336
341
  );
337
342
  }
338
343
  export const resolveDDA425 = (data) => {
@@ -377,7 +382,8 @@ export const getDDA420Async = async (deviceId) => {
377
382
  return { verified: c1 == _c1 && c2 == _c2 };
378
383
  },
379
384
  },
380
- 'DDA422'
385
+ 'DDA422',
386
+ 3000
381
387
  );
382
388
  }
383
389
  /** 解析充电器参数22指令响应
@@ -406,46 +412,66 @@ export const getDDA420Async = async (deviceId) => {
406
412
  * 设置充电器参数23指令
407
413
  */
408
414
  export const getDDA423Async = async (deviceId, startReg, endReg, values, valuesLength) => {
409
- // 转为2字节十六进制字符串
410
- const startRegHex = decimalToHex(startReg, 4);
411
- // 起始地址
412
- const startRegArr = [
413
- parseInt(startRegHex.slice(0, 2), 16),
414
- parseInt(startRegHex.slice(2, 4), 16)
415
- ];
416
- // 结束地址
417
- const endRegHex = decimalToHex(endReg, 4);
418
- const endRegArr = [
419
- parseInt(endRegHex.slice(0, 2), 16),
420
- parseInt(endRegHex.slice(2, 4), 16)
421
- ];
422
- // 数据内容
423
- const valueRegHex = decimalToHex(values, valuesLength * 2);
424
- let valueArr = [];
425
- for (let i = 0; i < valuesLength; i++) {
426
- const hex = valueRegHex.slice(i * 2, i * 2 + 2);
427
- valueArr.push(parseInt(hex.slice(0, 2), 16));
428
- }
429
-
430
- const lengthHex = decimalToHex(4+valuesLength, 2);
415
+ try {
416
+ // 起始/结束地址 2 字节大端
417
+ const startRegHex = decimalToHex(startReg, 4);
418
+ const startRegArr = [
419
+ parseInt(startRegHex.slice(0, 2), 16),
420
+ parseInt(startRegHex.slice(2, 4), 16)
421
+ ];
422
+ const endRegHex = decimalToHex(endReg, 4);
423
+ const endRegArr = [
424
+ parseInt(endRegHex.slice(0, 2), 16),
425
+ parseInt(endRegHex.slice(2, 4), 16)
426
+ ];
427
+
428
+ let valueArr = [];
429
+ // 批量模式:传入数组
430
+ if (Array.isArray(values)) {
431
+ valueArr = values.map(v => (Number(v) || 0) & 0xFF);
432
+ const expectLen = endReg - startReg + 1;
433
+ if (valueArr.length !== expectLen) {
434
+ if (valueArr.length > expectLen) {
435
+ valueArr = valueArr.slice(0, expectLen);
436
+ } else {
437
+ while (valueArr.length < expectLen) valueArr.push(0);
438
+ }
439
+ }
440
+ valuesLength = valueArr.length;
441
+ } else {
442
+ // 单值模式:保持兼容旧逻辑
443
+ const len = valuesLength || (endReg - startReg + 1);
444
+ const valueRegHex = decimalToHex(values, len * 2);
445
+ for (let i = 0; i < len; i++) {
446
+ const hex = valueRegHex.slice(i * 2, i * 2 + 2);
447
+ valueArr.push(parseInt(hex, 16));
448
+ }
449
+ valuesLength = len;
450
+ }
431
451
 
432
- const _command = ['0x23', lengthHex, ...startRegArr, ...endRegArr, ...valueArr];
433
- const checks = generateCrcCheckSum(_command);
434
- const command = ['0xDD', '0xA4', ..._command, ...checks, '0x77'];
435
- return getData(
436
- deviceId,
437
- {
438
- command,
439
- commandVerifyHandler: (hexArr) => ({ verified: hexArr[0] == 0xdd && hexArr[1] == 0x23, pkgLen: hexArr[3] + 7 }),
440
- pkgVerifyHandler: (pkg) => {
441
- const len = pkg.length;
442
- const [c1, c2] = generateCrcCheckSum(pkg.slice(2, len - 3));
443
- const [_c1, _c2] = [pkg[len - 3], pkg[len - 2]];
444
- return { verified: c1 == _c1 && c2 == _c2 };
452
+ const lengthHex = 4 + valuesLength;
453
+ const _command = ['0x23', lengthHex, ...startRegArr, ...endRegArr, ...valueArr];
454
+ const checks = generateCrcCheckSum(_command);
455
+ const command = ['0xDD', '0xA4', ..._command, ...checks, '0x77'];
456
+ return getData(
457
+ deviceId,
458
+ {
459
+ command,
460
+ commandVerifyHandler: (hexArr) => ({ verified: hexArr[0] == 0xdd && hexArr[1] == 0x23, pkgLen: hexArr[3] + 7 }),
461
+ pkgVerifyHandler: (pkg) => {
462
+ const len = pkg.length;
463
+ const [c1, c2] = generateCrcCheckSum(pkg.slice(2, len - 3));
464
+ const [_c1, _c2] = [pkg[len - 3], pkg[len - 2]];
465
+ return { verified: c1 == _c1 && c2 == _c2 };
466
+ },
445
467
  },
446
- },
447
- 'DDA423'
448
- );
468
+ 'DDA423',
469
+ 3000
470
+ );
471
+ } catch (e) {
472
+ console.warn('getDDA423Async build frame error', e);
473
+ return Promise.reject(e);
474
+ }
449
475
  }
450
476
  export const resolveDDA423 = (data) => {
451
477
  if (!data) return null;
@@ -475,14 +501,14 @@ export const getDDA420Async = async (deviceId) => {
475
501
 
476
502
  // 转 4 字节 (大端) 十六进制 -> 数组
477
503
  const to4Bytes = (val) => {
478
- const hex = commonfun.decimalToHex(val, 8); // 8位十六进制字符串
504
+ const hex = decimalToHex(val, 8); // 8位十六进制字符串
479
505
  return [0, 2, 4, 6].map(i => parseInt(hex.slice(i, i + 2), 16));
480
506
  };
481
507
  const voltageArr = to4Bytes(outputVoltage);
482
508
  const currentArr = to4Bytes(outputCurrent);
483
509
 
484
510
  // 长度 = 1(模式) +4(电压)+4(电流) = 9
485
- const lengthHex = commonfun.decimalToHex(9, 2); // '09'
511
+ const lengthHex = decimalToHex(9, 2); // '09'
486
512
  const _command = ['0x26', `0x${lengthHex}`, testMode & 0xFF, ...voltageArr, ...currentArr].map(o => typeof o === 'number' ? `0x${('00' + o.toString(16)).slice(-2)}` : o);
487
513
  // 去掉 0x 前缀转成数值数组生成 CRC
488
514
  const _commandNums = _command.map(h => parseInt(h, 16));
@@ -615,49 +641,31 @@ export const getDDA420Async = async (deviceId) => {
615
641
  * @param {*} deviceId
616
642
  * @returns
617
643
  */
618
- export const getDDA429Async = async (deviceId, id) => {
619
- // id、是四个bites
644
+ export const getDDA429Async = async (deviceId, id = 1, seq = 0) => {
645
+ // ID 与 SEQ 均为 4 字节大端
620
646
  const idHex = decimalToHex(id, 8);
621
- // 拆分为4字节
647
+ const seqHex = decimalToHex(seq, 8);
622
648
  const idArr = [
623
649
  parseInt(idHex.slice(0, 2), 16),
624
650
  parseInt(idHex.slice(2, 4), 16),
625
651
  parseInt(idHex.slice(4, 6), 16),
626
- parseInt(idHex.slice(4, 6), 16),
627
652
  parseInt(idHex.slice(6, 8), 16)
628
653
  ];
629
- const _command = ['0x29', '0x04', ...idArr];
654
+ const seqArr = [
655
+ parseInt(seqHex.slice(0, 2), 16),
656
+ parseInt(seqHex.slice(2, 4), 16),
657
+ parseInt(seqHex.slice(4, 6), 16),
658
+ parseInt(seqHex.slice(6, 8), 16)
659
+ ];
660
+ // 长度 = 8 (ID+SEQ)
661
+ const _command = ['0x29', '0x08', ...idArr, ...seqArr];
630
662
  const checks = generateCrcCheckSum(_command);
631
- const command = ['0xdd', '0xa4', ..._command, ...checks, '0x77'];
632
-
633
-
663
+ const command = ['0xDD', '0xA4', ..._command, ...checks, '0x77'];
634
664
  return getData(
635
665
  deviceId,
636
666
  {
637
667
  command,
638
- commandVerifyHandler: (hexArr) => {
639
- // 基本头部验证
640
- if (hexArr[0] != 0xdd || hexArr[1] != 0x29) return { verified: false, pkgLen: null };
641
-
642
- // 验证数据包长度是否合理
643
- if (hexArr.length < 8) return { verified: false, pkgLen: null };
644
-
645
- // 根据resolveDDA429的解析结构,ID在响应偏移32位置
646
- // 实际协议中可能有所不同,需要根据协议规范调整
647
- if (hexArr.length >= 36) {
648
- // 从resolveDDA429可知,ID位于n=32处的4个字节
649
- const respIdHex = decimalToHex(hexArr[32]) +
650
- decimalToHex(hexArr[33]) +
651
- decimalToHex(hexArr[34]) +
652
- decimalToHex(hexArr[35]);
653
- const respId = hexToDecimal(respIdHex);
654
-
655
- // 如果ID不匹配,则拒绝该数据包
656
- if (respId !== id) return { verified: false, pkgLen: null };
657
- }
658
-
659
- return { verified: true, pkgLen: hexArr[3] + 7 };
660
- },
668
+ commandVerifyHandler: (hexArr) => ({ verified: hexArr[0] == 0xdd && hexArr[1] == 0x29, pkgLen: hexArr[3] + 7 }),
661
669
  pkgVerifyHandler: (pkg) => {
662
670
  const len = pkg.length;
663
671
  const [c1, c2] = generateCrcCheckSum(pkg.slice(2, len - 3));
@@ -665,161 +673,80 @@ export const getDDA420Async = async (deviceId) => {
665
673
  return { verified: c1 == _c1 && c2 == _c2 };
666
674
  },
667
675
  },
668
- 'DDA429'
676
+ 'DDA429',
677
+ 3000
669
678
  );
670
679
  }
671
680
  export const resolveDDA429 = (data) => {
672
681
  if (!data) return null;
682
+ const status = data[2];
683
+ const content = data.slice(4, data.length - 3);
673
684
  const dataStr = hexArr2string(data);
674
- let n = 4; // 起始偏移
675
-
676
- // 1. 工作状态
677
- const workStatus = data[n++];
678
-
679
- // 2. 充电状态
680
- const chargeStatus = data[n++];
681
-
682
- // 3. 充电电压(4字节)
683
- const chargeVoltage = hexToDecimal(
684
- decimalToHex(data[n++]) +
685
- decimalToHex(data[n++]) +
686
- decimalToHex(data[n++]) +
687
- decimalToHex(data[n++])
688
- );
689
-
690
- // 4. 充电电流(4字节)
691
- const chargeElectricity = hexToDecimal(
692
- decimalToHex(data[n++]) +
693
- decimalToHex(data[n++]) +
694
- decimalToHex(data[n++]) +
695
- decimalToHex(data[n++])
696
- );
697
-
698
- // 5. 充电功率(2字节)
699
- const chargePower = hexToDecimal(
700
- decimalToHex(data[n++]) +
701
- decimalToHex(data[n++])
702
- );
703
-
704
- // 6. 充电器温度(2字节)
705
- const chargeTemperature = hexToDecimal(
706
- decimalToHex(data[n++]) +
707
- decimalToHex(data[n++])
708
- ) / 10;
709
-
710
- // 7. 已充电量(4字节)
711
- const chargeCapacity = hexToDecimal(
712
- decimalToHex(data[n++]) +
713
- decimalToHex(data[n++]) +
714
- decimalToHex(data[n++]) +
715
- decimalToHex(data[n++])
716
- );
717
-
718
- // 8. 充电时长(2字节)
719
- const chargeTime = hexToDecimal(
720
- decimalToHex(data[n++]) +
721
- decimalToHex(data[n++])
722
- );
723
-
724
- // 9. 充电剩余时间(2字节)
725
- const chargeRemainTime = hexToDecimal(
726
- decimalToHex(data[n++]) +
727
- decimalToHex(data[n++])
728
- );
729
-
730
- // 10. 充电完成时长(2字节)
731
- const chargeCompleteTime = hexToDecimal(
732
- decimalToHex(data[n++]) +
733
- decimalToHex(data[n++])
734
- );
735
-
736
- // 输出电压占空比
737
- const outputVoltagePercent = data[n++];
738
-
739
- // 输出电流占空比
740
- const outputElectricityPercent = data[n++];
741
-
742
- // id(4字节)
743
- const id1 = hexToDecimal(
744
- decimalToHex(data[n++]) +
745
- decimalToHex(data[n++]) +
746
- decimalToHex(data[n++]) +
747
- decimalToHex(data[n++])
748
- );
749
-
750
- // 检测输出电流(4字节)
751
- const outputElectricity = hexToDecimal(
752
- decimalToHex(data[n++]) +
753
- decimalToHex(data[n++]) +
754
- decimalToHex(data[n++]) +
755
- decimalToHex(data[n++])
756
- );
757
-
758
- // 检测电池电压(4字节)
759
- const id = hexToDecimal(
760
- decimalToHex(data[n++]) +
761
- decimalToHex(data[n++]) +
762
- decimalToHex(data[n++]) +
763
- decimalToHex(data[n++])
764
- );
765
-
766
- // 开关状态(2字节)
767
- const switchStatus = hexToDecimal(
768
- decimalToHex(data[n++]) +
769
- decimalToHex(data[n++])
770
- );
771
- const swtichStatusArr = switchStatus.toString(2).padStart(16, '0').split('').reverse();
772
- const chargeSwitch = swtichStatusArr[0] == '1';
773
- const preChargeSwitch = swtichStatusArr[1] == '1';
774
- const fanSwitch = swtichStatusArr[2] == '1';
775
-
776
- // 保护状态(4字节)
777
- const protectStatus = hexToDecimal(
778
- decimalToHex(data[n++]) +
779
- decimalToHex(data[n++]) +
780
- decimalToHex(data[n++]) +
781
- decimalToHex(data[n++])
782
- );
783
- const protectStatusArr = protectStatus.toString(2).padStart(32, '0').split('').reverse();
784
- let protectStatusIndexs = [];
785
- for (let i = 0; i < protectStatusArr.length; i++) {
786
- if (protectStatusArr[i] == '1') protectStatusIndexs.push(i);
685
+ if (content.length < 8) return { dataStr, status, error: 'content too short' };
686
+
687
+ const id = hexToDecimal(decimalToHex(content[0]) + decimalToHex(content[1]) + decimalToHex(content[2]) + decimalToHex(content[3]));
688
+ const seq = hexToDecimal(decimalToHex(content[4]) + decimalToHex(content[5]) + decimalToHex(content[6]) + decimalToHex(content[7]));
689
+ const body = content.slice(8);
690
+
691
+ // ID=1 解析:末尾 57 字节固定含义,其余视作工作信息原始区
692
+ if (id === 1) {
693
+ const peerTailLen = 57;
694
+ let workInfo = [];
695
+ let peerSection = [];
696
+ if (body.length >= peerTailLen) {
697
+ workInfo = body.slice(0, body.length - peerTailLen);
698
+ peerSection = body.slice(body.length - peerTailLen);
699
+ } else {
700
+ peerSection = body.slice();
701
+ }
702
+ const workinfoField = {
703
+ state: workInfo[0] || 0,
704
+ ipwm: hexToDecimal(decimalToHex(workInfo[24]) + decimalToHex(workInfo[25]) + decimalToHex(workInfo[26]) + decimalToHex(workInfo[27])),
705
+ vpwm: hexToDecimal(decimalToHex(workInfo[28]) + decimalToHex(workInfo[29]) + decimalToHex(workInfo[30]) + decimalToHex(workInfo[31])),
706
+ vout: hexToDecimal(decimalToHex(workInfo[32]) + decimalToHex(workInfo[33]) + decimalToHex(workInfo[34]) + decimalToHex(workInfo[35])),
707
+ iout: hexToDecimal(decimalToHex(workInfo[36]) + decimalToHex(workInfo[37]) + decimalToHex(workInfo[38]) + decimalToHex(workInfo[39])),
708
+ vbat: hexToDecimal(decimalToHex(workInfo[40]) + decimalToHex(workInfo[41]) + decimalToHex(workInfo[42]) + decimalToHex(workInfo[43])),
709
+ port: String(workInfo[54]) || 0
710
+ };
711
+ const fieldNames = ['peer_curr', 'peer_num', 'ble_state', 'ble_init', 'ble_release', 'release_cnt', 'scan_start', 'scan_end', 'scan_res', 'scan_resp', 'conn_start', 'conn_resp', 'conn_end', 'conn_idx', 'conn_res', 'cmp_resp', 'handshake_resp', 'qr_chg', 'blacklist', 'ext_resp', 'ext_num'];
712
+ const peerMap = {};
713
+ peerSection.slice(0, 21).forEach((b, i) => { peerMap[fieldNames[i] || (`extra_${i}`)] = b; });
714
+
715
+ const extraBytes = peerSection.slice(21);
716
+ let i = 0;
717
+ let j = 0;
718
+ const fieldNamesExtra = ['run_ts', 'scan_ts', 'scan_end_ts', 'get_ts', 'get_end_ts', 'conn_ts', 'conn_end_ts', 'cmp_ts', 'cmp_end_ts'];
719
+ while (i < extraBytes.length) {
720
+ peerMap[fieldNamesExtra[j] || (`extra_${j}`)] = hexToDecimal(
721
+ decimalToHex(extraBytes[i] || 0) +
722
+ decimalToHex(extraBytes[i + 1] || 0) +
723
+ decimalToHex(extraBytes[i + 2] || 0) +
724
+ decimalToHex(extraBytes[i + 3] || 0)
725
+ );
726
+ i += 4;
727
+ j += 1;
728
+ }
729
+ return { dataStr, status, id, seq, type: 'ID1', ...workinfoField, ...peerMap };
787
730
  }
788
731
 
789
- // 告警状态(4字节)
790
- const alarmStatus = hexToDecimal(
791
- decimalToHex(data[n++]) +
792
- decimalToHex(data[n++]) +
793
- decimalToHex(data[n++]) +
794
- decimalToHex(data[n++])
795
- );
796
- const alarmStatusArr = alarmStatus.toString(2).padStart(32, '0').split('').reverse();
797
- let alarmStatusIndexs = [];
798
- for (let i = 0; i < alarmStatusArr.length; i++) {
799
- if (alarmStatusArr[i] == '1') alarmStatusIndexs.push(i);
732
+ // ID=2/3 解析:按 16 字节一组 peer_info
733
+ if (id === 2 || id === 3) {
734
+ const peerInfos = [];
735
+ for (let i = 0; i + 16 <= body.length; i += 16) {
736
+ const seg = body.slice(i, i + 16);
737
+ const macBytes = seg.slice(0, 6).map(b => decimalToHex(b));
738
+ const mac = macBytes.map(m => m.toUpperCase()).join(':');
739
+ const state = seg[6] === 255 ? -1 : seg[6];
740
+ const cmp = seg[7] === 255 ? -1 : seg[7];
741
+ const voltage = hexToDecimal(decimalToHex(seg[8]) + decimalToHex(seg[9]));
742
+ const b_voltage = hexToDecimal(decimalToHex(seg[10]) + decimalToHex(seg[11]));
743
+ const current = hexToDecimal(decimalToHex(seg[12]) + decimalToHex(seg[13]));
744
+ const b_current = hexToDecimal(decimalToHex(seg[14]) + decimalToHex(seg[15]));
745
+ peerInfos.push({ mac, state, cmp, voltage, b_voltage, current, b_current });
746
+ }
747
+ return { dataStr, status, id, seq, type: `ID${id}`, peerInfos: peerInfos.map((item, i) => ({ id: i, ...item })) };
800
748
  }
801
749
 
802
- return {
803
- dataStr,
804
- workStatus,
805
- chargeStatus,
806
- chargeVoltage,
807
- chargeElectricity,
808
- chargePower,
809
- chargeTemperature,
810
- chargeCapacity,
811
- chargeTime,
812
- chargeRemainTime,
813
- chargeCompleteTime,
814
- outputVoltagePercent,
815
- outputElectricityPercent,
816
- id,
817
- outputElectricity,
818
- id1,
819
- chargeSwitch,
820
- preChargeSwitch,
821
- fanSwitch,
822
- protectStatusIndexs,
823
- alarmStatusIndexs,
824
- };
750
+ // 未知 ID
751
+ return { dataStr, status, id, seq, raw: body };
825
752
  }
@@ -168,6 +168,7 @@ export const getFFAA80Async = async (deviceId, ATStr) => {
168
168
  },
169
169
  'FFAA_80(AT)'
170
170
  );
171
+ console.log('getFFAA80Async', hex)
171
172
  if(!hex) return null;
172
173
  return resolveFFAA80(hex);
173
174
  }