smart-nodes 0.3.22 → 0.3.27
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/LICENSE.md +1 -1
- package/README.md +51 -21
- package/central/central.js +10 -8
- package/compare/compare.html +48 -0
- package/compare/compare.js +36 -20
- package/counter/counter.html +104 -0
- package/counter/counter.js +120 -0
- package/delay/delay.js +39 -37
- package/examples/heating-curve.json +480 -0
- package/examples/heating-curve.png +0 -0
- package/examples/mixing-valve.json +622 -0
- package/examples/mixing-valve.png +0 -0
- package/forwarder/forwarder.js +28 -26
- package/heating-curve/heating-curve.html +348 -0
- package/heating-curve/heating-curve.js +134 -0
- package/hysteresis/hysteresis.js +47 -46
- package/icons/counter.png +0 -0
- package/light-control/light-control.js +30 -28
- package/logic/logic.html +18 -2
- package/logic/logic.js +25 -23
- package/long-press-control/long-press-control.js +6 -4
- package/mixing-valve/mixing-valve.html +188 -0
- package/mixing-valve/mixing-valve.js +357 -0
- package/multi-press-control/multi-press-control.js +3 -1
- package/package.json +8 -1
- package/scene-control/scene-control.js +29 -27
- package/scheduler/scheduler.js +27 -25
- package/shutter-complex-control/shutter-complex-control.js +62 -62
- package/shutter-control/shutter-control.js +39 -37
- package/smart_helper.js +135 -20
- package/statistic/statistic.js +30 -28
- package/text-exec/text-exec.js +5 -1
- package/LICENSE +0 -21
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
module.exports = function (RED)
|
|
2
2
|
{
|
|
3
|
+
"use strict";
|
|
4
|
+
|
|
3
5
|
function SceneControlNode(config)
|
|
4
6
|
{
|
|
5
7
|
const node = this;
|
|
6
8
|
RED.nodes.createNode(node, config);
|
|
7
9
|
|
|
8
|
-
const
|
|
10
|
+
const smart_context = require("../persistence.js")(RED);
|
|
9
11
|
const helper = require("../smart_helper.js");
|
|
10
12
|
|
|
11
13
|
// used from text-exec node
|
|
@@ -15,9 +17,9 @@ module.exports = function (RED)
|
|
|
15
17
|
node.exec_text_names = [];
|
|
16
18
|
|
|
17
19
|
// persistent values
|
|
18
|
-
var
|
|
20
|
+
var node_settings = Object.assign({}, {
|
|
19
21
|
last_values: [], // light is on or off for a scene
|
|
20
|
-
},
|
|
22
|
+
}, smart_context.get(node.id));
|
|
21
23
|
|
|
22
24
|
// dynamic config
|
|
23
25
|
let max_time_on = helper.getTimeInMs(config.max_time_on, config.max_time_on_unit);
|
|
@@ -36,10 +38,10 @@ module.exports = function (RED)
|
|
|
36
38
|
RED.events.on(event, handler);
|
|
37
39
|
|
|
38
40
|
|
|
39
|
-
if (
|
|
41
|
+
if (node_settings.last_values.length != config.scenes.length)
|
|
40
42
|
{
|
|
41
43
|
// Per default expect that all outputs are off
|
|
42
|
-
|
|
44
|
+
node_settings.last_values = new Array(config.outputs).fill(false);
|
|
43
45
|
}
|
|
44
46
|
|
|
45
47
|
node.status({});
|
|
@@ -53,7 +55,7 @@ module.exports = function (RED)
|
|
|
53
55
|
startAutoOffIfNeeded(helper.getTimeInMsFromString(msg.time_on ?? max_time_on));
|
|
54
56
|
|
|
55
57
|
status();
|
|
56
|
-
|
|
58
|
+
smart_context.set(node.id, node_settings);
|
|
57
59
|
});
|
|
58
60
|
|
|
59
61
|
node.on("close", function ()
|
|
@@ -65,15 +67,15 @@ module.exports = function (RED)
|
|
|
65
67
|
let handleTopic = msg =>
|
|
66
68
|
{
|
|
67
69
|
let currentScene = getCurrentScene();
|
|
68
|
-
let [
|
|
70
|
+
let [real_topic, scenes] = helper.getTopicName(msg.topic).split("_");
|
|
69
71
|
let number = helper.getTopicNumber(msg.topic) - 1; // number should be used 0-based
|
|
70
72
|
|
|
71
|
-
switch (
|
|
73
|
+
switch (real_topic)
|
|
72
74
|
{
|
|
73
75
|
case "status":
|
|
74
76
|
// Make sure it is bool
|
|
75
77
|
msg.payload = !!msg.payload;
|
|
76
|
-
|
|
78
|
+
node_settings.last_values[number] = msg.payload;
|
|
77
79
|
|
|
78
80
|
notifyCentral();
|
|
79
81
|
|
|
@@ -85,17 +87,17 @@ module.exports = function (RED)
|
|
|
85
87
|
return;
|
|
86
88
|
|
|
87
89
|
case "off":
|
|
88
|
-
|
|
90
|
+
node_settings.last_values = new Array(config.outputs).fill(false);
|
|
89
91
|
break;
|
|
90
92
|
|
|
91
93
|
case "on":
|
|
92
|
-
|
|
94
|
+
node_settings.last_values = new Array(config.outputs).fill(true);
|
|
93
95
|
break;
|
|
94
96
|
|
|
95
97
|
case "set":
|
|
96
98
|
// Make sure it is bool
|
|
97
99
|
msg.payload = !!msg.payload;
|
|
98
|
-
|
|
100
|
+
node_settings.last_values = new Array(config.outputs).fill(msg.payload);
|
|
99
101
|
|
|
100
102
|
// This happens because of splitting by _ for scenes
|
|
101
103
|
if (scenes == "permanent")
|
|
@@ -133,19 +135,19 @@ module.exports = function (RED)
|
|
|
133
135
|
|
|
134
136
|
if (nextSceneIndex == 0)
|
|
135
137
|
{
|
|
136
|
-
|
|
138
|
+
node_settings.last_values = new Array(config.outputs).fill(false);
|
|
137
139
|
}
|
|
138
140
|
else
|
|
139
141
|
{
|
|
140
142
|
const scene = config.scenes[nextSceneIndex - 1]; // scene numbers are 1 based
|
|
141
143
|
const expectedOn = scene.outputs.split(",");
|
|
142
|
-
for (let o = 0; o <
|
|
144
|
+
for (let o = 0; o < node_settings.last_values.length; o++)
|
|
143
145
|
{
|
|
144
|
-
const output =
|
|
146
|
+
const output = node_settings.last_values[o];
|
|
145
147
|
// Check if output has to be changed
|
|
146
148
|
if ((output && !expectedOn.includes("" + (o + 1))) || (!output && expectedOn.includes("" + (o + 1))))
|
|
147
149
|
{
|
|
148
|
-
|
|
150
|
+
node_settings.last_values[o] = !output;
|
|
149
151
|
}
|
|
150
152
|
}
|
|
151
153
|
}
|
|
@@ -156,20 +158,20 @@ module.exports = function (RED)
|
|
|
156
158
|
if (msg.payload === false)
|
|
157
159
|
return;
|
|
158
160
|
|
|
159
|
-
|
|
161
|
+
node_settings.last_values = new Array(config.outputs).fill(currentScene == 0);
|
|
160
162
|
break;
|
|
161
163
|
}
|
|
162
164
|
|
|
163
165
|
stopAutoOff();
|
|
164
166
|
|
|
165
|
-
node.send(
|
|
167
|
+
node.send(node_settings.last_values.map(val => { return { payload: val }; }));
|
|
166
168
|
notifyCentral();
|
|
167
169
|
}
|
|
168
170
|
|
|
169
171
|
let getCurrentScene = () =>
|
|
170
172
|
{
|
|
171
173
|
// All off ist scene 0
|
|
172
|
-
if (!
|
|
174
|
+
if (!node_settings.last_values.includes(true))
|
|
173
175
|
return 0;
|
|
174
176
|
|
|
175
177
|
for (let s = 0; s < config.scenes.length; s++)
|
|
@@ -178,9 +180,9 @@ module.exports = function (RED)
|
|
|
178
180
|
const expectedOn = scene.outputs.split(",");
|
|
179
181
|
let skipScene = false;
|
|
180
182
|
|
|
181
|
-
for (let o = 0; o <
|
|
183
|
+
for (let o = 0; o < node_settings.last_values.length; o++)
|
|
182
184
|
{
|
|
183
|
-
const output =
|
|
185
|
+
const output = node_settings.last_values[o];
|
|
184
186
|
// Check if one condition fails
|
|
185
187
|
if ((output && !expectedOn.includes("" + (o + 1))) || (!output && expectedOn.includes("" + (o + 1))))
|
|
186
188
|
{
|
|
@@ -220,12 +222,12 @@ module.exports = function (RED)
|
|
|
220
222
|
|
|
221
223
|
max_time_on_timeout = setTimeout(() =>
|
|
222
224
|
{
|
|
223
|
-
|
|
224
|
-
node.send(
|
|
225
|
+
node_settings.last_values = new Array(config.outputs).fill(false);
|
|
226
|
+
node.send(node_settings.last_values.map(val => { return { payload: val }; }));
|
|
225
227
|
notifyCentral();
|
|
226
228
|
|
|
227
229
|
status();
|
|
228
|
-
|
|
230
|
+
smart_context.set(node.id, node_settings);
|
|
229
231
|
}, timeMs);
|
|
230
232
|
}
|
|
231
233
|
|
|
@@ -244,13 +246,13 @@ module.exports = function (RED)
|
|
|
244
246
|
if (scene != 0)
|
|
245
247
|
{
|
|
246
248
|
if (isPermanent || current_timeout_ms <= 0)
|
|
247
|
-
node.status({ fill: "green", shape: "dot", text:
|
|
249
|
+
node.status({ fill: "green", shape: "dot", text: helper.getCurrentTimeForStatus() + ": Scene " + scene + " active" });
|
|
248
250
|
else if (max_time_on_timeout)
|
|
249
|
-
node.status({ fill: "yellow", shape: "ring", text:
|
|
251
|
+
node.status({ fill: "yellow", shape: "ring", text: helper.getCurrentTimeForStatus() + ": Scene " + scene + " active, wait " + helper.formatMsToStatus(current_timeout_ms, "until") + " for auto off" });
|
|
250
252
|
}
|
|
251
253
|
else
|
|
252
254
|
{
|
|
253
|
-
node.status({ fill: "red", shape: "dot", text:
|
|
255
|
+
node.status({ fill: "red", shape: "dot", text: helper.getCurrentTimeForStatus() + ": Off" });
|
|
254
256
|
}
|
|
255
257
|
}
|
|
256
258
|
|
package/scheduler/scheduler.js
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
module.exports = function (RED)
|
|
2
2
|
{
|
|
3
|
+
"use strict";
|
|
4
|
+
|
|
3
5
|
function SchedulerNode(config)
|
|
4
6
|
{
|
|
5
7
|
const node = this;
|
|
6
8
|
RED.nodes.createNode(node, config);
|
|
7
9
|
|
|
8
|
-
const
|
|
10
|
+
const smart_context = require("../persistence.js")(RED);
|
|
9
11
|
const helper = require("../smart_helper.js");
|
|
10
12
|
|
|
11
|
-
var
|
|
13
|
+
var node_settings = {
|
|
12
14
|
enabled: config.enabled,
|
|
13
15
|
lastMessage: null,
|
|
14
16
|
};
|
|
@@ -16,12 +18,12 @@ module.exports = function (RED)
|
|
|
16
18
|
if (config.save_state)
|
|
17
19
|
{
|
|
18
20
|
// load old saved values
|
|
19
|
-
|
|
21
|
+
node_settings = Object.assign(node_settings, smart_context.get(node.id));
|
|
20
22
|
}
|
|
21
23
|
else
|
|
22
24
|
{
|
|
23
25
|
// delete old saved values
|
|
24
|
-
|
|
26
|
+
smart_context.del(node.id);
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
let timeout = null;
|
|
@@ -38,7 +40,7 @@ module.exports = function (RED)
|
|
|
38
40
|
schedule.days = schedule.days.split(",");
|
|
39
41
|
}
|
|
40
42
|
|
|
41
|
-
if (
|
|
43
|
+
if (node_settings.enabled)
|
|
42
44
|
initNextTimeout();
|
|
43
45
|
|
|
44
46
|
setStatus();
|
|
@@ -50,43 +52,43 @@ module.exports = function (RED)
|
|
|
50
52
|
switch (helper.getTopicName(msg.topic))
|
|
51
53
|
{
|
|
52
54
|
case "enable":
|
|
53
|
-
if (
|
|
55
|
+
if (node_settings.enabled)
|
|
54
56
|
return;
|
|
55
57
|
|
|
56
|
-
|
|
58
|
+
node_settings.enabled = true;
|
|
57
59
|
if (config.save_state)
|
|
58
|
-
|
|
60
|
+
smart_context.set(node.id, node_settings);
|
|
59
61
|
break;
|
|
60
62
|
|
|
61
63
|
case "disable":
|
|
62
|
-
if (!
|
|
64
|
+
if (!node_settings.enabled)
|
|
63
65
|
return;
|
|
64
66
|
|
|
65
|
-
|
|
67
|
+
node_settings.enabled = false;
|
|
66
68
|
if (config.save_state)
|
|
67
|
-
|
|
69
|
+
smart_context.set(node.id, node_settings);
|
|
68
70
|
break;
|
|
69
71
|
|
|
70
72
|
case "set_state":
|
|
71
|
-
if (
|
|
73
|
+
if (node_settings.enabled == !!msg.payload)
|
|
72
74
|
return;
|
|
73
75
|
|
|
74
|
-
|
|
76
|
+
node_settings.enabled = !!msg.payload;
|
|
75
77
|
if (config.save_state)
|
|
76
|
-
|
|
78
|
+
smart_context.set(node.id, node_settings);
|
|
77
79
|
break;
|
|
78
80
|
|
|
79
81
|
default:
|
|
80
82
|
return;
|
|
81
83
|
}
|
|
82
84
|
|
|
83
|
-
if (
|
|
85
|
+
if (node_settings.enabled)
|
|
84
86
|
initTimeouts();
|
|
85
87
|
else
|
|
86
88
|
clearTimeouts();
|
|
87
89
|
|
|
88
90
|
setStatus();
|
|
89
|
-
|
|
91
|
+
smart_context.set(node.id, node_settings);
|
|
90
92
|
});
|
|
91
93
|
|
|
92
94
|
node.on("close", function ()
|
|
@@ -185,15 +187,15 @@ module.exports = function (RED)
|
|
|
185
187
|
{
|
|
186
188
|
const schedule = config.schedules[i];
|
|
187
189
|
|
|
188
|
-
if (!
|
|
190
|
+
if (!node_settings.enabled)
|
|
189
191
|
return;
|
|
190
192
|
|
|
191
193
|
timeout = null;
|
|
192
194
|
node.send(schedule.message);
|
|
193
|
-
|
|
195
|
+
node_settings.lastMessage = schedule.message;
|
|
194
196
|
|
|
195
197
|
if (config.save_state)
|
|
196
|
-
|
|
198
|
+
smart_context.set(node.id, node_settings);
|
|
197
199
|
|
|
198
200
|
initNextTimeout();
|
|
199
201
|
setStatus();
|
|
@@ -201,12 +203,12 @@ module.exports = function (RED)
|
|
|
201
203
|
|
|
202
204
|
let setStatus = () =>
|
|
203
205
|
{
|
|
204
|
-
if (!
|
|
206
|
+
if (!node_settings.enabled)
|
|
205
207
|
{
|
|
206
208
|
node.status({
|
|
207
209
|
fill: "red",
|
|
208
210
|
shape: "dot",
|
|
209
|
-
text:
|
|
211
|
+
text: helper.getCurrentTimeForStatus() + ": Scheduler disabled"
|
|
210
212
|
});
|
|
211
213
|
}
|
|
212
214
|
else if (nextEvent == null)
|
|
@@ -214,7 +216,7 @@ module.exports = function (RED)
|
|
|
214
216
|
node.status({
|
|
215
217
|
fill: "red",
|
|
216
218
|
shape: "dot",
|
|
217
|
-
text:
|
|
219
|
+
text: helper.getCurrentTimeForStatus() + ": No events planned"
|
|
218
220
|
});
|
|
219
221
|
}
|
|
220
222
|
else
|
|
@@ -226,16 +228,16 @@ module.exports = function (RED)
|
|
|
226
228
|
node.status({
|
|
227
229
|
fill: "yellow",
|
|
228
230
|
shape: "dot",
|
|
229
|
-
text:
|
|
231
|
+
text: helper.getCurrentTimeForStatus() + ": Wait " + helper.formatMsToStatus(time, "until") + " to raise next event"
|
|
230
232
|
});
|
|
231
233
|
}
|
|
232
234
|
}
|
|
233
235
|
|
|
234
|
-
if (config.save_state && config.resend_on_start &&
|
|
236
|
+
if (config.save_state && config.resend_on_start && node_settings.lastMessage != null)
|
|
235
237
|
{
|
|
236
238
|
setTimeout(() =>
|
|
237
239
|
{
|
|
238
|
-
node.send(
|
|
240
|
+
node.send(node_settings.lastMessage);
|
|
239
241
|
}, 10000);
|
|
240
242
|
}
|
|
241
243
|
}
|