node-red-contrib-symi-mesh 1.7.5 → 1.7.7

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
@@ -1522,7 +1522,16 @@ node-red-contrib-symi-mesh/
1522
1522
  - 内存安全,无调试日志,断电断网恢复后正常工作
1523
1523
  - 缓存队列处理,符合MQTT协议要求
1524
1524
 
1525
- ### v1.7.2 (2025-12-22)
1525
+ ### v1.7.7 (2026-01-05)
1526
+ - **RS485桥接节点逻辑优化**:
1527
+ - 修复自定义码模式下"反馈"按钮点击部署后依旧开启的问题
1528
+ - 完善 `oneditsave` 逻辑,确保反馈选项状态被持久化保存
1529
+ - **防循环优化**:优化 `loopKey` 生成逻辑,加入 `meshChannel` 字段,支持多通道设备独立防循环,解决多路开关干扰问题
1530
+ - **冷却时间调整**:将防死循环冷却时间从 500ms 延长至 800ms,提高复杂网络环境下的同步稳定性
1531
+ - **反馈逻辑细化**:严格执行"反馈"勾选逻辑,未勾选时禁止回环发送自定义码到总线
1532
+ - **调试增强**:增加自定义码匹配成功的详细日志(包含设备 MAC 和具体动作)
1533
+
1534
+ ### v1.7.5 (2025-12-24)
1526
1535
  - **RS485双向同步节点**:新增`symi-rs485-sync`独立节点实现两种不同RS485协议之间的双向同步
1527
1536
  - 支持中弘VRF网关协议(功能码0x31-0x34控制,0x50查询)
1528
1537
  - 支持SYMI空调面板Modbus协议
@@ -1610,8 +1619,8 @@ Copyright (c) 2025 SYMI 亖米
1610
1619
  ## 关于
1611
1620
 
1612
1621
  **作者**: SYMI 亖米
1613
- **版本**: 1.7.5
1622
+ **版本**: 1.7.6
1614
1623
  **协议**: 蓝牙MESH网关(初级版)串口协议V1.0
1615
- **最后更新**: 2025-12-24
1624
+ **最后更新**: 2026-01-05
1616
1625
  **仓库**: https://github.com/symi-daguo/node-red-contrib-symi-mesh
1617
1626
  **npm包**: https://www.npmjs.com/package/node-red-contrib-symi-mesh
@@ -662,7 +662,8 @@
662
662
  brand: $(this).find('.brand-select').val() || '',
663
663
  device: $(this).find('.device-select').val() || '',
664
664
  address: address,
665
- rs485Channel: parseInt($(this).find('.rs485-channel').val()) || 1
665
+ rs485Channel: parseInt($(this).find('.rs485-channel').val()) || 1,
666
+ feedback: $(this).find('.feedback-checkbox').is(':checked')
666
667
  };
667
668
  // 保存杜亚窗帘2字节地址
668
669
  if (m.brand === 'duya') {
@@ -964,7 +964,7 @@ module.exports = function(RED) {
964
964
  node.commandQueue = [];
965
965
  node.processing = false;
966
966
  node.syncLock = false;
967
- node.lastSyncTime = 0;
967
+ node.lastSyncTime = {};
968
968
  node.pendingVerify = false;
969
969
 
970
970
  // RS485连接信息
@@ -1597,7 +1597,7 @@ module.exports = function(RED) {
1597
1597
  }
1598
1598
  } finally {
1599
1599
  node.processing = false;
1600
- node.lastSyncTime = Date.now();
1600
+ node.lastQueueProcessTime = Date.now();
1601
1601
  }
1602
1602
  };
1603
1603
 
