@bldgblocks/node-red-contrib-control 0.1.27 → 0.1.29
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 +1 -1
- package/nodes/average-block.js +1 -1
- package/nodes/boolean-switch-block.html +2 -1
- package/nodes/boolean-switch-block.js +1 -2
- package/nodes/call-status-block.html +30 -45
- package/nodes/call-status-block.js +81 -195
- package/nodes/changeover-block.html +76 -12
- package/nodes/changeover-block.js +24 -8
- package/nodes/delay-block.html +1 -1
- package/nodes/frequency-block.html +3 -1
- package/nodes/frequency-block.js +64 -7
- package/nodes/global-getter.html +96 -0
- package/nodes/global-getter.js +42 -0
- package/nodes/global-setter.html +72 -0
- package/nodes/global-setter.js +43 -0
- package/nodes/hysteresis-block.js +1 -1
- package/nodes/latch-block.html +55 -0
- package/nodes/latch-block.js +77 -0
- package/nodes/on-change-block.html +0 -1
- package/nodes/on-change-block.js +2 -12
- package/nodes/pid-block.html +102 -80
- package/nodes/pid-block.js +120 -110
- package/nodes/rate-of-change-block.html +110 -0
- package/nodes/rate-of-change-block.js +233 -0
- package/nodes/string-builder-block.html +112 -0
- package/nodes/string-builder-block.js +89 -0
- package/nodes/tstat-block.html +85 -39
- package/nodes/tstat-block.js +66 -30
- package/package.json +6 -1
package/nodes/tstat-block.js
CHANGED
|
@@ -21,7 +21,9 @@ module.exports = function(RED) {
|
|
|
21
21
|
node.heatingOn = parseFloat(RED.util.evaluateNodeProperty( config.heatingOn, config.heatingOnType, node ));
|
|
22
22
|
node.diff = parseFloat(RED.util.evaluateNodeProperty( config.diff, config.diffType, node ));
|
|
23
23
|
node.anticipator = parseFloat(RED.util.evaluateNodeProperty( config.anticipator, config.anticipatorType, node ));
|
|
24
|
-
node.ignoreAnticipatorCycles = Math.floor(RED.util.evaluateNodeProperty( config.ignoreAnticipatorCycles, config.ignoreAnticipatorCyclesType, node ));
|
|
24
|
+
node.ignoreAnticipatorCycles = Math.floor(RED.util.evaluateNodeProperty( config.ignoreAnticipatorCycles, config.ignoreAnticipatorCyclesType, node ));
|
|
25
|
+
node.isHeating = RED.util.evaluateNodeProperty( config.isHeating, config.isHeatingType, node ) === true;
|
|
26
|
+
node.algorithm = RED.util.evaluateNodeProperty( config.algorithm, config.algorithmType, node );
|
|
25
27
|
} catch (err) {
|
|
26
28
|
node.error(`Error evaluating properties: ${err.message}`);
|
|
27
29
|
}
|
|
@@ -75,6 +77,12 @@ module.exports = function(RED) {
|
|
|
75
77
|
if (utils.requiresEvaluation(config.ignoreAnticipatorCyclesType)) {
|
|
76
78
|
node.ignoreAnticipatorCycles = Math.floor(RED.util.evaluateNodeProperty( config.ignoreAnticipatorCycles, config.ignoreAnticipatorCyclesType, node, msg ));
|
|
77
79
|
}
|
|
80
|
+
if (utils.requiresEvaluation(config.isHeatingType)) {
|
|
81
|
+
node.isHeating = RED.util.evaluateNodeProperty( config.isHeating, config.isHeatingType, node, msg ) === true;
|
|
82
|
+
}
|
|
83
|
+
if (utils.requiresEvaluation(config.algorithmType)) {
|
|
84
|
+
node.algorithm = RED.util.evaluateNodeProperty( config.algorithm, config.algorithmType, node, msg );
|
|
85
|
+
}
|
|
78
86
|
} catch (err) {
|
|
79
87
|
node.error(`Error evaluating properties: ${err.message}`);
|
|
80
88
|
if (done) done();
|
|
@@ -197,14 +205,14 @@ module.exports = function(RED) {
|
|
|
197
205
|
}
|
|
198
206
|
|
|
199
207
|
if (!msg.hasOwnProperty("payload")) {
|
|
200
|
-
node.status({ fill: "red", shape: "ring", text: "missing
|
|
208
|
+
node.status({ fill: "red", shape: "ring", text: "missing payload" });
|
|
201
209
|
if (done) done();
|
|
202
210
|
return;
|
|
203
211
|
}
|
|
204
212
|
|
|
205
213
|
const input = parseFloat(msg.payload);
|
|
206
214
|
if (isNaN(input)) {
|
|
207
|
-
node.status({ fill: "red", shape: "ring", text: "invalid
|
|
215
|
+
node.status({ fill: "red", shape: "ring", text: "invalid payload" });
|
|
208
216
|
if (done) done();
|
|
209
217
|
return;
|
|
210
218
|
}
|
|
@@ -236,31 +244,52 @@ module.exports = function(RED) {
|
|
|
236
244
|
|
|
237
245
|
lastAbove = above;
|
|
238
246
|
lastBelow = below;
|
|
247
|
+
let delta = 0;
|
|
248
|
+
let hiValue = 0;
|
|
249
|
+
let loValue = 0;
|
|
250
|
+
let hiOffValue = 0;
|
|
251
|
+
let loOffValue = 0;
|
|
252
|
+
let activeHeatingSetpoint = 0;
|
|
253
|
+
let activeCoolingSetpoint = 0;
|
|
239
254
|
|
|
240
255
|
// Main thermostat logic
|
|
256
|
+
// The Tstat node does not control heating/cooling mode, only operates heating or cooling according to the mode set and respective setpoints.
|
|
241
257
|
if (node.algorithm === "single") {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
258
|
+
// Note:
|
|
259
|
+
// Make sure your mode selection is handled upstream and does not osciallate modes.
|
|
260
|
+
// This was changed to allow for broader anticipator authority, or even negative (overshoot) so duty cycle can be better managed.
|
|
261
|
+
// So the same setpoint can be used year round and maintain tight control.
|
|
262
|
+
// Alternatively, you would need a larger diff value to prevent oscillation.
|
|
263
|
+
delta = node.diff / 2;
|
|
264
|
+
hiValue = node.setpoint + delta;
|
|
265
|
+
loValue = node.setpoint - delta;
|
|
266
|
+
hiOffValue = node.setpoint + effectiveAnticipator;
|
|
267
|
+
loOffValue = node.setpoint - effectiveAnticipator;
|
|
268
|
+
activeHeatingSetpoint = node.setpoint;
|
|
269
|
+
activeCoolingSetpoint = node.setpoint;
|
|
247
270
|
|
|
248
|
-
if (
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
} else if (above && input < hiOffValue) {
|
|
271
|
+
if (isHeating) {
|
|
272
|
+
if (input < loValue) {
|
|
273
|
+
below = true;
|
|
274
|
+
} else if (below && input > loOffValue) {
|
|
275
|
+
below = false;
|
|
276
|
+
}
|
|
255
277
|
above = false;
|
|
256
|
-
} else
|
|
278
|
+
} else {
|
|
279
|
+
if (input > hiValue) {
|
|
280
|
+
above = true;
|
|
281
|
+
} else if (above && input < hiOffValue) {
|
|
282
|
+
above = false;
|
|
283
|
+
}
|
|
257
284
|
below = false;
|
|
258
285
|
}
|
|
259
286
|
} else if (node.algorithm === "split") {
|
|
287
|
+
activeHeatingSetpoint = node.heatingSetpoint;
|
|
288
|
+
activeCoolingSetpoint = node.coolingSetpoint;
|
|
260
289
|
if (node.isHeating) {
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
290
|
+
delta = node.diff / 2;
|
|
291
|
+
loValue = node.heatingSetpoint - delta;
|
|
292
|
+
loOffValue = node.heatingSetpoint - effectiveAnticipator;
|
|
264
293
|
|
|
265
294
|
if (input < loValue) {
|
|
266
295
|
below = true;
|
|
@@ -269,9 +298,9 @@ module.exports = function(RED) {
|
|
|
269
298
|
}
|
|
270
299
|
above = false;
|
|
271
300
|
} else {
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
301
|
+
delta = node.diff / 2;
|
|
302
|
+
hiValue = node.coolingSetpoint + delta;
|
|
303
|
+
hiOffValue = node.coolingSetpoint + effectiveAnticipator;
|
|
275
304
|
|
|
276
305
|
if (input > hiValue) {
|
|
277
306
|
above = true;
|
|
@@ -281,6 +310,8 @@ module.exports = function(RED) {
|
|
|
281
310
|
below = false;
|
|
282
311
|
}
|
|
283
312
|
} else if (node.algorithm === "specified") {
|
|
313
|
+
activeHeatingSetpoint = node.heatingOn;
|
|
314
|
+
activeCoolingSetpoint = node.coolingOn;
|
|
284
315
|
if (node.isHeating) {
|
|
285
316
|
if (input < node.heatingOn) {
|
|
286
317
|
below = true;
|
|
@@ -311,20 +342,25 @@ module.exports = function(RED) {
|
|
|
311
342
|
};
|
|
312
343
|
|
|
313
344
|
// Add algorithm-specific status
|
|
345
|
+
statusInfo.activeHeatingSetpoint = activeHeatingSetpoint;
|
|
346
|
+
statusInfo.activeCoolingSetpoint = activeCoolingSetpoint;
|
|
347
|
+
statusInfo.diff = node.diff;
|
|
348
|
+
statusInfo.anticipator = node.anticipator;
|
|
349
|
+
statusInfo.loValue = loValue;
|
|
350
|
+
statusInfo.hiValue = hiValue;
|
|
351
|
+
statusInfo.loOffValue = loOffValue;
|
|
352
|
+
statusInfo.hiOffValue = hiOffValue;
|
|
353
|
+
|
|
314
354
|
if (node.algorithm === "single") {
|
|
315
355
|
statusInfo.setpoint = node.setpoint;
|
|
316
|
-
statusInfo.diff = node.diff;
|
|
317
|
-
statusInfo.anticipator = node.anticipator;
|
|
318
356
|
} else if (node.algorithm === "split") {
|
|
319
357
|
statusInfo.heatingSetpoint = node.heatingSetpoint;
|
|
320
358
|
statusInfo.coolingSetpoint = node.coolingSetpoint;
|
|
321
|
-
statusInfo.diff = node.diff;
|
|
322
|
-
statusInfo.anticipator = node.anticipator;
|
|
323
359
|
} else {
|
|
324
|
-
statusInfo.
|
|
325
|
-
statusInfo.
|
|
326
|
-
statusInfo.
|
|
327
|
-
statusInfo.
|
|
360
|
+
statusInfo.hiValue = node.coolingOn;
|
|
361
|
+
statusInfo.hiOffValue = node.coolingOff;
|
|
362
|
+
statusInfo.loOffValue = node.heatingOff;
|
|
363
|
+
statusInfo.loValue = node.heatingOn;
|
|
328
364
|
statusInfo.anticipator = node.anticipator;
|
|
329
365
|
}
|
|
330
366
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bldgblocks/node-red-contrib-control",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.29",
|
|
4
4
|
"description": "Sedona-inspired control nodes for Node-RED",
|
|
5
5
|
"keywords": [ "node-red", "sedona", "control", "hvac" ],
|
|
6
6
|
"files": ["nodes/*.js", "nodes/*.html"],
|
|
@@ -31,8 +31,11 @@
|
|
|
31
31
|
"edge-block": "nodes/edge-block.js",
|
|
32
32
|
"enum-switch-block": "nodes/enum-switch-block.js",
|
|
33
33
|
"frequency-block": "nodes/frequency-block.js",
|
|
34
|
+
"global-getter": "nodes/global-getter.js",
|
|
35
|
+
"global-setter": "nodes/global-setter.js",
|
|
34
36
|
"hysteresis-block": "nodes/hysteresis-block.js",
|
|
35
37
|
"interpolate-block": "nodes/interpolate-block.js",
|
|
38
|
+
"latch-block": "nodes/latch-block.js",
|
|
36
39
|
"load-sequence-block": "nodes/load-sequence-block.js",
|
|
37
40
|
"max-block": "nodes/max-block.js",
|
|
38
41
|
"memory-block": "nodes/memory-block.js",
|
|
@@ -48,10 +51,12 @@
|
|
|
48
51
|
"pid-block": "nodes/pid-block.js",
|
|
49
52
|
"priority-block": "nodes/priority-block.js",
|
|
50
53
|
"rate-limit-block": "nodes/rate-limit-block.js",
|
|
54
|
+
"rate-of-change-block": "nodes/rate-of-change-block.js",
|
|
51
55
|
"round-block": "nodes/round-block.js",
|
|
52
56
|
"saw-tooth-wave-block": "nodes/saw-tooth-wave-block.js",
|
|
53
57
|
"scale-range-block": "nodes/scale-range-block.js",
|
|
54
58
|
"sine-wave-block": "nodes/sine-wave-block.js",
|
|
59
|
+
"string-builder-block": "nodes/string-builder-block.js",
|
|
55
60
|
"subtract-block": "nodes/subtract-block.js",
|
|
56
61
|
"thermistor-block": "nodes/thermistor-block.js",
|
|
57
62
|
"tick-tock-block": "nodes/tick-tock-block.js",
|