node-red-contrib-modbus-modpackqt 3.2.0 → 3.2.1

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.2.1] — 2026-05-10
8
+
9
+ ### Changed — Picker-first node UI
10
+
11
+ - **"My Profiles" / "My Slaves" dropdown is now the primary input** on
12
+ master-read, master-write, master-probe and slave-probe. Pick a saved
13
+ device from your modpackqt.com account and the node is configured.
14
+ - **Runtime config + manual Host/Port/Unit/Timeout fields are now
15
+ hidden** under a small **▸ Advanced — runtime config & manual entry**
16
+ toggle. Auto-expanded for first-time setup (no runtime configured),
17
+ collapsed once you have a runtime + Account Key set up.
18
+ - No behaviour change for existing flows — fields, defaults and
19
+ validation are identical to v3.2.0.
20
+
7
21
  ## [3.2.0] — 2026-05-10
8
22
 
9
23
  ### Added — Cloud profile pickers
@@ -18,7 +18,7 @@
18
18
  const http = require('http');
19
19
  const { URL } = require('url');
20
20
 
21
- const PALETTE_VERSION = '3.2.0';
21
+ const PALETTE_VERSION = '3.2.1';
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;
@@ -19,8 +19,8 @@
19
19
  paletteLabel: 'modbus master probe',
