smart-nodes 0.3.36 → 0.4.0

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.
Files changed (116) hide show
  1. package/CHANGELOG.md +62 -0
  2. package/README.md +35 -17
  3. package/central/central.html +27 -24
  4. package/central/central.js +84 -26
  5. package/central/locales/de-DE/central.html +10 -0
  6. package/central/locales/de-DE/central.json +14 -0
  7. package/central/locales/en-US/central.html +10 -0
  8. package/central/locales/en-US/central.json +14 -0
  9. package/compare/compare.html +64 -87
  10. package/compare/compare.js +69 -29
  11. package/compare/locales/de-DE/compare.html +36 -0
  12. package/compare/locales/de-DE/compare.json +35 -0
  13. package/compare/locales/en-US/compare.html +36 -0
  14. package/compare/locales/en-US/compare.json +35 -0
  15. package/counter/counter.html +70 -72
  16. package/counter/counter.js +43 -20
  17. package/counter/locales/de-DE/counter.html +48 -0
  18. package/counter/locales/de-DE/counter.json +21 -0
  19. package/counter/locales/en-US/counter.html +48 -0
  20. package/counter/locales/en-US/counter.json +21 -0
  21. package/delay/delay.html +30 -102
  22. package/delay/delay.js +63 -20
  23. package/delay/locales/de-DE/delay.html +71 -0
  24. package/delay/locales/de-DE/delay.json +19 -0
  25. package/delay/locales/en-US/delay.html +76 -0
  26. package/delay/locales/en-US/delay.json +19 -0
  27. package/forwarder/forwarder.html +11 -42
  28. package/forwarder/forwarder.js +59 -18
  29. package/forwarder/locales/de-DE/forwarder.html +32 -0
  30. package/forwarder/locales/de-DE/forwarder.json +15 -0
  31. package/forwarder/locales/en-US/forwarder.html +32 -0
  32. package/forwarder/locales/en-US/forwarder.json +15 -0
  33. package/heating-curve/heating-curve.html +10 -51
  34. package/heating-curve/heating-curve.js +38 -13
  35. package/heating-curve/locales/de-DE/heating-curve.html +38 -0
  36. package/heating-curve/locales/de-DE/heating-curve.json +12 -0
  37. package/heating-curve/locales/en-US/heating-curve.html +38 -0
  38. package/heating-curve/locales/en-US/heating-curve.json +12 -0
  39. package/hysteresis/hysteresis.html +49 -69
  40. package/hysteresis/hysteresis.js +94 -68
  41. package/hysteresis/locales/de-DE/hysteresis.html +36 -0
  42. package/hysteresis/locales/de-DE/hysteresis.json +27 -0
  43. package/hysteresis/locales/en-US/hysteresis.html +36 -0
  44. package/hysteresis/locales/en-US/hysteresis.json +27 -0
  45. package/light/light.html +250 -0
  46. package/{light-control/light-control.js → light/light.js} +151 -32
  47. package/light/locales/de-DE/light.html +149 -0
  48. package/light/locales/de-DE/light.json +24 -0
  49. package/light/locales/en-US/light.html +148 -0
  50. package/light/locales/en-US/light.json +24 -0
  51. package/logic/locales/de-DE/logic.html +12 -0
  52. package/logic/locales/de-DE/logic.json +26 -0
  53. package/logic/locales/en-US/logic.html +12 -0
  54. package/logic/locales/en-US/logic.json +26 -0
  55. package/logic/logic.html +48 -64
  56. package/logic/logic.js +63 -29
  57. package/long-press/locales/de-DE/long-press.html +5 -0
  58. package/long-press/locales/de-DE/long-press.json +13 -0
  59. package/long-press/locales/en-US/long-press.html +5 -0
  60. package/long-press/locales/en-US/long-press.json +13 -0
  61. package/{long-press-control/long-press-control.html → long-press/long-press.html} +10 -14
  62. package/long-press/long-press.js +163 -0
  63. package/mixing-valve/locales/de-DE/mixing-valve.html +65 -0
  64. package/mixing-valve/locales/de-DE/mixing-valve.json +19 -0
  65. package/mixing-valve/locales/en-US/mixing-valve.html +66 -0
  66. package/mixing-valve/locales/en-US/mixing-valve.json +19 -0
  67. package/mixing-valve/mixing-valve.html +27 -93
  68. package/mixing-valve/mixing-valve.js +87 -61
  69. package/multi-press/locales/de-DE/multi-press.html +5 -0
  70. package/multi-press/locales/de-DE/multi-press.json +12 -0
  71. package/multi-press/locales/en-US/multi-press.html +5 -0
  72. package/multi-press/locales/en-US/multi-press.json +12 -0
  73. package/{multi-press-control/multi-press-control.html → multi-press/multi-press.html} +9 -13
  74. package/{multi-press-control/multi-press-control.js → multi-press/multi-press.js} +53 -5
  75. package/package.json +7 -7
  76. package/persistence.js +1 -0
  77. package/scene/locales/de-DE/scene.html +105 -0
  78. package/scene/locales/de-DE/scene.json +21 -0
  79. package/scene/locales/en-US/scene.html +107 -0
  80. package/scene/locales/en-US/scene.json +20 -0
  81. package/{scene-control/scene-control.html → scene/scene.html} +30 -132
  82. package/{scene-control/scene-control.js → scene/scene.js} +76 -26
  83. package/scheduler/locales/de-DE/scheduler.html +30 -0
  84. package/scheduler/locales/de-DE/scheduler.json +21 -0
  85. package/scheduler/locales/en-US/scheduler.html +30 -0
  86. package/scheduler/locales/en-US/scheduler.json +21 -0
  87. package/scheduler/scheduler.html +34 -64
  88. package/scheduler/scheduler.js +85 -53
  89. package/shutter/locales/de-DE/shutter.html +127 -0
  90. package/shutter/locales/de-DE/shutter.json +11 -0
  91. package/shutter/locales/en-US/shutter.html +133 -0
  92. package/shutter/locales/en-US/shutter.json +11 -0
  93. package/{shutter-control/shutter-control.html → shutter/shutter.html} +7 -133
  94. package/{shutter-control/shutter-control.js → shutter/shutter.js} +116 -56
  95. package/shutter-complex/locales/de-DE/shutter-complex.html +120 -0
  96. package/shutter-complex/locales/de-DE/shutter-complex.json +20 -0
  97. package/shutter-complex/locales/en-US/shutter-complex.html +120 -0
  98. package/shutter-complex/locales/en-US/shutter-complex.json +20 -0
  99. package/{shutter-complex-control/shutter-complex-control.html → shutter-complex/shutter-complex.html} +36 -140
  100. package/shutter-complex/shutter-complex.js +578 -0
  101. package/smart_helper.js +52 -9
  102. package/statistic/locales/de-DE/statistic.html +10 -0
  103. package/statistic/locales/de-DE/statistic.json +29 -0
  104. package/statistic/locales/en-US/statistic.html +10 -0
  105. package/statistic/locales/en-US/statistic.json +29 -0
  106. package/statistic/statistic.html +38 -43
  107. package/statistic/statistic.js +57 -28
  108. package/text-exec/locales/de-DE/text-exec.html +18 -0
  109. package/text-exec/locales/de-DE/text-exec.json +7 -0
  110. package/text-exec/locales/en-US/text-exec.html +18 -0
  111. package/text-exec/locales/en-US/text-exec.json +7 -0
  112. package/text-exec/text-exec.html +9 -25
  113. package/text-exec/text-exec.js +43 -2
  114. package/light-control/light-control.html +0 -363
  115. package/long-press-control/long-press-control.js +0 -76
  116. package/shutter-complex-control/shutter-complex-control.js +0 -442
