node-red-contrib-symi-modbus 2.6.8 → 2.7.2

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
@@ -18,6 +18,9 @@ Node-RED的Modbus继电器控制节点,支持TCP/串口通信和MQTT集成,
18
18
  - Telnet ASCII(推荐用于TCP转RS485网关)
19
19
  - **Symi开关集成**:自动识别并处理Symi私有协议按键事件,实现开关面板与继电器的双向同步
20
20
  - **HomeKit网桥**:一键桥接到Apple HomeKit,支持Siri语音控制,自动同步主站配置,名称可自定义
21
+ - **智能写入队列**:所有写入操作串行执行,支持HomeKit群控160个继电器同时动作,流畅无卡顿
22
+ - **可视化控制看板**:实时显示和控制所有继电器状态,美观易用,适合现场调试和日常监控
23
+ - **自定义协议转换**:支持非标准485协议设备,窗帘循环控制,配置界面可测试发送
21
24
  - **多设备轮询**:支持最多10台Modbus从站设备,每台32路继电器
22
25
  - **智能轮询机制**:从站上报时自动暂停轮询,优先处理数据,避免冲突
23
26
  - **稳定可靠**:完整的内存管理、错误处理、断线重连,适合7x24小时长期运行
@@ -183,6 +186,35 @@ node-red-restart
183
186
  - 支持Siri语音控制:"嘿Siri,打开客厅灯"
184
187
  - 支持HomeKit自动化和场景
185
188
  - 配置会自动保存,重启后无需重新配对
189
+ - **群控性能**:支持同时控制多个继电器(如创建编组),智能队列机制确保流畅无卡顿
190
+
191
+ **群控说明**(客户友好模式):
192
+
193
+ 本节点专为智能家居群控场景优化,支持以下高性能操作:
194
+
195
+ 1. **HomeKit编组群控**:
196
+ - 在HomeKit中创建房间或编组,可同时控制多个继电器
197
+ - 例如:创建"客厅"编组,包含10个灯光开关,一键全开/全关
198
+ - 智能队列机制确保所有继电器按序快速执行,无超时警告
199
+ - 10个继电器同时动作仅需约200ms(20ms间隔×10)
200
+
201
+ 2. **场景联动**:
202
+ - 支持HomeKit场景(如"回家模式"、"离家模式")
203
+ - 场景可包含多个继电器动作,自动串行执行
204
+ - 前16个线圈(继电器)可同时动作,后16个线圈(场景)按需触发
205
+
206
+ 3. **性能保证**:
207
+ - 最大支持10台继电器(每台32路),共320个线圈
208
+ - 前160个线圈(10台×16路)可用于继电器控制,支持群控
209
+ - 后160个线圈(10台×16路)可用于场景触发,一般不会全部同时动作
210
+ - 智能写入队列确保所有操作串行执行,避免总线冲突
211
+ - 长期稳定运行,反复控制不会造成内存增加、卡顿或死机
212
+
213
+ 4. **技术细节**:
214
+ - 写入队列间隔:20ms(确保总线稳定)
215
+ - 轮询恢复时间:20ms(快速响应)
216
+ - 锁等待超时:100ms(快速检测异常)
217
+ - 队列自动处理,无需手动干预
186
218
 
187
219
  ## 核心特性说明
188
220
 
@@ -650,6 +682,102 @@ HomeKit网桥节点无需输入消息,自动同步主站配置和状态。
650
682
  - 配置信息持久化存储在~/.node-red/homekit-persist目录
651
683
  - 重启Node-RED后自动恢复配对状态,无需重新配对
652
684
 
