node-zserial 1.0.31 → 1.0.32

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 (2) hide show
  1. package/package.json +1 -1
  2. package/zserial.js +32 -21
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-zserial",
3
- "version": "1.0.31",
3
+ "version": "1.0.32",
4
4
  "description": "Node-RED nodes to talk to serial ports",
5
5
  "dependencies": {
6
6
  "serialport": "^12.0.0"
package/zserial.js CHANGED
@@ -1035,8 +1035,10 @@ module.exports = function (RED) {
1035
1035
 
1036
1036
  // 698(68-LEN 变体):68 LL LH C ... DATA ... FCS(2) 16 ;兼容 FE* 前导
1037
1037
  function tryParse698Len(input) {
1038
- // 剥离前导 FE(注意:这里只做 698-LEN 侧的兼容;645 另有自己的 FE 处理)
1039
- const b = stripFE(input);
1038
+ // 统计 FE 前导(用于 used/frame 回到原始 input)
1039
+ let feCount = 0;
1040
+ while (feCount < input.length && input[feCount] === 0xFE) feCount++;
1041
+ const b = input.slice(feCount);
1040
1042
  if (b.length < 6 || b[0] !== 0x68) return { ok: false };
1041
1043
 
1042
1044
  // ---- 读取长度域 ----
@@ -1072,7 +1074,7 @@ module.exports = function (RED) {
1072
1074
  // 掉电次数等业务回包通常远小于 2KB;超出则高度可疑,丢 1 字节推进重同步
1073
1075
  const MAX_698_LEN_L = 2048;
1074
1076
  if (L > MAX_698_LEN_L) {
1075
- return { ok: false, used: 1, frame: b.slice(0, 1), err: "698_LEN_TOO_LARGE" };
1077
+ return { ok: false, used: feCount + 1, frame: input.slice(0, feCount + 1), err: "698_LEN_TOO_LARGE" };
1076
1078
  }
1077
1079
 
1078
1080
  // 约束 2:控制域 C 在 b[3],不可能是 0x16(结束符)
@@ -1093,7 +1095,7 @@ module.exports = function (RED) {
1093
1095
  // 若 expectedEnd 位置不是 0x16,说明起点错位或存在脏字节
1094
1096
  // 这里消费 1 字节,避免死循环卡住
1095
1097
  if (b[expectedEnd] !== 0x16) {
1096
- return { ok: false, used: 1, frame: b.slice(0, 1), err: "698_LEN_BAD_END" };
1098
+ return { ok: false, used: feCount + 1, frame: input.slice(0, feCount + 1), err: "698_LEN_BAD_END" };
1097
1099
  }
1098
1100
 
1099
1101
  // ------------------------ FCS 校验(CRC-16/X.25) ------------------------
@@ -1117,8 +1119,8 @@ module.exports = function (RED) {
1117
1119
  if (!fcsOK) {
1118
1120
  return {
1119
1121
  ok: false,
1120
- used: expectedEnd + 1,
1121
- frame: b.slice(0, expectedEnd + 1),
1122
+ used: feCount + expectedEnd + 1,
1123
+ frame: input.slice(0, feCount + expectedEnd + 1),
1122
1124
  fcs_ok: false,
1123
1125
  fcs_frame: fcs,
1124
1126
  fcs_calc_a: calcA,
@@ -1130,8 +1132,8 @@ module.exports = function (RED) {
1130
1132
  // FCS 通过:返回完整帧(含 0x68..0x16)
1131
1133
  return {
1132
1134
  ok: true,
1133
- used: expectedEnd + 1,
1134
- frame: b.slice(0, expectedEnd + 1),
1135
+ used: feCount + expectedEnd + 1,
1136
+ frame: input.slice(0, feCount + expectedEnd + 1),
1135
1137
  fcs_ok: true
1136
1138
  };
1137
1139
  }
@@ -1222,34 +1224,43 @@ module.exports = function (RED) {
1222
1224
  continue;
1223
1225
  }
1224
1226
  if (r.used) {
1225
- // 如果 parser 返回了“可消费”的错误帧(例如 698-LEN FCS_FAIL),
1226
- // 这里把诊断信息写入 frame._meta,供上层日志/排障使用。
1227
- if (r && typeof r === 'object') {
1227
+ // resync/drop1 类(通常 used 很小)不应上报 ERR_FRAME,否则会产生大量重复输出
1228
+ const used = r.used >>> 0;
1229
+ const frameBuf = r.frame ? Buffer.from(r.frame) : null;
1230
+ const frameLen = frameBuf ? frameBuf.length : 0;
1231
+
1232
+ // 判定是否为“仅推进同步点”的消费:
1233
+ // - used == 1 或 frameLen <= 1:典型 drop1
1234
+ // - 或 err 属于已知的 resync 类原因
1235
+ const errCode = (r && r.err) ? String(r.err) : "";
1236
+ const isResyncDrop = (used <= 1) || (frameLen <= 1) ||
1237
+ errCode === "DROP_7E_BADFRAME" ||
1238
+ errCode === "645_BAD_SHAPE_DROP1" ||
1239
+ errCode === "698_LEN_BAD_END" ||
1240
+ errCode === "698_LEN_TOO_LARGE" ||
1241
+ errCode === "645_SECOND_68_NOT_FOUND";
1242
+
1243
+ if (!isResyncDrop) {
1244
+ // 只有“闭合候选帧但校验/结构失败”的情况才上报 ERR_FRAME
1228
1245
  try {
1229
1246
  if (r.frame) {
1230
- // 统一把元数据挂到 frame 上,避免引用未定义变量导致运行期异常
1231
1247
  r.frame._meta = Object.assign({}, r.frame._meta || {}, {
1232
- // proto:用于上层区分到底是 645 / 698-hdlc / 698-len / ble 等
1233
1248
  proto: (r.fcs_ok === false) ? '698-len' : (r.proto || undefined),
1234
- // FCS 校验信息(仅当 698-LEN 校验失败时有意义)
1235
1249
  fcs_ok: (typeof r.fcs_ok === 'boolean') ? r.fcs_ok : undefined,
1236
1250
  fcs_frame: r.fcs_frame,
1237
1251
  fcs_calc_a: r.fcs_calc_a,
1238
1252
  fcs_calc_b: r.fcs_calc_b,
1239
- // err:更精确的错误原因
1240
1253
  err: r.err || "FRAME_INVALID"
1241
1254
  });
1242
1255
  }
1243
1256
  } catch (e) {
1244
- // ignore:不要因为诊断信息影响主流程
1257
+ // ignore
1245
1258
  }
1259
+ emitErr(r.frame, errCode || "FRAME_INVALID");
1246
1260
  }
1247
1261
 
1248
- // 错误帧统一走 emitErr,reason 以 r.err 为准
1249
- emitErr(r.frame, (r && r.err) ? r.err : "FRAME_INVALID");
1250
-
1251
- // 消费掉该段,防止 assembleBuf 卡死
1252
- assembleBuf = assembleBuf.slice(r.used);
1262
+ // 无论是否上报,都必须消费,防止 assembleBuf 卡死
1263
+ assembleBuf = assembleBuf.slice(used);
1253
1264
  continue;
1254
1265
  }
1255
1266
  break; // 需要更多数据