@@ -1,442 +0,0 @@
1
- module.exports = function (RED)
2
- {
3
- "use strict";
4
-
5
- function ShutterComplexControlNode(config)
6
- {
7
- const node = this;
8
- RED.nodes.createNode(node, config);
9
-
10
- const smart_context = require("../persistence.js")(RED);
11
- const helper = require("../smart_helper.js");
12
-
13
- // used from text-exec node
14
- if (typeof config.exec_text_names == "string")
15
- node.exec_text_names = config.exec_text_names.split(",").map(n => n.trim().toLowerCase());
16
- else
17
- node.exec_text_names = [];
18
-
19
- // persistent values
20
- var node_settings = Object.assign({}, {
21
- last_position: 0, // 0 = opened, 100 = closed
22
- last_direction_up: true, // remember last direction for toggle action
23
- }, smart_context.get(node.id));
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
-
33
- // dynamic config
34
- let max_time_up = parseInt(config.max_time_up || 60);
35
- let max_time_down = parseInt(config.max_time_down || 60);
36
- let revert_time_ms = parseInt(config.revert_time_ms || 100);
37
- let alarm_action = config.alarm_action || "NOTHING";
38
-
39
- // runtime values
40
- let max_time_timeout = null;
41
- let on_time = null;
42
- let off_time = null;
43
- let wait_for_up = false;
44
- let wait_for_down = false;
45
- let wait_timeout = null;
46
- let alarm_active = false;
47
-
48
- // central handling
49
- var event = "node:" + config.id;
50
- var handler = function (msg)
51
- {
52
- node.receive(msg);
53
- }
54
- RED.events.on(event, handler);
55
-
56
-
57
- node.on("input", function (msg)
58
- {
59
- handleTopic(msg);
60
-
61
- smart_context.set(node.id, node_settings);
62
- });
63
-
64
- node.on("close", function ()
65
- {
66
- stopAutoOff();
67
- RED.events.off(event, handler);
68
- });
69
-
70
- let handleTopic = msg =>
71
- {
72
- var resultUp = false;
73
- var resultDown = false;
74
- var resultStop = false;
75
-
76
- let real_topic = helper.getTopicName(msg.topic);
77
-
78
- // set default topic if invalid value is send
79
- if (!["up", "up_stop", "down", "down_stop", "stop", "toggle", "up_down", "position", "alarm"].includes(real_topic))
80
- real_topic = "toggle";
81
-
82
- // skip if button is released
83
- if (msg.payload === false && ["up", "up_stop", "down", "down_stop", "stop", "toggle"].includes(real_topic))
84
- return;
85
-
86
- // Convert up_down from HA UI to next command
87
- if (real_topic == "up_down")
88
- {
89
- if (msg.payload)
90
- real_topic = "down";
91
- else
92
- real_topic = "up";
93
- }
94
-
95
- // Correct next topic to avoid handling up_stop, down_stop or toggle separately.
96
- if (max_time_timeout != null && (real_topic == "up_stop" || real_topic == "down_stop" || real_topic == "toggle"))
97
- {
98
- real_topic = "stop";
99
- }
100
- else if (max_time_timeout == null)
101
- {
102
- // shutter is not running, set next command depending on topic
103
- if (real_topic == "up_stop")
104
- real_topic = "up";
105
- else if (real_topic == "down_stop")
106
- real_topic = "down";
107
- else if (node_settings.last_direction_up && real_topic == "toggle")
108
- real_topic = "down";
109
- else if (!node_settings.last_direction_up && real_topic == "toggle")
110
- real_topic = "up";
111
- }
112
-
113
- // console.log("Convert topic to: " + real_topic);
114
-
115
- switch (real_topic)
116
- {
117
- case "up":
118
- if (max_time_timeout != null)
119
- {
120
- // Nothing todo
121
- if (node_settings.last_direction_up)
122
- return;
123
-
124
- // Runs down at the moment, so stop first
125
- if (node_settings.last_direction_up == false)
126
- {
127
- // console.log("--- Sub topic ---");
128
- handleTopic({ topic: "stop" });
129
- // console.log("-----------------");
130
- }
131
- }
132
-
133
- on_time = Date.now();
134
- resultUp = true;
135
- startAutoOff(false, helper.getTimeInMsFromString(msg.time_on) || null, null, msg.exact);
136
- break;
137
-
138
- case "stop":
139
- if (alarm_active)
140
- break;
141
-
142
- resultStop = true;
143
- if (max_time_timeout != null)
144
- {
145
- if (node_settings.last_direction_up)
146
- {
147
- const change_percentage = (Date.now() - on_time) / 1000 / max_time_up * 100;
148
- node_settings.last_position = Math.max(0, node_settings.last_position - change_percentage);
149
- }
150
- else
151
- {
152
- const change_percentage = (Date.now() - on_time) / 1000 / max_time_down * 100;
153
- node_settings.last_position = Math.min(100, node_settings.last_position + change_percentage);
154
- }
155
- }
156
- off_time = Date.now();
157
- stopAutoOff();
158
- break;
159
-
160
- case "down":
161
- if (max_time_timeout != null)
162
- {
163
- // Nothing todo
164
- if (node_settings.last_direction_up == false)
165
- return;
166
-
167
- // Runs up at the moment, so stop first
168
- if (node_settings.last_direction_up)
169
- {
170
- // console.log("--- Sub topic ---");
171
- handleTopic({ topic: "stop" });
172
- // console.log("-----------------");
173
- }
174
- }
175
-
176
- on_time = Date.now();
177
- resultDown = true;
178
- startAutoOff(true, helper.getTimeInMsFromString(msg.time_on) || null, null, msg.exact);
179
- break;
180
-
181
- case "position":
182
- if (alarm_active)
183
- break;
184
-
185
- let value = parseFloat(msg.payload);
186
-
187
- if (value < 0) value = 0;
188
- if (value > 100) value = 100;
189
-
190
- const now = Date.now();
191
-
192
- if (max_time_timeout != null)
193
- {
194
- // Change position while running,
195
- // Calculate current position first
196
- if (node_settings.last_direction_up)
197
- {
198
- const change_percentage = (now - on_time) / 1000 / max_time_up * 100;
199
- node_settings.last_position = Math.max(0, node_settings.last_position - change_percentage);
200
- }
201
- else
202
- {
203
- const change_percentage = (now - on_time) / 1000 / max_time_down * 100;
204
- node_settings.last_position = Math.min(100, node_settings.last_position + change_percentage);
205
- }
206
-
207
- // Runs in the wrong direction at the moment, so stop first
208
- if (node_settings.last_direction_up && value > node_settings.last_position)
209
- {
210
- // console.log("--- Sub topic ---");
211
- handleTopic({ topic: "stop" });
212
- // console.log("-----------------");
213
- }
214
- else if (node_settings.last_direction_up == false && value < node_settings.last_position)
215
- {
216
- // console.log("--- Sub topic ---");
217
- handleTopic({ topic: "stop" });
218
- // console.log("-----------------");
219
- }
220
- }
221
-
222
- on_time = now;
223
-
224
- if (value < node_settings.last_position)
225
- {
226
- // Go up
227
- resultUp = true;
228
- startAutoOff(false, (node_settings.last_position - value) / 100 * max_time_up * 1000, value);
229
- }
230
- else if (value > node_settings.last_position)
231
- {
232
- // Go down
233
- resultDown = true;
234
- startAutoOff(true, (value - node_settings.last_position) / 100 * max_time_down * 1000, value);
235
- }
236
- else
237
- {
238
- // Really an exact match
239
- handleTopic({ topic: "stop" });
240
- return;
241
- }
242
- break;
243
-
244
- case "alarm":
245
- alarm_active = msg.payload;
246
-
247
- if (alarm_active)
248
- {
249
- node.status({ fill: "red", shape: "dot", text: helper.getCurrentTimeForStatus() + ": ALARM turned on" });
250
-
251
- switch (alarm_action)
252
- {
253
- case "UP":
254
- handleTopic({ topic: "up" });
255
- break;
256
-
257
- case "DOWN":
258
- handleTopic({ topic: "down" });
259
- break;
260
- }
261
- }
262
- else
263
- {
264
- node.status({ fill: "red", shape: "dot", text: helper.getCurrentTimeForStatus() + ": ALARM turned off" });
265
- }
266
- break;
267
- }
268
-
269
- sendResult(resultUp, resultDown, resultStop, msg.exact);
270
- };
271
-
272
- let startAutoOff = (down, wait_time_ms = null, new_position = null, exact = false) =>
273
- {
274
- // console.log("startAutoOff (" + down + ", " + wait_time_ms + ", " + new_position + ");");
275
-
276
- // Stop if any timeout is set
277
- stopAutoOff();
278
-
279
- if (new_position != null)
280
- {
281
- // use normal times for top or bottom position
282
- if (new_position == 0)
283
- {
284
- new_position = null;
285
- down = false;
286
- }
287
- else if (new_position == 100)
288
- {
289
- new_position = null;
290
- down = true;
291
- }
292
- }
293
-
294
- if (wait_time_ms == null)
295
- {
296
- if (down)
297
- wait_time_ms = (100 - node_settings.last_position) * max_time_down / 100 * 1000;
298
- else
299
- wait_time_ms = node_settings.last_position * max_time_up / 100 * 1000;
300
-
301
- if (exact !== true)
302
- {
303
- // Run at least for 5 seconds
304
- if (wait_time_ms < 5000)
305
- wait_time_ms = 5000;
306
- }
307
- }
308
-
309
- if (wait_time_ms < 0)
310
- {
311
- node.status({ fill: "red", shape: "dot", text: helper.getCurrentTimeForStatus() + ": time_on value has to be greater than 0" });
312
- return;
313
- }
314
-
315
- if (wait_time_ms == 0)
316
- return;
317
-
318
- if (!alarm_active)
319
- node.status({ fill: "yellow", shape: "ring", text: helper.getCurrentTimeForStatus() + ": " + (down ? "Down" : "Up") + ", wait " + helper.formatMsToStatus(wait_time_ms, "until") + " for auto off" });
320
-
321
- max_time_timeout = setTimeout(() =>
322
- {
323
- handleTopic({ topic: "stop" });
324
- if (new_position != null)
325
- node_settings.last_position = new_position;
326
- smart_context.set(node.id, node_settings);
327
- }, wait_time_ms);
328
- };
329
-
330
- let stopAutoOff = () =>
331
- {
332
- if (max_time_timeout != null)
333
- {
334
- // console.log("stopAutoOff");
335
- if (!alarm_active)
336
- node.status({ fill: "green", shape: "dot", text: helper.getCurrentTimeForStatus() + ": Stopped at " + Math.round(node_settings.last_position) + "%" });
337
- clearTimeout(max_time_timeout);
338
- off_time = Date.now();
339
- max_time_timeout = null;
340
- }
341
- };
342
-
343
- let sendResult = (up, down, stop, exact) =>
344
- {
345
- if (exact === true)
346
- {
347
- // console.log({ up, down, stop, exact, last_pos: node_settings.last_position });
348
-
349
- // Don't start moving if exact is enabled and already on top/bottom.
350
- if (down && node_settings.last_position == 100)
351
- return;
352
- if (up && node_settings.last_position == 0)
353
- return;
354
- }
355
-
356
- // console.log("sendResult(" + up + ", " + down + ", " + stop + ");");
357
- if ((up && wait_for_down) || (down && wait_for_up))
358
- {
359
- // console.log("Stop wait timeout");
360
- clearTimeout(wait_timeout);
361
- wait_timeout = null;
362
- }
363
-
364
- let now = Date.now();
365
- if (off_time + revert_time_ms > now)
366
- {
367
- // Output has to possibly wait until the revert time has passed
368
- if ((node_settings.last_direction_up && down) || (node_settings.last_direction_up == false && up))
369
- {
370
- // console.log("Start wait timeout for " + (off_time + revert_time_ms - now) + "ms");
371
-
372
- if (off_time + revert_time_ms - now > revert_time_ms)
373
- return;
374
-
375
- wait_timeout = setTimeout(() =>
376
- {
377
- wait_timeout = null;
378
- sendResult(up, down, stop, exact);
379
- }, off_time + revert_time_ms - now);
380
- return;
381
- }
382
- }
383
-
384
- if (stop && wait_timeout != null)
385
- {
386
- clearTimeout(wait_timeout);
387
- wait_timeout = null;
388
- }
389
-
390
- // console.log("really sendResult(" + up + ", " + down + ", " + stop + ", " + exact + ");");
391
- if (up)
392
- {
393
- if (!alarm_active || alarm_action === "UP")
394
- {
395
- node_settings.last_direction_up = true;
396
- node.send([{ payload: true }, { payload: false }, { payload: node_settings.last_position }]);
397
- notifyCentral(true);
398
- node.status({ fill: "green", shape: "dot", text: helper.getCurrentTimeForStatus() + ": Up" });
399
- }
400
- }
401
- else if (down)
402
- {
403
- if (!alarm_active || alarm_action === "DOWN")
404
- {
405
- node_settings.last_direction_up = false;
406
- node.send([{ payload: false }, { payload: true }, { payload: node_settings.last_position }]);
407
- notifyCentral(true);
408
- node.status({ fill: "green", shape: "dot", text: helper.getCurrentTimeForStatus() + ": Down" });
409
- }
410
- }
411
- else if (stop && !alarm_active)
412
- {
413
- node.send([{ payload: false }, { payload: false }, { payload: node_settings.last_position }]);
414
- notifyCentral(false);
415
- node.status({ fill: "red", shape: "dot", text: helper.getCurrentTimeForStatus() + ": Stopped at " + Math.round(node_settings.last_position) + "%" });
416
- }
417
- };
418
-
419
- let notifyCentral = state =>
420
- {
421
- if (!config.links)
422
- return;
423
-
424
- config.links.forEach(link =>
425
- {
426
- // console.log(node.id + " -> " + link);
427
- // console.log({ source: node.id, state: state });
428
- RED.events.emit("node:" + link, { source: node.id, state: state });
429
- });
430
- };
431
-
432
- // For security reason, stop shutter at node start
433
- wait_timeout = setTimeout(() =>
434
- {
435
- node.send([{ payload: false }, { payload: false }, { payload: node_settings.last_position }]);
436
- node.status({ fill: "red", shape: "dot", text: helper.getCurrentTimeForStatus() + ": Stopped at " + Math.round(node_settings.last_position) + "%" });
437
- notifyCentral(false);
438
- }, 10000);
439
- }
440
-
441
- RED.nodes.registerType("smart_shutter-complex-control", ShutterComplexControlNode);
442
- };