685
+ ### 控制看板节点(客户友好模式)
686
+
687
+ 控制看板节点提供可视化界面,实时显示和控制所有从站的继电器状态,适合现场调试和日常监控。
688
+
689
+ **配置参数**:
690
+ - **节点名称**:控制看板的显示名称(默认:Modbus控制看板)
691
+ - **主站节点**:选择要监控的Modbus主站节点(必填)
692
+
693
+ **功能特性**:
694
+ - **实时状态显示**:在配置界面中显示所有从站和线圈的实时状态
695
+ - **一键控制**:点击按钮即可控制继电器开关,无需部署流程
696
+ - **美观布局**:网格布局,按从站分组显示,一目了然
697
+ - **名称同步**:自动同步HomeKit网桥配置的继电器名称
698
+ - **快速响应**:状态实时更新(500ms轮询),响应迅速
699
+ - **零开销**:不参与实际Modbus通信,不影响主站性能
700
+
701
+ **使用步骤**:
702
+ 1. 在Node-RED中添加控制看板节点
703
+ 2. 选择已配置的Modbus主站节点
704
+ 3. 双击节点打开配置界面,即可看到所有继电器状态
705
+ 4. 点击按钮即可控制继电器开关(绿色=ON,红色=OFF)
706
+ 5. 部署流程后,节点会显示"监控中"状态
707
+
708
+ **使用场景**:
709
+ - **现场调试**:快速测试继电器是否正常工作
710
+ - **日常监控**:实时查看所有继电器状态
711
+ - **批量控制**:快速控制多个继电器
712
+ - **客户演示**:美观的界面,适合向客户展示系统功能
713
+
714
+ **技术细节**:
715
+ - 使用HTTP API与主站通信,通过内部事件发送控制命令
716
+ - 状态缓存机制,减少网络请求
717
+ - 仅在配置界面打开时才轮询状态,关闭后自动停止
718
+ - 与HomeKit网桥共享继电器名称配置,保持一致性
719
+
720
+ **注意事项**:
721
+ - 确保主站节点已正确配置并运行
722
+ - 控制看板只在配置界面打开时才轮询状态
723
+ - 继电器名称需在HomeKit网桥节点中配置
724
+ - 本节点不参与实际Modbus通信,不会增加主站负担
725
+
726
+ ### 自定义协议节点
727
+
728
+ 自定义协议节点用于控制非标准Modbus协议的485设备,支持开关、窗帘、其他三种设备类型。
729
+
730
+ **配置参数**:
731
+ - **节点名称**:自定义协议节点的显示名称(默认:自定义协议)
732
+ - **设备类型**:选择设备类型(开关/窗帘/其他)
733
+ - **串口配置**:选择串口配置节点(必填)
734
+ - **打开指令**:16进制打开指令(最多48字节)
735
+ - **关闭指令**:16进制关闭指令(最多48字节)
736
+ - **暂停指令**:16进制暂停指令(仅窗帘模式,最多48字节)
737
+
738
+ **设备类型说明**:
739
+ - **开关模式**:接收`true`发送打开指令,接收`false`发送关闭指令
740
+ - **窗帘模式**:`true/false`交替触发,循环发送打开→关闭→暂停→打开...
741
+ - **其他模式**:与开关模式相同,接收`true/false`发送对应指令
742
+
743
+ **功能特性**:
744
+ - **16进制配置**:支持空格分隔的16进制码,自动格式化为大写
745
+ - **字节限制**:每个指令最多48字节,超出自动截断
746
+ - **测试功能**:配置界面可直接点击"测试"按钮发送指令到串口总线
747
+ - **持久化保存**:配置自动保存,重启后自动恢复
748
+ - **连线方式**:从站开关 → 自定义协议 → debug节点
749
+
750
+ **使用示例**:
751
+ 1. 在Node-RED中添加自定义协议节点
752
+ 2. 选择设备类型(例如:窗帘)
753
+ 3. 选择串口配置节点
754
+ 4. 输入16进制指令(例如:`01 05 00 00 FF 00 8C 3A`)
755
+ 5. 点击"测试"按钮验证指令是否正确
756
+ 6. 连线:从站开关 → 自定义协议 → debug节点
757
+ 7. 部署流程,触发从站开关即可发送自定义指令
758
+
759
+ **窗帘模式示例**:
760
+ ```
761
+ 第1次收到true → 发送"打开"指令(例如:01 05 00 00 FF 00 8C 3A)
762
+ 第2次收到false → 发送"关闭"指令(例如:01 05 00 00 00 00 CD CA)
763
+ 第3次收到true → 发送"暂停"指令(例如:01 05 00 01 FF 00 DD FA)
764
+ 第4次收到false → 循环回到"打开"指令
765
+ ```
766
+
767
+ **技术细节**:
768
+ - 输入消息:`msg.payload = true/false`(从从站开关节点接收)
769
+ - 输出消息:`msg.payload = Buffer`(16进制数据,可连线到debug节点)
770
+ - 16进制字符串自动转换为Buffer格式
771
+ - 支持空格、大小写混合输入,自动格式化
772
+ - 窗帘模式内部维护状态索引,自动循环
773
+
774
+ **注意事项**:
775
+ - 16进制指令最多48字节
776
+ - 窗帘模式需要配置三个指令(打开、关闭、暂停)
777
+ - 测试功能需要先选择串口配置且串口已打开
778
+ - 输出需要连线到debug节点才能发送到串口
779
+ - 非标准协议设备数量不多时推荐使用连线方式
780
+
653
781
  ## 输出消息格式
