node-red-contrib-modbus-modpackqt 3.3.19 → 3.3.21

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,28 @@ 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.21] — 2026-05-10
8
+
9
+ ### Changed
10
+
11
+ - **All ModPackQT nodes now use the ModPackQT logo as their icon**
12
+ (the white chart-line mark) instead of generic Font Awesome icons.
13
+ Easier to spot ModPackQT nodes at a glance in any flow.
14
+
15
+ ## [3.3.20] — 2026-05-10
16
+
17
+ ### Fixed
18
+
19
+ - **Slave-read / slave-write Slave Server dropdown now actually
20
+ finds the slave-server nodes on the canvas.** The picker walks
21
+ three Node-RED APIs (`eachNode`, `eachConfig`, `filterNodes`)
22
+ and dedupes — robust against the API quirks that left the list
23
+ empty even with deployed slave-server nodes present.
24
+ - Added a refresh button next to the dropdown so you can reload
25
+ without closing the dialog after dropping a new slave-server.
26
+ - Hint text now reports how many slave servers were found, or
27
+ tells you what to do if none.
28
+
7
29
  ## [3.3.19] — 2026-05-10
8
30
 
9
31
  ### Changed
@@ -0,0 +1,5 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
2
+ <path d="M14 70 L32 32 L48 60 L64 26 L82 56" fill="none" stroke="#ffffff" stroke-width="11" stroke-linecap="round" stroke-linejoin="round"/>
3
+ <circle cx="14" cy="70" r="6" fill="#ffffff"/>
4
+ <circle cx="82" cy="56" r="6" fill="#ffffff"/>
5
+ </svg>
@@ -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.21';
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;
@@ -14,7 +14,7 @@
14
14
  },
15
15
  inputs: 0,
16
16
  outputs: 0,
17
- icon: 'font-awesome/fa-rocket',
17
+ icon: 'modpackqt.svg',
18
18
  label: function () {
19
19
  return this.name || 'master probe';
20
20
  },
@@ -17,7 +17,7 @@
17
17
  },
18
18
  inputs: 1,
19
19
  outputs: 1,
20
- icon: 'font-awesome/fa-download',
20
+ icon: 'modpackqt.svg',
21
21
  label: function () {
22
22
  return this.name || `Master Read FC${this.functionCode} @${this.address}`;
23
23
  },
@@ -14,7 +14,7 @@
14
14
  },
15
15
  inputs: 1,
16
16
  outputs: 1,
17
- icon: 'font-awesome/fa-upload',
17
+ icon: 'modpackqt.svg',
18
18
  label: function () {
19
19
  return this.name || `Master Write FC${this.functionCode} @${this.address}`;
20
20
  },
@@ -14,7 +14,7 @@
14
14
  },
15
15
  inputs: 0,
16
16
  outputs: 0,
17
- icon: 'font-awesome/fa-server',
17
+ icon: 'modpackqt.svg',
18
18
  label: function () {
19
19
  return this.name || `slave probe :${this.bindPort} #${this.unitId}`;
20
20
  },
@@ -12,20 +12,44 @@
12
12
  },
13
13
  inputs: 1,
14
14
  outputs: 1,
15
- icon: 'font-awesome/fa-server',
15
+ icon: 'modpackqt.svg',
16
16
  label: function () {
17
17
  return this.name || ('Slave Read ' + (this.registerType || 'holding') + ' @' + this.address);
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">
@@ -15,7 +15,7 @@
15
15
  outputs: 1,
16
16
  outputLabels: ['external client read/write events'],
17
17
  align: 'right',
18
- icon: 'font-awesome/fa-server',
18
+ icon: 'modpackqt.svg',
19
19
  label: function () {
20
20
  const tag = `:${this.bindPort || 1502} #${this.unitId || 1}`;
21
21
  return this.name ? `${this.name} — Modbus TCP Slave ${tag}`
@@ -12,20 +12,47 @@
12
12
  },
13
13
  inputs: 1,
14
14
  outputs: 1,
15
- icon: 'font-awesome/fa-hdd-o',
15
+ icon: 'modpackqt.svg',
16
16
  label: function () {
17
17
  return this.name || ('Slave Write ' + (this.registerType || 'holding') + ' @' + this.address);
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.21",
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",
@@ -33,6 +33,7 @@
33
33
  },
34
34
  "files": [
35
35
  "nodes/",
36
+ "icons/",
36
37
  "examples/",
37
38
  "README.md",
38
39
  "LICENSE",