smart-nodes 0.3.27 → 0.3.28
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 +20 -0
- package/compare/compare.html +52 -6
- package/compare/compare.js +40 -12
- package/counter/counter.html +41 -1
- package/counter/counter.js +20 -2
- package/delay/delay.js +19 -5
- package/heating-curve/heating-curve.html +0 -1
- package/heating-curve/heating-curve.js +4 -4
- package/hysteresis/hysteresis.html +70 -17
- package/hysteresis/hysteresis.js +65 -48
- package/logic/logic.html +44 -1
- package/logic/logic.js +44 -22
- package/mixing-valve/icons/mixing-valve.png +0 -0
- package/mixing-valve/mixing-valve.html +1 -1
- package/mixing-valve/mixing-valve.js +2 -2
- package/package.json +1 -1
- package/shutter-complex-control/shutter-complex-control.html +38 -5
- package/shutter-complex-control/shutter-complex-control.js +62 -28
- package/smart_helper.js +2 -1
- package/statistic/statistic.html +28 -0
- package/statistic/statistic.js +6 -1
- /package/{icons → counter/icons}/counter.png +0 -0
|
@@ -22,8 +22,17 @@ module.exports = function (RED)
|
|
|
22
22
|
last_direction_up: true, // remember last direction for toggle action
|
|
23
23
|
}, smart_context.get(node.id));
|
|
24
24
|
|
|
25
|
+
// Backward compatibility
|
|
26
|
+
if (typeof config.max_time != "undefined")
|
|
27
|
+
{
|
|
28
|
+
config.max_time_up = config.max_time;
|
|
29
|
+
config.max_time_down = config.max_time;
|
|
30
|
+
delete config.max_time;
|
|
31
|
+
}
|
|
32
|
+
|
|
25
33
|
// dynamic config
|
|
26
|
-
let
|
|
34
|
+
let max_time_up = parseInt(config.max_time_up || 60);
|
|
35
|
+
let max_time_down = parseInt(config.max_time_down || 60);
|
|
27
36
|
let revert_time_ms = parseInt(config.revert_time_ms || 100);
|
|
28
37
|
let alarm_action = config.alarm_action || "NOTHING";
|
|
29
38
|
|
|
@@ -123,9 +132,7 @@ module.exports = function (RED)
|
|
|
123
132
|
|
|
124
133
|
on_time = Date.now();
|
|
125
134
|
resultUp = true;
|
|
126
|
-
startAutoOff(false, helper.getTimeInMsFromString(msg.time_on) || null);
|
|
127
|
-
if (!alarm_active)
|
|
128
|
-
node.status({ fill: "green", shape: "dot", text: helper.getCurrentTimeForStatus() + ": Up" });
|
|
135
|
+
startAutoOff(false, helper.getTimeInMsFromString(msg.time_on) || null, null, msg.exact);
|
|
129
136
|
break;
|
|
130
137
|
|
|
131
138
|
case "stop":
|
|
@@ -135,15 +142,19 @@ module.exports = function (RED)
|
|
|
135
142
|
resultStop = true;
|
|
136
143
|
if (max_time_timeout != null)
|
|
137
144
|
{
|
|
138
|
-
const change_percentage = (Date.now() - on_time) / 1000 / max_time * 100;
|
|
139
145
|
if (node_settings.last_direction_up)
|
|
146
|
+
{
|
|
147
|
+
const change_percentage = (Date.now() - on_time) / 1000 / max_time_up * 100;
|
|
140
148
|
node_settings.last_position = Math.max(0, node_settings.last_position - change_percentage);
|
|
149
|
+
}
|
|
141
150
|
else
|
|
151
|
+
{
|
|
152
|
+
const change_percentage = (Date.now() - on_time) / 1000 / max_time_down * 100;
|
|
142
153
|
node_settings.last_position = Math.min(100, node_settings.last_position + change_percentage);
|
|
154
|
+
}
|
|
143
155
|
}
|
|
144
156
|
off_time = Date.now();
|
|
145
157
|
stopAutoOff();
|
|
146
|
-
node.status({ fill: "red", shape: "dot", text: helper.getCurrentTimeForStatus() + ": Stopped at " + Math.round(node_settings.last_position) + "%" });
|
|
147
158
|
break;
|
|
148
159
|
|
|
149
160
|
case "down":
|
|
@@ -164,9 +175,7 @@ module.exports = function (RED)
|
|
|
164
175
|
|
|
165
176
|
on_time = Date.now();
|
|
166
177
|
resultDown = true;
|
|
167
|
-
startAutoOff(true, helper.getTimeInMsFromString(msg.time_on) || null);
|
|
168
|
-
if (!alarm_active)
|
|
169
|
-
node.status({ fill: "green", shape: "dot", text: helper.getCurrentTimeForStatus() + ": Down" });
|
|
178
|
+
startAutoOff(true, helper.getTimeInMsFromString(msg.time_on) || null, null, msg.exact);
|
|
170
179
|
break;
|
|
171
180
|
|
|
172
181
|
case "position":
|
|
@@ -184,13 +193,16 @@ module.exports = function (RED)
|
|
|
184
193
|
{
|
|
185
194
|
// Change position while running,
|
|
186
195
|
// Calculate current position first
|
|
187
|
-
const change_percentage = (now - on_time) / 1000 / max_time * 100;
|
|
188
196
|
if (node_settings.last_direction_up)
|
|
197
|
+
{
|
|
198
|
+
const change_percentage = (now - on_time) / 1000 / max_time_up * 100;
|
|
189
199
|
node_settings.last_position = Math.max(0, node_settings.last_position - change_percentage);
|
|
200
|
+
}
|
|
190
201
|
else
|
|
202
|
+
{
|
|
203
|
+
const change_percentage = (now - on_time) / 1000 / max_time_down * 100;
|
|
191
204
|
node_settings.last_position = Math.min(100, node_settings.last_position + change_percentage);
|
|
192
|
-
|
|
193
|
-
node.status({ fill: "gray", shape: "dot", text: helper.getCurrentTimeForStatus() + ": Update current position to " + node_settings.last_position + "%" });
|
|
205
|
+
}
|
|
194
206
|
|
|
195
207
|
// Runs in the wrong direction at the moment, so stop first
|
|
196
208
|
if (node_settings.last_direction_up && value > node_settings.last_position)
|
|
@@ -213,13 +225,13 @@ module.exports = function (RED)
|
|
|
213
225
|
{
|
|
214
226
|
// Go up
|
|
215
227
|
resultUp = true;
|
|
216
|
-
startAutoOff(false, (node_settings.last_position - value) / 100 *
|
|
228
|
+
startAutoOff(false, (node_settings.last_position - value) / 100 * max_time_up * 1000, value);
|
|
217
229
|
}
|
|
218
230
|
else if (value > node_settings.last_position)
|
|
219
231
|
{
|
|
220
232
|
// Go down
|
|
221
233
|
resultDown = true;
|
|
222
|
-
startAutoOff(true, (value - node_settings.last_position) / 100 *
|
|
234
|
+
startAutoOff(true, (value - node_settings.last_position) / 100 * max_time_down * 1000, value);
|
|
223
235
|
}
|
|
224
236
|
else
|
|
225
237
|
{
|
|
@@ -227,8 +239,6 @@ module.exports = function (RED)
|
|
|
227
239
|
handleTopic({ topic: "stop" });
|
|
228
240
|
return;
|
|
229
241
|
}
|
|
230
|
-
|
|
231
|
-
node.status({ fill: "green", shape: "dot", text: helper.getCurrentTimeForStatus() + ": Set position from " + node_settings.last_position + "% to " + value + "%" });
|
|
232
242
|
break;
|
|
233
243
|
|
|
234
244
|
case "alarm":
|
|
@@ -236,7 +246,7 @@ module.exports = function (RED)
|
|
|
236
246
|
|
|
237
247
|
if (alarm_active)
|
|
238
248
|
{
|
|
239
|
-
node.status({ fill: "red", shape: "dot", text: helper.getCurrentTimeForStatus() + ": ALARM
|
|
249
|
+
node.status({ fill: "red", shape: "dot", text: helper.getCurrentTimeForStatus() + ": ALARM turned on" });
|
|
240
250
|
|
|
241
251
|
switch (alarm_action)
|
|
242
252
|
{
|
|
@@ -249,13 +259,17 @@ module.exports = function (RED)
|
|
|
249
259
|
break;
|
|
250
260
|
}
|
|
251
261
|
}
|
|
262
|
+
else
|
|
263
|
+
{
|
|
264
|
+
node.status({ fill: "red", shape: "dot", text: helper.getCurrentTimeForStatus() + ": ALARM turned off" });
|
|
265
|
+
}
|
|
252
266
|
break;
|
|
253
267
|
}
|
|
254
268
|
|
|
255
|
-
sendResult(resultUp, resultDown, resultStop);
|
|
269
|
+
sendResult(resultUp, resultDown, resultStop, msg.exact);
|
|
256
270
|
};
|
|
257
271
|
|
|
258
|
-
let startAutoOff = (down, wait_time_ms = null, new_position = null) =>
|
|
272
|
+
let startAutoOff = (down, wait_time_ms = null, new_position = null, exact = false) =>
|
|
259
273
|
{
|
|
260
274
|
// console.log("startAutoOff (" + down + ", " + wait_time_ms + ", " + new_position + ");");
|
|
261
275
|
|
|
@@ -276,16 +290,20 @@ module.exports = function (RED)
|
|
|
276
290
|
down = true;
|
|
277
291
|
}
|
|
278
292
|
}
|
|
293
|
+
|
|
279
294
|
if (wait_time_ms == null)
|
|
280
295
|
{
|
|
281
296
|
if (down)
|
|
282
|
-
wait_time_ms = (100 - node_settings.last_position) *
|
|
297
|
+
wait_time_ms = (100 - node_settings.last_position) * max_time_down / 100 * 1000;
|
|
283
298
|
else
|
|
284
|
-
wait_time_ms = node_settings.last_position *
|
|
299
|
+
wait_time_ms = node_settings.last_position * max_time_up / 100 * 1000;
|
|
285
300
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
301
|
+
if (exact !== true)
|
|
302
|
+
{
|
|
303
|
+
// Run at least for 5 seconds
|
|
304
|
+
if (wait_time_ms < 5000)
|
|
305
|
+
wait_time_ms = 5000;
|
|
306
|
+
}
|
|
289
307
|
}
|
|
290
308
|
|
|
291
309
|
if (wait_time_ms < 0)
|
|
@@ -294,6 +312,9 @@ module.exports = function (RED)
|
|
|
294
312
|
return;
|
|
295
313
|
}
|
|
296
314
|
|
|
315
|
+
if (wait_time_ms == 0)
|
|
316
|
+
return;
|
|
317
|
+
|
|
297
318
|
if (!alarm_active)
|
|
298
319
|
node.status({ fill: "yellow", shape: "ring", text: helper.getCurrentTimeForStatus() + ": " + (down ? "Down" : "Up") + ", wait " + helper.formatMsToStatus(wait_time_ms, "until") + " for auto off" });
|
|
299
320
|
|
|
@@ -319,8 +340,18 @@ module.exports = function (RED)
|
|
|
319
340
|
}
|
|
320
341
|
};
|
|
321
342
|
|
|
322
|
-
let sendResult = (up, down, stop) =>
|
|
343
|
+
let sendResult = (up, down, stop, exact) =>
|
|
323
344
|
{
|
|
345
|
+
if (exact === true)
|
|
346
|
+
{
|
|
347
|
+
console.log({ up, down, stop, exact, last_pos: node_settings.last_position });
|
|
348
|
+
// Don't start moving if exact is enabled and already on top/bottom.
|
|
349
|
+
if (down && node_settings.last_position == 100)
|
|
350
|
+
return;
|
|
351
|
+
if (up && node_settings.last_position == 0)
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
|
|
324
355
|
// console.log("sendResult(" + up + ", " + down + ", " + stop + ");");
|
|
325
356
|
if ((up && wait_for_down) || (down && wait_for_up))
|
|
326
357
|
{
|
|
@@ -343,7 +374,7 @@ module.exports = function (RED)
|
|
|
343
374
|
wait_timeout = setTimeout(() =>
|
|
344
375
|
{
|
|
345
376
|
wait_timeout = null;
|
|
346
|
-
sendResult(up, down, stop);
|
|
377
|
+
sendResult(up, down, stop, exact);
|
|
347
378
|
}, off_time + revert_time_ms - now);
|
|
348
379
|
return;
|
|
349
380
|
}
|
|
@@ -355,7 +386,7 @@ module.exports = function (RED)
|
|
|
355
386
|
wait_timeout = null;
|
|
356
387
|
}
|
|
357
388
|
|
|
358
|
-
// console.log("really sendResult(" + up + ", " + down + ", " + stop + ");");
|
|
389
|
+
// console.log("really sendResult(" + up + ", " + down + ", " + stop + ", " + exact + ");");
|
|
359
390
|
if (up)
|
|
360
391
|
{
|
|
361
392
|
if (!alarm_active || alarm_action === "UP")
|
|
@@ -363,6 +394,7 @@ module.exports = function (RED)
|
|
|
363
394
|
node_settings.last_direction_up = true;
|
|
364
395
|
node.send([{ payload: true }, { payload: false }, { payload: node_settings.last_position }]);
|
|
365
396
|
notifyCentral(true);
|
|
397
|
+
node.status({ fill: "green", shape: "dot", text: helper.getCurrentTimeForStatus() + ": Up" });
|
|
366
398
|
}
|
|
367
399
|
}
|
|
368
400
|
else if (down)
|
|
@@ -372,12 +404,14 @@ module.exports = function (RED)
|
|
|
372
404
|
node_settings.last_direction_up = false;
|
|
373
405
|
node.send([{ payload: false }, { payload: true }, { payload: node_settings.last_position }]);
|
|
374
406
|
notifyCentral(true);
|
|
407
|
+
node.status({ fill: "green", shape: "dot", text: helper.getCurrentTimeForStatus() + ": Down" });
|
|
375
408
|
}
|
|
376
409
|
}
|
|
377
410
|
else if (stop && !alarm_active)
|
|
378
411
|
{
|
|
379
412
|
node.send([{ payload: false }, { payload: false }, { payload: node_settings.last_position }]);
|
|
380
413
|
notifyCentral(false);
|
|
414
|
+
node.status({ fill: "red", shape: "dot", text: helper.getCurrentTimeForStatus() + ": Stopped at " + Math.round(node_settings.last_position) + "%" });
|
|
381
415
|
}
|
|
382
416
|
};
|
|
383
417
|
|
|
@@ -395,7 +429,7 @@ module.exports = function (RED)
|
|
|
395
429
|
};
|
|
396
430
|
|
|
397
431
|
// For security reason, stop shutter at node start
|
|
398
|
-
setTimeout(() =>
|
|
432
|
+
wait_timeout = setTimeout(() =>
|
|
399
433
|
{
|
|
400
434
|
node.send([{ payload: false }, { payload: false }, { payload: node_settings.last_position }]);
|
|
401
435
|
node.status({ fill: "red", shape: "dot", text: helper.getCurrentTimeForStatus() + ": Stopped at " + Math.round(node_settings.last_position) + "%" });
|
package/smart_helper.js
CHANGED
|
@@ -5,7 +5,7 @@ module.exports = {
|
|
|
5
5
|
* If a type is unknown the NodeRed function is used for conversation.
|
|
6
6
|
*
|
|
7
7
|
* Known types are:
|
|
8
|
-
* - null, which will return always null
|
|
8
|
+
* - "null", which will return always null
|
|
9
9
|
*/
|
|
10
10
|
evaluateNodeProperty(RED, value, type)
|
|
11
11
|
{
|
|
@@ -26,6 +26,7 @@ module.exports = {
|
|
|
26
26
|
console.error(value);
|
|
27
27
|
console.error(type);
|
|
28
28
|
console.error(error);
|
|
29
|
+
console.error(msg);
|
|
29
30
|
return null;
|
|
30
31
|
}
|
|
31
32
|
},
|
package/statistic/statistic.html
CHANGED
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
name: { value: "" },
|
|
8
8
|
operation: { value: "MIN" }, // MIN, MAX, SUM, DIFF, ABS, ABS_DIFF, AVG, MOV_AVG
|
|
9
9
|
count: { value: 10 },
|
|
10
|
+
out_message: { value: '{"topic": ""}' },
|
|
11
|
+
out_message_type: { value: 'json' },
|
|
10
12
|
save_state: { value: true },
|
|
11
13
|
resend_on_start: { value: true }
|
|
12
14
|
},
|
|
@@ -58,6 +60,17 @@
|
|
|
58
60
|
$(".statistic-moving-average-row").hide();
|
|
59
61
|
});
|
|
60
62
|
|
|
63
|
+
$("#node-input-out_message").typedInput({
|
|
64
|
+
type: "json",
|
|
65
|
+
types: ["json", {
|
|
66
|
+
value: "null",
|
|
67
|
+
label: "Standard",
|
|
68
|
+
icon: "fa fa-times",
|
|
69
|
+
hasValue: false,
|
|
70
|
+
}],
|
|
71
|
+
typeField: "#node-input-out_message_type"
|
|
72
|
+
});
|
|
73
|
+
|
|
61
74
|
$("#node-input-save_state").on("change", ev =>
|
|
62
75
|
{
|
|
63
76
|
if (ev.target.checked)
|
|
@@ -84,6 +97,21 @@
|
|
|
84
97
|
<input id="node-input-count" />
|
|
85
98
|
</div>
|
|
86
99
|
<hr/>
|
|
100
|
+
<h4 style="margin: 0.5rem 0;">Ausgangsnachricht</h4>
|
|
101
|
+
<div class="form-row">
|
|
102
|
+
<label for="node-input-out_message"><i class="fa fa-check-circle"></i> Nachricht</label>
|
|
103
|
+
<input type="text" id="node-input-out_message"/>
|
|
104
|
+
<input type="hidden" id="node-input-out_message_type">
|
|
105
|
+
</div>
|
|
106
|
+
<div class="form-row">
|
|
107
|
+
<span><strong>Hinweis:</strong></span>
|
|
108
|
+
</div>
|
|
109
|
+
<div class="form-row">
|
|
110
|
+
<span>
|
|
111
|
+
<code>msg.payload</code> wird immer automatisch auf den Ergebnis-Wert gesetzt.
|
|
112
|
+
</span>
|
|
113
|
+
</div>
|
|
114
|
+
<hr/>
|
|
87
115
|
<h4 style="margin: 0.5rem 0;">Systemstart</h4>
|
|
88
116
|
<div class="form-row">
|
|
89
117
|
<input type="checkbox" id="node-input-save_state" style="width: 20px;" />
|
package/statistic/statistic.js
CHANGED
|
@@ -28,6 +28,7 @@ module.exports = function (RED)
|
|
|
28
28
|
|
|
29
29
|
// dynamic config
|
|
30
30
|
let operation = config.operation
|
|
31
|
+
let out_message = helper.evaluateNodeProperty(RED, config.out_message, config.out_message_type);
|
|
31
32
|
let count = config.count;
|
|
32
33
|
|
|
33
34
|
// runtime values
|
|
@@ -66,6 +67,10 @@ module.exports = function (RED)
|
|
|
66
67
|
|
|
67
68
|
if (msg)
|
|
68
69
|
{
|
|
70
|
+
// if out_message is set, use this instead of the default message
|
|
71
|
+
if (out_message)
|
|
72
|
+
msg = Object.assign({}, out_message, { payload: msg.payload });
|
|
73
|
+
|
|
69
74
|
node_settings.lastMessage = msg;
|
|
70
75
|
node.send(msg);
|
|
71
76
|
}
|
|
@@ -180,7 +185,7 @@ module.exports = function (RED)
|
|
|
180
185
|
if (operation === "ABS")
|
|
181
186
|
node.status({ fill: "yellow", shape: "ring", text: helper.getCurrentTimeForStatus() + ": " + operation + " => " + msg.payload });
|
|
182
187
|
else
|
|
183
|
-
node.status({ fill: "yellow", shape: "ring", text: helper.getCurrentTimeForStatus() + ": " + operation + "(" + Object.entries(node_settings.values).map(v => v[1]).join(",") + ") => " + msg.payload });
|
|
188
|
+
node.status({ fill: "yellow", shape: "ring", text: helper.getCurrentTimeForStatus() + ": " + operation + "(" + Object.entries(node_settings.values).map(v => v[1]).join(", ") + ") => " + msg.payload });
|
|
184
189
|
}
|
|
185
190
|
|
|
186
191
|
if (config.save_state && config.resend_on_start && node_settings.lastMessage != null)
|
|
File without changes
|