20
20
  oneditprepare: function () {
21
21
  const node = this;
22
- // Optional cloud profile picker (fills targetHost/targetPort/unitId)
23
22
  if (window.ModPackQTMasterPicker) ModPackQTMasterPicker.attach(this);
23
+ if (window.ModPackQTAdvancedToggle) ModPackQTAdvancedToggle.attach('modpackqt-master-probe');
24
24
  const buildLink = (info) => {
25
25
  const probeHost = (info && info.host) || '127.0.0.1';
26
26
  const probePort = (info && info.port) || 8502;
@@ -49,35 +49,42 @@
49
49
  <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
50
50
  <input type="text" id="node-input-name" placeholder="(optional, e.g. Inverter A)">
51
51
  </div>
52
- <div class="form-row">
53
- <label for="node-input-server"><i class="fa fa-cog"></i> Runtime <span style="color:#9ca3af;font-weight:normal">(for picker)</span></label>
54
- <input type="text" id="node-input-server">
55
- </div>
56
52
  <div class="form-row">
57
53
  <label for="node-input-modpackqt-picker"><i class="fa fa-cloud-download"></i> My Profiles</label>
58
54
  <select id="node-input-modpackqt-picker" style="width:65%"></select>
59
55
  <button type="button" id="modpackqt-picker-refresh" class="red-ui-button" title="Reload from modpackqt.com" style="margin-left:4px"><i class="fa fa-refresh"></i></button>
60
56
  </div>
61
- <div class="form-tips" style="font-size:11px;color:#6b7280;margin:-8px 0 8px 105px">
62
- Pick a saved Modbus profile from your account — fills host/port/unit below. Requires Account Key on the runtime config.
63
- </div>
64
- <div class="form-row">
65
- <label for="node-input-targetHost"><i class="fa fa-plug"></i> Target Host</label>
66
- <input type="text" id="node-input-targetHost" placeholder="192.168.1.10">
67
- </div>
68
- <div class="form-row">
69
- <label for="node-input-targetPort"><i class="fa fa-hashtag"></i> Target Port</label>
70
- <input type="number" id="node-input-targetPort" min="1" max="65535" placeholder="502">
57
+ <div class="form-tips" style="font-size:11px;color:#6b7280;margin:-8px 0 12px 105px">
58
+ Pick a saved Modbus profile from your modpackqt.com account — auto-fills host/port/unit. Set up your Account Key under <b>Advanced</b> below.
71
59
  </div>
72
- <div class="form-row">
73
- <label for="node-input-unitId"><i class="fa fa-id-card"></i> Unit ID</label>
74
- <input type="number" id="node-input-unitId" min="1" max="247" placeholder="1">
60
+
61
+ <div class="form-row" style="margin:14px 0 4px 0;border-top:1px solid #e5e7eb;padding-top:10px">
62
+ <a href="#" class="modpackqt-advanced-toggle" style="font-size:12px;color:#6b7280;text-decoration:none;cursor:pointer">▸ Advanced — runtime config &amp; manual entry</a>
75
63
  </div>
76
- <div class="form-row">
77
- <label for="node-input-timeoutMs"><i class="fa fa-clock-o"></i> Timeout (ms)</label>
78
- <input type="number" id="node-input-timeoutMs" placeholder="3000">
64
+ <div class="modpackqt-advanced" style="display:none">
65
+ <div class="form-row">
66
+ <label for="node-input-server"><i class="fa fa-cog"></i> Runtime</label>
67
+ <input type="text" id="node-input-server">
68
+ </div>
69
+ <div class="form-row">
70
+ <label for="node-input-targetHost"><i class="fa fa-plug"></i> Target Host</label>
71
+ <input type="text" id="node-input-targetHost" placeholder="192.168.1.10">
72
+ </div>
73
+ <div class="form-row">
74
+ <label for="node-input-targetPort"><i class="fa fa-hashtag"></i> Target Port</label>
75
+ <input type="number" id="node-input-targetPort" min="1" max="65535" placeholder="502">
76
+ </div>
77
+ <div class="form-row">
78
+ <label for="node-input-unitId"><i class="fa fa-id-card"></i> Unit ID</label>
79
+ <input type="number" id="node-input-unitId" min="1" max="247" placeholder="1">
80
+ </div>
81
+ <div class="form-row">
82
+ <label for="node-input-timeoutMs"><i class="fa fa-clock-o"></i> Timeout (ms)</label>
83
+ <input type="number" id="node-input-timeoutMs" placeholder="3000">
84
+ </div>
79
85
  </div>
80
- <div class="form-tips">
86
+
87
+ <div class="form-tips" style="margin-top:14px">
81
88
  <b>One probe = one device.</b> Drop additional master-probe nodes for additional devices —
82
89
  the web console aggregates them all into a unified sidebar.
83
90
  </div>
@@ -20,7 +20,10 @@
20
20
  return this.name || `Master Read FC${this.functionCode} @${this.address}`;
21
21
  },
22
22
  paletteLabel: 'modbus master read',
23
- oneditprepare: function () { ModPackQTMasterPicker.attach(this); }
23
+ oneditprepare: function () {
24
+ ModPackQTMasterPicker.attach(this);
25
+ if (window.ModPackQTAdvancedToggle) ModPackQTAdvancedToggle.attach('modpackqt-master-read');
26
+ }
24
27
  });
25
28
  </script>
26
29
 
@@ -35,12 +38,12 @@
35
38
  const cfgId = $('#node-input-server').val();
36
39
  $sel.empty().append('<option value="">— Loading… —</option>');
37
40
  if (!cfgId || cfgId === '_ADD_') {
38
- $sel.empty().append('<option value="">— Set runtime config first —</option>');
41
+ $sel.empty().append('<option value="">— Set up runtime &amp; Account Key under Advanced —</option>');
39
42
  return;
40
43
  }
41
44
  $.getJSON('modpackqt/connections?config=' + encodeURIComponent(cfgId))