654
782
 
655
783
  ### 主站节点
@@ -710,7 +838,7 @@ HomeKit网桥节点无需输入消息,自动同步主站配置和状态。
710
838
 
711
839
  ## 项目信息
712
840
 
713
- **版本**: v2.6.8
841
+ **版本**: v2.7.2
714
842
 
715
843
  **核心功能**:
716
844
  - 支持多种Modbus协议(Telnet ASCII、RTU over TCP、Modbus TCP、Modbus RTU串口)
@@ -718,6 +846,9 @@ HomeKit网桥节点无需输入消息,自动同步主站配置和状态。
718
846
  - 🔥 **双模式支持**(本地模式和MQTT模式可选切换,断网也能稳定运行)
719
847
  - 🔥 **免连线通信**(主站和从站通过内部事件通信,无需连线)
720
848
  - 🔥 **HomeKit网桥**(一键桥接到Apple HomeKit,支持Siri语音控制)
849
+ - 🔥 **智能写入队列**(所有写入操作串行执行,避免锁竞争,支持HomeKit群控)
850
+ - 🔥 **可视化控制看板**(实时显示和控制所有继电器状态,美观易用)
851
+ - 🔥 **自定义协议转换**(支持非标准485协议设备,窗帘循环控制)
721
852
  - MQTT集成(可选启用,Home Assistant自动发现)
722
853
  - 物理开关面板双向同步(支持开关模式和场景模式)
723
854
  - 长期稳定运行(内存管理、智能重连、异步处理)
@@ -726,59 +857,25 @@ HomeKit网桥节点无需输入消息,自动同步主站配置和状态。
726
857
  - Node.js: >=14.0.0
727
858
  - Node-RED: >=2.0.0
728
859
 
