node-red-contrib-symi-modbus 2.5.2 → 2.5.4

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.
@@ -0,0 +1,174 @@
1
+ <script type="text/javascript">
2
+ RED.nodes.registerType('modbus-server-config', {
3
+ category: 'config',
4
+ defaults: {
5
+ name: {value: ""},
6
+ connectionType: {value: "tcp"},
7
+ tcpMode: {value: "telnet"},
8
+ tcpHost: {value: "192.168.2.12"},
9
+ tcpPort: {value: 502},
10
+ serialPort: {value: "/dev/ttyUSB0"},
11
+ serialBaudRate: {value: 9600},
12
+ serialDataBits: {value: 8},
13
+ serialStopBits: {value: 1},
14
+ serialParity: {value: "none"}
15
+ },
16
+ label: function() {
17
+ if (this.name) {
18
+ return this.name;
19
+ }
20
+ if (this.connectionType === "tcp") {
21
+ return "TCP: " + this.tcpHost + ":" + this.tcpPort;
22
+ } else {
23
+ return "串口: " + this.serialPort + " @ " + this.serialBaudRate;
24
+ }
25
+ },
26
+ oneditprepare: function() {
27
+ $("#node-config-input-connectionType").on("change", function() {
28
+ var connType = $(this).val();
29
+ if (connType === "tcp") {
30
+ $(".form-row-tcp").show();
31
+ $(".form-row-serial").hide();
32
+ } else {
33
+ $(".form-row-tcp").hide();
34
+ $(".form-row-serial").show();
35
+ }
36
+ });
37
+
38
+ $("#node-config-input-connectionType").trigger("change");
39
+
40
+ // 串口列表刷新按钮
41
+ $("#node-config-refresh-serial").on("click", function() {
42
+ var btn = $(this);
43
+ btn.prop("disabled", true).html('<i class="fa fa-spinner fa-spin"></i> 搜索中...');
44
+
45
+ $.getJSON('modbus-master/serialports', function(data) {
46
+ var select = $("#node-config-input-serialPort");
47
+ var currentVal = select.val();
48
+
49
+ // 清空并重新填充
50
+ select.empty();
51
+
52
+ if (data && data.length > 0) {
53
+ data.forEach(function(port) {
54
+ if (port.isError) {
55
+ select.append($('<option></option>')
56
+ .attr('value', port.comName)
57
+ .attr('disabled', true)
58
+ .text(port.comName + ' - ' + port.manufacturer));
59
+ } else {
60
+ var label = port.comName;
61
+ if (port.manufacturer && port.manufacturer !== '未知设备') {
62
+ label += ' (' + port.manufacturer + ')';
63
+ }
64
+ select.append($('<option></option>')
65
+ .attr('value', port.comName)
66
+ .text(label));
67
+ }
68
+ });
69
+
70
+ // 恢复之前的选择
71
+ if (currentVal) {
72
+ select.val(currentVal);
73
+ }
74
+ } else {
75
+ select.append($('<option></option>')
76
+ .attr('value', '/dev/ttyUSB0')
77
+ .text('未检测到串口,请手动输入'));
78
+ }
79
+
80
+ btn.prop("disabled", false).html('<i class="fa fa-refresh"></i> 刷新串口列表');
81
+ }).fail(function() {
82
+ btn.prop("disabled", false).html('<i class="fa fa-refresh"></i> 刷新串口列表');
83
+ RED.notify("串口列表获取失败", "error");
84
+ });
85
+ });
86
+
87
+ // 页面加载时自动刷新一次
88
+ setTimeout(function() {
89
+ $("#node-config-refresh-serial").trigger("click");
90
+ }, 100);
91
+ }
92
+ });
93
+ </script>
94
+
95
+ <script type="text/html" data-template-name="modbus-server-config">
96
+ <div class="form-row">
97
+ <label for="node-config-input-name"><i class="fa fa-tag"></i> 名称</label>
98
+ <input type="text" id="node-config-input-name" placeholder="Modbus服务器">
99
+ </div>
100
+
101
+ <div class="form-row">
102
+ <label for="node-config-input-connectionType"><i class="fa fa-exchange"></i> 连接类型</label>
103
+ <select id="node-config-input-connectionType" style="width: 70%;">
104
+ <option value="tcp">TCP/IP</option>
105
+ <option value="serial">串口</option>
106
+ </select>
107
+ </div>
108
+
109
+ <div class="form-row form-row-tcp">
110
+ <label for="node-config-input-tcpMode"><i class="fa fa-cog"></i> TCP模式</label>
111
+ <select id="node-config-input-tcpMode" style="width: 70%;">
112
+ <option value="telnet">Telnet ASCII (推荐)</option>
113
+ <option value="rtu">RTU over TCP</option>
114
+ <option value="tcp">Modbus TCP</option>
115
+ </select>
116
+ </div>
117
+
118
+ <div class="form-row form-row-tcp">
119
+ <label for="node-config-input-tcpHost"><i class="fa fa-server"></i> TCP主机</label>
120
+ <input type="text" id="node-config-input-tcpHost" placeholder="192.168.2.12" style="width: 70%;">
121
+ </div>
122
+
123
+ <div class="form-row form-row-tcp">
124
+ <label for="node-config-input-tcpPort"><i class="fa fa-plug"></i> TCP端口</label>
125
+ <input type="number" id="node-config-input-tcpPort" placeholder="502" style="width: 100px;">
126
+ </div>
127
+
128
+ <div class="form-row form-row-serial">
129
+ <label for="node-config-input-serialPort"><i class="fa fa-terminal"></i> 串口</label>
130
+ <select id="node-config-input-serialPort" style="width: 50%;">
131
+ <option value="/dev/ttyUSB0">/dev/ttyUSB0</option>
132
+ </select>
133
+ <button type="button" id="node-config-refresh-serial" class="red-ui-button" style="margin-left: 10px;">
134
+ <i class="fa fa-refresh"></i> 刷新串口列表
135
+ </button>
136
+ </div>
137
+
138
+ <div class="form-row form-row-serial">
139
+ <label for="node-config-input-serialBaudRate"><i class="fa fa-tachometer"></i> 波特率</label>
140
+ <select id="node-config-input-serialBaudRate" style="width: 150px;">
141
+ <option value="9600">9600</option>
142
+ <option value="19200">19200</option>
143
+ <option value="38400">38400</option>
144
+ <option value="57600">57600</option>
145
+ <option value="115200">115200</option>
146
+ </select>
147
+ </div>
148
+
149
+ <div class="form-row form-row-serial" style="display: none;">
150
+ <label for="node-config-input-serialDataBits"><i class="fa fa-database"></i> 数据位</label>
151
+ <select id="node-config-input-serialDataBits" style="width: 100px;">
152
+ <option value="7">7</option>
153
+ <option value="8" selected>8</option>
154
+ </select>
155
+ </div>
156
+
157
+ <div class="form-row form-row-serial" style="display: none;">
158
+ <label for="node-config-input-serialStopBits"><i class="fa fa-stop"></i> 停止位</label>
159
+ <select id="node-config-input-serialStopBits" style="width: 100px;">
160
+ <option value="1" selected>1</option>
161
+ <option value="2">2</option>
162
+ </select>
163
+ </div>
164
+
165
+ <div class="form-row form-row-serial" style="display: none;">
166
+ <label for="node-config-input-serialParity"><i class="fa fa-check"></i> 校验位</label>
167
+ <select id="node-config-input-serialParity" style="width: 100px;">
168
+ <option value="none" selected>无</option>
169
+ <option value="even">偶校验</option>
170
+ <option value="odd">奇校验</option>
171
+ </select>
172
+ </div>
173
+ </script>
174
+
@@ -0,0 +1,18 @@
1
+ module.exports = function(RED) {
2
+ "use strict";
3
+
4
+ function ModbusServerConfigNode(config) {
5
+ RED.nodes.createNode(this, config);
6
+ this.connectionType = config.connectionType;
7
+ this.tcpHost = config.tcpHost;
8
+ this.tcpPort = parseInt(config.tcpPort) || 502;
9
+ this.serialPort = config.serialPort;
10
+ this.serialBaudRate = parseInt(config.serialBaudRate) || 9600;
11
+ this.serialDataBits = parseInt(config.serialDataBits) || 8;
12
+ this.serialStopBits = parseInt(config.serialStopBits) || 1;
13
+ this.serialParity = config.serialParity || "none";
14
+ }
15
+
16
+ RED.nodes.registerType("modbus-server-config", ModbusServerConfigNode);
17
+ };
18
+
@@ -4,94 +4,26 @@
4
4
  color: '#E9967A',