42
45
  .done(function (rows) {
43
- $sel.empty().append('<option value="">— Manual entry below —</option>');
46
+ $sel.empty().append('<option value="">— Manual entry (see Advanced) —</option>');
44
47
  (rows || [])
45
48
  .filter(function (c) { return c && (c.connectionType === 'tcp' || !c.connectionType); })
46
49
  .forEach(function (c) {
@@ -66,6 +69,27 @@
66
69
  }
67
70
  };
68
71
  }
72
+ if (!window.ModPackQTAdvancedToggle) {
73
+ window.ModPackQTAdvancedToggle = {
74
+ attach: function (/* nodeType */) {
75
+ const $adv = $('.modpackqt-advanced');
76
+ const $tog = $('.modpackqt-advanced-toggle');
77
+ if (!$adv.length || !$tog.length) return;
78
+ const setOpen = function (open) {
79
+ $adv.toggle(open);
80
+ $tog.html((open ? '▾ Hide advanced' : '▸ Advanced — runtime config &amp; manual entry'));
81
+ };
82
+ // Auto-expand if runtime not yet configured
83
+ const cfgId = $('#node-input-server').val();
84
+ const needsSetup = !cfgId || cfgId === '' || cfgId === '_ADD_';
85
+ setOpen(needsSetup);
86
+ $tog.off('click.modpackqt').on('click.modpackqt', function (e) {
87
+ e.preventDefault();
88
+ setOpen($adv.is(':hidden'));
89
+ });
90
+ }
91
+ };
92
+ }
69
93
  </script>
70
94
 
71
95
  <script type="text/html" data-template-name="modpackqt-master-read">
@@ -73,30 +97,15 @@
73
97
  <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
74
98
  <input type="text" id="node-input-name" placeholder="Name">
75
99
  </div>
76
- <div class="form-row">
77
- <label for="node-input-server"><i class="fa fa-cog"></i> Runtime</label>
78
- <input type="text" id="node-input-server">
79
- </div>
80
100
  <div class="form-row">
81
101
  <label for="node-input-modpackqt-picker"><i class="fa fa-cloud-download"></i> My Profiles</label>
82
102
  <select id="node-input-modpackqt-picker" style="width:65%"></select>
83
103
  <button type="button" id="modpackqt-picker-refresh" class="red-ui-button" title="Reload from modpackqt.com" style="margin-left:4px"><i class="fa fa-refresh"></i></button>
84
104
  </div>
85
- <div class="form-tips" style="font-size:11px;color:#6b7280;margin:-8px 0 8px 105px">
86
- Pick a saved Modbus profile from your account — fills host/port/unit below. Requires Account Key on the runtime config.
87
- </div>
88
- <div class="form-row">
89
- <label for="node-input-targetHost"><i class="fa fa-plug"></i> Target Host</label>
90
- <input type="text" id="node-input-targetHost" placeholder="Modbus device IP/hostname (TCP only)">
91
- </div>
92
- <div class="form-row">
93
- <label for="node-input-targetPort"><i class="fa fa-hashtag"></i> Target Port</label>
94
- <input type="number" id="node-input-targetPort" min="1" max="65535" placeholder="502">
95
- </div>
96
- <div class="form-row">
97
- <label for="node-input-unitId"><i class="fa fa-id-card"></i> Unit ID</label>
98
- <input type="number" id="node-input-unitId" min="1" max="247" placeholder="1">
105
+ <div class="form-tips" style="font-size:11px;color:#6b7280;margin:-8px 0 12px 105px">
106
+ Pick a saved Modbus profile from your modpackqt.com account — auto-fills host/port/unit. Set up your Account Key under <b>Advanced</b> below.
99
107
  </div>
108
+
100
109
  <div class="form-row">
101
110
  <label for="node-input-functionCode"><i class="fa fa-list"></i> Function Code</label>
102
111
  <select id="node-input-functionCode">
@@ -118,7 +127,30 @@
118
127
  <label for="node-input-pollInterval"><i class="fa fa-clock-o"></i> Poll Interval (ms)</label>
119
128
  <input type="number" id="node-input-pollInterval" min="0" placeholder="0 = disabled">
120
129
  </div>
121
- <div class="form-tips">
130
+
131
+ <div class="form-row" style="margin:14px 0 4px 0;border-top:1px solid #e5e7eb;padding-top:10px">
132
+ <a href="#" class="modpackqt-advanced-toggle" style="font-size:12px;color:#6b7280;text-decoration:none;cursor:pointer">▸ Advanced — runtime config &amp; manual entry</a>
133
+ </div>
134
+ <div class="modpackqt-advanced" style="display:none">
135
+ <div class="form-row">
136
+ <label for="node-input-server"><i class="fa fa-cog"></i> Runtime</label>
137
+ <input type="text" id="node-input-server">
138
+ </div>
139
+ <div class="form-row">
140
+ <label for="node-input-targetHost"><i class="fa fa-plug"></i> Target Host</label>
141
+ <input type="text" id="node-input-targetHost" placeholder="Modbus device IP/hostname (TCP only)">
142
+ </div>
143
+ <div class="form-row">
144
+ <label for="node-input-targetPort"><i class="fa fa-hashtag"></i> Target Port</label>
145
+ <input type="number" id="node-input-targetPort" min="1" max="65535" placeholder="502">
146
+ </div>
147
+ <div class="form-row">
148
+ <label for="node-input-unitId"><i class="fa fa-id-card"></i> Unit ID</label>
149
+ <input type="number" id="node-input-unitId" min="1" max="247" placeholder="1">
150
+ </div>
151
+ </div>
152
+
153
+ <div class="form-tips" style="margin-top:14px">
122
154
  <b>Output:</b> <code>msg.payload</code> = raw register array. To decode int / float / string,
123
155
  pair with <a href="https://www.npmjs.com/package/node-red-contrib-bytes-modpackqt" target="_blank">node-red-contrib-bytes-modpackqt</a>.
124
156
  </div>
@@ -18,7 +18,10 @@
18
18
  return this.name || `Master Write FC${this.functionCode} @${this.address}`;
19
19
  },
