node-red-zelecproto 0.0.9 → 0.1.1

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 (3) hide show
  1. package/645.js +7 -80
  2. package/698.js +45 -46
  3. package/package.json +1 -1
package/645.js CHANGED
@@ -534,52 +534,17 @@ function decode645(_msg) {
534
534
  }
535
535
  };
536
536
 
537
- // —— 状态字2(与你现有的 04000502 保持一致)——
537
+ // 状态字2/3只保留原始数值和binary,具体位义由上层业务或文档表解释。
538
538
  const w2 = readU16LE();
539
- const dir = (b) => (b ? '反向' : '正向');
540
539
  const word2 = (w2 === null) ? null : {
541
540
  rawValue: w2,
542
- binary: bin16(w2),
543
- fields: {
544
- 'A相有功功率方向': dir(bit(w2, 0)),
545
- 'B相有功功率方向': dir(bit(w2, 1)),
546
- 'C相有功功率方向': dir(bit(w2, 2)),
547
- 'A相无功功率方向': dir(bit(w2, 4)),
548
- 'B相无功功率方向': dir(bit(w2, 5)),
549
- 'C相无功功率方向': dir(bit(w2, 6))
550
- }
541
+ binary: bin16(w2)
551
542
  };
552
543
 
553
- // —— 状态字3(与你现有的 04000503 保持一致)——
554
544
  const w3 = readU16LE();
555
- const supplyBits = (w3 === null) ? 0 : ((w3 >> 1) & 0b11);
556
- const supplyMode = (
557
- supplyBits === 0 ? '主电源' :
558
- supplyBits === 1 ? '辅助电源' :
559
- supplyBits === 2 ? '电池供电' : '保留'
560
- );
561
- const meterTypeBits = (w3 === null) ? 0 : ((w3 >> 8) & 0b11);
562
- const meterType = (
563
- meterTypeBits === 0 ? '非预付费表' :
564
- meterTypeBits === 1 ? '电量型预付费表' :
565
- meterTypeBits === 2 ? '电费型预付费表' : '保留'
566
- );
567
545
  const word3 = (w3 === null) ? null : {
568
546
  rawValue: w3,
569
- binary: bin16(w3),
570
- fields: {
571
- 当前运行时段套数: (bit(w3, 0) ? '第二套' : '第一套'),
572
- 供电方式: supplyMode,
573
- 编程允许状态: (bit(w3, 3) ? '有效' : '失效'),
574
- 继电器状态: (bit(w3, 4) ? '断' : '通'),
575
- 当前运行时区套数: (bit(w3, 5) ? '第二套' : '第一套'),
576
- 继电器命令状态: (bit(w3, 6) ? '断' : '通'),
577
- 预跳闸报警状态: (bit(w3, 7) ? '有' : '无'),
578
- 电能表类型: meterType,
579
- 当前运行分时费率套数: (bit(w3, 10) ? '第二套' : '第一套'),
580
- 当前阶梯套数: (bit(w3, 11) ? '第二套' : '第一套'),
581
- 保电状态: (bit(w3, 12) ? '保电' : '非保电')
582
- }
547
+ binary: bin16(w3)
583
548
  };
584
549
 
585
550
  // —— 密钥状态字(与你现有的 04000508 保持一致,32位)——
@@ -630,64 +595,26 @@ function decode645(_msg) {
630
595
  }
631
596
  };
