node-red-contrib-i3x 0.0.2 → 0.0.4

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.
@@ -11,6 +11,9 @@
11
11
  <label for="node-input-elementIds"><i class="fa fa-list"></i> Element IDs</label>
12
12
  <input type="text" id="node-input-elementIds" placeholder="comma-separated element IDs">
13
13
  </div>
14
+ <div class="form-row">
15
+ <div id="i3x-history-browser"></div>
16
+ </div>
14
17
  <div class="form-row">
15
18
  <label for="node-input-startTime"><i class="fa fa-clock-o"></i> Start Time</label>
16
19
  <input type="text" id="node-input-startTime" placeholder="ISO 8601 or relative (e.g. -1h, -7d)">
@@ -50,6 +53,7 @@
50
53
  <p>Uses <code>POST /objects/history</code>. Time values support both ISO 8601 and
51
54
  relative notation: <code>-30s</code> (seconds), <code>-5m</code> (minutes), <code>-1h</code> (hours),
52
55
  <code>-7d</code> (days), <code>-1w</code> (weeks).</p>
56
+ <p>Use the <b>Browse</b> button to visually select elements from the server.</p>
53
57
  </script>
54
58
 
55
59
  <script type="text/javascript">
@@ -71,5 +75,15 @@
71
75
  label: function () {
72
76
  return this.name || this.elementIds || "i3x history";
73
77
  },
78
+ oneditprepare: function () {
79
+ if (window.I3XBrowser) {
80
+ this._browser = I3XBrowser.create({
81
+ container: "#i3x-history-browser",
82
+ serverField: "#node-input-server",
83
+ targetField: "#node-input-elementIds",
84
+ mode: "multi",
85
+ });
86
+ }
87
+ },
74
88
  });
75
89
  </script>
@@ -3,7 +3,7 @@
3
3
  */
4
4
  "use strict";
5
5
 
6
- const { bindServer, parseIds, safeSend } = require("../lib/node-utils");
6
+ const { bindServer, parseIds, safeSend, statusError, clampMaxDepth } = require("../lib/node-utils");
7
7
 
