node-red-contrib-modbus-modpackqt 3.3.10 → 3.3.12

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,32 @@ 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.12] — 2026-05-10
8
+
9
+ ### Changed
10
+
11
+ - **Two separate config node types now.** Master-read and master-write
12
+ use the original `modpackqt-config` (full editable Target Device,
13
+ Transport, embedded slave server) — restored after v3.3.11.
14
+ Master-probe uses a new minimal `modpackqt-probe-config` —
15
+ Name + Account Key + My Connections only, no manual fields. Existing
16
+ flows that wired master-probe to a `modpackqt-config` need to pick
17
+ a probe-config instead (the dropdown will only show valid types).
18
+
19
+ ## [3.3.11] — 2026-05-10
20
+
21
+ ### Changed
22
+
23
+ - **Config dialog is now picker-only.** Hand-edited Target Device
24
+ (IP / Port / Unit ID), Transport (Mode / Serial / Baud / Parity /
25
+ Timeout) and the collapsible embedded-slave-server section have all
26
+ been removed from the runtime config dialog. Everything is set by
27
+ the **My Connections** picker, which auto-fills hidden fields the
28
+ runtime still uses. Same dialog appears regardless of whether you
29
+ open it from a master-read, master-write, or master-probe node.
30
+ To run an embedded Modbus TCP slave, drop a `modpackqt-slave-server`
31
+ node onto the canvas (it has its own My Slaves picker).
32
+
7
33
  ## [3.3.10] — 2026-05-10
8
34
 
9
35
  ### Removed
@@ -18,7 +18,7 @@
18
18
  const http = require('http');
19
19
  const { URL } = require('url');
20
20
 
21
- const PALETTE_VERSION = '3.3.10';
21
+ const PALETTE_VERSION = '3.3.12';
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;
@@ -4,7 +4,7 @@
4
4
  color: '#7c3aed',
