node-red-contrib-modbus-modpackqt 3.3.19 → 3.3.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/CHANGELOG.md CHANGED
@@ -4,6 +4,20 @@ All notable changes to **node-red-contrib-modbus-modpackqt** are documented
4
4
  here. This project follows [Semantic Versioning](https://semver.org/) — pin a
5
5
  major version (`^2.0.0`) in production.
6
6
 
7
+ ## [3.3.20] — 2026-05-10
8
+
9
+ ### Fixed
10
+
11
+ - **Slave-read / slave-write Slave Server dropdown now actually
12
+ finds the slave-server nodes on the canvas.** The picker walks
13
+ three Node-RED APIs (`eachNode`, `eachConfig`, `filterNodes`)
14
+ and dedupes — robust against the API quirks that left the list
15
+ empty even with deployed slave-server nodes present.
16
+ - Added a refresh button next to the dropdown so you can reload
17
+ without closing the dialog after dropping a new slave-server.
18
+ - Hint text now reports how many slave servers were found, or
19
+ tells you what to do if none.
20
+
7
21
  ## [3.3.19] — 2026-05-10
8
22
 
9
23
  ### Changed
@@ -18,7 +18,7 @@
18
18
  const http = require('http');
19
19
  const { URL } = require('url');
20
20
 
21
- const PALETTE_VERSION = '3.3.19';
21
+ const PALETTE_VERSION = '3.3.20';
22
22
  const DEFAULT_PORT = parseInt(process.env.MODPACKQT_PROBE_PORT, 10) || 8502;
23
23
  const BIND_HOST = process.env.MODPACKQT_PROBE_HOST || '127.0.0.1';
24
24
  const PORT_RETRY = 5;
@@ -18,14 +18,38 @@
18
18
  },
19
19
  paletteLabel: 'modbus slave read',
20
20
  oneditprepare: function () {
21
+ const node = this;
21
22
  const $sel = $('#node-input-slaveServerId');
22
- $sel.empty().append('<option value="">— select a slave server node —</option>');
23
- RED.nodes.eachNode(function (n) {
24
- if (n.type === 'modpackqt-slave-server') {
25
- const label = (n.name || (':' + n.bindPort + ' #' + n.unitId));
26
- $('<option>').val(n.id).text(label).appendTo($sel);
23
+ const $hint = $('#modpackqt-slave-read-hint');
24
+ const reload = function () {
25
+ const seen = new Set();
26
+ const found = [];
27
+ const addIfMatch = function (n) {
28
+ if (!n || seen.has(n.id)) return;
29
+ if (n.type === 'modpackqt-slave-server') { seen.add(n.id); found.push(n); }
30
+ };
31
+ try { RED.nodes.eachNode(addIfMatch); } catch (_) {}
32
+ try { RED.nodes.eachConfig(addIfMatch); } catch (_) {}
33
+ try {
34
+ if (typeof RED.nodes.filterNodes === 'function') {
35
+ RED.nodes.filterNodes({ type: 'modpackqt-slave-server' }).forEach(addIfMatch);
36
+ }
37
+ } catch (_) {}
38
+ $sel.empty().append('<option value="">— select a slave server node —</option>');
39
+ if (!found.length) {
40
+ $hint.html('No <b>modbus slave server</b> nodes on the canvas yet. Drop one, click Deploy, then reopen this dialog.');
41
+ } else {
42
+ found.forEach(function (n) {
43
+ const tag = ':' + (n.bindPort || 1502) + ' #' + (n.unitId || 1);
44
+ const label = n.name ? (n.name + ' — ' + tag) : tag;
45
+ $('<option>').val(n.id).text(label).appendTo($sel);
46
+ });
47
+ $hint.text('Pick a modbus slave server node from the canvas. ' + found.length + ' available.');
27
48
  }
28
- });
49
+ if (node.slaveServerId) $sel.val(node.slaveServerId);
50
+ };
51
+ reload();
52
+ $('#modpackqt-slave-read-refresh').on('click', function (e) { e.preventDefault(); reload(); });
29
53
  }
30
54
  });
31
55
  </script>
@@ -37,9 +61,10 @@
37
61
  </div>
38
62
  <div class="form-row">
39
63
  <label for="node-input-slaveServerId"><i class="fa fa-server"></i> Slave Server</label>