@@ -1709,12 +1709,12 @@ module.exports = function(RED) {
1709
1709
  const codes = mapping.customCodes;
1710
1710
 
1711
1711
  // 检查反馈选项:如果feedback=false,检查是否是RS485触发的状态变化
1712
- // 如果是RS485触发的(500ms内有同步记录),则跳过发送反馈码
1713
- const loopKey = `${mapping.meshMac}_${mapping.device}`;
1712
+ // 如果是RS485触发的(800ms内有同步记录),则跳过发送反馈码,防止死循环
1713
+ const loopKey = `${mapping.meshMac}_${mapping.device}_${mapping.meshChannel || 1}`;
1714
1714
  if (mapping.feedback === false) {
1715
- const lastSync = node.lastSyncTime ? node.lastSyncTime[loopKey] : 0;
1716
- if (lastSync && Date.now() - lastSync < 500) {
1717
- node.debug(`[Mesh->自定义] 反馈已禁用,跳过发送`);
1715
+ const lastSync = (node.lastSyncTime && typeof node.lastSyncTime === 'object') ? node.lastSyncTime[loopKey] : 0;
1716
+ if (lastSync && Date.now() - lastSync < 800) {
1717
+ node.debug(`[Mesh->自定义] 反馈已禁用,跳过回环发送`);
1718
1718
  return;
1719
1719
  }
1720
1720
  }
@@ -1753,7 +1753,7 @@ module.exports = function(RED) {
1753
1753
  const hexCode = switchValue ? codes.sendOn : codes.sendOff;
1754
1754
  if (hexCode) {
1755
1755
  // 记录发送时间用于防死循环
1756
- const loopKey = `${mapping.meshMac}_${mapping.device}`;
1756
+ const loopKey = `${mapping.meshMac}_${mapping.device}_${mapping.meshChannel || 1}`;
1757
1757
  if (!node.lastSyncTime) node.lastSyncTime = {};
1758
1758
  node.lastSyncTime[loopKey] = Date.now();
1759
1759
 
@@ -1811,7 +1811,7 @@ module.exports = function(RED) {
1811
1811
  node.lastSentTime[cacheKey] = now;
1812
1812
 
1813
1813
  // 记录发送时间用于防死循环
1814
- const loopKey = `${mapping.meshMac}_${mapping.device}`;
1814
+ const loopKey = `${mapping.meshMac}_${mapping.device}_${mapping.meshChannel || 1}`;
1815
1815
  if (!node.lastSyncTime) node.lastSyncTime = {};
1816
1816
  node.lastSyncTime[loopKey] = now;
1817
1817
 
@@ -1825,7 +1825,7 @@ module.exports = function(RED) {
1825
1825
  node.debug(`[自定义空调] 处理状态: ${JSON.stringify(state)}, codes存在: ${!!codes}`);
1826
1826
 
1827
1827
  // 记录发送时间用于防死循环
1828
- const loopKey = `${mapping.meshMac}_${mapping.device}`;
1828
+ const loopKey = `${mapping.meshMac}_${mapping.device}_${mapping.meshChannel || 1}`;
1829
1829
  if (!node.lastSyncTime) node.lastSyncTime = {};
1830
1830
 
1831
1831
  // 去重处理:记录已处理的命令类型
@@ -2813,14 +2813,14 @@ module.exports = function(RED) {
2813
2813
  if (matchedAction) {
2814
2814
  // 防死循环:检查是否刚刚从Mesh发送过来
2815
2815
  // 使用映射特定的时间戳,避免其他设备的同步影响
2816
- const loopKey = `${mapping.meshMac}_${mapping.device}`;
2816
+ const loopKey = `${mapping.meshMac}_${mapping.device}_${mapping.meshChannel || 1}`;
2817
2817
  if (!node.lastSyncTime) node.lastSyncTime = {};
2818
- if (node.lastSyncTime[loopKey] && Date.now() - node.lastSyncTime[loopKey] < 500) {
2818
+ if (node.lastSyncTime[loopKey] && Date.now() - node.lastSyncTime[loopKey] < 800) {
2819
2819
  node.debug(`[防循环] 忽略刚刚同步的帧: ${hexFormatted}`);
2820
2820
  return;
2821
2821
  }
2822
2822
 
2823
- node.log(`[自定义码匹配] ${mapping.device}: ${JSON.stringify(matchedAction)}, 帧: ${hexFormatted}`);
2823
+ node.log(`[自定义码匹配成功] 设备:${mapping.device}, MAC:${mapping.meshMac}, 动作:${JSON.stringify(matchedAction)}`);
2824
2824
 
2825
2825
  // 输出调试信息到节点输出端口
2826
2826
  node.send({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-red-contrib-symi-mesh",
3
- "version": "1.7.5",
3
+ "version": "1.7.7",
4
4
  "description": "Node-RED节点集合,用于通过TCP/串口连接Symi蓝牙Mesh网关,支持Home Assistant MQTT Discovery自动发现和云端数据同步",
5
5
  "main": "nodes/symi-gateway.js",
6
6
  "scripts": {