729
- **最新更新(v2.6.8)**:
730
- - **🔥 新增HomeKit网桥节点**:
731
- - 一键桥接Modbus继电器到Apple HomeKit
732
- - 自动同步主站配置的所有从站和继电器
733
- - 支持在Node-RED中配置继电器友好名称
734
- - 双向同步:HomeKit控制继电器,继电器状态实时同步到HomeKit
735
- - 支持Siri语音控制和HomeKit自动化场景
736
- - 持久化存储配对信息,重启后自动恢复
737
- - 线圈0-15显示为开关,线圈16-31显示为插座(避免误触发)
738
-
739
- **v2.6.7更新**:
740
- - **🔥 修复LED反馈功能**:
741
- - 主站轮询检测到状态变化时自动广播事件
742
- - 从站开关节点监听状态变化并发送LED反馈到物理面板
743
- - 支持开关模式(SET协议)和场景模式(REPORT协议)
744
- - LED反馈队列间隔20ms,避免总线拥堵
745
- - **🔥 TCP连接稳定性优化**:
746
- - 禁用TCP超时(永久连接),避免无数据时超时断开
747
- - Keep-Alive间隔从30秒优化到10秒
748
- - 适应客户长期不在家、总线无数据的场景
749
- - **日志优化**:
750
- - 移除频繁的轮询日志("轮询持续运行中"、"正在轮询从站X")
751
- - 轮询永久稳定运行,无需频繁确认
752
- - 减少日志输出,降低硬盘占用
753
-
754
- **v2.6.6更新**:
755
- - **🔥 彻底解决MQTT日志刷屏问题**:
756
- - 局域网IP检测优化:配置192.168.x.x等IP后不再尝试fallback地址
757
- - 高频MQTT日志改为debug级别:broker候选、认证、重连等
758
- - 默认不输出到日志文件和调试窗口
759
- - 配置局域网IP后立即连接,不产生多余日志
760
- - **日志输出优化**:
761
- - 连接成功/失败:仍使用log(重要信息)
762
- - 重连尝试、fallback地址、认证信息:改为debug(调试信息)
763
- - 仅启用debug模式时才在调试窗口显示
764
- - 彻底解决日志刷屏和硬盘占用问题
765
-
766
- **v2.6.5更新**:
767
- - **🔥 修复MQTT报错问题**:从站开关节点新增"启用MQTT"勾选框
768
- - 默认不启用MQTT,不会尝试连接
769
- - 本地模式和MQTT模式自由切换
770
-
771
- **v2.6.4更新**:
772
- - **🔥 日志优化**:大幅减少日志输出,保证长期稳定运行
773
- - 高频操作日志改为debug级别
774
- - 默认不输出到日志文件
775
- - 完善的内存清理机制
776
-
777
- **v2.6.3更新**:
778
- - **🔥 MQTT可选配置**:完全兼容无MQTT环境
779
- - 本地模式:纯串口通信
780
- - MQTT模式:可选接入HA
781
- - 智能切换和状态显示
860
+ **最新更新(v2.7.2)**:
861
+ - **🔥 新增自定义协议节点**:
862
+ - 支持控制非标准Modbus协议的485设备
863
+ - 三种设备类型:开关(打开/关闭)、窗帘(打开/关闭/暂停循环)、其他(打开/关闭)
864
+ - 窗帘模式:true/false交替触发,循环发送打开→关闭→暂停→打开...
865
+ - 16进制指令配置,最多48字节,自动格式化
866
+ - 配置界面可直接测试发送指令到串口总线
867
+ - 配置持久化保存,重启后自动恢复
868
+ - 连线方式:从站开关 → 自定义协议 → debug节点
869
+
870
+ **历史更新**:
871
+ - **v2.7.1**:新增可视化控制看板节点,实时显示和控制所有继电器状态
872
+ - **v2.7.0**:智能写入队列机制,解决HomeKit群控锁竞争问题,支持160个继电器同时群控
873
+ - **v2.6.8**:新增HomeKit网桥节点,一键桥接到Apple HomeKit,支持Siri语音控制
874
+ - **v2.6.7**:修复LED反馈功能,TCP连接稳定性优化,日志优化
875
+ - **v2.6.6**:解决MQTT日志刷屏问题,局域网IP检测优化
876
+ - **v2.6.5**:修复MQTT报错问题,新增"启用MQTT"勾选框
877
+ - **v2.6.4**:日志优化,大幅减少日志输出
878
+ - **v2.6.3**:MQTT可选配置,完全兼容无MQTT环境
782
879
 
783
880
  **性能优化**:
784
881
  - 轮询间隔优化:修复间隔计算逻辑,确保每个从站使用正确的轮询间隔