20
20
  paletteLabel: 'modbus master write',
21
- oneditprepare: function () { if (window.ModPackQTMasterPicker) ModPackQTMasterPicker.attach(this); }
21
+ oneditprepare: function () {
22
+ if (window.ModPackQTMasterPicker) ModPackQTMasterPicker.attach(this);
23
+ if (window.ModPackQTAdvancedToggle) ModPackQTAdvancedToggle.attach('modpackqt-master-write');
24
+ }
22
25
  });
23
26
  </script>
24
27
 
@@ -27,30 +30,15 @@
27
30
  <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
28
31
  <input type="text" id="node-input-name" placeholder="Name">
29
32
  </div>
30
- <div class="form-row">
31
- <label for="node-input-server"><i class="fa fa-cog"></i> Runtime</label>
32
- <input type="text" id="node-input-server">
33
- </div>
34
33
  <div class="form-row">
35
34
  <label for="node-input-modpackqt-picker"><i class="fa fa-cloud-download"></i> My Profiles</label>
36
35
  <select id="node-input-modpackqt-picker" style="width:65%"></select>
37
36
  <button type="button" id="modpackqt-picker-refresh" class="red-ui-button" title="Reload from modpackqt.com" style="margin-left:4px"><i class="fa fa-refresh"></i></button>
38
37
  </div>
39
- <div class="form-tips" style="font-size:11px;color:#6b7280;margin:-8px 0 8px 105px">
40
- Pick a saved Modbus profile from your account — fills host/port/unit below. Requires Account Key on the runtime config.
41
- </div>
42
- <div class="form-row">
43
- <label for="node-input-targetHost"><i class="fa fa-plug"></i> Target Host</label>
44
- <input type="text" id="node-input-targetHost" placeholder="Modbus device IP/hostname (TCP only)">
45
- </div>
46
- <div class="form-row">
47
- <label for="node-input-targetPort"><i class="fa fa-hashtag"></i> Target Port</label>
48
- <input type="number" id="node-input-targetPort" min="1" max="65535" placeholder="502">
49
- </div>
50
- <div class="form-row">
51
- <label for="node-input-unitId"><i class="fa fa-id-card"></i> Unit ID</label>
52
- <input type="number" id="node-input-unitId" min="1" max="247" placeholder="1">
38
+ <div class="form-tips" style="font-size:11px;color:#6b7280;margin:-8px 0 12px 105px">
39
+ Pick a saved Modbus profile from your modpackqt.com account — auto-fills host/port/unit. Set up your Account Key under <b>Advanced</b> below.
53
40
  </div>
