@bldgblocks/node-red-contrib-control 0.1.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.
- package/README.md +43 -0
- package/nodes/accumulate-block.html +71 -0
- package/nodes/accumulate-block.js +104 -0
- package/nodes/add-block.html +67 -0
- package/nodes/add-block.js +97 -0
- package/nodes/analog-switch-block.html +65 -0
- package/nodes/analog-switch-block.js +129 -0
- package/nodes/and-block.html +64 -0
- package/nodes/and-block.js +73 -0
- package/nodes/average-block.html +97 -0
- package/nodes/average-block.js +137 -0
- package/nodes/boolean-switch-block.html +59 -0
- package/nodes/boolean-switch-block.js +88 -0
- package/nodes/boolean-to-number-block.html +59 -0
- package/nodes/boolean-to-number-block.js +45 -0
- package/nodes/cache-block.html +69 -0
- package/nodes/cache-block.js +106 -0
- package/nodes/call-status-block.html +111 -0
- package/nodes/call-status-block.js +274 -0
- package/nodes/changeover-block.html +234 -0
- package/nodes/changeover-block.js +392 -0
- package/nodes/comment-block.html +83 -0
- package/nodes/comment-block.js +53 -0
- package/nodes/compare-block.html +64 -0
- package/nodes/compare-block.js +84 -0
- package/nodes/contextual-label-block.html +67 -0
- package/nodes/contextual-label-block.js +52 -0
- package/nodes/convert-block.html +179 -0
- package/nodes/convert-block.js +289 -0
- package/nodes/count-block.html +57 -0
- package/nodes/count-block.js +92 -0
- package/nodes/debounce-block.html +64 -0
- package/nodes/debounce-block.js +140 -0
- package/nodes/delay-block.html +104 -0
- package/nodes/delay-block.js +180 -0
- package/nodes/divide-block.html +65 -0
- package/nodes/divide-block.js +123 -0
- package/nodes/edge-block.html +71 -0
- package/nodes/edge-block.js +120 -0
- package/nodes/frequency-block.html +55 -0
- package/nodes/frequency-block.js +140 -0
- package/nodes/hysteresis-block.html +131 -0
- package/nodes/hysteresis-block.js +142 -0
- package/nodes/interpolate-block.html +74 -0
- package/nodes/interpolate-block.js +141 -0
- package/nodes/load-sequence-block.html +134 -0
- package/nodes/load-sequence-block.js +272 -0
- package/nodes/max-block.html +76 -0
- package/nodes/max-block.js +103 -0
- package/nodes/memory-block.html +90 -0
- package/nodes/memory-block.js +241 -0
- package/nodes/min-block.html +77 -0
- package/nodes/min-block.js +106 -0
- package/nodes/minmax-block.html +89 -0
- package/nodes/minmax-block.js +119 -0
- package/nodes/modulo-block.html +73 -0
- package/nodes/modulo-block.js +126 -0
- package/nodes/multiply-block.html +63 -0
- package/nodes/multiply-block.js +115 -0
- package/nodes/negate-block.html +55 -0
- package/nodes/negate-block.js +91 -0
- package/nodes/nullify-block.html +111 -0
- package/nodes/nullify-block.js +78 -0
- package/nodes/on-change-block.html +79 -0
- package/nodes/on-change-block.js +191 -0
- package/nodes/oneshot-block.html +96 -0
- package/nodes/oneshot-block.js +169 -0
- package/nodes/or-block.html +64 -0
- package/nodes/or-block.js +73 -0
- package/nodes/pid-block.html +205 -0
- package/nodes/pid-block.js +407 -0
- package/nodes/priority-block.html +66 -0
- package/nodes/priority-block.js +239 -0
- package/nodes/rate-limit-block.html +99 -0
- package/nodes/rate-limit-block.js +221 -0
- package/nodes/round-block.html +73 -0
- package/nodes/round-block.js +89 -0
- package/nodes/saw-tooth-wave-block.html +87 -0
- package/nodes/saw-tooth-wave-block.js +161 -0
- package/nodes/scale-range-block.html +90 -0
- package/nodes/scale-range-block.js +137 -0
- package/nodes/sine-wave-block.html +88 -0
- package/nodes/sine-wave-block.js +142 -0
- package/nodes/subtract-block.html +64 -0
- package/nodes/subtract-block.js +103 -0
- package/nodes/thermistor-block.html +81 -0
- package/nodes/thermistor-block.js +146 -0
- package/nodes/tick-tock-block.html +66 -0
- package/nodes/tick-tock-block.js +110 -0
- package/nodes/time-sequence-block.html +67 -0
- package/nodes/time-sequence-block.js +144 -0
- package/nodes/triangle-wave-block.html +86 -0
- package/nodes/triangle-wave-block.js +154 -0
- package/nodes/tstat-block.html +311 -0
- package/nodes/tstat-block.js +499 -0
- package/nodes/units-block.html +150 -0
- package/nodes/units-block.js +106 -0
- package/package.json +73 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
<script type="text/html" data-template-name="comment-block">
|
|
2
|
+
<div class="form-row">
|
|
3
|
+
<label for="node-input-name" title="Display name shown on the canvas"><i class="fa fa-tag"></i> Name</label>
|
|
4
|
+
<input type="text" id="node-input-name" placeholder="Name">
|
|
5
|
+
</div>
|
|
6
|
+
<div class="form-row">
|
|
7
|
+
<label for="node-input-comment" title="Comment shown in status when Default is selected (max 100 characters)"><i class="fa fa-comment"></i> Comment</label>
|
|
8
|
+
<input type="text" id="node-input-comment" placeholder="Enter comment (max 100 chars)" maxlength="100">
|
|
9
|
+
</div>
|
|
10
|
+
<div class="form-row">
|
|
11
|
+
<label for="node-input-statusDisplay" title="Select what to display in the node status"><i class="fa fa-eye"></i> Status Display</label>
|
|
12
|
+
<select id="node-input-statusDisplay">
|
|
13
|
+
<option value="default">Comment to status (Default)</option>
|
|
14
|
+
<option value="name">Name to status</option>
|
|
15
|
+
<option value="none">No status</option>
|
|
16
|
+
</select>
|
|
17
|
+
</div>
|
|
18
|
+
</script>
|
|
19
|
+
|
|
20
|
+
<script type="text/javascript">
|
|
21
|
+
RED.nodes.registerType("comment-block", {
|
|
22
|
+
category: "control",
|
|
23
|
+
color: "#301934",
|
|
24
|
+
defaults: {
|
|
25
|
+
name: { value: "comment" },
|
|
26
|
+
comment: { value: "No comment", validate: function(v) { return v.length < 100 } },
|
|
27
|
+
statusDisplay: { value: "default" }
|
|
28
|
+
},
|
|
29
|
+
inputs: 1,
|
|
30
|
+
outputs: 1,
|
|
31
|
+
inputLabels: ["input"],
|
|
32
|
+
outputLabels: ["output"],
|
|
33
|
+
icon: "font-awesome/fa-comment",
|
|
34
|
+
paletteLabel: "comment",
|
|
35
|
+
label: function() {
|
|
36
|
+
return this.name || this.comment || "comment";
|
|
37
|
+
},
|
|
38
|
+
oneditsave: function() {
|
|
39
|
+
// Update status immediately
|
|
40
|
+
const node = RED.nodes.getNode(this.id);
|
|
41
|
+
let status = {};
|
|
42
|
+
switch (node.statusDisplay) {
|
|
43
|
+
case "default":
|
|
44
|
+
status = { fill: "green", shape: "dot", text: node.comment || "No comment set" };
|
|
45
|
+
break;
|
|
46
|
+
case "name":
|
|
47
|
+
status = { fill: "green", shape: "dot", text: node.name || "comment" };
|
|
48
|
+
break;
|
|
49
|
+
case "none":
|
|
50
|
+
break;
|
|
51
|
+
default:
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
node.status(status);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
</script>
|
|
58
|
+
|
|
59
|
+
<script type="text/markdown" data-help-name="comment-block">
|
|
60
|
+
Displays a configurable comment, node name, or no status persistently and on input.
|
|
61
|
+
|
|
62
|
+
### Inputs
|
|
63
|
+
: payload (any) : Passthrough.
|
|
64
|
+
|
|
65
|
+
### Outputs
|
|
66
|
+
: payload (any) : Passthrough.
|
|
67
|
+
|
|
68
|
+
### Details
|
|
69
|
+
Displays a status (comment, node name, or none) on node creation, editor saves, and input messages.
|
|
70
|
+
|
|
71
|
+
Used for flow annotations or debugging without requiring input to trigger status.
|
|
72
|
+
|
|
73
|
+
### Status
|
|
74
|
+
- Green (dot): Configuration update
|
|
75
|
+
- Blue (dot): State changed
|
|
76
|
+
- Blue (ring): State unchanged
|
|
77
|
+
- Red (ring): Error
|
|
78
|
+
- Yellow: Warning
|
|
79
|
+
|
|
80
|
+
### References
|
|
81
|
+
- [Node-RED Documentation](https://nodered.org/docs/)
|
|
82
|
+
- [GitHub Repository](https://github.com/BldgBlocks/node-red-contrib-buildingblocks-control.git)
|
|
83
|
+
</script>
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
module.exports = function(RED) {
|
|
2
|
+
function CommentBlockNode(config) {
|
|
3
|
+
RED.nodes.createNode(this, config);
|
|
4
|
+
const node = this;
|
|
5
|
+
|
|
6
|
+
// Initialize properties
|
|
7
|
+
node.name = config.name;
|
|
8
|
+
node.comment = config.comment;
|
|
9
|
+
node.statusDisplay = config.statusDisplay;
|
|
10
|
+
|
|
11
|
+
// Ensure comment is within 100 characters
|
|
12
|
+
if (node.comment.length > 100) {
|
|
13
|
+
node.comment = node.comment.substring(0, 100);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Status helper function
|
|
17
|
+
const updateStatus = function() {
|
|
18
|
+
switch (node.statusDisplay) {
|
|
19
|
+
case "default":
|
|
20
|
+
return { fill: "green", shape: "dot", text: node.comment || "No comment set" };
|
|
21
|
+
case "name":
|
|
22
|
+
return { fill: "green", shape: "dot", text: node.name || "comment" };
|
|
23
|
+
case "none":
|
|
24
|
+
default:
|
|
25
|
+
return {};
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
node.status(updateStatus());
|
|
30
|
+
|
|
31
|
+
node.on("input", function(msg, send, done) {
|
|
32
|
+
send = send || function() { node.send.apply(node, arguments); };
|
|
33
|
+
|
|
34
|
+
// Guard against invalid msg
|
|
35
|
+
if (!msg) {
|
|
36
|
+
node.status({ fill: "red", shape: "ring", text: "invalid message" });
|
|
37
|
+
if (done) done();
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
node.status(updateStatus());
|
|
42
|
+
|
|
43
|
+
send(msg);
|
|
44
|
+
if (done) done();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
node.on("close", function(done) {
|
|
48
|
+
done();
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
RED.nodes.registerType("comment-block", CommentBlockNode);
|
|
53
|
+
};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
<!-- UI Template Section: Defines the edit dialog -->
|
|
2
|
+
<script type="text/html" data-template-name="compare-block">
|
|
3
|
+
<div class="form-row">
|
|
4
|
+
<label for="node-input-name" title="Display name shown on the canvas"><i class="fa fa-tag"></i> Name</label>
|
|
5
|
+
<input type="text" id="node-input-name" placeholder="Name">
|
|
6
|
+
</div>
|
|
7
|
+
<div class="form-row">
|
|
8
|
+
<label for="node-input-setpoint" title="Default setpoint value for comparison (number)"><i class="fa fa-crosshairs"></i> Setpoint</label>
|
|
9
|
+
<input type="number" id="node-input-setpoint" placeholder="50" step="any">
|
|
10
|
+
</div>
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<!-- JavaScript Section: Registers the node and handles editor logic -->
|
|
14
|
+
<script type="text/javascript">
|
|
15
|
+
RED.nodes.registerType("compare-block", {
|
|
16
|
+
category: "control",
|
|
17
|
+
color: "#301934",
|
|
18
|
+
defaults: {
|
|
19
|
+
name: { value: "" },
|
|
20
|
+
setpoint: { value: 50, required: true, validate: function(v) { return !isNaN(+v) && isFinite(+v); } }
|
|
21
|
+
},
|
|
22
|
+
inputs: 1,
|
|
23
|
+
outputs: 3,
|
|
24
|
+
outputLabels: ["greater than", "equal to", "less than"],
|
|
25
|
+
inputLabels: ["input"],
|
|
26
|
+
icon: "font-awesome/fa-balance-scale",
|
|
27
|
+
paletteLabel: "compare",
|
|
28
|
+
label: function() {
|
|
29
|
+
return this.name || "compare";
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
</script>
|
|
33
|
+
|
|
34
|
+
<!-- Help Section -->
|
|
35
|
+
<script type="text/markdown" data-help-name="compare-block">
|
|
36
|
+
Compares a numeric input to a setpoint, outputting three boolean signals.
|
|
37
|
+
|
|
38
|
+
### Inputs
|
|
39
|
+
: context (string) : Configuration commands - setpoint (`"setpoint"`). Unmatched values trigger error.
|
|
40
|
+
: payload (number) : Input number to compare, or setpoint value for config.
|
|
41
|
+
|
|
42
|
+
### Outputs
|
|
43
|
+
: greater than (boolean) : `true` if input > setpoint, else `false`.
|
|
44
|
+
: equal to (boolean) : `true` if input = setpoint, else `false`.
|
|
45
|
+
: less than (boolean) : `true` if input < setpoint, else `false`.
|
|
46
|
+
|
|
47
|
+
### Properties
|
|
48
|
+
: setpoint (number) : Value for comparison.
|
|
49
|
+
|
|
50
|
+
### Details
|
|
51
|
+
Compares `msg.payload` (number) to a `setpoint` (default: 50), outputting three messages to separate ports:
|
|
52
|
+
`true` for greater than, equal to, or less than the setpoint, respectively; `false` otherwise.
|
|
53
|
+
|
|
54
|
+
### Status
|
|
55
|
+
- Green (dot): Configuration update
|
|
56
|
+
- Blue (dot): State changed
|
|
57
|
+
- Blue (ring): State unchanged
|
|
58
|
+
- Red (ring): Error
|
|
59
|
+
- Yellow (ring): Warning
|
|
60
|
+
|
|
61
|
+
### References
|
|
62
|
+
- [Node-RED Documentation](https://nodered.org/docs/)
|
|
63
|
+
- [GitHub Repository](https://github.com/BldgBlocks/node-red-contrib-buildingblocks-control.git)
|
|
64
|
+
</script>
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
module.exports = function(RED) {
|
|
2
|
+
function CompareBlockNode(config) {
|
|
3
|
+
RED.nodes.createNode(this, config);
|
|
4
|
+
const node = this;
|
|
5
|
+
|
|
6
|
+
node.setpoint = Number(config.setpoint);
|
|
7
|
+
|
|
8
|
+
node.on("input", function(msg, send, done) {
|
|
9
|
+
send = send || function() { node.send.apply(node, arguments); };
|
|
10
|
+
|
|
11
|
+
// Guard against invalid message
|
|
12
|
+
if (!msg) {
|
|
13
|
+
node.status({ fill: "red", shape: "ring", text: "invalid message" });
|
|
14
|
+
if (done) done();
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Handle context updates
|
|
19
|
+
if (msg.hasOwnProperty("context")) {
|
|
20
|
+
if (!msg.hasOwnProperty("payload")) {
|
|
21
|
+
node.status({ fill: "red", shape: "ring", text: "missing payload for setpoint" });
|
|
22
|
+
if (done) done();
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (msg.context === "setpoint") {
|
|
27
|
+
const setpointValue = parseFloat(msg.payload);
|
|
28
|
+
if (!isNaN(setpointValue) && isFinite(setpointValue)) {
|
|
29
|
+
node.setpoint = setpointValue;
|
|
30
|
+
node.status({ fill: "green", shape: "dot", text: `setpoint: ${setpointValue.toFixed(2)}` });
|
|
31
|
+
} else {
|
|
32
|
+
node.status({ fill: "red", shape: "ring", text: "invalid setpoint" });
|
|
33
|
+
}
|
|
34
|
+
if (done) done();
|
|
35
|
+
return;
|
|
36
|
+
} else {
|
|
37
|
+
node.status({ fill: "yellow", shape: "ring", text: "unknown context" });
|
|
38
|
+
if (done) done("Unknown context");
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Validate input
|
|
44
|
+
if (!msg.hasOwnProperty("payload")) {
|
|
45
|
+
node.status({ fill: "red", shape: "ring", text: "missing input" });
|
|
46
|
+
if (done) done();
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const inputValue = parseFloat(msg.payload);
|
|
51
|
+
if (isNaN(inputValue) || !isFinite(inputValue)) {
|
|
52
|
+
node.status({ fill: "red", shape: "ring", text: "invalid input" });
|
|
53
|
+
if (done) done();
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Compare input to setpoint
|
|
58
|
+
const greater = inputValue > node.setpoint;
|
|
59
|
+
const equal = inputValue === node.setpoint;
|
|
60
|
+
const less = inputValue < node.setpoint;
|
|
61
|
+
const outputs = [
|
|
62
|
+
{ payload: greater },
|
|
63
|
+
{ payload: equal },
|
|
64
|
+
{ payload: less }
|
|
65
|
+
];
|
|
66
|
+
|
|
67
|
+
node.status({
|
|
68
|
+
fill: "blue",
|
|
69
|
+
shape: "dot",
|
|
70
|
+
text: `in: ${inputValue.toFixed(2)}, sp: ${node.setpoint.toFixed(2)}, out: [${greater}, ${equal}, ${less}]`
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
send(outputs);
|
|
74
|
+
|
|
75
|
+
if (done) done();
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
node.on("close", function(done) {
|
|
79
|
+
done();
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
RED.nodes.registerType("compare-block", CompareBlockNode);
|
|
84
|
+
};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
<script type="text/html" data-template-name="contextual-label-block">
|
|
2
|
+
<div class="form-row">
|
|
3
|
+
<label for="node-input-name" title="Display name shown on the canvas"><i class="fa fa-tag"></i> Name</label>
|
|
4
|
+
<input type="text" id="node-input-name" placeholder="Name">
|
|
5
|
+
</div>
|
|
6
|
+
<div class="form-row">
|
|
7
|
+
<label for="node-input-contextPropertyName" title="Context property to set (e.g., priority, clear, in1)"><i class="fa fa-key"></i> Context Property</label>
|
|
8
|
+
<input type="text" id="node-input-contextPropertyName" placeholder="e.g., priority">
|
|
9
|
+
</div>
|
|
10
|
+
<div class="form-row">
|
|
11
|
+
<label for="node-input-removeLabel" title="Remove msg.context instead of setting it"><i class="fa fa-trash"></i> Remove Context</label>
|
|
12
|
+
<input type="checkbox" id="node-input-removeLabel" style="width: auto; vertical-align: middle;">
|
|
13
|
+
</div>
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<script type="text/javascript">
|
|
17
|
+
RED.nodes.registerType("contextual-label-block", {
|
|
18
|
+
category: "control",
|
|
19
|
+
color: "#301934",
|
|
20
|
+
defaults: {
|
|
21
|
+
name: { value: "" },
|
|
22
|
+
contextPropertyName: {
|
|
23
|
+
value: "in1",
|
|
24
|
+
required: true,
|
|
25
|
+
validate: function(v) { return v && typeof v === "string" && v.trim().length > 0; }
|
|
26
|
+
},
|
|
27
|
+
removeLabel: { value: false }
|
|
28
|
+
},
|
|
29
|
+
inputs: 1,
|
|
30
|
+
outputs: 1,
|
|
31
|
+
inputLabels: ["input"],
|
|
32
|
+
outputLabels: ["output"],
|
|
33
|
+
icon: "font-awesome/fa-tag",
|
|
34
|
+
paletteLabel: "contextual label",
|
|
35
|
+
label: function() {
|
|
36
|
+
if (this.name) return this.name;
|
|
37
|
+
return this.removeLabel ? "remove context" : `🛈 ${this.contextPropertyName || "context"}`;
|
|
38
|
+
},
|
|
39
|
+
oneditprepare: function() {
|
|
40
|
+
$("#node-input-removeLabel").prop("checked", this.removeLabel || false);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
</script>
|
|
44
|
+
|
|
45
|
+
<script type="text/markdown" data-help-name="contextual-label-block">
|
|
46
|
+
Sets or removes the msg.context property in a message.
|
|
47
|
+
|
|
48
|
+
### Inputs
|
|
49
|
+
: payload (any) : Input message payload, passed through unchanged.
|
|
50
|
+
|
|
51
|
+
### Outputs
|
|
52
|
+
: context (string) : Configured context property (e.g., `priority`, `clear`, `in1`) if set, or absent if removed.
|
|
53
|
+
: payload (any) : Original message object with context added or deleted.
|
|
54
|
+
|
|
55
|
+
### Details
|
|
56
|
+
Either sets `msg.context` to a configured property (e.g., `priority`, `clear`, `in1`) or removes `msg.context` based on the `Remove Context` toggle.
|
|
57
|
+
|
|
58
|
+
### Status
|
|
59
|
+
- Green (dot): Configuration updates
|
|
60
|
+
- Blue (dot): Outputs when input changes
|
|
61
|
+
- Blue (ring): Outputs when input unchanged
|
|
62
|
+
- Red (ring): Errors
|
|
63
|
+
|
|
64
|
+
### References
|
|
65
|
+
- [Node-RED Documentation](https://nodered.org/docs/)
|
|
66
|
+
- [GitHub Repository](https://github.com/BldgBlocks/node-red-contrib-buildingblocks-control.git)
|
|
67
|
+
</script>
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
module.exports = function(RED) {
|
|
2
|
+
function ContextualLabelBlockNode(config) {
|
|
3
|
+
RED.nodes.createNode(this, config);
|
|
4
|
+
const node = this;
|
|
5
|
+
|
|
6
|
+
node.contextPropertyName = config.contextPropertyName || "in1";
|
|
7
|
+
node.removeLabel = config.removeLabel || false;
|
|
8
|
+
|
|
9
|
+
node.status({
|
|
10
|
+
fill: "green",
|
|
11
|
+
shape: "dot",
|
|
12
|
+
text: `mode: ${node.removeLabel ? "remove" : "set"}, property: ${node.contextPropertyName}`
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
node.on("input", function(msg, send, done) {
|
|
16
|
+
send = send || function() { node.send.apply(node, arguments); };
|
|
17
|
+
|
|
18
|
+
if (!msg) {
|
|
19
|
+
node.status({ fill: "red", shape: "ring", text: "missing message" });
|
|
20
|
+
node.warn("Missing message");
|
|
21
|
+
if (done) done();
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Set or remove context property
|
|
26
|
+
if (node.removeLabel) {
|
|
27
|
+
delete msg.context;
|
|
28
|
+
node.status({
|
|
29
|
+
fill: "blue",
|
|
30
|
+
shape: "dot",
|
|
31
|
+
text: `in: ${msg.payload}, out: removed context`
|
|
32
|
+
});
|
|
33
|
+
} else {
|
|
34
|
+
msg.context = node.contextPropertyName;
|
|
35
|
+
node.status({
|
|
36
|
+
fill: "blue",
|
|
37
|
+
shape: "dot",
|
|
38
|
+
text: `in: ${msg.payload}, out: ${node.contextPropertyName}`
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
send(msg);
|
|
43
|
+
if (done) done();
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
node.on("close", function(done) {
|
|
47
|
+
done();
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
RED.nodes.registerType("contextual-label-block", ContextualLabelBlockNode);
|
|
52
|
+
};
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
<script type="text/html" data-template-name="convert-block">
|
|
2
|
+
<div class="form-row">
|
|
3
|
+
<label for="node-input-name" title="Display name shown on the canvas"><i class="fa fa-tag"></i> Name</label>
|
|
4
|
+
<input type="text" id="node-input-name" placeholder="Name">
|
|
5
|
+
</div>
|
|
6
|
+
<div class="form-row">
|
|
7
|
+
<label for="node-input-conversion" title="Select the unit conversion to perform"><i class="fa fa-exchange"></i> Conversion</label>
|
|
8
|
+
<select id="node-input-conversion">
|
|
9
|
+
<optgroup label="Temperature">
|
|
10
|
+
<option value="C to F">C to F (Celsius to Fahrenheit)</option>
|
|
11
|
+
<option value="F to C">F to C (Fahrenheit to Celsius)</option>
|
|
12
|
+
<option value="K to C">K to C (Kelvin to Celsius)</option>
|
|
13
|
+
<option value="C to K">C to K (Celsius to Kelvin)</option>
|
|
14
|
+
<option value="K to F">K to F (Kelvin to Fahrenheit)</option>
|
|
15
|
+
<option value="F to K">F to K (Fahrenheit to Kelvin)</option>
|
|
16
|
+
<option value="R to F">R to F (Rankine to Fahrenheit)</option>
|
|
17
|
+
<option value="F to R">F to R (Fahrenheit to Rankine)</option>
|
|
18
|
+
</optgroup>
|
|
19
|
+
<optgroup label="Math">
|
|
20
|
+
<option value="decimal to %">Decimal to Percent</option>
|
|
21
|
+
<option value="% to decimal">Percent to Decimal</option>
|
|
22
|
+
<option value="rad to deg">Radians to Degrees</option>
|
|
23
|
+
<option value="deg to rad">Degrees to Radians</option>
|
|
24
|
+
</optgroup>
|
|
25
|
+
<optgroup label="Pressure">
|
|
26
|
+
<option value="Pa to inH₂O">Pa to inH₂O (Pascal to Inches of Water)</option>
|
|
27
|
+
<option value="inH₂O to Pa">inH₂O to Pa (Inches of Water to Pascal)</option>
|
|
28
|
+
<option value="Pa to inHg">Pa to inHg (Pascal to Inches of Mercury)</option>
|
|
29
|
+
<option value="inHg to Pa">inHg to Pa (Inches of Mercury to Pascal)</option>
|
|
30
|
+
<option value="Pa to bar">Pa to bar (Pascal to Bar)</option>
|
|
31
|
+
<option value="bar to Pa">bar to Pa (Bar to Pascal)</option>
|
|
32
|
+
<option value="Pa to psi">Pa to psi (Pascal to PSI)</option>
|
|
33
|
+
<option value="psi to Pa">psi to Pa (PSI to Pascal)</option>
|
|
34
|
+
</optgroup>
|
|
35
|
+
<optgroup label="Length">
|
|
36
|
+
<option value="m to ft">m to ft (Meters to Feet)</option>
|
|
37
|
+
<option value="ft to m">ft to m (Feet to Meters)</option>
|
|
38
|
+
<option value="m to in">m to in (Meters to Inches)</option>
|
|
39
|
+
<option value="in to m">in to m (Inches to Meters)</option>
|
|
40
|
+
<option value="mm to in">mm to in (Millimeters to Inches)</option>
|
|
41
|
+
<option value="in to mm">in to mm (Inches to Millimeters)</option>
|
|
42
|
+
</optgroup>
|
|
43
|
+
<optgroup label="Mass & Volume">
|
|
44
|
+
<option value="kg to lb">kg to lb (Kilograms to Pounds)</option>
|
|
45
|
+
<option value="lb to kg">lb to kg (Pounds to Kilograms)</option>
|
|
46
|
+
<option value="L to gal">L to gal (Liters to Gallons)</option>
|
|
47
|
+
<option value="gal to L">gal to L (Gallons to Liters)</option>
|
|
48
|
+
</optgroup>
|
|
49
|
+
<optgroup label="Power & Time">
|
|
50
|
+
<option value="kW to hp">kW to hp (Kilowatts to Horsepower)</option>
|
|
51
|
+
<option value="hp to kW">hp to kW (Horsepower to Kilowatts)</option>
|
|
52
|
+
<option value="s to min">s to min (Seconds to Minutes)</option>
|
|
53
|
+
<option value="min to s">min to s (Minutes to Seconds)</option>
|
|
54
|
+
</optgroup>
|
|
55
|
+
</select>
|
|
56
|
+
</div>
|
|
57
|
+
</script>
|
|
58
|
+
|
|
59
|
+
<script type="text/javascript">
|
|
60
|
+
RED.nodes.registerType("convert-block", {
|
|
61
|
+
category: "control",
|
|
62
|
+
color: "#301934",
|
|
63
|
+
defaults: {
|
|
64
|
+
name: { value: "" },
|
|
65
|
+
conversion: { value: "C to F", required: true }
|
|
66
|
+
},
|
|
67
|
+
inputs: 1,
|
|
68
|
+
outputs: 1,
|
|
69
|
+
inputLabels: ["input"],
|
|
70
|
+
outputLabels: ["converted output"],
|
|
71
|
+
icon: "font-awesome/fa-exchange",
|
|
72
|
+
paletteLabel: "convert",
|
|
73
|
+
label: function() {
|
|
74
|
+
return this.name || `Convert (${this.conversion})`;
|
|
75
|
+
},
|
|
76
|
+
oneditvalidate: function() {
|
|
77
|
+
const conversion = $("#node-input-conversion").val();
|
|
78
|
+
const validConversions = [
|
|
79
|
+
"F to C",
|
|
80
|
+
"C to F",
|
|
81
|
+
"K to C",
|
|
82
|
+
"C to K",
|
|
83
|
+
"K to F",
|
|
84
|
+
"F to K",
|
|
85
|
+
"R to F",
|
|
86
|
+
"F to R",
|
|
87
|
+
"decimal to %",
|
|
88
|
+
"% to decimal",
|
|
89
|
+
"Pa to inH₂O",
|
|
90
|
+
"inH₂O to Pa",
|
|
91
|
+
"Pa to inHg",
|
|
92
|
+
"inHg to Pa",
|
|
93
|
+
"Pa to bar",
|
|
94
|
+
"bar to Pa",
|
|
95
|
+
"Pa to psi",
|
|
96
|
+
"psi to Pa",
|
|
97
|
+
"m to ft",
|
|
98
|
+
"ft to m",
|
|
99
|
+
"m to in",
|
|
100
|
+
"in to m",
|
|
101
|
+
"mm to in",
|
|
102
|
+
"in to mm",
|
|
103
|
+
"kg to lb",
|
|
104
|
+
"lb to kg",
|
|
105
|
+
"L to gal",
|
|
106
|
+
"gal to L",
|
|
107
|
+
"kW to hp",
|
|
108
|
+
"hp to kW",
|
|
109
|
+
"rad to deg",
|
|
110
|
+
"deg to rad",
|
|
111
|
+
"s to min",
|
|
112
|
+
"min to s"
|
|
113
|
+
];
|
|
114
|
+
return validConversions.includes(conversion);
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
</script>
|
|
118
|
+
|
|
119
|
+
<script type="text/markdown" data-help-name="convert-block">
|
|
120
|
+
Converts numeric input payload between temperature or pressure units.
|
|
121
|
+
|
|
122
|
+
### Inputs
|
|
123
|
+
: context (string) : Configures the conversion (`"conversion"`). Unmatched values ignored.
|
|
124
|
+
: payload (number) : Numeric value to convert
|
|
125
|
+
|
|
126
|
+
### Outputs
|
|
127
|
+
: payload (number) : Converted value (e.g., °C to °F, Pa to inH₂O).
|
|
128
|
+
|
|
129
|
+
### Details
|
|
130
|
+
Converts `msg.payload` between units based on the selected conversion.
|
|
131
|
+
|
|
132
|
+
### validConversions = [
|
|
133
|
+
"F to C",
|
|
134
|
+
"C to F",
|
|
135
|
+
"K to C",
|
|
136
|
+
"C to K",
|
|
137
|
+
"K to F",
|
|
138
|
+
"F to K",
|
|
139
|
+
"R to F",
|
|
140
|
+
"F to R",
|
|
141
|
+
"decimal to %",
|
|
142
|
+
"% to decimal",
|
|
143
|
+
"Pa to inH₂O",
|
|
144
|
+
"inH₂O to Pa",
|
|
145
|
+
"Pa to inHg",
|
|
146
|
+
"inHg to Pa",
|
|
147
|
+
"Pa to bar",
|
|
148
|
+
"bar to Pa",
|
|
149
|
+
"Pa to psi",
|
|
150
|
+
"psi to Pa",
|
|
151
|
+
"m to ft",
|
|
152
|
+
"ft to m",
|
|
153
|
+
"m to in",
|
|
154
|
+
"in to m",
|
|
155
|
+
"mm to in",
|
|
156
|
+
"in to mm",
|
|
157
|
+
"kg to lb",
|
|
158
|
+
"lb to kg",
|
|
159
|
+
"L to gal",
|
|
160
|
+
"gal to L",
|
|
161
|
+
"kW to hp",
|
|
162
|
+
"hp to kW",
|
|
163
|
+
"rad to deg",
|
|
164
|
+
"deg to rad",
|
|
165
|
+
"s to min",
|
|
166
|
+
"min to s"
|
|
167
|
+
];
|
|
168
|
+
|
|
169
|
+
### Status
|
|
170
|
+
- Green (dot): Configuration update
|
|
171
|
+
- Blue (dot): State changed
|
|
172
|
+
- Blue (ring): State unchanged
|
|
173
|
+
- Red (ring): Error
|
|
174
|
+
- Yellow (ring): Warning
|
|
175
|
+
|
|
176
|
+
### References
|
|
177
|
+
- [Node-RED Documentation](https://nodered.org/docs/)
|
|
178
|
+
- [GitHub Repository](https://github.com/BldgBlocks/node-red-contrib-buildingblocks-control.git)
|
|
179
|
+
</script>
|