5
5
  defaults: {
6
6
  name: {value: "从站开关"},
7
- // RS-485总线连接配置
8
- connectionType: {value: "tcp"},
9
- tcpHost: {value: "127.0.0.1"},
10
- tcpPort: {value: 8888},
11
- serialPort: {value: "COM1"},
12
- serialBaudRate: {value: 9600},
13
- serialDataBits: {value: 8},
14
- serialStopBits: {value: 1},
15
- serialParity: {value: "none"},
7
+ // RS-485连接配置(共享配置节点)
8
+ serialPortConfig: {value: "", type: "serial-port-config"},
16
9
  // MQTT配置
17
10
  mqttServer: {value: "", type: "mqtt-server-config"},
18
11
  // 开关面板配置
19
12
  switchBrand: {value: "symi"}, // 品牌选择
13
+ buttonType: {value: "switch"}, // 按钮类型:switch=开关模式,scene=场景模式
20
14
  switchId: {value: 0, validate: RED.validators.number()},
21
15
  buttonNumber: {value: 1, validate: RED.validators.number()},
22
16
  // 映射到继电器
23
17
  targetSlaveAddress: {value: 10, validate: RED.validators.number()},
24
- targetCoilNumber: {value: 0, validate: RED.validators.number()}
18
+ targetCoilNumber: {value: 1, validate: RED.validators.number()} // 默认值改为1(显示为1路)
25
19
  },