41
+
54
42
  <div class="form-row">
55
43
  <label for="node-input-functionCode"><i class="fa fa-list"></i> Function Code</label>
56
44
  <select id="node-input-functionCode">
@@ -64,7 +52,30 @@
64
52
  <label for="node-input-address"><i class="fa fa-map-marker"></i> Start Address</label>
65
53
  <input type="number" id="node-input-address" min="0" max="65535" placeholder="0">
66
54
  </div>
67
- <div class="form-tips">
55
+
56
+ <div class="form-row" style="margin:14px 0 4px 0;border-top:1px solid #e5e7eb;padding-top:10px">
57
+ <a href="#" class="modpackqt-advanced-toggle" style="font-size:12px;color:#6b7280;text-decoration:none;cursor:pointer">▸ Advanced — runtime config &amp; manual entry</a>
58
+ </div>
59
+ <div class="modpackqt-advanced" style="display:none">
60
+ <div class="form-row">
61
+ <label for="node-input-server"><i class="fa fa-cog"></i> Runtime</label>
62
+ <input type="text" id="node-input-server">
63
+ </div>
64
+ <div class="form-row">
65
+ <label for="node-input-targetHost"><i class="fa fa-plug"></i> Target Host</label>
66
+ <input type="text" id="node-input-targetHost" placeholder="Modbus device IP/hostname (TCP only)">
67
+ </div>
68
+ <div class="form-row">
69
+ <label for="node-input-targetPort"><i class="fa fa-hashtag"></i> Target Port</label>
70
+ <input type="number" id="node-input-targetPort" min="1" max="65535" placeholder="502">
71
+ </div>
72
+ <div class="form-row">
73
+ <label for="node-input-unitId"><i class="fa fa-id-card"></i> Unit ID</label>
74
+ <input type="number" id="node-input-unitId" min="1" max="247" placeholder="1">
75
+ </div>
76
+ </div>
77
+
78
+ <div class="form-tips" style="margin-top:14px">
68
79
  <b>Input:</b> <code>msg.payload</code> = number (FC5/FC6) or array of numbers (FC15/FC16).
69
80
  Encode multi-register values upstream with
70
81
  <a href="https://www.npmjs.com/package/node-red-contrib-bytes-modpackqt" target="_blank">node-red-contrib-bytes-modpackqt</a>.
@@ -18,8 +18,8 @@
18
18
  paletteLabel: 'modbus slave probe',
