node-red-contrib-symi-modbus 2.10.19 → 2.10.20
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 +10 -36
- package/nodes/mesh-protocol.js +21 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -487,47 +487,21 @@ msg.payload = 1; // 或 0
|
|
|
487
487
|
|
|
488
488
|
### 更新日志
|
|
489
489
|
|
|
490
|
-
#### v2.10.
|
|
490
|
+
#### v2.10.20 (2026-06-30)
|
|
491
491
|
|
|
492
|
-
- **[
|
|
493
|
-
- **[工程]**
|
|
492
|
+
- **[打包]** 修复 npm 发布包误含 `.codebase-memory/` 开发索引的问题,包体积约 158KB;规范 `.npmignore` / `.gitignore`,开发缓存目录不进入发布包。
|
|
493
|
+
- **[工程]** 提取 `lib/lru-map.js`、`lib/slave-switch-cache.js`,全局 LRU 缓存与 Mesh LED 定时器上限(5000);新增 `lib/http-admin-utils.js`,14 个 HTTP Admin 路由统一 read/write 权限校验。
|
|
494
494
|
- **[工程]** `modbus-master` 串口列表 API 复用 `lib/serial-utils`,消除重复实现。
|
|
495
495
|
- **[测试]** 新增 `mesh-protocol`、`lightweight-protocol` 协议帧解析单元测试(`npm test`)。
|
|
496
|
+
- **[修复]** 修正 `isMeshFrame` 请求帧长度判定,与 `parseAllFrames` 保持一致。
|
|
497
|
+
- **[Mesh 窗帘]** 按《蓝牙MESH网关(初级版)串口协议V1.0》修正 0x53 0x80 0x06 状态帧解析;窗帘动作/位置分离存储;开停关停与打开-关闭逻辑完善;Clowire 场景按键统一处理。
|
|
498
|
+
- **[Mesh 透传]** 合并重复 close 监听;热路径日志降为 debug;杜亚电机状态双向同步优化;实体持久化增强。
|
|
496
499
|
|
|
497
|
-
#### v2.10.
|
|
500
|
+
#### 更早版本 (v2.10.14 ~ v2.10.17)
|
|
498
501
|
|
|
499
|
-
-
|
|
500
|
-
-
|
|
501
|
-
|
|
502
|
-
#### v2.10.17 (2026-02-07)
|
|
503
|
-
|
|
504
|
-
- **Mesh 窗帘协议兼容性**:按照《蓝牙MESH网关(初级版)串口协议V1.0》修正 0x53 0x80 0x06 节点状态帧解析逻辑,明确区分事件类型 RESULT_EVENT_NODE_STATUS(0x06) 与 `VD_MSG_TYPE_CURT_RUN_STATUS(0x05)` / `VD_MSG_TYPE_CURT_RUN_PER_POS(0x06)`,不再误把 `subOp` 当成窗帘 msg_type 使用,严格从数据区解析 `[msg_type][param]`。
|
|
505
|
-
- **窗帘状态与端点记忆**:窗帘动作(0x05) 与位置(0x06) 在内部状态中分离存储,位置只由真正的 0x06 位置帧(含杜亚485位置反馈)更新;仅当位置为 0%/100% 且确认为当前运动方向的目标端点时才标记到达端点并更新 `lastAction/lastDirection`,避免 0x05 帧或“打开中收到0% / 关闭中收到100%”被误判为端点。
|
|
506
|
-
- **开停关停 / 打开-关闭 行为**:
|
|
507
|
-
- 引入 `isMoving` 统一表示“运动过程”,只要执行过开/关且未到端点(0%/100%),物理按键再次点击必发送暂停(3),不会直接翻转方向。
|
|
508
|
-
- 停在 0%/100% 后会进行“端点收敛”:端点上报后不会再多走一次暂停,下一次按键一定是「关着→打开 / 开着→关闭」,到顶/到底后再次点击必然反向(关/开)。
|
|
509
|
-
- 修正 cycle 模式下起点 0%/100% 刚起步时第二下按键误判为翻转的问题;到端点仅在 `isMoving=false && reachedEndpoint=true && endpointPosition=0/100` 时生效,并移除“>50% / <=50% 位置兜底”,中途暂停后的方向完全由 `lastDirection/lastAction` 决定,保证绝对的「开-停-关-停」节奏。
|
|
510
|
-
- **Mesh 透传与日志**:合并重复 close 监听、Mesh 透传热路径日志改为 debug,减少生产环境刷屏;仍兼容 Mesh 动作反馈(0x05) 与位置反馈(0x06),但不再因为偶发“停止/运动中”状态抖动误判为已停止,避免运动过程误触发开/关。
|
|
511
|
-
- **Clowire 场景按键**:Clowire 面板按键在从站开关 / 继电器输出 / Mesh 透传中统一按“场景按钮”处理,每次物理按下都会触发一次事件;运动中的窗帘再次按下必然发送暂停,不会误翻转方向。
|
|
512
|
-
|
|
513
|
-
#### v2.10.16 (2026-02-06)
|
|
514
|
-
|
|
515
|
-
- **按键记忆**:同一帧内若同时上报位置与动作(如 position=100 + action=打开中),以位置为准到端点即按「已停止」记忆,避免被动作覆盖导致下次按键误判。
|
|
516
|
-
- **开停关停 / 打开关闭**:状态记忆更稳,到顶/到底后再次按键必为关/开;开停关停模式下运动中点击会正确发送暂停(3)。
|
|
517
|
-
- **场景按键**:场景模式下不再因 value=false 忽略一次按下,每次物理按键都会触发控制,解决「多按一次」才生效的问题。
|
|
518
|
-
|
|
519
|
-
#### v2.10.15 (2026-02-05)
|
|
520
|
-
|
|
521
|
-
- **Mesh 窗帘控制**:修复重启后实体消失、到头不记忆位置、再次点击误发暂停等问题;新增「打开/关闭」单键循环逻辑;「开-停-关-停」循环逻辑完整可用。
|
|
522
|
-
- **配置界面**:控制逻辑选项正确保存与显示,选择「打开/关闭」后不再被覆盖为「循环」。
|
|
523
|
-
- **Mesh 透传与杜亚**:与杜亚电机状态双向同步优化;窗帘到端点(0%/100%)状态正确同步到按键,点击时能正确执行开/关。
|
|
524
|
-
- **稳定性**:实体持久化与存储校验增强,兼容更多固件版本的窗帘协议。
|
|
525
|
-
|
|
526
|
-
#### v2.10.14 (2026-02-03)
|
|
527
|
-
|
|
528
|
-
- 多种 Modbus 协议支持(Telnet ASCII、RTU over TCP、TCP、串口);智能轮询暂停,面板事件响应更及时。
|
|
529
|
-
- Home Assistant MQTT Discovery 与实体唯一 ID;串口热插拔与 TCP 故障自动恢复。
|
|
530
|
-
- 开关/场景按钮双模式,LED 反馈同步。
|
|
502
|
+
- 多种 Modbus 协议(Telnet ASCII、RTU over TCP、TCP、串口)与智能轮询暂停。
|
|
503
|
+
- Home Assistant MQTT Discovery、HomeKit 网桥、控制看板、Mesh 透传节点、继电器输出。
|
|
504
|
+
- 按键记忆与端点收敛、场景按键每次按下均触发、LED 反馈同步、串口热插拔与 TCP 自动恢复。
|
|
531
505
|
|
|
532
506
|
## 许可证
|
|
533
507
|
MIT License
|
package/nodes/mesh-protocol.js
CHANGED
|
@@ -512,18 +512,31 @@ module.exports = function(_RED) {
|
|
|
512
512
|
* @returns {boolean} 是否有效
|
|
513
513
|
*/
|
|
514
514
|
function isMeshFrame(buffer) {
|
|
515
|
-
if (!buffer || buffer.length <
|
|
515
|
+
if (!buffer || buffer.length < 4) {return false;}
|
|
516
516
|
if (buffer[0] !== PROTOCOL.HEADER) {return false;}
|
|
517
|
-
|
|
518
|
-
const
|
|
519
|
-
|
|
520
|
-
|
|
517
|
+
|
|
518
|
+
const opCode = buffer[1];
|
|
519
|
+
let dataLenIndex;
|
|
520
|
+
let overhead;
|
|
521
|
+
|
|
522
|
+
if (opCode >= 0x80) {
|
|
523
|
+
dataLenIndex = 3;
|
|
524
|
+
overhead = 5;
|
|
525
|
+
} else {
|
|
526
|
+
dataLenIndex = 2;
|
|
527
|
+
overhead = 4;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
if (dataLenIndex >= buffer.length) {return false;}
|
|
531
|
+
|
|
532
|
+
const dataLen = buffer[dataLenIndex];
|
|
533
|
+
const totalLen = overhead + dataLen;
|
|
534
|
+
|
|
521
535
|
if (buffer.length !== totalLen) {return false;}
|
|
522
|
-
|
|
523
|
-
// 校验和验证
|
|
536
|
+
|
|
524
537
|
const receivedChecksum = buffer[buffer.length - 1];
|
|
525
538
|
const calculatedChecksum = calculateChecksum(buffer.slice(0, buffer.length - 1));
|
|
526
|
-
|
|
539
|
+
|
|
527
540
|
return receivedChecksum === calculatedChecksum;
|
|
528
541
|
}
|
|
529
542
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-red-contrib-symi-modbus",
|
|
3
|
-
"version": "2.10.
|
|
3
|
+
"version": "2.10.20",
|
|
4
4
|
"description": "Node-RED Modbus节点,支持TCP/串口通信、多主站独立运行、串口自动搜索、多设备轮询、可选MQTT集成(支持纯本地模式和MQTT模式)、Home Assistant自动发现、HomeKit网桥、可视化控制看板、自定义协议转换和物理开关面板双向同步(支持Symi/Clowire品牌),工控机长期稳定运行",
|
|
5
5
|
"main": "nodes/modbus-master.js",
|
|
6
6
|
"scripts": {
|