26
20
  inputs: 1,
27
21
  outputs: 1,
28
22
  icon: "light.png",
29
23
  label: function() {
30
- return this.name || `开关${this.switchId}-按钮${this.buttonNumber} → 继电器${this.targetSlaveAddress}-${this.targetCoilNumber}`;
31
- },
32
- oneditprepare: function() {
33
- // 切换连接类型时显示/隐藏相关配置
34
- $("#node-input-connectionType").on("change", function() {
35
- var connType = $(this).val();
36
- if (connType === "tcp") {
37
- $(".form-row-tcp").show();
38
- $(".form-row-serial").hide();
39
- } else {
40
- $(".form-row-tcp").hide();
41
- $(".form-row-serial").show();
42
- }
43
- });
44
-
45
- // 搜索串口按钮
46
- $("#btn-search-ports").on("click", function() {
47
- var btn = $(this);
48
- var inputBox = $("#node-input-serialPort");
49
- var selectBox = $("#port-list");
50
-
51
- btn.prop("disabled", true).html('<i class="fa fa-spinner fa-spin"></i> 搜索中');
52
-
53
- $.ajax({
54
- url: 'modbus-slave-switch/serialports',
55
- type: 'GET',
56
- success: function(ports) {
57
- selectBox.empty().append('<option value="">-- 选择检测到的串口 --</option>');
58
-
59
- if (ports.length === 0) {
60
- selectBox.append('<option disabled>未找到可用串口</option>');
61
- RED.notify("未找到可用串口,请手动输入串口路径", "warning");
62
- } else {
63
- ports.forEach(function(port) {
64
- var label = port.comName;
65
- if (port.manufacturer && port.manufacturer !== '未知设备') {
66
- label += ' - ' + port.manufacturer;
67
- }
68
- selectBox.append('<option value="' + port.comName + '">' + label + '</option>');
69
- });
70
- // 显示下拉框,隐藏输入框
71
- inputBox.hide();
72
- selectBox.show();
73
- }
74
-
75
- btn.prop("disabled", false).html('<i class="fa fa-search"></i> 搜索');
76
- },
77
- error: function() {
78
- RED.notify("搜索串口失败", "error");
79
- btn.prop("disabled", false).html('<i class="fa fa-search"></i> 搜索');
80
- }
81
- });
82
- });
83
-
84
- // 选择串口(下拉选择)
85
- $("#port-list").on("change", function() {
86
- var selectedPort = $(this).val();
87
- if (selectedPort) {
88
- $("#node-input-serialPort").val(selectedPort).show();
89
- $(this).hide();
90
- }
91
- });
92
-
93
- // 初始化显示
94
- $("#node-input-connectionType").trigger("change");
24
+ // 显示时直接使用用户输入的路数(1-32)
25
+ const coilDisplay = this.targetCoilNumber || 1;
26
+ return this.name || `开关${this.switchId}-按钮${this.buttonNumber} → 继电器${this.targetSlaveAddress}-${coilDisplay}路`;
95
27
  }
96
28
  });
97
29
  </script>
@@ -102,98 +34,27 @@
102
34
  <label for="node-input-name"><i class="fa fa-tag"></i> 名称</label>
103
35
  <input type="text" id="node-input-name" placeholder="从站开关">
104
36
  </div>
105
-
106
- <!-- RS-485总线连接配置 -->
37
+
38
+ <!-- RS-485连接配置 -->
107
39
  <hr style="margin: 15px 0; border: 0; border-top: 2px solid #e0e0e0;">