8
8
  /**
9
9
  * Resolve relative time strings like "-1h", "-7d", "-30m" to ISO 8601.
@@ -28,8 +28,7 @@ module.exports = function (RED) {
28
28
  node.elementIds = config.elementIds || "";
29
29
  node.startTime = config.startTime || "";
30
30
  node.endTime = config.endTime || "";
31
- node.maxDepth = parseInt(config.maxDepth, 10);
32
- if (isNaN(node.maxDepth)) node.maxDepth = 1;
31
+ node.maxDepth = clampMaxDepth(config.maxDepth);
33
32
 
34
33
  if (!bindServer(node, RED, config.server)) return;
35
34
 
@@ -46,18 +45,19 @@ module.exports = function (RED) {
46
45
 
47
46
  const startTime = resolveTime(msg.startTime || node.startTime);
48
47
  const endTime = resolveTime(msg.endTime || node.endTime);
49
- const maxDepth = msg.maxDepth !== undefined ? parseInt(msg.maxDepth, 10) : node.maxDepth;
48
+ const maxDepth = msg.maxDepth !== undefined ? clampMaxDepth(msg.maxDepth) : node.maxDepth;
50
49
 
51
50
  node.status({ fill: "blue", shape: "dot", text: "querying..." });
52
51
 
53
52
  try {
54
53
  const result = await client.readHistory(ids, { startTime, endTime, maxDepth });
55
54
  msg.payload = result;
56
- node.status({ fill: "green", shape: "dot", text: "ok" });
55
+ const count = Array.isArray(result) ? result.length : 1;
56
+ node.status({ fill: "green", shape: "dot", text: count + " record" + (count !== 1 ? "s" : "") });
57
57
  send(msg);
58
58
  if (done) done();
59
59
  } catch (err) {
60
- node.status({ fill: "red", shape: "ring", text: err.message.substring(0, 32) });
60
+ node.status({ fill: "red", shape: "ring", text: statusError(err.message) });
61
61
  if (done) done(err); else node.error(err, msg);
62
62
  }
63
63
  });
@@ -11,6 +11,9 @@
11
11
  <label for="node-input-elementIds"><i class="fa fa-list"></i> Element IDs</label>
12
12
  <input type="text" id="node-input-elementIds" placeholder="comma-separated element IDs">
13
13
  </div>
14
+ <div class="form-row">
15
+ <div id="i3x-read-browser"></div>
16
+ </div>
14
17
  <div class="form-row">
15
18
  <label for="node-input-maxDepth"><i class="fa fa-level-down"></i> Max Depth</label>
16
19
  <input type="number" id="node-input-maxDepth" placeholder="1" min="0" step="1">
@@ -37,6 +40,8 @@
37
40
  <h3>Details</h3>
38
41
  <p>Uses <code>POST /objects/value</code>. The <code>maxDepth</code> parameter controls whether
39
42
  child component values are included recursively.</p>
43
+ <p>Use the <b>Browse</b> button to visually select elements from the server,
44
+ or provide element IDs via <code>msg.elementIds</code> at runtime.</p>
40
45
  </script>
41
46
 
42
47
  <script type="text/javascript">
@@ -56,5 +61,15 @@
56
61
  label: function () {
57
62
  return this.name || this.elementIds || "i3x read";
58
63
  },
64
+ oneditprepare: function () {
65
+ if (window.I3XBrowser) {
66
+ this._browser = I3XBrowser.create({
67
+ container: "#i3x-read-browser",
68
+ serverField: "#node-input-server",
69
+ targetField: "#node-input-elementIds",
70
+ mode: "multi",
71
+ });
72
+ }
73
+ },
59
74
  });
60
75
  </script>
package/nodes/i3x-read.js CHANGED
@@ -3,7 +3,7 @@
3
3
  */
4
4
  "use strict";
5
5
 
6
- const { bindServer, parseIds, safeSend } = require("../lib/node-utils");
6
+ const { bindServer, parseIds, safeSend, statusError, clampMaxDepth } = require("../lib/node-utils");
7
7
 
8
8
  module.exports = function (RED) {
9
9
  function I3XReadNode(config) {
@@ -11,8 +11,7 @@ module.exports = function (RED) {
11
11
  const node = this;
12
12
 
13
13
  node.elementIds = config.elementIds || "";
14
- node.maxDepth = parseInt(config.maxDepth, 10);
15
- if (isNaN(node.maxDepth)) node.maxDepth = 1;
14
+ node.maxDepth = clampMaxDepth(config.maxDepth);
16
15
 
17
16
  if (!bindServer(node, RED, config.server)) return;
18
17
 
@@ -27,18 +26,19 @@ module.exports = function (RED) {
27
26
  return;
28
27
  }
29
28
 
30
- const maxDepth = msg.maxDepth !== undefined ? parseInt(msg.maxDepth, 10) : node.maxDepth;
29
+ const maxDepth = msg.maxDepth !== undefined ? clampMaxDepth(msg.maxDepth) : node.maxDepth;
31
30
 
32
31
  node.status({ fill: "blue", shape: "dot", text: "requesting..." });
33
32
 
34
33
  try {
35
34
  const result = await client.readValues(ids, { maxDepth });
36
35
  msg.payload = result;
37
- node.status({ fill: "green", shape: "dot", text: "ok" });
36
+ const count = Array.isArray(result) ? result.length : 1;
37
+ node.status({ fill: "green", shape: "dot", text: count + " value" + (count !== 1 ? "s" : "") });
38
38
  send(msg);
39
39
  if (done) done();
40
40
  } catch (err) {
41
- node.status({ fill: "red", shape: "ring", text: err.message.substring(0, 32) });
41
+ node.status({ fill: "red", shape: "ring", text: statusError(err.message) });
42
42
  if (done) done(err); else node.error(err, msg);
43
43
  }
44
44
  });