node-red-contrib-modbus-modpackqt 3.3.29 → 3.3.30
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/nodes/modpackqt-slave-server.html +140 -32
- package/nodes/modpackqt-slave-server.js +68 -45
- package/package.json +1 -1
|
@@ -3,10 +3,16 @@
|
|
|
3
3
|
category: 'ModPackQT',
|
|
4
4
|
color: '#f97316',
|
|
5
5
|
defaults: {
|
|
6
|
-
name:
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
name: { value: '' },
|
|
7
|
+
protocol: { value: 'tcp' },
|
|
8
|
+
bindHost: { value: '0.0.0.0' },
|
|
9
|
+
bindPort: { value: 1502, validate: RED.validators.number() },
|
|
10
|
+
unitId: { value: 1, validate: RED.validators.number() },
|
|
11
|
+
serialPort: { value: '' },
|
|
12
|
+
baudRate: { value: 9600, validate: RED.validators.number() },
|
|
13
|
+
parity: { value: 'none' },
|
|
14
|
+
dataBits: { value: 8, validate: RED.validators.number() },
|
|
15
|
+
stopBits: { value: 1, validate: RED.validators.number() }
|
|
10
16
|
},
|
|
11
17
|
credentials: {
|
|
12
18
|
apiKey: { type: 'password' }
|
|
@@ -17,6 +23,11 @@
|
|
|
17
23
|
align: 'right',
|
|
18
24
|
icon: 'modpackqt.png',
|
|
19
25
|
label: function () {
|
|
26
|
+
if (this.protocol === 'rtu') {
|
|
27
|
+
const tag = `${this.serialPort || 'COM?'} #${this.unitId || 1}`;
|
|
28
|
+
return this.name ? `${this.name} — Modbus RTU Slave ${tag}`
|
|
29
|
+
: `Modbus RTU Slave Server ${tag}`;
|
|
30
|
+
}
|
|
20
31
|
const tag = `:${this.bindPort || 1502} #${this.unitId || 1}`;
|
|
21
32
|
return this.name ? `${this.name} — Modbus TCP Slave ${tag}`
|
|
22
33
|
: `Modbus TCP Slave Server ${tag}`;
|
|
@@ -26,7 +37,19 @@
|
|
|
26
37
|
oneditprepare: function () {
|
|
27
38
|
const node = this;
|
|
28
39
|
|
|
29
|
-
// ──
|
|
40
|
+
// ── Protocol toggle
|
|
41
|
+
const $proto = $('#node-input-protocol');
|
|
42
|
+
const toggleProtocol = function () {
|
|
43
|
+
const isTcp = $proto.val() === 'tcp';
|
|
44
|
+
$('#modpackqt-slave-row-tcp').toggle(isTcp);
|
|
45
|
+
$('#modpackqt-slave-row-rtu').toggle(!isTcp);
|
|
46
|
+
reload();
|
|
47
|
+
buildLink();
|
|
48
|
+
};
|
|
49
|
+
$proto.on('change', toggleProtocol);
|
|
50
|
+
toggleProtocol();
|
|
51
|
+
|
|
52
|
+
// ── My Slaves picker
|
|
30
53
|
const $sel = $('#node-input-modpackqt-slave-picker');
|
|
31
54
|
const reload = function () {
|
|
32
55
|
$sel.empty().append('<option value="">— Loading… —</option>');
|
|
@@ -34,16 +57,22 @@
|
|
|
34
57
|
$sel.empty().append('<option value="">— Save this node first, then reopen —</option>');
|
|
35
58
|
return;
|
|
36
59
|
}
|
|
60
|
+
const proto = $proto.val();
|
|
37
61
|
$.getJSON('modpackqt/slaves?probe=' + encodeURIComponent(node.id))
|
|
38
62
|
.done(function (rows) {
|
|
39
63
|
$sel.empty().append('<option value="">— Manual entry —</option>');
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
64
|
+
const filtered = (rows || []).filter(function (s) {
|
|
65
|
+
return !!s && (proto === 'rtu' ? s.protocol === 'rtu' : s.protocol !== 'rtu');
|
|
66
|
+
});
|
|
67
|
+
if (filtered.length === 0) {
|
|
68
|
+
const msg = proto === 'rtu' ? '— No RTU slaves saved yet —' : '— No TCP slaves saved yet —';
|
|
69
|
+
$sel.empty().append($('<option>').val('').text(msg));
|
|
43
70
|
} else {
|
|
44
|
-
|
|
45
|
-
const
|
|
46
|
-
|
|
71
|
+
filtered.forEach(function (s) {
|
|
72
|
+
const conn = s.protocol === 'rtu'
|
|
73
|
+
? ' — unit #' + (s.unitId || 1)
|
|
74
|
+
: ' — :' + (s.port || 1502) + ' #' + (s.unitId || 1);
|
|
75
|
+
$('<option>').val(s.id).text((s.name || '(unnamed)') + conn).data('row', s).appendTo($sel);
|
|
47
76
|
});
|
|
48
77
|
}
|
|
49
78
|
})
|
|
@@ -57,7 +86,15 @@
|
|
|
57
86
|
const row = $(this).find('option:selected').data('row');
|
|
58
87
|
if (!row) return;
|
|
59
88
|
if (!node.name) $('#node-input-name').val(row.name || '');
|
|
60
|
-
if (row.
|
|
89
|
+
if (row.protocol === 'rtu') {
|
|
90
|
+
if (row.serialPort) $('#node-input-serialPort').val(row.serialPort);
|
|
91
|
+
if (row.baudRate) $('#node-input-baudRate').val(row.baudRate);
|
|
92
|
+
if (row.parity) $('#node-input-parity').val(row.parity);
|
|
93
|
+
if (row.dataBits) $('#node-input-dataBits').val(row.dataBits);
|
|
94
|
+
if (row.stopBits) $('#node-input-stopBits').val(row.stopBits);
|
|
95
|
+
} else {
|
|
96
|
+
if (row.port) $('#node-input-bindPort').val(row.port);
|
|
97
|
+
}
|
|
61
98
|
$('#node-input-unitId').val(row.unitId || 1);
|
|
62
99
|
buildLink();
|
|
63
100
|
});
|
|
@@ -71,9 +108,10 @@
|
|
|
71
108
|
const renderLink = function (info) {
|
|
72
109
|
const probeHost = (info && info.host) || '127.0.0.1';
|
|
73
110
|
const probePort = (info && info.port) || 8502;
|
|
111
|
+
const unitId = $('#node-input-unitId').val() || node.unitId || 1;
|
|
112
|
+
const name = $('#node-input-name').val() || node.name || '';
|
|
113
|
+
const isTcp = $proto.val() === 'tcp';
|
|
74
114
|
const bindPort = $('#node-input-bindPort').val() || node.bindPort || 1502;
|
|
75
|
-
const unitId = $('#node-input-unitId').val() || node.unitId || 1;
|
|
76
|
-
const name = $('#node-input-name').val() || node.name || '';
|
|
77
115
|
const url = 'https://modpackqt.com/slave'
|
|
78
116
|
+ '?probe=' + encodeURIComponent(node.id || '')
|
|
79
117
|
+ '&probeHost=' + encodeURIComponent(probeHost)
|
|
@@ -83,10 +121,15 @@
|
|
|
83
121
|
+ (name ? '&name=' + encodeURIComponent(name) : '');
|
|
84
122
|
$('#modpackqt-slave-server-link').attr('href', url);
|
|
85
123
|
$('#modpackqt-slave-server-runtime').text(probeHost + ':' + probePort);
|
|
86
|
-
|
|
124
|
+
if (isTcp) {
|
|
125
|
+
$('#modpackqt-slave-server-target').text(':' + bindPort + ' · unit ' + unitId);
|
|
126
|
+
} else {
|
|
127
|
+
const sp = $('#node-input-serialPort').val() || node.serialPort || 'COM?';
|
|
128
|
+
$('#modpackqt-slave-server-target').text(sp + ' · unit ' + unitId);
|
|
129
|
+
}
|
|
87
130
|
};
|
|
88
131
|
buildLink();
|
|
89
|
-
$('#node-input-bindPort, #node-input-unitId').on('change input', buildLink);
|
|
132
|
+
$('#node-input-bindPort, #node-input-unitId, #node-input-serialPort').on('change input', buildLink);
|
|
90
133
|
}
|
|
91
134
|
});
|
|
92
135
|
</script>
|
|
@@ -98,12 +141,78 @@
|
|
|
98
141
|
</div>
|
|
99
142
|
|
|
100
143
|
<div class="form-row">
|
|
101
|
-
<label for="node-input-
|
|
144
|
+
<label for="node-input-protocol"><i class="fa fa-plug"></i> Protocol</label>
|
|
145
|
+
<select id="node-input-protocol" style="width:70%">
|
|
146
|
+
<option value="tcp">Modbus TCP (network)</option>
|
|
147
|
+
<option value="rtu">Modbus RTU (serial port)</option>
|
|
148
|
+
</select>
|
|
149
|
+
</div>
|
|
150
|
+
|
|
151
|
+
<!-- TCP fields -->
|
|
152
|
+
<div id="modpackqt-slave-row-tcp">
|
|
153
|
+
<input type="hidden" id="node-input-bindHost">
|
|
154
|
+
<div class="form-row">
|
|
155
|
+
<label for="node-input-bindPort"><i class="fa fa-ethernet"></i> Bind Port</label>
|
|
156
|
+
<input type="number" id="node-input-bindPort" min="1" max="65535" style="width:120px" placeholder="1502">
|
|
157
|
+
</div>
|
|
158
|
+
</div>
|
|
159
|
+
|
|
160
|
+
<!-- RTU fields -->
|
|
161
|
+
<div id="modpackqt-slave-row-rtu" style="display:none">
|
|
162
|
+
<div class="form-row">
|
|
163
|
+
<label for="node-input-serialPort"><i class="fa fa-usb"></i> Serial Port</label>
|
|
164
|
+
<input type="text" id="node-input-serialPort" placeholder="e.g. COM3 or /dev/ttyUSB0" style="width:60%">
|
|
165
|
+
</div>
|
|
166
|
+
<div class="form-row">
|
|
167
|
+
<label for="node-input-baudRate"><i class="fa fa-tachometer"></i> Baud Rate</label>
|
|
168
|
+
<select id="node-input-baudRate" style="width:140px">
|
|
169
|
+
<option value="1200">1200</option>
|
|
170
|
+
<option value="2400">2400</option>
|
|
171
|
+
<option value="4800">4800</option>
|
|
172
|
+
<option value="9600" selected>9600</option>
|
|
173
|
+
<option value="19200">19200</option>
|
|
174
|
+
<option value="38400">38400</option>
|
|
175
|
+
<option value="57600">57600</option>
|
|
176
|
+
<option value="115200">115200</option>
|
|
177
|
+
</select>
|
|
178
|
+
</div>
|
|
179
|
+
<div class="form-row">
|
|
180
|
+
<label for="node-input-parity"><i class="fa fa-check-circle-o"></i> Parity</label>
|
|
181
|
+
<select id="node-input-parity" style="width:140px">
|
|
182
|
+
<option value="none">None</option>
|
|
183
|
+
<option value="even">Even</option>
|
|
184
|
+
<option value="odd">Odd</option>
|
|
185
|
+
</select>
|
|
186
|
+
</div>
|
|
187
|
+
<div class="form-row">
|
|
188
|
+
<label for="node-input-dataBits"><i class="fa fa-sliders"></i> Data Bits</label>
|
|
189
|
+
<select id="node-input-dataBits" style="width:100px">
|
|
190
|
+
<option value="7">7</option>
|
|
191
|
+
<option value="8" selected>8</option>
|
|
192
|
+
</select>
|
|
193
|
+
|
|
194
|
+
<label for="node-input-stopBits" style="width:auto;margin:0 8px 0 0">Stop Bits</label>
|
|
195
|
+
<select id="node-input-stopBits" style="width:100px">
|
|
196
|
+
<option value="1" selected>1</option>
|
|
197
|
+
<option value="2">2</option>
|
|
198
|
+
</select>
|
|
199
|
+
</div>
|
|
200
|
+
</div>
|
|
201
|
+
|
|
202
|
+
<div class="form-row">
|
|
203
|
+
<label for="node-input-unitId"><i class="fa fa-hashtag"></i> Unit ID</label>
|
|
204
|
+
<input type="number" id="node-input-unitId" min="1" max="247" style="width:80px" placeholder="1">
|
|
205
|
+
</div>
|
|
206
|
+
|
|
207
|
+
<hr style="margin:14px 0;border-color:#e5e7eb;">
|
|
208
|
+
|
|
209
|
+
<div class="form-row">
|
|
210
|
+
<label for="node-input-apiKey"><i class="fa fa-key"></i> Gateway Key</label>
|
|
102
211
|
<input type="password" id="node-input-apiKey" placeholder="Paste your ModPackQT tunnel key">
|
|
103
212
|
</div>
|
|
104
213
|
<div class="form-tips" style="font-size:11px;color:#6b7280;margin:-8px 0 12px 105px">
|
|
105
214
|
Generate at <a href="https://modpackqt.com/settings" target="_blank" rel="noopener">modpackqt.com → Settings → Cloud Gateways</a>.
|
|
106
|
-
Loads
|
|
215
|
+
Loads matching saved slave configs in the picker below.
|
|
107
216
|
</div>
|
|
108
217
|
|
|
109
218
|
<div class="form-row">
|
|
@@ -112,14 +221,9 @@
|
|
|
112
221
|
<button type="button" id="modpackqt-slave-server-picker-refresh" class="red-ui-button" title="Reload" style="margin-left:4px"><i class="fa fa-refresh"></i></button>
|
|
113
222
|
</div>
|
|
114
223
|
<div class="form-tips" style="font-size:11px;color:#6b7280;margin:-8px 0 12px 105px">
|
|
115
|
-
|
|
116
|
-
Register layout and limits are managed from the web console.
|
|
224
|
+
Pick a saved slave to auto-fill settings. Register layout is managed from the web console.
|
|
117
225
|
</div>
|
|
118
226
|
|
|
119
|
-
<input type="hidden" id="node-input-bindHost">
|
|
120
|
-
<input type="hidden" id="node-input-bindPort">
|
|
121
|
-
<input type="hidden" id="node-input-unitId">
|
|
122
|
-
|
|
123
227
|
<div class="form-row" style="margin-top:18px;padding-top:14px;border-top:1px solid #e5e7eb;text-align:center;">
|
|
124
228
|
<a id="modpackqt-slave-server-link" href="https://modpackqt.com" target="_blank" rel="noopener noreferrer"
|
|
125
229
|
style="display:inline-block;padding:10px 24px;background:#7c3aed;color:#fff;
|
|
@@ -133,7 +237,7 @@
|
|
|
133
237
|
<div style="margin-top:10px;font-size:12px;">
|
|
134
238
|
<a href="https://modpackqt.com/settings#slaves" target="_blank" rel="noopener noreferrer"
|
|
135
239
|
style="color:#7c3aed;text-decoration:none;font-weight:500;">
|
|
136
|
-
<i class="fa fa-pencil" style="margin-right:4px;"></i>Edit
|
|
240
|
+
<i class="fa fa-pencil" style="margin-right:4px;"></i>Edit settings / register layout on modpackqt.com →
|
|
137
241
|
</a>
|
|
138
242
|
</div>
|
|
139
243
|
</div>
|
|
@@ -141,20 +245,24 @@
|
|
|
141
245
|
|
|
142
246
|
<script type="text/html" data-help-name="modpackqt-slave-server">
|
|
143
247
|
<p>
|
|
144
|
-
Runs a Modbus
|
|
145
|
-
Drop one on the canvas per fake device. <b>Slave-read</b> and
|
|
146
|
-
|
|
147
|
-
registers from the flow.
|
|
248
|
+
Runs a Modbus slave server — either TCP (network) or RTU (serial port) — with its own full register store.
|
|
249
|
+
Drop one on the canvas per fake device. <b>Slave-read</b> and <b>slave-write</b> nodes target it by node ID
|
|
250
|
+
to read and write registers from the flow.
|
|
148
251
|
</p>
|
|
252
|
+
<h3>Protocol</h3>
|
|
253
|
+
<ul>
|
|
254
|
+
<li><b>Modbus TCP</b> — listens on a TCP port. Any Modbus master on the network can connect.</li>
|
|
255
|
+
<li><b>Modbus RTU</b> — listens on a serial port (COM3, /dev/ttyUSB0, etc.). The node acts as a serial slave device.</li>
|
|
256
|
+
</ul>
|
|
149
257
|
<h3>Setup</h3>
|
|
150
258
|
<ol>
|
|
151
|
-
<li>
|
|
259
|
+
<li>Choose protocol, set the port/serial settings and Unit ID (or pick from <b>My Slaves</b>).</li>
|
|
152
260
|
<li>On your slave-read / slave-write nodes, select this node in the <b>Slave Server</b> dropdown.</li>
|
|
153
261
|
<li>Click <b>Open in ModPackQT Console</b> to manage the register layout from the web.</li>
|
|
154
262
|
</ol>
|
|
155
263
|
<h3>Cloud Gateway Key</h3>
|
|
156
264
|
<p>Generate at <a href="https://modpackqt.com/settings" target="_blank" rel="noopener">modpackqt.com → Settings → Cloud Gateways</a>.
|
|
157
265
|
Lets the web console connect and loads your saved slave configs.</p>
|
|
158
|
-
<h3>
|
|
159
|
-
<p>Use ports above 1024 (e.g. 1502, 1503) to avoid needing root privileges. Each server must use a unique port.</p>
|
|
266
|
+
<h3>TCP port note</h3>
|
|
267
|
+
<p>Use ports above 1024 (e.g. 1502, 1503) to avoid needing root privileges. Each TCP server must use a unique port.</p>
|
|
160
268
|
</script>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* ModPackQT Slave Server — Modbus TCP slave with a full register store.
|
|
2
|
+
* ModPackQT Slave Server — Modbus TCP or RTU slave with a full register store.
|
|
3
3
|
*
|
|
4
4
|
* Drop one on the canvas per fake device. Each server:
|
|
5
|
-
* - Binds
|
|
5
|
+
* - Binds either a TCP port (ServerTCP) or a serial port (ServerSerial)
|
|
6
6
|
* - Owns 65 536 registers per type (coils, discrete, holding, input)
|
|
7
7
|
* - Exposes slaveGet() / slaveSet() so slave-read / slave-write nodes
|
|
8
8
|
* can push and pull values from the flow side
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* register editor for it
|
|
11
11
|
*
|
|
12
12
|
* Register limits and layout are managed from the modpackqt.com web
|
|
13
|
-
* console — this node only needs
|
|
13
|
+
* console — this node only needs transport settings and unit ID to bind.
|
|
14
14
|
*/
|
|
15
15
|
module.exports = function (RED) {
|
|
16
16
|
const ModbusRTU = require('modbus-serial');
|
|
@@ -20,10 +20,16 @@ module.exports = function (RED) {
|
|
|
20
20
|
RED.nodes.createNode(this, config);
|
|
21
21
|
const node = this;
|
|
22
22
|
|
|
23
|
-
node.name
|
|
24
|
-
node.
|
|
25
|
-
node.
|
|
26
|
-
node.
|
|
23
|
+
node.name = config.name || '';
|
|
24
|
+
node.protocol = config.protocol || 'tcp';
|
|
25
|
+
node.bindHost = config.bindHost || '0.0.0.0';
|
|
26
|
+
node.bindPort = parseInt(config.bindPort, 10) || 1502;
|
|
27
|
+
node.unitId = parseInt(config.unitId, 10) || 1;
|
|
28
|
+
node.serialPort = config.serialPort || '';
|
|
29
|
+
node.baudRate = parseInt(config.baudRate, 10) || 9600;
|
|
30
|
+
node.parity = config.parity || 'none';
|
|
31
|
+
node.dataBits = parseInt(config.dataBits, 10) || 8;
|
|
32
|
+
node.stopBits = parseInt(config.stopBits, 10) || 1;
|
|
27
33
|
|
|
28
34
|
// ── Register store
|
|
29
35
|
const store = {
|
|
@@ -50,39 +56,58 @@ module.exports = function (RED) {
|
|
|
50
56
|
stored.forEach((v, i) => { arr[address + i] = v; });
|
|
51
57
|
};
|
|
52
58
|
|
|
53
|
-
// ── Modbus TCP
|
|
59
|
+
// ── Modbus server (TCP or RTU)
|
|
54
60
|
let server = null;
|
|
61
|
+
const emit = (direction, type, address, values) => {
|
|
62
|
+
try {
|
|
63
|
+
node.send({
|
|
64
|
+
payload: {
|
|
65
|
+
ts: new Date().toISOString(),
|
|
66
|
+
direction, type, address,
|
|
67
|
+
values: Array.isArray(values) ? values : [values],
|
|
68
|
+
protocol: node.protocol,
|
|
69
|
+
unitId: node.unitId
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
} catch (_) { /* never let listener errors break the slave */ }
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const vector = {
|
|
76
|
+
getCoil: (addr, _u, cb) => { const v = store.coils[addr]; emit('read', 'coils', addr, v); cb(null, v); },
|
|
77
|
+
getDiscreteInput: (addr, _u, cb) => { const v = store.discrete[addr]; emit('read', 'discrete', addr, v); cb(null, v); },
|
|
78
|
+
getHoldingRegister: (addr, _u, cb) => { const v = store.holding[addr]; emit('read', 'holding', addr, v); cb(null, v); },
|
|
79
|
+
getInputRegister: (addr, _u, cb) => { const v = store.input[addr]; emit('read', 'input', addr, v); cb(null, v); },
|
|
80
|
+
setCoil: (addr, val, _u, cb) => { store.coils[addr] = !!val; emit('write', 'coils', addr, !!val); cb(null); },
|
|
81
|
+
setRegister: (addr, val, _u, cb) => { const v = val & 0xFFFF; store.holding[addr] = v; emit('write', 'holding', addr, v); cb(null); }
|
|
82
|
+
};
|
|
83
|
+
|
|
55
84
|
try {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
}
|
|
82
|
-
server.on('socketError', (err) => node.warn(`[slave-server] socket: ${err.message}`));
|
|
83
|
-
server.on('serverError', (err) => node.error(`[slave-server] server: ${err.message}`));
|
|
84
|
-
node.log(`[modpackqt] slave server listening on ${node.bindHost}:${node.bindPort} #${node.unitId}`);
|
|
85
|
-
node.status({ fill: 'green', shape: 'dot', text: `listening :${node.bindPort} #${node.unitId}` });
|
|
85
|
+
if (node.protocol === 'rtu') {
|
|
86
|
+
if (!node.serialPort) throw new Error('Serial port path is required for RTU mode');
|
|
87
|
+
server = new ModbusRTU.ServerSerial(vector, {
|
|
88
|
+
port: node.serialPort,
|
|
89
|
+
baudRate: node.baudRate,
|
|
90
|
+
parity: node.parity,
|
|
91
|
+
dataBits: node.dataBits,
|
|
92
|
+
stopBits: node.stopBits,
|
|
93
|
+
unitID: node.unitId
|
|
94
|
+
});
|
|
95
|
+
server.on('socketError', (err) => node.warn(`[slave-server] serial: ${err.message}`));
|
|
96
|
+
server.on('serverError', (err) => node.error(`[slave-server] serial: ${err.message}`));
|
|
97
|
+
node.log(`[modpackqt] RTU slave listening on ${node.serialPort} #${node.unitId}`);
|
|
98
|
+
node.status({ fill: 'green', shape: 'dot', text: `RTU ${node.serialPort} #${node.unitId}` });
|
|
99
|
+
} else {
|
|
100
|
+
server = new ModbusRTU.ServerTCP(vector, {
|
|
101
|
+
host: node.bindHost,
|
|
102
|
+
port: node.bindPort,
|
|
103
|
+
debug: false,
|
|
104
|
+
unitID: node.unitId
|
|
105
|
+
});
|
|
106
|
+
server.on('socketError', (err) => node.warn(`[slave-server] socket: ${err.message}`));
|
|
107
|
+
server.on('serverError', (err) => node.error(`[slave-server] server: ${err.message}`));
|
|
108
|
+
node.log(`[modpackqt] TCP slave listening on ${node.bindHost}:${node.bindPort} #${node.unitId}`);
|
|
109
|
+
node.status({ fill: 'green', shape: 'dot', text: `TCP :${node.bindPort} #${node.unitId}` });
|
|
110
|
+
}
|
|
86
111
|
} catch (err) {
|
|
87
112
|
node.error(`Failed to start slave server: ${err.message}`);
|
|
88
113
|
node.status({ fill: 'red', shape: 'ring', text: 'failed to start' });
|
|
@@ -93,16 +118,14 @@ module.exports = function (RED) {
|
|
|
93
118
|
id: node.id,
|
|
94
119
|
kind: 'slave',
|
|
95
120
|
describe(_detailed = false) {
|
|
121
|
+
const target = node.protocol === 'rtu'
|
|
122
|
+
? { mode: 'rtu', serialPort: node.serialPort, baudRate: node.baudRate, parity: node.parity, dataBits: node.dataBits, stopBits: node.stopBits, unitId: node.unitId }
|
|
123
|
+
: { mode: 'tcp', host: node.bindHost, port: node.bindPort, unitId: node.unitId };
|
|
96
124
|
return {
|
|
97
125
|
id: node.id,
|
|
98
126
|
kind: 'slave',
|
|
99
|
-
name: node.name || `Slave :${node.bindPort} #${node.unitId}
|
|
100
|
-
target
|
|
101
|
-
mode: 'tcp',
|
|
102
|
-
host: node.bindHost,
|
|
103
|
-
port: node.bindPort,
|
|
104
|
-
unitId: node.unitId
|
|
105
|
-
},
|
|
127
|
+
name: node.name || (node.protocol === 'rtu' ? `RTU Slave ${node.serialPort} #${node.unitId}` : `Slave :${node.bindPort} #${node.unitId}`),
|
|
128
|
+
target,
|
|
106
129
|
status: server ? 'listening' : 'error'
|
|
107
130
|
};
|
|
108
131
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-red-contrib-modbus-modpackqt",
|
|
3
|
-
"version": "3.3.
|
|
3
|
+
"version": "3.3.30",
|
|
4
4
|
"description": "Modbus commissioning, testing & analysis tools for Node-RED. Embedded Modbus TCP/RTU master + slave server, FC1/FC2/FC3/FC4 reads, FC5/FC6/FC15/FC16 writes, built-in slave register store, and a passive traffic monitor for debugging. 100% free, MIT, no usage limits. By ModPackQT — open the matching web console at modpackqt.com for register decoding, simulation and AI assistance.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"node-red",
|