@@ -787,6 +884,7 @@ HomeKit网桥节点无需输入消息,自动同步主站配置和状态。
787
884
  - 减少调试日志输出,降低CPU占用
788
885
  - 互斥锁机制确保读写操作不冲突
789
886
  - 共享连接配置节点,避免串口资源冲突
887
+ - 写入队列20ms间隔,快速响应,总线稳定
790
888
 
791
889
  **许可证**: MIT License
792
890
 
@@ -801,11 +899,17 @@ HomeKit网桥节点无需输入消息,自动同步主站配置和状态。
801
899
  ### 节点与分类(Palette)
802
900
 
803
901
  - 侧边栏分类名:`SYMI-MODBUS`
804
- - 包含节点:`modbus-master`(主站)、`modbus-slave-switch`(从站开关)、`modbus-debug`(调试)
902
+ - 包含节点:
903
+ - `modbus-master`(主站)
904
+ - `modbus-slave-switch`(从站开关)
905
+ - `modbus-dashboard`(控制看板)
906
+ - `homekit-bridge`(HomeKit网桥)
907
+ - `custom-protocol`(自定义协议)
908
+ - `modbus-debug`(调试)
805
909
  - 如果未显示该分类或节点:
806
910
  - 刷新浏览器缓存(Shift+刷新)
807
911
  - 重启 Node-RED(如:`node-red-restart` 或系统服务方式)
808
- - 在“节点管理(Manage Palette)”确认安装版本为 `v2.6.6`
912
+ - 在“节点管理(Manage Palette)”确认安装版本为最新版
809
913
 
810
914
  ### 调试节点(modbus-debug)使用要点
811
915
 
@@ -1063,7 +1167,7 @@ msg.payload = 1; // 或 0
1063
1167
 
1064
1168
  ## 项目信息
1065
1169
 
1066
- **版本**: v2.6.8
1170
+ **版本**: v2.7.2
1067
1171
 
1068
1172
  **核心功能**:
1069
1173
  - 支持多种Modbus协议(Telnet ASCII、RTU over TCP、Modbus TCP、Modbus RTU串口)
@@ -1073,6 +1177,9 @@ msg.payload = 1; // 或 0
1073
1177
  - 🔥 **双模式支持**(本地模式和MQTT模式可选切换,断网也能稳定运行)
1074
1178
  - 🔥 **免连线通信**(主站和从站通过内部事件通信,无需连线,支持本地模式和MQTT模式)
1075
1179
  - 🔥 **HomeKit网桥**(一键桥接到Apple HomeKit,支持Siri语音控制,名称可自定义)
1180
+ - 🔥 **智能写入队列**(所有写入操作串行执行,避免锁竞争,支持HomeKit群控)
1181
+ - 🔥 **可视化控制看板**(实时显示和控制所有继电器状态,美观易用,客户友好)
1182
+ - 🔥 **自定义协议转换**(支持非标准485协议设备,窗帘循环控制,配置界面可测试)
1076
1183
  - MQTT集成(可选启用,Home Assistant自动发现,实体唯一性保证,QoS=0高性能发布)
1077
1184
  - 物理开关面板双向同步(亖米协议支持,LED反馈同步,支持开关模式和场景模式)
1078
1185
  - 共享连接架构(多个从站开关节点共享同一个串口/TCP连接,支持500+节点)
