@bldgblocks/node-red-contrib-control 0.1.31 → 0.1.32
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/nodes/global-getter.html +10 -2
- package/nodes/global-getter.js +72 -18
- package/nodes/global-setter.js +6 -6
- package/package.json +1 -1
package/nodes/global-getter.html
CHANGED
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
</button>
|
|
13
13
|
</div>
|
|
14
14
|
|
|
15
|
-
<!-- NEW: Trigger Mode Selection -->
|
|
16
15
|
<div class="form-row">
|
|
17
16
|
<label for="node-input-updates"><i class="fa fa-bolt"></i> Trigger</label>
|
|
18
17
|
<select id="node-input-updates" style="width: 70%;">
|
|
@@ -26,6 +25,14 @@
|
|
|
26
25
|
<input type="text" id="node-input-outputProperty" placeholder="payload" style="width:70%;">
|
|
27
26
|
</div>
|
|
28
27
|
|
|
28
|
+
<div class="form-row">
|
|
29
|
+
<label for="node-input-detail"><i class="fa fa-bolt"></i> Trigger</label>
|
|
30
|
+
<select id="node-input-detail" style="width: 70%;">
|
|
31
|
+
<option value="getValue">Get Simple Value</option>
|
|
32
|
+
<option value="getObject">Get Full Object</option>
|
|
33
|
+
</select>
|
|
34
|
+
</div>
|
|
35
|
+
|
|
29
36
|
<div class="form-tips">
|
|
30
37
|
<b>Note:</b> Targeting by Node ID allows the source path to change without breaking this link.
|
|
31
38
|
</div>
|
|
@@ -39,7 +46,8 @@
|
|
|
39
46
|
name: { value: "" },
|
|
40
47
|
targetNode: { value: "", required: true },
|
|
41
48
|
outputProperty: { value: "payload", required: true },
|
|
42
|
-
updates: { value: "always", required: true }
|
|
49
|
+
updates: { value: "always", required: true },
|
|
50
|
+
detail: {value: "getObject", required: true }
|
|
43
51
|
},
|
|
44
52
|
inputs: 1,
|
|
45
53
|
outputs: 1,
|
package/nodes/global-getter.js
CHANGED
|
@@ -5,14 +5,20 @@ module.exports = function(RED) {
|
|
|
5
5
|
node.targetNodeId = config.targetNode;
|
|
6
6
|
node.outputProperty = config.outputProperty || "payload";
|
|
7
7
|
node.updates = config.updates;
|
|
8
|
+
node.detail = config.detail;
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
let setterNode = null;
|
|
11
|
+
let retryInterval = null;
|
|
12
|
+
let updateListener = null;
|
|
13
|
+
let retryCount = 0;
|
|
14
|
+
const retryDelays = [0, 100, 500, 1000, 2000, 4000, 8000, 16000];
|
|
15
|
+
const maxRetries = retryDelays.length - 1;
|
|
10
16
|
|
|
11
17
|
// --- HELPER: Process Wrapper and Send Msg ---
|
|
12
18
|
function sendValue(storedObject, msgToReuse) {
|
|
13
19
|
const msg = msgToReuse || {};
|
|
14
20
|
|
|
15
|
-
if (storedObject !== undefined) {
|
|
21
|
+
if (storedObject !== undefined && storedObject !== null) {
|
|
16
22
|
|
|
17
23
|
// CHECK: Is this our Wrapper Format? (Created by Global Setter)
|
|
18
24
|
if (storedObject && typeof storedObject === 'object' && storedObject.hasOwnProperty('value')) {
|
|
@@ -26,7 +32,9 @@ module.exports = function(RED) {
|
|
|
26
32
|
|
|
27
33
|
// 3. Merge all attributes onto the msg root
|
|
28
34
|
// This automatically handles priority, units, metadata, and any future fields
|
|
29
|
-
|
|
35
|
+
if (node.detail === "getObject") {
|
|
36
|
+
Object.assign(msg, attributes);
|
|
37
|
+
}
|
|
30
38
|
|
|
31
39
|
} else {
|
|
32
40
|
// Handle Legacy/Raw values (not created by your Setter)
|
|
@@ -36,7 +44,7 @@ module.exports = function(RED) {
|
|
|
36
44
|
|
|
37
45
|
// Visual Status
|
|
38
46
|
const valDisplay = RED.util.getMessageProperty(msg, node.outputProperty);
|
|
39
|
-
node.status({ fill: "blue", shape: "dot", text: `
|
|
47
|
+
node.status({ fill: "blue", shape: "dot", text: `get: ${valDisplay}` });
|
|
40
48
|
|
|
41
49
|
node.send(msg);
|
|
42
50
|
|
|
@@ -45,7 +53,37 @@ module.exports = function(RED) {
|
|
|
45
53
|
}
|
|
46
54
|
}
|
|
47
55
|
|
|
48
|
-
// ---
|
|
56
|
+
// --- HELPER: Manage Event Subscription ---
|
|
57
|
+
function establishListener() {
|
|
58
|
+
setterNode = RED.nodes.getNode(node.targetNodeId);
|
|
59
|
+
|
|
60
|
+
if (setterNode && setterNode.varName && node.updates === 'always') {
|
|
61
|
+
if (updateListener) {
|
|
62
|
+
// Remove existing listener if we're retrying
|
|
63
|
+
RED.events.removeListener("bldgblocks-global-update", updateListener);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
updateListener = function(evt) {
|
|
67
|
+
if (evt.key === setterNode.varName && evt.store === setterNode.storeName) {
|
|
68
|
+
sendValue(evt.data, {});
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
RED.events.on("bldgblocks-global-update", updateListener);
|
|
73
|
+
|
|
74
|
+
// Clear retry interval once successful
|
|
75
|
+
if (retryInterval) {
|
|
76
|
+
clearInterval(retryInterval);
|
|
77
|
+
retryInterval = null;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
node.status({ fill: "green", shape: "dot", text: "Connected" });
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// --- HANDLE MANUAL INPUT ---
|
|
49
87
|
node.on('input', function(msg, send, done) {
|
|
50
88
|
send = send || function() { node.send.apply(node, arguments); };
|
|
51
89
|
|
|
@@ -61,24 +99,40 @@ module.exports = function(RED) {
|
|
|
61
99
|
if (done) done();
|
|
62
100
|
});
|
|
63
101
|
|
|
64
|
-
// ---
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
102
|
+
// --- HANDLE REACTIVE UPDATES ---
|
|
103
|
+
if (node.updates === 'always') {
|
|
104
|
+
if (!establishListener()) {
|
|
105
|
+
// Recursive retry
|
|
106
|
+
const retry = () => {
|
|
107
|
+
if (retryCount >= maxRetries) {
|
|
108
|
+
node.error("Failed to connect to setter node after multiple attempts");
|
|
109
|
+
node.status({ fill: "red", shape: "ring", text: "Connection failed" });
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (establishListener()) {
|
|
114
|
+
retryCount = 0;
|
|
115
|
+
return; // Success
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
retryCount++;
|
|
119
|
+
setTimeout(retry, retryDelays[Math.min(retryCount, maxRetries - 1)]);
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
// Try immediately
|
|
123
|
+
setTimeout(retry, retryDelays[0]);
|
|
124
|
+
}
|
|
75
125
|
}
|
|
76
126
|
|
|
77
127
|
// --- CLEANUP ---
|
|
78
|
-
node.on('close', function() {
|
|
79
|
-
if (
|
|
128
|
+
node.on('close', function(removed, done) {
|
|
129
|
+
if (retryInterval) {
|
|
130
|
+
clearInterval(retryInterval);
|
|
131
|
+
}
|
|
132
|
+
if (removed && updateListener) {
|
|
80
133
|
RED.events.removeListener("bldgblocks-global-update", updateListener);
|
|
81
134
|
}
|
|
135
|
+
done();
|
|
82
136
|
});
|
|
83
137
|
}
|
|
84
138
|
RED.nodes.registerType("global-getter", GlobalGetterNode);
|
package/nodes/global-setter.js
CHANGED
|
@@ -60,7 +60,7 @@ module.exports = function(RED) {
|
|
|
60
60
|
evaluations.push(
|
|
61
61
|
utils.requiresEvaluation(config.writePriorityType)
|
|
62
62
|
? utils.evaluateNodeProperty( config.writePriority, config.writePriorityType, node, msg )
|
|
63
|
-
: Promise.resolve(
|
|
63
|
+
: Promise.resolve(node.writePriority),
|
|
64
64
|
);
|
|
65
65
|
|
|
66
66
|
const results = await Promise.all(evaluations);
|
|
@@ -118,6 +118,10 @@ module.exports = function(RED) {
|
|
|
118
118
|
if (done) done();
|
|
119
119
|
return;
|
|
120
120
|
}
|
|
121
|
+
|
|
122
|
+
if (inputValue !== undefined) {
|
|
123
|
+
state.priority[node.writePriority] = inputValue;
|
|
124
|
+
}
|
|
121
125
|
}
|
|
122
126
|
|
|
123
127
|
// Ensure defaultValue always has a value
|
|
@@ -125,11 +129,6 @@ module.exports = function(RED) {
|
|
|
125
129
|
state.defaultValue = node.defaultValue;
|
|
126
130
|
}
|
|
127
131
|
|
|
128
|
-
// Update Specific Priority Slot
|
|
129
|
-
if (inputValue !== undefined) {
|
|
130
|
-
state.priority[node.writePriority] = inputValue;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
132
|
// Calculate Winner
|
|
134
133
|
state.value = calculateWinner(state);
|
|
135
134
|
|
|
@@ -166,6 +165,7 @@ module.exports = function(RED) {
|
|
|
166
165
|
|
|
167
166
|
node.on('close', function(removed, done) {
|
|
168
167
|
if (removed && node.varName) {
|
|
168
|
+
//RED.events.removeAllListeners("bldgblocks-global-update");
|
|
169
169
|
const globalContext = node.context().global;
|
|
170
170
|
globalContext.set(node.varName, undefined, node.storeName);
|
|
171
171
|
}
|
package/package.json
CHANGED