19
19
  oneditprepare: function () {
20
20
  const node = this;
21
- // Optional cloud slave-config picker (fills bindPort/unitId)
22
21
  if (window.ModPackQTSlavePicker) ModPackQTSlavePicker.attach(this);
22
+ if (window.ModPackQTAdvancedToggle) ModPackQTAdvancedToggle.attach('modpackqt-slave-probe');
23
23
  const buildLink = (info) => {
24
24
  const probeHost = (info && info.host) || '127.0.0.1';
25
25
  const probePort = (info && info.port) || 8502;
@@ -52,12 +52,12 @@
52
52
  const cfgId = $('#node-input-server').val();
53
53
  $sel.empty().append('<option value="">— Loading… —</option>');
54
54
  if (!cfgId || cfgId === '_ADD_') {
55
- $sel.empty().append('<option value="">— Set runtime config first —</option>');
55
+ $sel.empty().append('<option value="">— Set up runtime &amp; Account Key under Advanced —</option>');
56
56
  return;
57
57
  }
58
58
  $.getJSON('modpackqt/slaves?config=' + encodeURIComponent(cfgId))
59
59
  .done(function (rows) {
60
- $sel.empty().append('<option value="">— Manual entry below —</option>');
60
+ $sel.empty().append('<option value="">— Manual entry (see Advanced) —</option>');
61
61
  (rows || [])
62
62
  .filter(function (s) { return s && (s.protocol === 'tcp' || !s.protocol); })
63
63
  .forEach(function (s) {
@@ -89,31 +89,38 @@
89
89
  <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
90
90
  <input type="text" id="node-input-name" placeholder="(optional, e.g. Fake Inverter)">
91
91
  </div>
92
- <div class="form-row">
93
- <label for="node-input-server"><i class="fa fa-cog"></i> Runtime <span style="color:#9ca3af;font-weight:normal">(for picker)</span></label>
94
- <input type="text" id="node-input-server">
95
- </div>
96
92
  <div class="form-row">
97
93
  <label for="node-input-modpackqt-slave-picker"><i class="fa fa-cloud-download"></i> My Slaves</label>
98
94
  <select id="node-input-modpackqt-slave-picker" style="width:65%"></select>
99
95
  <button type="button" id="modpackqt-slave-picker-refresh" class="red-ui-button" title="Reload from modpackqt.com" style="margin-left:4px"><i class="fa fa-refresh"></i></button>
100
96
  </div>
101
- <div class="form-tips" style="font-size:11px;color:#6b7280;margin:-8px 0 8px 105px">
102
- Pick a saved slave config from your account — fills port/unit below. Requires Account Key on the runtime config.
103
- </div>
104
- <div class="form-row">
105
- <label for="node-input-bindHost"><i class="fa fa-globe"></i> Bind Host</label>
106
- <input type="text" id="node-input-bindHost" placeholder="0.0.0.0 (all interfaces)">
97
+ <div class="form-tips" style="font-size:11px;color:#6b7280;margin:-8px 0 12px 105px">
98
+ Pick a saved slave config from your modpackqt.com account — auto-fills port/unit. Set up your Account Key under <b>Advanced</b> below.
107
99
  </div>
108
- <div class="form-row">
109
- <label for="node-input-bindPort"><i class="fa fa-hashtag"></i> Listen Port</label>
110
- <input type="number" id="node-input-bindPort" min="1" max="65535" placeholder="1502">
100
+
101
+ <div class="form-row" style="margin:14px 0 4px 0;border-top:1px solid #e5e7eb;padding-top:10px">
102
+ <a href="#" class="modpackqt-advanced-toggle" style="font-size:12px;color:#6b7280;text-decoration:none;cursor:pointer">▸ Advanced — runtime config &amp; manual entry</a>
111
103
  </div>
112
- <div class="form-row">
113
- <label for="node-input-unitId"><i class="fa fa-id-card"></i> Unit ID</label>
114
- <input type="number" id="node-input-unitId" min="1" max="247" placeholder="1">
104
+ <div class="modpackqt-advanced" style="display:none">
105
+ <div class="form-row">
106
+ <label for="node-input-server"><i class="fa fa-cog"></i> Runtime</label>
107
+ <input type="text" id="node-input-server">
108
+ </div>
109
+ <div class="form-row">
110
+ <label for="node-input-bindHost"><i class="fa fa-globe"></i> Bind Host</label>
111
+ <input type="text" id="node-input-bindHost" placeholder="0.0.0.0 (all interfaces)">
112
+ </div>
113
+ <div class="form-row">
114
+ <label for="node-input-bindPort"><i class="fa fa-hashtag"></i> Listen Port</label>
115
+ <input type="number" id="node-input-bindPort" min="1" max="65535" placeholder="1502">
116
+ </div>
117
+ <div class="form-row">
118
+ <label for="node-input-unitId"><i class="fa fa-id-card"></i> Unit ID</label>
119
+ <input type="number" id="node-input-unitId" min="1" max="247" placeholder="1">
120
+ </div>
115
121
  </div>
116
- <div class="form-tips">
122
+
123
+ <div class="form-tips" style="margin-top:14px">
117
124
  <b>One probe = one fake slave.</b> For multiple slaves, drop one node per
118
125
  port. The web console aggregates all slave probes into a unified register
119
126
  editor — switch between them with one click.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-red-contrib-modbus-modpackqt",
3
- "version": "3.2.0",
3
+ "version": "3.2.1",
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",