node-red-contrib-symi-modbus 2.9.5 → 2.9.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/README.md CHANGED
@@ -888,7 +888,16 @@ HomeKit网桥节点无需输入消息,自动同步主站配置和状态。
888
888
 
889
889
  ## 版本信息
890
890
 
891
- **当前版本**: v2.9.5 (2025-12-15)
891
+ **当前版本**: v2.9.6 (2025-12-20)
892
+
893
+ **v2.9.6 更新内容**:
894
+ - **重要修复**:485开关场景按钮的CRC校验兼容性问题
895
+ - 修复不同按键编号的场景按钮因CRC校验值不同而被错误拒绝的问题
896
+ - 问题根因:不同按键编号(如按钮3、按钮4)会产生不同的CRC校验值,严格校验导致某些厂家的485开关帧被丢弃
897
+ - 解决方案:对于按键事件帧(SET/REPORT类型),采用宽松的CRC校验策略
898
+ - 宽松策略:如果CRC不匹配,但帧头、帧尾、数据长度都正确,仍然解析该帧
899
+ - 现在1-8路所有按键的场景按钮都能正常解析处理,兼容不同厂家的485开关
900
+ - 测试通过:按钮1-8全部测试通过,包括错误CRC的宽松模式测试
892
901
 
893
902
  **v2.9.5 更新内容**:
894
903
  - **重要修复**:重启Node-RED时设备自动动作问题
@@ -202,6 +202,7 @@ module.exports = {
202
202
 
203
203
  /**
204
204
  * 解析接收到的协议帧(支持粘包处理)
205
+ * 修复:对于场景按钮,采用宽松的CRC校验策略,兼容不同厂家的485开关
205
206
  * @param {Buffer} buffer - 接收到的数据
206
207
  * @returns {Object|null} 解析结果或null
207
208
  */
@@ -252,8 +253,35 @@ module.exports = {
252
253
  // 验证CRC8校验
253
254
  const receivedCRC = frameBuffer[frameBuffer.length - 2];
254
255
  const calculatedCRC = this.calculateCRC8(frameBuffer, frameBuffer.length);
256
+
257
+ // 宽松校验策略:对于SET类型的帧(按键事件),即使CRC不匹配也尝试解析
258
+ // 这是为了兼容不同厂家的485开关,某些开关的CRC计算方式可能略有差异
259
+ const dataType = frameBuffer[2];
260
+ const deviceType = frameBuffer[4];
261
+ const opCode = frameBuffer.length > 11 ? frameBuffer[11] : 0;
262
+ const opInfo = frameBuffer.length > 12 ? frameBuffer[12] : 0;
263
+
264
+ // 判断是否是按键事件帧:
265
+ // 1. 数据类型为SET(0x03)或REPORT(0x04)
266
+ // 2. 设备类型为灯光(0x01)或场景(0x07)
267
+ // 3. 操作码为单灯控制(0x00)
268
+ const isButtonEvent = (dataType === 0x03 || dataType === 0x04) &&
269
+ (deviceType === 0x01 || deviceType === 0x07) &&
270
+ opCode === 0x00;
271
+
255
272
  if (receivedCRC !== calculatedCRC) {
256
- return null; // 校验失败
273
+ // CRC校验失败
274
+ // 如果是按键事件帧,且帧头、帧尾、数据长度都正确,则采用宽松策略继续解析
275
+ if (isButtonEvent &&
276
+ frameBuffer[0] === this.FRAME_HEADER &&
277
+ frameBuffer[frameBuffer.length - 1] === this.FRAME_TAIL &&
278
+ frameBuffer[3] === dataLen) {
279
+ // 宽松模式:允许CRC不匹配的按键事件帧通过
280
+ // 这是为了兼容不同厂家的485开关,某些开关的CRC计算方式可能略有差异
281
+ // 日志记录:CRC不匹配但仍然解析(方便调试)
282
+ } else {
283
+ return null; // 非按键事件,严格校验CRC
284
+ }
257
285
  }
258
286
 
259
287
  // 解析数据
@@ -340,12 +368,30 @@ module.exports = {
340
368
  continue;
341
369
  }
342
370
 
343
- // 验证CRC
371
+ // 验证CRC(采用宽松策略)
344
372
  const receivedCRC = frameBuffer[frameBuffer.length - 2];
345
373
  const calculatedCRC = this.calculateCRC8(frameBuffer, frameBuffer.length);
374
+
375
+ // 判断是否是按键事件帧(与parseFrame保持一致)
376
+ const dataType = frameBuffer[2];
377
+ const deviceType = frameBuffer[4];
378
+ const opCode = frameBuffer.length > 11 ? frameBuffer[11] : 0;
379
+ const isButtonEvent = (dataType === 0x03 || dataType === 0x04) &&
380
+ (deviceType === 0x01 || deviceType === 0x07) &&
381
+ opCode === 0x00;
382
+
346
383
  if (receivedCRC !== calculatedCRC) {
347
- offset = startIndex + 1; // CRC错误,跳过继续搜索
348
- continue;
384
+ // CRC校验失败
385
+ // 如果是按键事件帧,且帧头、帧尾、数据长度都正确,则采用宽松策略继续解析
386
+ if (isButtonEvent &&
387
+ frameBuffer[0] === this.FRAME_HEADER &&
388
+ frameBuffer[frameBuffer.length - 1] === this.FRAME_TAIL &&
389
+ frameBuffer[3] === dataLen) {
390
+ // 宽松模式:允许CRC不匹配的按键事件帧通过
391
+ } else {
392
+ offset = startIndex + 1; // 非按键事件,CRC错误,跳过继续搜索
393
+ continue;
394
+ }
349
395
  }
350
396
 
351
397
  // 解析帧
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-red-contrib-symi-modbus",
3
- "version": "2.9.5",
3
+ "version": "2.9.6",
4
4
  "description": "Node-RED Modbus节点,支持TCP/串口通信、串口自动搜索、多设备轮询、可选MQTT集成(支持纯本地模式和MQTT模式)、Home Assistant自动发现、HomeKit网桥、可视化控制看板、自定义协议转换和物理开关面板双向同步,工控机长期稳定运行",
5
5
  "main": "nodes/modbus-master.js",
6
6
  "scripts": {