632
597
  } else if (di === '04000502' && arrPush.length >= 6) {
633
- // 运行状态字2(方向类):A/B/C 相有功与无功功率方向(0=正向,1=反向)
598
+ // 状态字2只返回原始数值,binary为bit15..bit0。
634
599
  const lo = arrPush[4] & 0xFF;
635
600
  const hi = arrPush[5] & 0xFF;
636
601
  const v = (hi << 8) | lo;
637
602
  const bin = v.toString(2).padStart(16, '0');
638
603
 
639
- const bit = (n) => ((v >> n) & 0x1);
640
- const dir = (b) => (b ? '反向' : '正向');
641
-
642
604
  value = {
643
605
  rawValue: v,
644
- binary: bin,
645
- fields: {
646
- 'A相有功功率方向': dir(bit(0)),
647
- 'B相有功功率方向': dir(bit(1)),
648
- 'C相有功功率方向': dir(bit(2)),
649
- 'A相无功功率方向': dir(bit(4)),
650
- 'B相无功功率方向': dir(bit(5)),
651
- 'C相无功功率方向': dir(bit(6))
652
- }
606
+ binary: bin
653
607
  };
654
608
  } else if (di === '04000503' && arrPush.length >= 6) {
655
- // 运行状态字3(操作类)
609
+ // 状态字3只返回原始数值,binary为bit15..bit0。
656
610
  const lo = arrPush[4] & 0xFF;
657
611
  const hi = arrPush[5] & 0xFF;
658
612
  const v = (hi << 8) | lo;
659
613
  const bin = v.toString(2).padStart(16, '0');
660
614
 
661
- const supplyBits = (v >> 1) & 0b11; // bit2-bit1
662
- const supplyMode = (
663
- supplyBits === 0 ? '主电源' :
664
- supplyBits === 1 ? '辅助电源' :
665
- supplyBits === 2 ? '电池供电' : '保留'
666
- );
667
-
668
- const meterTypeBits = (v >> 8) & 0b11; // bit9-bit8
669
- const meterType = (
670
- meterTypeBits === 0 ? '非预付费表' :
671
- meterTypeBits === 1 ? '电量型预付费表' :
672
- meterTypeBits === 2 ? '电费型预付费表' : '保留'
673
- );
674
-
675
615
  value = {
676
616
  rawValue: v,
677
- binary: bin,
678
- fields: {
679
- 当前运行时段套数: (v & 0x1) ? '第二套' : '第一套', // bit0
680
- 供电方式: supplyMode, // bit2-bit1
681
- 编程允许状态: (v & (1 << 3)) ? '有效' : '失效', // bit3
682
- 继电器状态: (v & (1 << 4)) ? '断' : '通', // bit4(线路实际工作状态)
683
- 当前运行时区套数: (v & (1 << 5)) ? '第二套' : '第一套', // bit5
684
- 继电器命令状态: (v & (1 << 6)) ? '断' : '通', // bit6(远程拉闸命令)
685
- 预跳闸报警状态: (v & (1 << 7)) ? '有' : '无', // bit7
686
- 电能表类型: meterType, // bit9-bit8
687
- 当前运行分时费率套数: (v & (1 << 10)) ? '第二套' : '第一套', // bit10
688
- 当前阶梯套数: (v & (1 << 11)) ? '第二套' : '第一套', // bit11
689
- 保电状态: (v & (1 << 12)) ? '保电' : '非保电' // bit12
690
- }
617
+ binary: bin
691
618
  };
692
619
  }
693
620
  // else if (['0000FF00', '0001FF00', '0002FF00'].includes(di) && arrPush.length > 4) {
package/698.js CHANGED
@@ -859,6 +859,39 @@ function toBigEndian16(value) {
859
859
  // 将小端(低字节在前)转换为大端(高字节在前)
860
860
  return (lower << 8) | upper;
861
861
  }
