smart-nodes 0.3.37 → 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.
- package/CHANGELOG.md +62 -0
- package/README.md +35 -17
- package/central/central.html +26 -12
- package/central/central.js +84 -26
- package/central/locales/de-DE/central.json +1 -4
- package/central/locales/en-US/central.json +0 -3
- package/compare/compare.html +40 -24
- package/compare/compare.js +69 -29
- package/compare/locales/de-DE/compare.json +5 -7
- package/compare/locales/en-US/compare.json +18 -8
- package/counter/counter.html +64 -17
- package/counter/counter.js +43 -20
- package/counter/locales/de-DE/counter.json +6 -9
- package/counter/locales/en-US/counter.json +12 -16
- package/delay/delay.html +18 -88
- package/delay/delay.js +63 -20
- package/delay/locales/de-DE/delay.html +71 -0
- package/delay/locales/de-DE/delay.json +19 -0
- package/delay/locales/en-US/delay.html +76 -0
- package/delay/locales/en-US/delay.json +19 -0
- package/forwarder/forwarder.html +11 -42
- package/forwarder/forwarder.js +59 -18
- package/forwarder/locales/de-DE/forwarder.html +32 -0
- package/forwarder/locales/de-DE/forwarder.json +15 -0
- package/forwarder/locales/en-US/forwarder.html +32 -0
- package/forwarder/locales/en-US/forwarder.json +15 -0
- package/heating-curve/heating-curve.html +10 -51
- package/heating-curve/heating-curve.js +38 -13
- package/heating-curve/locales/de-DE/heating-curve.html +38 -0
- package/heating-curve/locales/de-DE/heating-curve.json +12 -0
- package/heating-curve/locales/en-US/heating-curve.html +38 -0
- package/heating-curve/locales/en-US/heating-curve.json +12 -0
- package/hysteresis/hysteresis.html +43 -65
- package/hysteresis/hysteresis.js +94 -68
- package/hysteresis/locales/de-DE/hysteresis.html +36 -0
- package/hysteresis/locales/de-DE/hysteresis.json +27 -0
- package/hysteresis/locales/en-US/hysteresis.html +36 -0
- package/hysteresis/locales/en-US/hysteresis.json +27 -0
- package/{light-control/light-control.html → light/light.html} +34 -144
- package/{light-control/light-control.js → light/light.js} +151 -32
- package/light/locales/de-DE/light.html +149 -0
- package/light/locales/de-DE/light.json +24 -0
- package/light/locales/en-US/light.html +148 -0
- package/light/locales/en-US/light.json +24 -0
- package/logic/locales/de-DE/logic.html +12 -0
- package/logic/locales/de-DE/logic.json +26 -0
- package/logic/locales/en-US/logic.html +12 -0
- package/logic/locales/en-US/logic.json +26 -0
- package/logic/logic.html +27 -40
- package/logic/logic.js +63 -29
- package/long-press/locales/de-DE/long-press.html +5 -0
- package/long-press/locales/de-DE/long-press.json +13 -0
- package/long-press/locales/en-US/long-press.html +5 -0
- package/long-press/locales/en-US/long-press.json +13 -0
- package/{long-press-control/long-press-control.html → long-press/long-press.html} +10 -14
- package/long-press/long-press.js +163 -0
- package/mixing-valve/locales/de-DE/mixing-valve.html +65 -0
- package/mixing-valve/locales/de-DE/mixing-valve.json +19 -0
- package/mixing-valve/locales/en-US/mixing-valve.html +66 -0
- package/mixing-valve/locales/en-US/mixing-valve.json +19 -0
- package/mixing-valve/mixing-valve.html +15 -79
- package/mixing-valve/mixing-valve.js +87 -61
- package/multi-press/locales/de-DE/multi-press.html +5 -0
- package/multi-press/locales/de-DE/multi-press.json +12 -0
- package/multi-press/locales/en-US/multi-press.html +5 -0
- package/multi-press/locales/en-US/multi-press.json +12 -0
- package/{multi-press-control/multi-press-control.html → multi-press/multi-press.html} +9 -13
- package/{multi-press-control/multi-press-control.js → multi-press/multi-press.js} +53 -5
- package/package.json +7 -7
- package/persistence.js +1 -0
- package/scene/locales/de-DE/scene.html +105 -0
- package/scene/locales/de-DE/scene.json +21 -0
- package/scene/locales/en-US/scene.html +107 -0
- package/scene/locales/en-US/scene.json +20 -0
- package/{scene-control/scene-control.html → scene/scene.html} +18 -121
- package/{scene-control/scene-control.js → scene/scene.js} +76 -26
- package/scheduler/locales/de-DE/scheduler.html +30 -0
- package/scheduler/locales/de-DE/scheduler.json +21 -0
- package/scheduler/locales/en-US/scheduler.html +30 -0
- package/scheduler/locales/en-US/scheduler.json +21 -0
- package/scheduler/scheduler.html +34 -64
- package/scheduler/scheduler.js +85 -53
- package/shutter/locales/de-DE/shutter.html +127 -0
- package/shutter/locales/de-DE/shutter.json +11 -0
- package/shutter/locales/en-US/shutter.html +133 -0
- package/shutter/locales/en-US/shutter.json +11 -0
- package/{shutter-control/shutter-control.html → shutter/shutter.html} +7 -133
- package/{shutter-control/shutter-control.js → shutter/shutter.js} +116 -56
- package/shutter-complex/locales/de-DE/shutter-complex.html +120 -0
- package/shutter-complex/locales/de-DE/shutter-complex.json +20 -0
- package/shutter-complex/locales/en-US/shutter-complex.html +120 -0
- package/shutter-complex/locales/en-US/shutter-complex.json +20 -0
- package/{shutter-complex-control/shutter-complex-control.html → shutter-complex/shutter-complex.html} +30 -133
- package/shutter-complex/shutter-complex.js +578 -0
- package/smart_helper.js +52 -9
- package/statistic/locales/de-DE/statistic.html +10 -0
- package/statistic/locales/de-DE/statistic.json +29 -0
- package/statistic/locales/en-US/statistic.html +10 -0
- package/statistic/locales/en-US/statistic.json +29 -0
- package/statistic/statistic.html +32 -36
- package/statistic/statistic.js +57 -28
- package/text-exec/locales/de-DE/text-exec.html +18 -0
- package/text-exec/locales/de-DE/text-exec.json +7 -0
- package/text-exec/locales/en-US/text-exec.html +18 -0
- package/text-exec/locales/en-US/text-exec.json +7 -0
- package/text-exec/text-exec.html +9 -25
- package/text-exec/text-exec.js +43 -2
- package/long-press-control/long-press-control.js +0 -76
- package/shutter-complex-control/shutter-complex-control.js +0 -442
|
@@ -142,6 +142,7 @@
|
|
|
142
142
|
max_time_on: { value: "0" },
|
|
143
143
|
max_time_on_unit: { value: "s" },
|
|
144
144
|
alarm_action: { value: 'NOTHING' }, // NOTHING | ON | OFF
|
|
145
|
+
alarm_off_action: { value: 'NOTHING' }, // NOTHING | ON | OFF | LAST | LAST_SENDED
|
|
145
146
|
links: { value: [], type: "smart_central-control[]" }
|
|
146
147
|
},
|
|
147
148
|
inputs: 1,
|
|
@@ -154,22 +155,10 @@
|
|
|
154
155
|
oneditprepare: function ()
|
|
155
156
|
{
|
|
156
157
|
let node = this;
|
|
158
|
+
|
|
157
159
|
onEditPrepare(this, ["smart_central-control"]);
|
|
158
160
|
initTreeList(node, ["smart_central-control"]);
|
|
159
161
|
|
|
160
|
-
$("#node-input-icon")
|
|
161
|
-
.css("max-width", "10rem")
|
|
162
|
-
.typedInput({
|
|
163
|
-
types: [{
|
|
164
|
-
value: "light",
|
|
165
|
-
default: "light",
|
|
166
|
-
options: [
|
|
167
|
-
{ value: "light", label: "Licht" },
|
|
168
|
-
{ value: "outlet", label: "Steckdose" }
|
|
169
|
-
],
|
|
170
|
-
}],
|
|
171
|
-
});
|
|
172
|
-
|
|
173
162
|
$("#node-input-max_time_on")
|
|
174
163
|
.spinner({
|
|
175
164
|
min: 0,
|
|
@@ -190,10 +179,10 @@
|
|
|
190
179
|
value: "max_time_on_unit",
|
|
191
180
|
default: "s",
|
|
192
181
|
options: [
|
|
193
|
-
{ value: "ms", label: "
|
|
194
|
-
{ value: "s", label: "
|
|
195
|
-
{ value: "min", label: "
|
|
196
|
-
{ value: "h", label: "
|
|
182
|
+
{ value: "ms", label: node._("light.ui.milliseconds") },
|
|
183
|
+
{ value: "s", label: node._("light.ui.seconds") },
|
|
184
|
+
{ value: "min", label: node._("light.ui.minutes") },
|
|
185
|
+
{ value: "h", label: node._("light.ui.hours") },
|
|
197
186
|
],
|
|
198
187
|
}],
|
|
199
188
|
});
|
|
@@ -203,9 +192,23 @@
|
|
|
203
192
|
value: "alarm_action",
|
|
204
193
|
default: "NOTHING",
|
|
205
194
|
options: [
|
|
206
|
-
{ value: "NOTHING", label: "
|
|
207
|
-
{ value: "ON", label: "
|
|
208
|
-
{ value: "OFF", label: "
|
|
195
|
+
{ value: "NOTHING", label: node._("light.ui.no_action") },
|
|
196
|
+
{ value: "ON", label: node._("light.ui.turn_on") },
|
|
197
|
+
{ value: "OFF", label: node._("light.ui.turn_off") }
|
|
198
|
+
],
|
|
199
|
+
}],
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
$("#node-input-alarm_off_action").typedInput({
|
|
203
|
+
types: [{
|
|
204
|
+
value: "alarm_off_action",
|
|
205
|
+
default: "NOTHING",
|
|
206
|
+
options: [
|
|
207
|
+
{ value: "NOTHING", label: node._("light.ui.no_action") },
|
|
208
|
+
{ value: "ON", label: node._("light.ui.turn_on") },
|
|
209
|
+
{ value: "OFF", label: node._("light.ui.turn_off") },
|
|
210
|
+
{ value: "LAST", label: node._("light.ui.last_state") },
|
|
211
|
+
{ value: "LAST_SENDED", label: node._("light.ui.last_sended_state") }
|
|
209
212
|
],
|
|
210
213
|
}],
|
|
211
214
|
});
|
|
@@ -221,140 +224,27 @@
|
|
|
221
224
|
|
|
222
225
|
<script type="text/html" data-template-name="smart_light-control">
|
|
223
226
|
<div class="form-row">
|
|
224
|
-
<label for="node-input-name"><i class="fa fa-tag"></i>
|
|
225
|
-
<input type="text" id="node-input-name"
|
|
227
|
+
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="light.ui.name"></span></label>
|
|
228
|
+
<input type="text" id="node-input-name" data-i18n="[placeholder]light.ui.name" />
|
|
226
229
|
</div>
|
|
227
230
|
<div class="form-row">
|
|
228
|
-
<label for="node-input-exec_text_names"><i class="fa fa-comments-o"></i>
|
|
231
|
+
<label for="node-input-exec_text_names"><i class="fa fa-comments-o"></i> <span data-i18n="light.ui.text"></span></label>
|
|
229
232
|
<input id="node-input-exec_text_names" type="text" />
|
|
230
|
-
<div style="max-width: 450px;"
|
|
233
|
+
<div style="max-width: 450px;" data-i18n="light.ui.controlled_by_words"></div>
|
|
231
234
|
</div>
|
|
232
235
|
<div class="form-row">
|
|
233
|
-
<label for="node-input-max_time_on"><i class="fa fa-clock-o"></i>
|
|
236
|
+
<label for="node-input-max_time_on"><i class="fa fa-clock-o"></i> <span data-i18n="light.ui.time_on"></span></label>
|
|
234
237
|
<input id="node-input-max_time_on" value="0" />
|
|
235
238
|
<input id="node-input-max_time_on_unit" />
|
|
236
239
|
</div>
|
|
237
240
|
<div class="form-row">
|
|
238
|
-
<label for="node-input-alarm_action"><i class="fa fa-exclamation-triangle"></i>
|
|
241
|
+
<label for="node-input-alarm_action"><i class="fa fa-exclamation-triangle"></i> <span data-i18n="light.ui.alarm_on"></span></label>
|
|
239
242
|
<input id="node-input-alarm_action"/>
|
|
240
243
|
</div>
|
|
241
|
-
<
|
|
244
|
+
<div class="form-row">
|
|
245
|
+
<label for="node-input-alarm_off_action"><i class="fa fa-exclamation-triangle"></i> <span data-i18n="light.ui.alarm_off"></span></label>
|
|
246
|
+
<input id="node-input-alarm_off_action"/>
|
|
247
|
+
</div>
|
|
248
|
+
<span><i class="fa fa-link"></i> <span data-i18n="light.ui.controlled_by_central"></span></span>
|
|
242
249
|
<div class="form-row node-input-link-row node-input-link-rows"></div>
|
|
243
|
-
</script>
|
|
244
|
-
|
|
245
|
-
<script type="text/html" data-help-name="smart_light-control">
|
|
246
|
-
<p>
|
|
247
|
-
Diese Node steuert einen Ausgang. Dies kann ein Licht, eine Steckdose oder ähnliches sein.
|
|
248
|
-
Als Ausgang wird immer <code>msg.payload = true</code> oder <code>msg.payload = false</code> gesendet um den Ausgang ein-, bzw. auszuschalten.
|
|
249
|
-
</p>
|
|
250
|
-
<p>
|
|
251
|
-
<b>Hinweis:</b> Smart Nodes verwenden Topics im Format <code>name#nummer</code>, damit können verschiedene Smart Nodes mit dem gleichen Topic angesteuert werden.<br/>
|
|
252
|
-
Diese Node verwendet nur den Teil <code>name</code>. <code>#</code> und <code>nummer</code> sind dabei optional.
|
|
253
|
-
</p>
|
|
254
|
-
<p>
|
|
255
|
-
Folgende topics werden akzeptiert:
|
|
256
|
-
<table>
|
|
257
|
-
<thead>
|
|
258
|
-
<tr>
|
|
259
|
-
<th>Topic</th>
|
|
260
|
-
<th>Beschreibung</th>
|
|
261
|
-
<th>msg.payload == false wird ignoriert</th>
|
|
262
|
-
</tr>
|
|
263
|
-
</thead>
|
|
264
|
-
<tbody>
|
|
265
|
-
<tr>
|
|
266
|
-
<td><code>status</code></td>
|
|
267
|
-
<td>
|
|
268
|
-
Gibt über <code>msg.payload = true</code> oder <code>msg.payload = false</code> den aktuellen Status des Ausgangs an.<br/>
|
|
269
|
-
Bei einem Wechsel von ausgeschaltet nach eingeschaltet wird die Zeitmessung für die hinterlegte, bzw. mitgesendete Zeit gestartet, sofern vorhanden.
|
|
270
|
-
</td>
|
|
271
|
-
<td>Nein</td>
|
|
272
|
-
</tr>
|
|
273
|
-
<tr>
|
|
274
|
-
<td><code>on</code></td>
|
|
275
|
-
<td>Schaltet den Ausgang ein und startet die Zeitmessung für die hinterlegte, bzw. mitgesendete Zeit gestartet, sofern vorhanden.</td>
|
|
276
|
-
<td>Ja</td>
|
|
277
|
-
</tr>
|
|
278
|
-
<tr>
|
|
279
|
-
<td><code>off</code></td>
|
|
280
|
-
<td>Schaltet den Ausgang aus.</td>
|
|
281
|
-
<td>Ja</td>
|
|
282
|
-
</tr>
|
|
283
|
-
<tr>
|
|
284
|
-
<td><code>set</code></td>
|
|
285
|
-
<td>
|
|
286
|
-
Schaltet den Ausgang bei <code>msg.payload = true</code> ein und bei <code>msg.payload = false</code> aus.<br/>
|
|
287
|
-
Bei einem Wechsel von ausgeschaltet nach eingeschaltet wird die Zeitmessung für die hinterlegte, bzw. mitgesendete Zeit gestartet, sofern vorhanden.
|
|
288
|
-
</td>
|
|
289
|
-
<td>Nein</td>
|
|
290
|
-
</tr>
|
|
291
|
-
<tr>
|
|
292
|
-
<td><code>set_permanent</code></td>
|
|
293
|
-
<td>
|
|
294
|
-
Schaltet den Ausgang bei <code>msg.payload = true</code> dauerhaft ein und bei <code>msg.payload = false</code> aus.<br/>
|
|
295
|
-
Es wird dabei keine Zeitmessung gestartet.
|
|
296
|
-
</td>
|
|
297
|
-
<td>Nein</td>
|
|
298
|
-
</tr>
|
|
299
|
-
<tr>
|
|
300
|
-
<td><code>motion</code></td>
|
|
301
|
-
<td>
|
|
302
|
-
Schaltet den Ausgang bei <code>msg.payload = true</code> ein ohne eine Zeitmessung.<br/>
|
|
303
|
-
Bei <code>msg.payload = false</code> wird die Zeitmessung für die hinterlegte, bzw. mitgesendete Zeit gestartet, sofern vorhanden.<br/>
|
|
304
|
-
Ist keine Zeit angegeben oder hinterlegt, schaltet sich der Ausgang sofort aus.
|
|
305
|
-
</td>
|
|
306
|
-
<td>Nein</td>
|
|
307
|
-
</tr>
|
|
308
|
-
<tr>
|
|
309
|
-
<td><code>alarm</code></td>
|
|
310
|
-
<td>Setzt den aktuellen Alarmzustand auf den Wert von <code>msg.payload</code> und löst die entsprechende Aktion aus.</td>
|
|
311
|
-
<td>Nein</td>
|
|
312
|
-
</tr>
|
|
313
|
-
<tr>
|
|
314
|
-
<td><code>toggle</code> (default)</td>
|
|
315
|
-
<td>
|
|
316
|
-
Schaltet den Ausgang abwechselnd ein und aus.<br/>
|
|
317
|
-
Bei einem Wechsel von ausgeschaltet nach eingeschaltet wird die Zeitmessung für die hinterlegte, bzw. mitgesendete Zeit gestartet, sofern vorhanden.
|
|
318
|
-
</td>
|
|
319
|
-
<td>Ja</td>
|
|
320
|
-
</tr>
|
|
321
|
-
</tbody>
|
|
322
|
-
</table>
|
|
323
|
-
</p>
|
|
324
|
-
<p>
|
|
325
|
-
Diese Node hat eine einstellbare Maximallaufzeit, bevor der Ausgang automatisch wieder ausgeschalten wird.
|
|
326
|
-
Diese Zeitmessung wird wie in der Tabelle oben verwendet.
|
|
327
|
-
Die eingestellte Zeit kann gezielt überschrieben werden.
|
|
328
|
-
Beispiel: <code>msg = { "topic": "on", "time_on": 5000 }</code> oder <code>msg = { "topic": "on", "time_on": "5s" }</code><br/>
|
|
329
|
-
Diese Nachricht schaltet das Licht für 5000 Millisekunden / 5 Sekunden an und anschließend wieder aus.
|
|
330
|
-
Die nächste Nachricht ohne <code>time_on</code> Angabe verwendet wieder die voreingestellte Zeit.
|
|
331
|
-
Ist die Zeit auf 0 eingestellt, wird das Licht <b>nicht</b> automatisch ausgeschalten.<br/>
|
|
332
|
-
Als Einheit für die Zeit können folgende Werte verwendet werden:
|
|
333
|
-
<table>
|
|
334
|
-
<thead>
|
|
335
|
-
<tr>
|
|
336
|
-
<th>Einheit</th>
|
|
337
|
-
<th>Beschreibung</th>
|
|
338
|
-
</tr>
|
|
339
|
-
</thead>
|
|
340
|
-
<tbody>
|
|
341
|
-
<tr>
|
|
342
|
-
<td><code>ms</code> (default)</td>
|
|
343
|
-
<td>Millisekunden</td>
|
|
344
|
-
</tr>
|
|
345
|
-
<tr>
|
|
346
|
-
<td><code>s</code> oder <code>sec</code></td>
|
|
347
|
-
<td>Sekunden</td>
|
|
348
|
-
</tr>
|
|
349
|
-
<tr>
|
|
350
|
-
<td><code>m</code> oder <code>min</code></td>
|
|
351
|
-
<td>Mintun.</td>
|
|
352
|
-
</tr>
|
|
353
|
-
<tr>
|
|
354
|
-
<td><code>h</code></td>
|
|
355
|
-
<td>Stunden</td>
|
|
356
|
-
</tr>
|
|
357
|
-
</tbody>
|
|
358
|
-
</table>
|
|
359
|
-
</p>
|
|
360
250
|
</script>
|
|
@@ -7,32 +7,69 @@ module.exports = function (RED)
|
|
|
7
7
|
const node = this;
|
|
8
8
|
RED.nodes.createNode(node, config);
|
|
9
9
|
|
|
10
|
+
// ###################
|
|
11
|
+
// # Class constants #
|
|
12
|
+
// ###################
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
// #######################
|
|
16
|
+
// # Global help objects #
|
|
17
|
+
// #######################
|
|
10
18
|
const smart_context = require("../persistence.js")(RED);
|
|
11
19
|
const helper = require("../smart_helper.js");
|
|
12
20
|
|
|
13
|
-
|
|
21
|
+
|
|
22
|
+
// ############################
|
|
23
|
+
// # Used from text-exec node #
|
|
24
|
+
// ############################
|
|
14
25
|
if (typeof config.exec_text_names == "string")
|
|
15
26
|
node.exec_text_names = config.exec_text_names.split(",").map(n => n.trim().toLowerCase());
|
|
16
27
|
else
|
|
17
28
|
node.exec_text_names = [];
|
|
18
29
|
|
|
19
|
-
|
|
20
|
-
|
|
30
|
+
|
|
31
|
+
// #####################
|
|
32
|
+
// # persistent values #
|
|
33
|
+
// #####################
|
|
34
|
+
var node_settings = helper.cloneObject({
|
|
21
35
|
last_value: false,
|
|
36
|
+
last_value_before_alarm: false,
|
|
37
|
+
last_value_sended: false,
|
|
38
|
+
alarm_active: false,
|
|
22
39
|
}, smart_context.get(node.id));
|
|
23
40
|
|
|
24
|
-
|
|
41
|
+
|
|
42
|
+
// ##################
|
|
43
|
+
// # Dynamic config #
|
|
44
|
+
// ##################
|
|
25
45
|
let max_time_on = helper.getTimeInMs(config.max_time_on, config.max_time_on_unit);
|
|
26
46
|
let alarm_action = config.alarm_action || "NOTHING";
|
|
47
|
+
let alarm_off_action = config.alarm_off_action || "NOTHING";
|
|
48
|
+
|
|
49
|
+
// ##################
|
|
50
|
+
// # Runtime values #
|
|
51
|
+
// ##################
|
|
27
52
|
|
|
28
|
-
//
|
|
29
|
-
|
|
53
|
+
// Here the setTimeout return value is stored to turn off the light.
|
|
54
|
+
// That means if it is null, the light will not be turned off automatically.
|
|
55
|
+
let timeout = null;
|
|
56
|
+
|
|
57
|
+
// If isPermanent is true, then a default on time value is ignored
|
|
58
|
+
// Also if the motion sensor turns off, no timeout is started.
|
|
30
59
|
let isPermanent = false;
|
|
60
|
+
|
|
61
|
+
// If this is on, a motion sensor has detected a move, so the on time value is ignored.
|
|
62
|
+
// The timeout starts only if the motion sensor goes off.
|
|
31
63
|
let isMotion = false;
|
|
64
|
+
|
|
65
|
+
// Here the date is stored, when the light should go off.
|
|
66
|
+
// This is used to calculate the node status.
|
|
32
67
|
let timeout_end_date = null;
|
|
33
|
-
let alarm_active = false;
|
|
34
68
|
|
|
35
|
-
|
|
69
|
+
|
|
70
|
+
// #########################
|
|
71
|
+
// # Central node handling #
|
|
72
|
+
// #########################
|
|
36
73
|
var event = "node:" + node.id;
|
|
37
74
|
var handler = function (msg)
|
|
38
75
|
{
|
|
@@ -41,6 +78,9 @@ module.exports = function (RED)
|
|
|
41
78
|
RED.events.on(event, handler);
|
|
42
79
|
|
|
43
80
|
|
|
81
|
+
// ###############
|
|
82
|
+
// # Node events #
|
|
83
|
+
// ###############
|
|
44
84
|
node.on("input", function (msg)
|
|
45
85
|
{
|
|
46
86
|
handleTopic(msg);
|
|
@@ -55,17 +95,26 @@ module.exports = function (RED)
|
|
|
55
95
|
RED.events.off(event, handler);
|
|
56
96
|
});
|
|
57
97
|
|
|
98
|
+
|
|
99
|
+
// #####################
|
|
100
|
+
// # Private functions #
|
|
101
|
+
// #####################
|
|
102
|
+
|
|
103
|
+
// This is the main function which handles all topics that was received.
|
|
58
104
|
let handleTopic = msg =>
|
|
59
105
|
{
|
|
60
106
|
let doRestartTimer = true;
|
|
107
|
+
let real_topic = helper.getTopicName(msg.topic);
|
|
61
108
|
|
|
62
|
-
switch (
|
|
109
|
+
switch (real_topic)
|
|
63
110
|
{
|
|
64
111
|
case "status":
|
|
65
112
|
// Make sure it is bool
|
|
66
113
|
msg.payload = !!msg.payload;
|
|
67
114
|
|
|
68
|
-
|
|
115
|
+
// Output is already in the state of the status value and the timeout is running.
|
|
116
|
+
// No need to restart the timeout.
|
|
117
|
+
if (node_settings.last_value == msg.payload && timeout != null)
|
|
69
118
|
doRestartTimer = false;
|
|
70
119
|
|
|
71
120
|
node_settings.last_value = msg.payload;
|
|
@@ -77,6 +126,7 @@ module.exports = function (RED)
|
|
|
77
126
|
return;
|
|
78
127
|
|
|
79
128
|
node_settings.last_value = false;
|
|
129
|
+
node_settings.last_value_sended = node_settings.last_value;
|
|
80
130
|
break;
|
|
81
131
|
|
|
82
132
|
case "on":
|
|
@@ -85,19 +135,24 @@ module.exports = function (RED)
|
|
|
85
135
|
return;
|
|
86
136
|
|
|
87
137
|
node_settings.last_value = true;
|
|
138
|
+
node_settings.last_value_sended = node_settings.last_value;
|
|
88
139
|
break;
|
|
89
140
|
|
|
90
141
|
case "set":
|
|
91
142
|
// Make sure it is bool
|
|
92
143
|
msg.payload = !!msg.payload;
|
|
144
|
+
|
|
93
145
|
node_settings.last_value = msg.payload;
|
|
146
|
+
node_settings.last_value_sended = node_settings.last_value;
|
|
94
147
|
break;
|
|
95
148
|
|
|
96
149
|
case "set_permanent":
|
|
97
150
|
// Make sure it is bool
|
|
98
151
|
msg.payload = !!msg.payload;
|
|
99
|
-
node_settings.last_value = msg.payload;
|
|
100
152
|
isPermanent = msg.payload;
|
|
153
|
+
|
|
154
|
+
node_settings.last_value = msg.payload;
|
|
155
|
+
node_settings.last_value_sended = node_settings.last_value;
|
|
101
156
|
break;
|
|
102
157
|
|
|
103
158
|
case "motion":
|
|
@@ -119,21 +174,67 @@ module.exports = function (RED)
|
|
|
119
174
|
{
|
|
120
175
|
node_settings.last_value = true;
|
|
121
176
|
}
|
|
177
|
+
node_settings.last_value_sended = node_settings.last_value;
|
|
178
|
+
break;
|
|
179
|
+
|
|
180
|
+
case "toggle":
|
|
181
|
+
// If button is released, don't handle this message
|
|
182
|
+
if (msg.payload === false)
|
|
183
|
+
return;
|
|
184
|
+
|
|
185
|
+
node_settings.last_value_sended = !node_settings.last_value;
|
|
186
|
+
|
|
187
|
+
if (!node_settings.alarm_active)
|
|
188
|
+
node_settings.last_value = !node_settings.last_value;
|
|
122
189
|
break;
|
|
123
190
|
|
|
124
191
|
case "alarm":
|
|
125
192
|
// Make sure it is bool
|
|
126
193
|
msg.payload = !!msg.payload;
|
|
127
|
-
|
|
194
|
+
|
|
195
|
+
// No alarm change, do nothing
|
|
196
|
+
if (node_settings.alarm_active == msg.payload)
|
|
197
|
+
return;
|
|
198
|
+
|
|
199
|
+
node_settings.alarm_active = msg.payload;
|
|
200
|
+
if (node_settings.alarm_active)
|
|
201
|
+
{
|
|
202
|
+
// Alarm turned on
|
|
203
|
+
node_settings.last_value_before_alarm = node_settings.last_value;
|
|
204
|
+
}
|
|
205
|
+
else
|
|
206
|
+
{
|
|
207
|
+
// Alarm turned off
|
|
208
|
+
switch (alarm_off_action)
|
|
209
|
+
{
|
|
210
|
+
case "NOTHING":
|
|
211
|
+
break;
|
|
212
|
+
|
|
213
|
+
case "ON":
|
|
214
|
+
node_settings.last_value = true;
|
|
215
|
+
break;
|
|
216
|
+
|
|
217
|
+
case "OFF":
|
|
218
|
+
node_settings.last_value = false;
|
|
219
|
+
break;
|
|
220
|
+
|
|
221
|
+
case "LAST":
|
|
222
|
+
node_settings.last_value = node_settings.last_value_before_alarm;
|
|
223
|
+
break;
|
|
224
|
+
|
|
225
|
+
case "LAST_SENDED":
|
|
226
|
+
node_settings.last_value = node_settings.last_value_sended;
|
|
227
|
+
break;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
128
231
|
break;
|
|
129
232
|
|
|
130
|
-
case "toggle":
|
|
131
233
|
default:
|
|
132
|
-
|
|
133
|
-
if (msg.payload === false)
|
|
134
|
-
return;
|
|
234
|
+
node_settings.last_value_sended = !node_settings.last_value;
|
|
135
235
|
|
|
136
|
-
|
|
236
|
+
if (!node_settings.alarm_active)
|
|
237
|
+
node_settings.last_value = !node_settings.last_value;
|
|
137
238
|
break;
|
|
138
239
|
}
|
|
139
240
|
|
|
@@ -141,7 +242,7 @@ module.exports = function (RED)
|
|
|
141
242
|
stopAutoOff();
|
|
142
243
|
|
|
143
244
|
// Check alarm values
|
|
144
|
-
if (alarm_active)
|
|
245
|
+
if (node_settings.alarm_active)
|
|
145
246
|
{
|
|
146
247
|
isPermanent = false;
|
|
147
248
|
|
|
@@ -151,14 +252,17 @@ module.exports = function (RED)
|
|
|
151
252
|
node_settings.last_value = true;
|
|
152
253
|
break;
|
|
153
254
|
|
|
154
|
-
default:
|
|
155
255
|
case "OFF":
|
|
156
256
|
node_settings.last_value = false;
|
|
157
257
|
break;
|
|
258
|
+
|
|
259
|
+
case "NOTHING":
|
|
260
|
+
default:
|
|
261
|
+
break;
|
|
158
262
|
}
|
|
159
263
|
}
|
|
160
264
|
|
|
161
|
-
if (alarm_active || helper.getTopicName(msg.topic) != "status")
|
|
265
|
+
if (node_settings.alarm_active || helper.getTopicName(msg.topic) != "status")
|
|
162
266
|
node.send({ payload: node_settings.last_value });
|
|
163
267
|
|
|
164
268
|
// Output is on, now
|
|
@@ -168,17 +272,22 @@ module.exports = function (RED)
|
|
|
168
272
|
notifyCentral(node_settings.last_value);
|
|
169
273
|
}
|
|
170
274
|
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* This function sets a timeout to turn off the light after the defined time is over.
|
|
278
|
+
* @param {*} origTimeMs The on time
|
|
279
|
+
*/
|
|
171
280
|
let startAutoOffIfNeeded = origTimeMs =>
|
|
172
281
|
{
|
|
173
282
|
// No timer when alarm is active
|
|
174
|
-
if (alarm_active)
|
|
283
|
+
if (node_settings.alarm_active)
|
|
175
284
|
return;
|
|
176
285
|
|
|
177
286
|
let timeMs = parseInt(origTimeMs);
|
|
178
287
|
|
|
179
288
|
if (isNaN(timeMs))
|
|
180
289
|
{
|
|
181
|
-
|
|
290
|
+
console.warn("Invalid time_on value send: " + origTimeMs);
|
|
182
291
|
timeMs = max_time_on;
|
|
183
292
|
}
|
|
184
293
|
|
|
@@ -193,9 +302,9 @@ module.exports = function (RED)
|
|
|
193
302
|
if (timeMs <= 0 || isPermanent || isMotion || !node_settings.last_value)
|
|
194
303
|
return;
|
|
195
304
|
|
|
196
|
-
|
|
305
|
+
timeout = setTimeout(() =>
|
|
197
306
|
{
|
|
198
|
-
|
|
307
|
+
timeout = null;
|
|
199
308
|
node_settings.last_value = false;
|
|
200
309
|
node.send({ payload: false });
|
|
201
310
|
notifyCentral(false);
|
|
@@ -205,26 +314,32 @@ module.exports = function (RED)
|
|
|
205
314
|
}, timeMs);
|
|
206
315
|
};
|
|
207
316
|
|
|
317
|
+
/**
|
|
318
|
+
* Stops the current running timeout
|
|
319
|
+
*/
|
|
208
320
|
let stopAutoOff = () =>
|
|
209
321
|
{
|
|
210
|
-
if (
|
|
322
|
+
if (timeout != null)
|
|
211
323
|
{
|
|
212
|
-
clearTimeout(
|
|
213
|
-
|
|
324
|
+
clearTimeout(timeout);
|
|
325
|
+
timeout = null;
|
|
214
326
|
}
|
|
215
327
|
};
|
|
216
328
|
|
|
329
|
+
/**
|
|
330
|
+
* Set the current node status
|
|
331
|
+
*/
|
|
217
332
|
let setStatus = () =>
|
|
218
333
|
{
|
|
219
|
-
if (alarm_active)
|
|
334
|
+
if (node_settings.alarm_active)
|
|
220
335
|
{
|
|
221
336
|
node.status({ fill: "red", shape: "dot", text: helper.getCurrentTimeForStatus() + ": ALARM is active" });
|
|
222
337
|
}
|
|
223
338
|
else if (node_settings.last_value)
|
|
224
339
|
{
|
|
225
|
-
if (isPermanent || isMotion ||
|
|
340
|
+
if (isPermanent || isMotion || timeout == null)
|
|
226
341
|
node.status({ fill: "green", shape: "dot", text: helper.getCurrentTimeForStatus() + ": On" });
|
|
227
|
-
else if (
|
|
342
|
+
else if (timeout)
|
|
228
343
|
node.status({ fill: "yellow", shape: "ring", text: helper.getCurrentTimeForStatus() + ": Wait " + helper.formatDateToStatus(timeout_end_date, "until") + " for auto off" });
|
|
229
344
|
}
|
|
230
345
|
else
|
|
@@ -233,6 +348,10 @@ module.exports = function (RED)
|
|
|
233
348
|
}
|
|
234
349
|
}
|
|
235
350
|
|
|
351
|
+
/**
|
|
352
|
+
* Notify all connected central nodes
|
|
353
|
+
* @param {boolean} state The state if the light is on
|
|
354
|
+
*/
|
|
236
355
|
let notifyCentral = state =>
|
|
237
356
|
{
|
|
238
357
|
if (!config.links)
|
|
@@ -240,8 +359,8 @@ module.exports = function (RED)
|
|
|
240
359
|
|
|
241
360
|
config.links.forEach(link =>
|
|
242
361
|
{
|
|
243
|
-
|
|
244
|
-
|
|
362
|
+
helper.log(node.id + " -> " + link);
|
|
363
|
+
helper.log({ source: node.id, state: state });
|
|
245
364
|
RED.events.emit("node:" + link, { source: node.id, state: state });
|
|
246
365
|
});
|
|
247
366
|
}
|