5
5
  defaults: {
6
6
  name: { value: '' },
7
- server: { value: '', type: 'modpackqt-config', required: true },
7
+ server: { value: '', type: 'modpackqt-probe-config', required: true },
8
8
  // Legacy per-node fields — kept hidden so old flows keep working.
9
9
  targetHost: { value: '' },
10
10
  targetPort: { value: 0, validate: function (v) { return v === '' || v === 0 || RED.validators.number()(v); } },
@@ -0,0 +1,154 @@
1
+ <script type="text/javascript">
2
+ RED.nodes.registerType('modpackqt-probe-config', {
3
+ category: 'config',
4
+ credentials: {
5
+ apiKey: { type: 'password' }
6
+ },
7
+ defaults: {
8
+ name: { value: 'ModPackQT Device' },
9
+ targetHost: { value: 'localhost' },
10
+ targetPort: { value: 502, validate: RED.validators.number() },
11
+ unitId: { value: 1, validate: RED.validators.number() },
12
+ masterMode: { value: 'tcp', required: true },
13
+ serialPort: { value: '' },
14
+ baudRate: { value: 9600 },
15
+ parity: { value: 'none' },
16
+ dataBits: { value: 8 },
17
+ stopBits: { value: 1 },
18
+ timeoutMs: { value: 3000, validate: RED.validators.number() },
19
+ slaveEnabled: { value: false },
20
+ slaveHost: { value: '0.0.0.0' },
21
+ slavePort: { value: 1502, validate: RED.validators.number() }
22
+ },
23
+ label: function () {
24
+ const t = this.masterMode === 'rtu'
25
+ ? `RTU ${this.serialPort || '?'} #${this.unitId || 1}`
26
+ : `${this.targetHost || 'localhost'}:${this.targetPort || 502} #${this.unitId || 1}`;
27
+ const s = this.slaveEnabled ? ` + slave :${this.slavePort}` : '';
28
+ return this.name && this.name !== 'ModPackQT Device' ? `${this.name} (${t})` : `${t}${s}`;
29
+ },
30
+ oneditprepare: function () {
31
+ // ── My Connections picker
32
+ const nodeId = this.id;
33
+ const $sel = $('#node-config-input-modpackqt-conn-picker');
34
+ const loadConnections = function () {
35
+ $sel.empty().append('<option value="">— Loading… —</option>');
36
+ if (!nodeId) {
37
+ $sel.empty().append('<option value="">— Save this config first, then reopen —</option>');
38
+ return;
39
+ }
40
+ $.getJSON('modpackqt/connections?probe=' + encodeURIComponent(nodeId))
41
+ .done(function (rows) {
42
+ $sel.empty().append('<option value="">— Manual entry —</option>');
43
+ (rows || []).forEach(function (c) {
44
+ const label = (c.name || '(unnamed)') + (c.connectionType === 'rtu'
45
+ ? ' — RTU'
46
+ : ' — ' + (c.host || '?') + ':' + (c.port || 502) + ' #' + (c.unitId || 1));
47
+ $('<option>').val(c.id).text(label).data('conn', c).appendTo($sel);
48
+ });
49
+ })
50
+ .fail(function (xhr) {
51
+ const msg = (xhr.responseJSON && xhr.responseJSON.error) || ('HTTP ' + xhr.status);
52
+ $sel.empty().append($('<option>').val('').text('— ' + msg + ' —'));
53
+ });
54
+ };
55
+ $('#modpackqt-conn-picker-refresh').on('click', function (e) {
56
+ e.preventDefault();
57
+ loadConnections();
58
+ });
59
+ $sel.on('change', function () {
60
+ const c = $(this).find('option:selected').data('conn');
61
+ if (!c) return;
62
+ if (!$('#node-config-input-name').val() || $('#node-config-input-name').val() === 'ModPackQT Device') {
63
+ $('#node-config-input-name').val(c.name || '');
64
+ }
65
+ if (c.host) $('#node-config-input-targetHost').val(c.host);
66
+ if (c.port) $('#node-config-input-targetPort').val(c.port);
67
+ if (c.unitId) $('#node-config-input-unitId').val(c.unitId);
68
+ $('#node-config-input-masterMode').val(c.connectionType === 'rtu' ? 'rtu' : 'tcp');
69
+ });
70
+ loadConnections();
71
+ }
72
+ });
73
+ </script>
74
+
75
+ <script type="text/html" data-template-name="modpackqt-probe-config">
76
+ <div class="form-row">
77
+ <label for="node-config-input-name"><i class="fa fa-tag"></i> Name</label>
78
+ <input type="text" id="node-config-input-name" placeholder="e.g. Inverter A">
79
+ </div>
80
+
81
+ <div class="form-row">
82
+ <label for="node-config-input-apiKey"><i class="fa fa-key"></i> Account Key</label>
83
+ <input type="password" id="node-config-input-apiKey" placeholder="Paste your ModPackQT tunnel key">
84
+ </div>
85
+ <div class="form-tips" style="font-size:11px;color:#6b7280;margin:-8px 0 4px 105px">
86
+ Generate at <a href="https://modpackqt.com/settings" target="_blank" rel="noopener">modpackqt.com → Settings → Cloud Gateways</a>.
87
+ Loads your saved connections in the picker below.
88
+ </div>
89
+
90
+ <div class="form-row">
91
+ <label for="node-config-input-modpackqt-conn-picker"><i class="fa fa-cloud-download"></i> My Connections</label>
92
+ <select id="node-config-input-modpackqt-conn-picker" style="width:65%"></select>
93
+ <button type="button" id="modpackqt-conn-picker-refresh" class="red-ui-button" title="Reload" style="margin-left:4px"><i class="fa fa-refresh"></i></button>
94
+ </div>
95
+ <div class="form-tips" style="font-size:11px;color:#6b7280;margin:-8px 0 12px 105px">
96
+ Picks a saved connection from modpackqt.com — auto-fills Host, Port, and Unit ID below.
97
+ </div>
98
+
99
+ <!-- All connection details (host/port/unit/mode/timeout/embedded-slave) are
100
+ set by the My Connections picker above. They live as hidden inputs so
101
+ the runtime still has them, but they are no longer hand-edited here. -->
102
+ <input type="hidden" id="node-config-input-targetHost">
103
+ <input type="hidden" id="node-config-input-targetPort">
104
+ <input type="hidden" id="node-config-input-unitId">
105
+ <input type="hidden" id="node-config-input-masterMode">
106
+ <input type="hidden" id="node-config-input-serialPort">
107
+ <input type="hidden" id="node-config-input-baudRate">
108
+ <input type="hidden" id="node-config-input-parity">
109
+ <input type="hidden" id="node-config-input-dataBits">
110
+ <input type="hidden" id="node-config-input-stopBits">
111
+ <input type="hidden" id="node-config-input-timeoutMs">
112
+ <input type="hidden" id="node-config-input-slaveEnabled">
113
+ <input type="hidden" id="node-config-input-slaveHost">
114
+ <input type="hidden" id="node-config-input-slavePort">
115
+
116
+ <div class="form-tips" style="margin-top:14px">
117
+ <b>One device per config.</b> Use the picker above to choose which saved
118
+ Modbus device this config talks to. For more devices, create another
119
+ config and pick a different one.
120
+ </div>
121
+ <div class="form-row" style="margin-top:18px;padding-top:14px;border-top:1px solid #e5e7eb;text-align:center;">
122
+ <a href="https://modpackqt.com" target="_blank" rel="noopener noreferrer"
123
+ style="display:inline-block;padding:8px 20px;background:#2563eb;color:#fff;
124
+ text-decoration:none;border-radius:6px;font-weight:600;font-size:13px;
125
+ box-shadow:0 1px 2px rgba(0,0,0,0.08);">
126
+ Premium Advanced Modbus Tester <i class="fa fa-external-link" style="margin-left:6px;"></i>
127
+ </a>
128
+ <div style="margin-top:6px;font-size:11px;color:#6b7280;">by ModPackQT &mdash; full-featured web tester, simulator &amp; AI helper</div>
129
+ </div>
130
+ </script>
131
+
132
+ <script type="text/html" data-help-name="modpackqt-probe-config">
133
+ <p>
134
+ Defines <b>one Modbus device</b> plus the embedded runtime that talks to it. Master and
135
+ probe nodes simply pick which runtime config to use — no need to retype host/port/unit
136
+ on every node.
137
+ </p>
138
+
139
+ <h3>One runtime = one device</h3>
140
+ <p>
141
+ For each remote Modbus device you want to read/write, create a separate runtime config.
142
+ Each carries its own Host / Port / Unit ID. Read and write nodes inherit those — they
143
+ only need to know the function code, address, and quantity.
144
+ </p>
145
+
146
+ <h3>Where do the connection details come from?</h3>
147
+ <p>
148
+ Paste your <b>Account Key</b>, then pick a saved device from <b>My
149
+ Connections</b>. The host, port, unit ID, and transport mode are all
150
+ pulled from your modpackqt.com profile — no hand-editing needed here.
151
+ To run an embedded Modbus TCP slave server, drop a
152
+ <code>modpackqt-slave-server</code> node onto the canvas instead.
153
+ </p>
154
+ </script>
@@ -0,0 +1,19 @@
1
+ /**
2
+ * ModPackQT Probe Config — lightweight config node used by master-probe only.
3
+ *
4
+ * No embedded Modbus runtime, no slave server, no master client pool.
5
+ * Just stores: account key (credential) + a chosen device's host / port /
6
+ * unit ID, all populated by the My Connections picker. Master-probe reads
7
+ * those to build its deep-link URL into the modpackqt.com web console.
8
+ */
9
+ module.exports = function (RED) {
10
+ function ModPackQTProbeConfigNode(config) {
11
+ RED.nodes.createNode(this, config);
12
+ this.targetHost = config.targetHost || '';
13
+ this.targetPort = parseInt(config.targetPort, 10) || 502;
14
+ this.unitId = parseInt(config.unitId, 10) || 1;
15
+ }
16
+ RED.nodes.registerType('modpackqt-probe-config', ModPackQTProbeConfigNode, {
17
+ credentials: { apiKey: { type: 'password' } }
18
+ });
19
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-red-contrib-modbus-modpackqt",
3
- "version": "3.3.10",
3
+ "version": "3.3.12",
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",
@@ -45,6 +45,7 @@
45
45
  "version": ">=2.0.0",
46
46
  "nodes": {
47
47
  "modpackqt-config": "nodes/modpackqt-config.js",
48
+ "modpackqt-probe-config": "nodes/modpackqt-probe-config.js",
48
49
  "modpackqt-master-read": "nodes/modpackqt-master-read.js",
49
50
  "modpackqt-master-write": "nodes/modpackqt-master-write.js",
50
51
  "modpackqt-slave-read": "nodes/modpackqt-slave-read.js",