862
+
863
+ function parseStatusWordFromAxdrBitString(buffer) {
864
+ if (!Buffer.isBuffer(buffer) || buffer.length < 3 || buffer[0] !== 0x04) return null;
865
+ const L = readAxdrLength(buffer, 1);
866
+ const byteLen = Math.ceil(L.len / 8);
867
+ const start = 1 + L.size;
868
+ const end = start + byteLen;
869
+ if (end > buffer.length) return null;
870
+ const bytes = buffer.slice(start, end);
871
+ if (bytes.length < 2) return null;
872
+ const bits = [];
873
+ const lowToHighBits = [];
874
+ // A-XDR bit-string按每字节高位到低位展开;另保留低位到高位展示用于和现场口径对照。
875
+ for (const byte of bytes.slice(0, 2)) {
876
+ for (let bit = 7; bit >= 0; bit--) {
877
+ bits.push((byte >> bit) & 0x01);
878
+ }
879
+ for (let bit = 0; bit <= 7; bit++) {
880
+ lowToHighBits.push((byte >> bit) & 0x01);
881
+ }
882
+ }
883
+ let statusWord = 0;
884
+ // 文档表F.x中的bit编号按展开后的bit-string下标映射,后续binary再按645一致的数值形式输出。
885
+ for (let i = 0; i < 16; i++) {
886
+ statusWord |= bits[i] << i;
887
+ }
888
+ return {
889
+ statusWord,
890
+ binaryLowToHigh: lowToHighBits.slice(0, 16).join(''),
891
+ binaryHighToLow: bits.slice(0, 16).join('')
892
+ };
893
+ }
894
+
862
895
  /**
863
896
  * 解析电表运行状态字2 - 与645协议格式保持一致
864
897
  * @param {Buffer} dataBuffer - 数据缓冲区
@@ -928,42 +961,19 @@ function parseMeterStatusWord3(dataBuffer) {
928
961
  const oad = '20140203';
929
962
  const result = createStandardResult("电表运行状态字3", oad, dataBuffer);
930
963
  try {
931
- const statusWord = parseMeterStatusOptimized(dataBuffer);
964
+ const bitStringStatus = parseStatusWordFromAxdrBitString(dataBuffer);
965
+ const statusWord = bitStringStatus?.statusWord ?? parseMeterStatusOptimized(dataBuffer);
932
966
  if (statusWord === null) throw new Error('无法解析状态字');
933
967
 
934
968
  const val16 = statusWord & 0xFFFF; // 低16位
969
+ // binary按最终状态字数值输出(bit15..bit0),与645状态字binary保持一致。
935
970
  const bin = val16.toString(2).padStart(16, '0');
936
971
 
937
- const supplyBits = (val16 >> 1) & 0b11; // bit2-bit1
938
- const supplyMode = (
939
- supplyBits === 0 ? '主电源' :
940
- supplyBits === 1 ? '辅助电源' :
941
- supplyBits === 2 ? '电池供电' : '保留'
942
- );
943
-
944
- const meterTypeBits = (val16 >> 8) & 0b11; // bit9-bit8
945
- const meterType = (
946
- meterTypeBits === 0 ? '非预付费表' :
947
- meterTypeBits === 1 ? '电量型预付费表' :
948
- meterTypeBits === 2 ? '电费型预付费表' : '保留'
949
- );
950
-
951
972
  result.value = {
952
973
  rawValue: val16,
953
974
  binary: bin,
954
- fields: {
955
- 当前运行时段套数: (val16 & 0x1) ? '第二套' : '第一套',
956
- 供电方式: supplyMode, // bit2-bit1
957
- 编程允许状态: (val16 & (1 << 3)) ? '有效' : '失效', // bit3
958
- 继电器状态: (val16 & (1 << 4)) ? '断' : '通', // bit4(线路实际工作状态)
959
- 当前运行时区套数: (val16 & (1 << 5)) ? '第二套' : '第一套',
960
- 继电器命令状态: (val16 & (1 << 6)) ? '断' : '通', // bit6(远程拉闸命令)
961
- 预跳闸报警状态: (val16 & (1 << 7)) ? '有' : '无', // bit7
962
- 电能表类型: meterType, // bit9-bit8
963
- 当前运行分时费率套数: (val16 & (1 << 10)) ? '第二套' : '第一套',
964
- 当前阶梯套数: (val16 & (1 << 11)) ? '第二套' : '第一套',
965
- 保电状态: (val16 & (1 << 12)) ? '保电' : '非保电'
966
- }
975
+ ...(bitStringStatus?.binaryLowToHigh ? { binaryLowToHigh: bitStringStatus.binaryLowToHigh } : {}),
976
+ ...(bitStringStatus?.binaryHighToLow ? { binaryHighToLow: bitStringStatus.binaryHighToLow } : {})
967
977
  };
968
978
 
969
979
  setSuccessResult(result, {
@@ -984,31 +994,20 @@ function parseMeterStatusWord2(dataBuffer) {
984
994
  const oad = '20140202';
985
995
  const result = createStandardResult("电表运行状态字2", oad, dataBuffer);
986
996
  try {
987
- const statusWord = parseMeterStatusOptimized(dataBuffer);
997
+ const bitStringStatus = parseStatusWordFromAxdrBitString(dataBuffer);
998
+ const statusWord = bitStringStatus?.statusWord ?? parseMeterStatusOptimized(dataBuffer);
988
999
  if (statusWord === null) throw new Error('无法解析状态字');
989
1000
 
990
1001
  const val16 = statusWord & 0xFFFF;
1002
+ // binary按最终状态字数值输出(bit15..bit0),与645状态字binary保持一致。
991
1003
  const bin = val16.toString(2).padStart(16, '0');
992
1004
 
993
- const bit = (n) => ((val16 >> n) & 0x1);
994
- const dir = (b) => (b ? '反向' : '正向'); // 0=正向, 1=反向
995
-
996
- // 按表F.2位义生成具名字段
997
- const fields = {
998
- 'A相有功功率方向': dir(bit(0)), // bit0
999
- 'B相有功功率方向': dir(bit(1)), // bit1
1000
- 'C相有功功率方向': dir(bit(2)), // bit2
1001
- 'A相无功功率方向': dir(bit(4)), // bit4
1002
- 'B相无功功率方向': dir(bit(5)), // bit5
1003
- 'C相无功功率方向': dir(bit(6)) // bit6
1004
- // 其余bit3、bit7、bit8~bit15为保留
1005
- };
1006
-
1007
1005
  result.value = {
1008
1006
  rawValue: val16,
1009
1007
  binary: bin,
1010
- bits: decodeMeterStatusBits(val16),
1011
- fields
1008
+ ...(bitStringStatus?.binaryLowToHigh ? { binaryLowToHigh: bitStringStatus.binaryLowToHigh } : {}),
1009
+ ...(bitStringStatus?.binaryHighToLow ? { binaryHighToLow: bitStringStatus.binaryHighToLow } : {}),
1010
+ bits: decodeMeterStatusBits(val16)
1012
1011
  };
1013
1012
 
1014
1013
  setSuccessResult(result, { statusWord: val16, statusWordHex: val16.toString(16).padStart(4, '0').toUpperCase(), statusBits: decodeMeterStatusBits(val16) }, { generic: { dataType: 'bit-string' } });
@@ -3005,4 +3004,4 @@ function batchMsg698(msg) {
3005
3004
  }
3006
3005
 
3007
3006
  module.exports = batchMsg698;
3008
- module.exports.batchMsg698 = batchMsg698;
3007
+ module.exports.batchMsg698 = batchMsg698;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-red-zelecproto",
3
- "version": "0.0.9",
3
+ "version": "0.1.1",
4
4
  "description": "node-red zelecproto node",
5
5
  "main": "index.js",
6
6
  "scripts": {