108
40
  <div class="form-row">
109
41
  <label style="width: 100%; margin-bottom: 8px;">
110
- <i class="fa fa-plug" style="color: #ff9800;"></i>
111
- <span style="font-size: 14px; font-weight: 600; color: #333;">RS-485总线连接配置</span>
42
+ <i class="fa fa-plug" style="color: #ff9800;"></i>
43
+ <span style="font-size: 14px; font-weight: 600; color: #333;">RS-485连接配置</span>
112
44
  </label>
113
45
  <div style="font-size: 11px; color: #555; padding: 10px 12px; background: linear-gradient(135deg, #fff3cd 0%, #fffbe6 100%); border-left: 4px solid #ffc107; border-radius: 4px; box-shadow: 0 1px 3px rgba(0,0,0,0.08);">
114
- <strong>总线说明:</strong>连接物理开关面板的RS-485总线,监听按键事件并发送控制指令
46
+ <strong>说明:</strong>多个从站开关节点可以共享同一个RS-485连接配置(支持TCP网关或串口)
115
47
  </div>
116
48
  </div>
117
-
49
+
118
50
  <div class="form-row">
119
- <label for="node-input-connectionType" style="width: 110px;"><i class="fa fa-exchange"></i> 连接类型</label>
120
- <select id="node-input-connectionType" style="width: calc(70% - 110px);">
121
- <option value="tcp">TCP/IP</option>
122
- <option value="serial">串口</option>
123
- </select>
124
- </div>
125
-
126
- <!-- TCP配置 -->
127
- <div class="form-row form-row-tcp">
128
- <label for="node-input-tcpHost" style="width: 110px;"><i class="fa fa-server"></i> TCP主机</label>
129
- <input type="text" id="node-input-tcpHost" placeholder="192.168.1.200" style="width: calc(70% - 110px);">
51
+ <label for="node-input-serialPortConfig" style="width: 110px;"><i class="fa fa-server"></i> 连接配置</label>
52
+ <input type="text" id="node-input-serialPortConfig" placeholder="选择或添加RS-485连接配置" style="width: calc(70% - 110px);">
130
53
  <div style="font-size: 11px; color: #888; margin-left: 110px; margin-top: 3px;">
131
- RS-485转TCP网关IP地址
54
+ 选择已配置的RS-485连接(支持多个节点共享)
132
55
  </div>
133
56
  </div>
134
57
 
135
- <div class="form-row form-row-tcp">
136
- <label for="node-input-tcpPort" style="width: 110px;"><i class="fa fa-plug"></i> TCP端口</label>
137
- <input type="number" id="node-input-tcpPort" placeholder="8888" style="width: 100px;">
138
- <span style="margin-left: 10px; font-size: 12px; color: #666;">默认 8888</span>
139
- </div>
140
-
141
- <!-- 串口配置 -->
142
- <div class="form-row form-row-serial">
143
- <label for="node-input-serialPort" style="width: 110px;"><i class="fa fa-terminal"></i> 串口</label>
144
- <div style="display: inline-block; width: calc(70% - 110px);">
145
- <div style="display: flex; gap: 5px; align-items: center;">
146
- <input type="text" id="node-input-serialPort" placeholder="COM1, /dev/ttyUSB0, /dev/ttyS1" style="flex: 1; padding: 5px 8px; border: 1px solid #ccc; border-radius: 4px; font-size: 13px;">
147
- <select id="port-list" style="flex: 1; padding: 5px; font-family: monospace; font-size: 12px; border: 1px solid #ccc; border-radius: 4px; display: none;">
148
- <option value="">-- 选择检测到的串口 --</option>
149
- </select>
150
- <button type="button" id="btn-search-ports" style="padding: 6px 12px; background: #2196f3; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 12px; white-space: nowrap; transition: background 0.3s;">
151
- <i class="fa fa-search"></i> 搜索
152
- </button>
153
- </div>
154
- <div style="font-size: 11px; color: #888; margin-top: 3px;">
155
- 支持COM1、/dev/ttyUSB0、/dev/ttyS1等RS-485串口设备
156
- </div>
157
- </div>
158
- </div>
159
-
160
- <div class="form-row form-row-serial">
161
- <label for="node-input-serialBaudRate" style="width: 110px;"><i class="fa fa-tachometer"></i> 波特率</label>
162
- <select id="node-input-serialBaudRate" style="width: 150px;">
163
- <option value="9600">9600</option>
164
- <option value="19200">19200</option>
165
- <option value="38400">38400</option>
166
- <option value="57600">57600</option>
167
- <option value="115200">115200</option>
168
- </select>
169
- <span style="margin-left: 10px; font-size: 11px; color: #888;">8-N-1固定配置(亖米协议)</span>
170
- </div>
171
-
172
- <div class="form-row form-row-serial" style="display: none;">
173
- <label for="node-input-serialDataBits" style="width: 110px;"><i class="fa fa-database"></i> 数据位</label>
174
- <select id="node-input-serialDataBits" style="width: 100px;">
175
- <option value="7">7</option>
176
- <option value="8" selected>8</option>
177
- </select>
178
- </div>
179
-
180
- <div class="form-row form-row-serial" style="display: none;">
181
- <label for="node-input-serialStopBits" style="width: 110px;"><i class="fa fa-stop"></i> 停止位</label>
182
- <select id="node-input-serialStopBits" style="width: 100px;">
183
- <option value="1" selected>1</option>
184
- <option value="2">2</option>
185
- </select>
186
- </div>
187
-
188
- <div class="form-row form-row-serial" style="display: none;">
189
- <label for="node-input-serialParity" style="width: 110px;"><i class="fa fa-check"></i> 校验位</label>
190
- <select id="node-input-serialParity" style="width: 100px;">
191
- <option value="none" selected>无</option>
192
- <option value="even">偶校验</option>
193
- <option value="odd">奇校验</option>
194
- </select>
195
- </div>
196
-
197
58
  <!-- MQTT配置 -->