40
- <select id="node-input-slaveServerId" style="width:70%"></select>
64
+ <select id="node-input-slaveServerId" style="width:65%"></select>
65
+ <button type="button" id="modpackqt-slave-read-refresh" class="red-ui-button" title="Reload" style="margin-left:4px"><i class="fa fa-refresh"></i></button>
41
66
  </div>
42
- <div class="form-tips" style="font-size:11px;color:#6b7280;margin:-8px 0 12px 105px">
67
+ <div id="modpackqt-slave-read-hint" class="form-tips" style="font-size:11px;color:#6b7280;margin:-8px 0 12px 105px">
43
68
  Pick a <b>modbus slave server</b> node from the canvas. Deploy the flow first if the list is empty.
44
69
  </div>
45
70
  <div class="form-row">
@@ -18,14 +18,41 @@
18
18
  },
19
19
  paletteLabel: 'modbus slave write',
20
20
  oneditprepare: function () {
21
+ const node = this;
21
22
  const $sel = $('#node-input-slaveServerId');
22
- $sel.empty().append('<option value="">— select a slave server node —</option>');
23
- RED.nodes.eachNode(function (n) {
24
- if (n.type === 'modpackqt-slave-server') {
25
- const label = (n.name || (':' + n.bindPort + ' #' + n.unitId));
26
- $('<option>').val(n.id).text(label).appendTo($sel);
23
+ const $hint = $('#modpackqt-slave-write-hint');
24
+ const reload = function () {
25
+ const seen = new Set();
26
+ const found = [];
27
+ const addIfMatch = function (n) {
28
+ if (!n || seen.has(n.id)) return;
29
+ if (n.type === 'modpackqt-slave-server') { seen.add(n.id); found.push(n); }
30
+ };
31
+ // Walk every known source — eachNode (regular flow nodes), eachConfig
32
+ // (configs) and filterNodes (everything by type) — to be robust against
33
+ // Node-RED API quirks where freshly-added nodes might miss one list.
34
+ try { RED.nodes.eachNode(addIfMatch); } catch (_) {}
35
+ try { RED.nodes.eachConfig(addIfMatch); } catch (_) {}
36
+ try {
37
+ if (typeof RED.nodes.filterNodes === 'function') {
38
+ RED.nodes.filterNodes({ type: 'modpackqt-slave-server' }).forEach(addIfMatch);
39
+ }
40
+ } catch (_) {}
41
+ $sel.empty().append('<option value="">— select a slave server node —</option>');
42
+ if (!found.length) {
43
+ $hint.html('No <b>modbus slave server</b> nodes on the canvas yet. Drop one, click Deploy, then reopen this dialog.');
44
+ } else {
45
+ found.forEach(function (n) {
46
+ const tag = ':' + (n.bindPort || 1502) + ' #' + (n.unitId || 1);
47
+ const label = n.name ? (n.name + ' — ' + tag) : tag;
48
+ $('<option>').val(n.id).text(label).appendTo($sel);
49
+ });
50
+ $hint.text('Pick a modbus slave server node from the canvas. ' + found.length + ' available.');
27
51
  }
28
- });
52
+ if (node.slaveServerId) $sel.val(node.slaveServerId);
53
+ };
54
+ reload();
55
+ $('#modpackqt-slave-write-refresh').on('click', function (e) { e.preventDefault(); reload(); });
29
56
  }
30
57
  });
31
58
  </script>
@@ -37,9 +64,10 @@
37
64
  </div>
38
65
  <div class="form-row">
39
66
  <label for="node-input-slaveServerId"><i class="fa fa-server"></i> Slave Server</label>
40
- <select id="node-input-slaveServerId" style="width:70%"></select>
67
+ <select id="node-input-slaveServerId" style="width:65%"></select>
68
+ <button type="button" id="modpackqt-slave-write-refresh" class="red-ui-button" title="Reload" style="margin-left:4px"><i class="fa fa-refresh"></i></button>
41
69
  </div>
42
- <div class="form-tips" style="font-size:11px;color:#6b7280;margin:-8px 0 12px 105px">
70
+ <div id="modpackqt-slave-write-hint" class="form-tips" style="font-size:11px;color:#6b7280;margin:-8px 0 12px 105px">
43
71
  Pick a <b>modbus slave server</b> node from the canvas. Deploy the flow first if the list is empty.
44
72
  </div>
45
73
  <div class="form-row">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-red-contrib-modbus-modpackqt",
3
- "version": "3.3.19",
3
+ "version": "3.3.20",
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",