@@ -0,0 +1,276 @@
1
+ <script type="text/javascript">
2
+ RED.nodes.registerType('custom-protocol', {
3
+ category: 'SYMI-MODBUS',
4
+ color: '#FF9800',
5
+ defaults: {
6
+ name: {value: "自定义协议"},
7
+ deviceType: {value: "switch", required: true},
8
+ serialConfig: {value: "", type: "serial-port-config", required: true},
9
+ openCmd: {value: ""},
10
+ closeCmd: {value: ""},
11
+ pauseCmd: {value: ""}
12
+ },
13
+ inputs: 1,
14
+ outputs: 1,
15
+ icon: "font-awesome/fa-code",
16
+ label: function() {
17
+ var typeNames = {
18
+ 'switch': '开关',
19
+ 'curtain': '窗帘',
20
+ 'other': '其他'
21
+ };
22
+ var typeName = typeNames[this.deviceType] || '自定义';
23
+ return this.name || (typeName + "协议");
24
+ },
25
+ oneditprepare: function() {
26
+ var node = this;
27
+
28
+ // 设备类型切换
29
+ $("#node-input-deviceType").on("change", function() {
30
+ var deviceType = $(this).val();
31
+ if (deviceType === "curtain") {
32
+ $("#pause-cmd-row").show();
33
+ } else {
34
+ $("#pause-cmd-row").hide();
35
+ }
36
+ });
37
+
38
+ // 初始化显示
39
+ if (node.deviceType === "curtain") {
40
+ $("#pause-cmd-row").show();
41
+ } else {
42
+ $("#pause-cmd-row").hide();
43
+ }
44
+
45
+ // 16进制输入验证和格式化
46
+ function validateHexInput(input) {
47
+ var value = $(input).val().trim();
48
+ // 移除所有非16进制字符
49
+ value = value.replace(/[^0-9A-Fa-f\s]/g, '');
50
+ // 自动添加空格分隔
51
+ value = value.replace(/\s+/g, '').match(/.{1,2}/g);
52
+ if (value) {
53
+ value = value.join(' ').toUpperCase();
54
+ // 限制48字节
55
+ var bytes = value.split(' ');
56
+ if (bytes.length > 48) {
57
+ bytes = bytes.slice(0, 48);
58
+ value = bytes.join(' ');
59
+ RED.notify('指令长度已限制为48字节', 'warning');
60
+ }
61
+ } else {
62
+ value = '';
63
+ }
64
+ $(input).val(value);
65
+ return value;
66
+ }
67
+
68
+ // 绑定输入验证
69
+ $("#node-input-openCmd, #node-input-closeCmd, #node-input-pauseCmd").on("blur", function() {
70
+ validateHexInput(this);
71
+ });
72
+
73
+ // 测试按钮功能
74
+ function sendTestCommand(hexString, cmdName) {
75
+ if (!hexString || hexString.trim() === '') {
76
+ RED.notify('请先输入16进制指令', 'warning');
77
+ return;
78
+ }
79
+
80
+ var serialConfig = $("#node-input-serialConfig").val();
81
+ if (!serialConfig) {
82
+ RED.notify('请先选择串口配置', 'warning');
83
+ return;
84
+ }
85
+
86
+ // 发送测试命令
87
+ $.ajax({
88
+ url: '/custom-protocol/test',
89
+ method: 'POST',
90
+ contentType: 'application/json',
91
+ data: JSON.stringify({
92
+ serialConfig: serialConfig,
93
+ hexString: hexString,
94
+ cmdName: cmdName
95
+ }),
96
+ success: function(result) {
97
+ if (result.success) {
98
+ RED.notify('✓ ' + cmdName + '指令已发送: ' + hexString, 'success');
99
+ } else {
100
+ RED.notify('✗ 发送失败: ' + result.error, 'error');
101
+ }
102
+ },
103
+ error: function(err) {
104
+ RED.notify('✗ 发送失败: ' + err.statusText, 'error');
105
+ }
106
+ });
107
+ }
108
+
109
+ // 绑定测试按钮
110
+ $("#btn-test-open").on("click", function() {
111
+ var hexString = validateHexInput("#node-input-openCmd");
112
+ sendTestCommand(hexString, '打开');
113
+ });
114
+
115
+ $("#btn-test-close").on("click", function() {
116
+ var hexString = validateHexInput("#node-input-closeCmd");
117
+ sendTestCommand(hexString, '关闭');
118
+ });
119
+
120
+ $("#btn-test-pause").on("click", function() {
121
+ var hexString = validateHexInput("#node-input-pauseCmd");
122
+ sendTestCommand(hexString, '暂停');
123
+ });
124
+ },
125
+ oneditsave: function() {
126
+ // 保存前验证和格式化
127
+ validateHexInput("#node-input-openCmd");
128
+ validateHexInput("#node-input-closeCmd");
129
+ if (this.deviceType === "curtain") {
130
+ validateHexInput("#node-input-pauseCmd");
131
+ }
132
+ }
133
+ });
134
+
135
+ // 辅助函数
136
+ function validateHexInput(selector) {
137
+ var input = $(selector);
138
+ var value = input.val().trim();
139
+ value = value.replace(/[^0-9A-Fa-f\s]/g, '');
140
+ value = value.replace(/\s+/g, '').match(/.{1,2}/g);
141
+ if (value) {
142
+ value = value.join(' ').toUpperCase();
143
+ var bytes = value.split(' ');
144
+ if (bytes.length > 48) {
145
+ bytes = bytes.slice(0, 48);
146
+ value = bytes.join(' ');
147
+ }
148
+ } else {
149
+ value = '';
150
+ }
151
+ input.val(value);
152
+ return value;
153
+ }
154
+ </script>
155
+
156
+ <script type="text/html" data-template-name="custom-protocol">
157
+ <div class="form-row">
158
+ <label for="node-input-name"><i class="fa fa-tag"></i> 节点名称</label>
159
+ <input type="text" id="node-input-name" placeholder="自定义协议">
160
+ </div>
161
+
162
+ <div class="form-row">
163
+ <label for="node-input-deviceType"><i class="fa fa-cog"></i> 设备类型</label>
164
+ <select id="node-input-deviceType" style="width: 70%;">
165
+ <option value="switch">开关(打开/关闭)</option>
166
+ <option value="curtain">窗帘(打开/关闭/暂停循环)</option>
167
+ <option value="other">其他(打开/关闭)</option>
168
+ </select>
169
+ </div>
170
+
171
+ <div class="form-row">
172
+ <label for="node-input-serialConfig"><i class="fa fa-plug"></i> 串口配置</label>
173
+ <input type="text" id="node-input-serialConfig" style="width: 70%;">
174
+ </div>
175
+
176
+ <div class="form-row">
177
+ <label style="width: 100%; font-weight: bold; margin-top: 15px; margin-bottom: 10px;">
178
+ <i class="fa fa-code"></i> 16进制指令配置(最多48字节)
179
+ </label>
180
+ </div>
181
+
182
+ <div class="form-row">
183
+ <label for="node-input-openCmd"><i class="fa fa-arrow-up"></i> 打开指令</label>
184
+ <input type="text" id="node-input-openCmd" placeholder="例如: 01 05 00 00 FF 00 8C 3A" style="width: 50%;">
185
+ <button type="button" id="btn-test-open" class="red-ui-button" style="margin-left: 5px;">
186
+ <i class="fa fa-play"></i> 测试
187
+ </button>
188
+ <div style="font-size: 11px; color: #999; margin-top: 5px; margin-left: 105px;">
189
+ 输入16进制码,空格分隔,自动格式化
190
+ </div>
191
+ </div>
192
+
193
+ <div class="form-row">
194
+ <label for="node-input-closeCmd"><i class="fa fa-arrow-down"></i> 关闭指令</label>
195
+ <input type="text" id="node-input-closeCmd" placeholder="例如: 01 05 00 00 00 00 CD CA" style="width: 50%;">
196
+ <button type="button" id="btn-test-close" class="red-ui-button" style="margin-left: 5px;">
197
+ <i class="fa fa-play"></i> 测试
198
+ </button>
199
+ </div>
200
+
201
+ <div class="form-row" id="pause-cmd-row" style="display: none;">
202
+ <label for="node-input-pauseCmd"><i class="fa fa-pause"></i> 暂停指令</label>
203
+ <input type="text" id="node-input-pauseCmd" placeholder="例如: 01 05 00 01 FF 00 DD FA" style="width: 50%;">
204
+ <button type="button" id="btn-test-pause" class="red-ui-button" style="margin-left: 5px;">
205
+ <i class="fa fa-play"></i> 测试
206
+ </button>
207
+ <div style="font-size: 11px; color: #999; margin-top: 5px; margin-left: 105px;">
208
+ 仅窗帘模式需要配置
209
+ </div>
210
+ </div>
211
+
212
+ <div class="form-row" style="margin-top: 20px;">
213
+ <div style="padding: 10px; background: #f0f8ff; border-left: 4px solid #2196F3; border-radius: 4px;">
214
+ <strong>使用说明:</strong><br>
215
+ <ul style="margin: 5px 0; padding-left: 20px; font-size: 12px;">
216
+ <li><strong>开关/其他模式</strong>: true发送打开指令,false发送关闭指令</li>
217
+ <li><strong>窗帘模式</strong>: true/false交替触发,循环发送打开→关闭→暂停→打开...</li>
218
+ <li>16进制码自动格式化为大写,空格分隔</li>
219
+ <li>点击"测试"按钮可直接发送到串口总线验证</li>
220
+ <li>配置自动持久化保存</li>
221
+ </ul>
222
+ </div>
223
+ </div>
224
+ </script>
225
+
226
+ <script type="text/html" data-help-name="custom-protocol">
227
+ <p>自定义协议节点,用于控制非标准Modbus协议的485设备。</p>
228
+
229
+ <h3>功能特性</h3>
230
+ <ul>
231
+ <li>支持三种设备类型:开关、窗帘、其他</li>
232
+ <li>窗帘模式支持打开/关闭/暂停循环控制</li>
233
+ <li>16进制指令配置,最多48字节</li>
234
+ <li>配置界面可直接测试发送指令</li>
235
+ <li>配置持久化保存</li>
236
+ </ul>
237
+
238
+ <h3>设备类型说明</h3>
239
+ <dl>
240
+ <dt>开关模式</dt>
241
+ <dd>接收true发送打开指令,接收false发送关闭指令</dd>
242
+
243
+ <dt>窗帘模式</dt>
244
+ <dd>true/false交替触发,循环发送:打开→关闭→暂停→打开...</dd>
245
+
246
+ <dt>其他模式</dt>
247
+ <dd>与开关模式相同,接收true/false发送对应指令</dd>
248
+ </dl>
249
+
250
+ <h3>输入消息</h3>
251
+ <p>从从站开关节点接收:</p>
252
+ <pre>msg.payload = true/false</pre>
253
+
254
+ <h3>输出消息</h3>
255
+ <p>输出Buffer格式的16进制数据,可连线到debug节点发送到串口:</p>
256
+ <pre>msg.payload = Buffer</pre>
257
+
258
+ <h3>使用示例</h3>
259
+ <ol>
260
+ <li>配置串口节点</li>
261
+ <li>选择设备类型(开关/窗帘/其他)</li>
262
+ <li>输入16进制指令(空格分隔)</li>
263
+ <li>点击"测试"按钮验证指令是否正确</li>
264
+ <li>连线:从站开关 → 自定义协议 → debug节点</li>
265
+ <li>部署流程,触发从站开关即可发送自定义指令</li>
266
+ </ol>
267
+
268
+ <h3>注意事项</h3>
269
+ <ul>
270
+ <li>16进制指令最多48字节</li>
271
+ <li>窗帘模式需要配置三个指令(打开、关闭、暂停)</li>
272
+ <li>测试功能需要先选择串口配置</li>
273
+ <li>输出需要连线到debug节点才能发送到串口</li>
274
+ </ul>
275
+ </script>
276
+