198
59
  <hr style="margin: 15px 0; border: 0; border-top: 2px solid #e0e0e0;">
199
60
  <div class="form-row">
@@ -229,7 +90,19 @@
229
90
  </select>
230
91
  <span style="margin-left: 10px; font-size: 11px; color: #666; font-style: italic;">支持1-8键开关</span>
231
92
  </div>
232
-
93
+
94
+ <div class="form-row">
95
+ <label for="node-input-buttonType" style="width: 110px;"><i class="fa fa-cog"></i> 按钮类型</label>
96
+ <select id="node-input-buttonType" style="width: 200px;">
97
+ <option value="switch">开关按钮</option>
98
+ <option value="scene">场景按钮</option>
99
+ </select>
100
+ <div style="font-size: 11px; color: #888; margin-left: 110px; margin-top: 3px;">
101
+ <strong>开关按钮</strong>:灯光、插座等开关控制,有开/关状态<br>
102
+ <strong>场景按钮</strong>:场景触发、一键全开/全关等,只触发动作
103
+ </div>
104
+ </div>
105
+
233
106
  <div class="form-row">
234
107
  <label for="node-input-switchId" style="width: 110px;"><i class="fa fa-id-card"></i> 开关ID</label>
235
108
  <input type="number" id="node-input-switchId" placeholder="0" min="0" max="255" style="width: 90px; padding: 5px 8px; border: 1px solid #ccc; border-radius: 4px; font-size: 13px;">
@@ -238,7 +111,7 @@
238
111
  RS-485总线上的设备地址标识
239
112
  </div>
240
113
  </div>
241
-
114
+
242
115
  <div class="form-row">
243
116
  <label for="node-input-buttonNumber" style="width: 110px;"><i class="fa fa-hand-pointer-o"></i> 按钮编号</label>
244
117
  <select id="node-input-buttonNumber" style="width: 150px;">
@@ -273,11 +146,10 @@
273
146
  </div>
274
147
 
275
148
  <div class="form-row">
276
- <label for="node-input-targetCoilNumber" style="width: 110px;"><i class="fa fa-plug"></i> 线圈编号</label>
277
- <input type="number" id="node-input-targetCoilNumber" placeholder="0" min="0" max="31" style="width: 90px; padding: 5px 8px; border: 1px solid #ccc; border-radius: 4px; font-size: 13px;">
278
- <span style="margin-left: 10px; color: #666; font-size: 12px;">继电器通道:<strong>0-31</strong></span>
149
+ <label for="node-input-targetCoilNumber" style="width: 110px;"><i class="fa fa-plug"></i> 继电器路数</label>
150
+ <input type="number" id="node-input-targetCoilNumber" placeholder="1" min="1" max="32" style="width: 90px; padding: 5px 8px; border: 1px solid #ccc; border-radius: 4px; font-size: 13px;">
279
151
  <div style="font-size: 11px; color: #888; margin-left: 110px; margin-top: 3px;">
280
- 32路继电器的具体通道编号
152
+ 继电器1-32路,对应线圈0-31,只需填写正确的继电器通道即可
281
153
  </div>
282
154
  </div>
283
155