smart-nodes 0.3.22 → 0.3.26
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/smart_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 +3 -1
- package/LICENSE +0 -21
package/hysteresis/hysteresis.js
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
|
|
2
1
|
module.exports = function (RED)
|
|
3
2
|
{
|
|
3
|
+
"use strict";
|
|
4
|
+
|
|
4
5
|
function HysteresisNode(config)
|
|
5
6
|
{
|
|
6
7
|
const node = this;
|
|
7
8
|
RED.nodes.createNode(node, config);
|
|
8
9
|
|
|
9
|
-
const
|
|
10
|
+
const smart_context = require("../persistence.js")(RED);
|
|
10
11
|
const helper = require("../smart_helper.js");
|
|
11
12
|
|
|
12
|
-
var
|
|
13
|
+
var node_settings = {
|
|
13
14
|
active: null,
|
|
14
|
-
|
|
15
|
+
last_message: null,
|
|
15
16
|
setpoint: parseFloat(config.setpoint),
|
|
16
17
|
hysteresis: parseFloat(config.hysteresis)
|
|
17
18
|
};
|
|
@@ -19,20 +20,20 @@ module.exports = function (RED)
|
|
|
19
20
|
if (config.save_state)
|
|
20
21
|
{
|
|
21
22
|
// load old saved values
|
|
22
|
-
|
|
23
|
+
node_settings = Object.assign(node_settings, smart_context.get(node.id));
|
|
23
24
|
|
|
24
|
-
switch (
|
|
25
|
+
switch (node_settings.active)
|
|
25
26
|
{
|
|
26
27
|
case true:
|
|
27
|
-
node.status({ fill: "green", shape: "dot", text:
|
|
28
|
+
node.status({ fill: "green", shape: "dot", text: helper.getCurrentTimeForStatus() + ": Load last state: Higher" });
|
|
28
29
|
break;
|
|
29
30
|
|
|
30
31
|
case false:
|
|
31
|
-
node.status({ fill: "red", shape: "dot", text:
|
|
32
|
+
node.status({ fill: "red", shape: "dot", text: helper.getCurrentTimeForStatus() + ": Load last state: Lower" });
|
|
32
33
|
break;
|
|
33
34
|
|
|
34
35
|
default:
|
|
35
|
-
node.status({ fill: "yellow", shape: "ring", text:
|
|
36
|
+
node.status({ fill: "yellow", shape: "ring", text: helper.getCurrentTimeForStatus() + ": No last state available" });
|
|
36
37
|
break;
|
|
37
38
|
}
|
|
38
39
|
}
|
|
@@ -40,7 +41,7 @@ module.exports = function (RED)
|
|
|
40
41
|
{
|
|
41
42
|
// delete old saved values
|
|
42
43
|
node.status({});
|
|
43
|
-
|
|
44
|
+
smart_context.del(node.id);
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
// dynamic config
|
|
@@ -52,75 +53,75 @@ module.exports = function (RED)
|
|
|
52
53
|
node.on("input", function (msg)
|
|
53
54
|
{
|
|
54
55
|
let value = parseFloat(msg.payload);
|
|
55
|
-
let
|
|
56
|
+
let real_topic = helper.getTopicName(msg.topic);
|
|
56
57
|
|
|
57
|
-
if (isNaN(value) &&
|
|
58
|
+
if (isNaN(value) && real_topic !== "resend")
|
|
58
59
|
{
|
|
59
60
|
// node.error("Invalid payload: " + msg.payload);
|
|
60
61
|
return;
|
|
61
62
|
}
|
|
62
63
|
|
|
63
|
-
switch (
|
|
64
|
+
switch (real_topic)
|
|
64
65
|
{
|
|
65
66
|
case "setpoint":
|
|
66
|
-
|
|
67
|
-
node.status({ fill:
|
|
67
|
+
node_settings.setpoint = value;
|
|
68
|
+
node.status({ fill: node_settings.active ? "green" : "red", shape: "ring", text: helper.getCurrentTimeForStatus() + ": New setpoint: " + value + "" });
|
|
68
69
|
|
|
69
70
|
if (config.save_state)
|
|
70
|
-
|
|
71
|
+
smart_context.set(node.id, node_settings);
|
|
71
72
|
break;
|
|
72
73
|
|
|
73
74
|
case "hysteresis":
|
|
74
|
-
|
|
75
|
-
node.status({ fill:
|
|
75
|
+
node_settings.hysteresis = value;
|
|
76
|
+
node.status({ fill: node_settings.active ? "green" : "red", shape: "ring", text: helper.getCurrentTimeForStatus() + ": New hysteresis: " + value + "" });
|
|
76
77
|
|
|
77
78
|
if (config.save_state)
|
|
78
|
-
|
|
79
|
+
smart_context.set(node.id, node_settings);
|
|
79
80
|
break;
|
|
80
81
|
|
|
81
82
|
case "resend":
|
|
82
|
-
if (
|
|
83
|
+
if (node_settings.active === true && node_settings.last_message != null)
|
|
83
84
|
{
|
|
84
|
-
node.status({ fill: "green", shape: "dot", text:
|
|
85
|
-
node.send([
|
|
85
|
+
node.status({ fill: "green", shape: "dot", text: helper.getCurrentTimeForStatus() + ": Resend higher value" });
|
|
86
|
+
node.send([node_settings.last_message, null]);
|
|
86
87
|
}
|
|
87
|
-
else if (
|
|
88
|
+
else if (node_settings.active === false && node_settings.last_message != null)
|
|
88
89
|
{
|
|
89
|
-
node.status({ fill: "red", shape: "dot", text:
|
|
90
|
-
node.send([null,
|
|
90
|
+
node.status({ fill: "red", shape: "dot", text: helper.getCurrentTimeForStatus() + ": Resend lower value" });
|
|
91
|
+
node.send([null, node_settings.last_message]);
|
|
91
92
|
}
|
|
92
93
|
else
|
|
93
94
|
{
|
|
94
|
-
node.status({ fill: "yellow", shape: "ring", text:
|
|
95
|
+
node.status({ fill: "yellow", shape: "ring", text: helper.getCurrentTimeForStatus() + ": No resend, state is unknown" });
|
|
95
96
|
}
|
|
96
97
|
break;
|
|
97
98
|
|
|
98
99
|
default:
|
|
99
|
-
if (value >=
|
|
100
|
+
if (value >= node_settings.setpoint + node_settings.hysteresis && node_settings.active !== true)
|
|
100
101
|
{
|
|
101
|
-
node.status({ fill: "green", shape: "dot", text:
|
|
102
|
-
|
|
103
|
-
|
|
102
|
+
node.status({ fill: "green", shape: "dot", text: helper.getCurrentTimeForStatus() + ": Turned higher by value " + value + "" });
|
|
103
|
+
node_settings.active = true;
|
|
104
|
+
node_settings.last_message = createMessage(out_higher ?? msg, value);
|
|
104
105
|
|
|
105
106
|
if (config.save_state)
|
|
106
|
-
|
|
107
|
+
smart_context.set(node.id, node_settings);
|
|
107
108
|
|
|
108
|
-
node.send([
|
|
109
|
+
node.send([node_settings.last_message, null]);
|
|
109
110
|
}
|
|
110
|
-
else if (value <=
|
|
111
|
+
else if (value <= node_settings.setpoint - node_settings.hysteresis && node_settings.active !== false)
|
|
111
112
|
{
|
|
112
|
-
node.status({ fill: "red", shape: "dot", text:
|
|
113
|
-
|
|
114
|
-
|
|
113
|
+
node.status({ fill: "red", shape: "dot", text: helper.getCurrentTimeForStatus() + ": Turned lower by value " + value + "" });
|
|
114
|
+
node_settings.active = false;
|
|
115
|
+
node_settings.last_message = createMessage(out_lower ?? msg, value);
|
|
115
116
|
|
|
116
117
|
if (config.save_state)
|
|
117
|
-
|
|
118
|
+
smart_context.set(node.id, node_settings);
|
|
118
119
|
|
|
119
|
-
node.send([null,
|
|
120
|
+
node.send([null, node_settings.last_message]);
|
|
120
121
|
}
|
|
121
122
|
else
|
|
122
123
|
{
|
|
123
|
-
node.status({ fill:
|
|
124
|
+
node.status({ fill: node_settings.active ? "green" : "red", shape: "ring", text: helper.getCurrentTimeForStatus() + ": No change by value " + value + "" });
|
|
124
125
|
}
|
|
125
126
|
break;
|
|
126
127
|
}
|
|
@@ -134,22 +135,22 @@ module.exports = function (RED)
|
|
|
134
135
|
{
|
|
135
136
|
return Object.assign({}, msg, {
|
|
136
137
|
smart_info: {
|
|
137
|
-
active:
|
|
138
|
-
hysteresis:
|
|
139
|
-
setpoint:
|
|
138
|
+
active: node_settings.active,
|
|
139
|
+
hysteresis: node_settings.hysteresis,
|
|
140
|
+
setpoint: node_settings.setpoint,
|
|
140
141
|
last_value: value
|
|
141
142
|
}
|
|
142
143
|
})
|
|
143
144
|
};
|
|
144
145
|
|
|
145
|
-
if (config.save_state && config.resend_on_start &&
|
|
146
|
+
if (config.save_state && config.resend_on_start && node_settings.active != null && node_settings.last_message != null)
|
|
146
147
|
{
|
|
147
148
|
setTimeout(() =>
|
|
148
149
|
{
|
|
149
|
-
if (
|
|
150
|
-
node.send([
|
|
150
|
+
if (node_settings.active)
|
|
151
|
+
node.send([node_settings.last_message, null]);
|
|
151
152
|
else
|
|
152
|
-
node.send([null,
|
|
153
|
+
node.send([null, node_settings.last_message]);
|
|
153
154
|
}, 10000);
|
|
154
155
|
}
|
|
155
156
|
}
|
|
Binary file
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
module.exports = function (RED)
|
|
2
2
|
{
|
|
3
|
+
"use strict";
|
|
4
|
+
|
|
3
5
|
function LightControlNode(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_value: false,
|
|
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);
|
|
@@ -44,7 +46,7 @@ module.exports = function (RED)
|
|
|
44
46
|
handleTopic(msg);
|
|
45
47
|
|
|
46
48
|
setStatus();
|
|
47
|
-
|
|
49
|
+
smart_context.set(node.id, node_settings);
|
|
48
50
|
});
|
|
49
51
|
|
|
50
52
|
node.on("close", function ()
|
|
@@ -63,10 +65,10 @@ module.exports = function (RED)
|
|
|
63
65
|
// Make sure it is bool
|
|
64
66
|
msg.payload = !!msg.payload;
|
|
65
67
|
|
|
66
|
-
if (
|
|
68
|
+
if (node_settings.last_value == msg.payload && max_time_on_timeout != null)
|
|
67
69
|
doRestartTimer = false;
|
|
68
70
|
|
|
69
|
-
|
|
71
|
+
node_settings.last_value = msg.payload;
|
|
70
72
|
break;
|
|
71
73
|
|
|
72
74
|
case "off":
|
|
@@ -74,7 +76,7 @@ module.exports = function (RED)
|
|
|
74
76
|
if (msg.payload === false)
|
|
75
77
|
return;
|
|
76
78
|
|
|
77
|
-
|
|
79
|
+
node_settings.last_value = false;
|
|
78
80
|
break;
|
|
79
81
|
|
|
80
82
|
case "on":
|
|
@@ -82,19 +84,19 @@ module.exports = function (RED)
|
|
|
82
84
|
if (msg.payload === false)
|
|
83
85
|
return;
|
|
84
86
|
|
|
85
|
-
|
|
87
|
+
node_settings.last_value = true;
|
|
86
88
|
break;
|
|
87
89
|
|
|
88
90
|
case "set":
|
|
89
91
|
// Make sure it is bool
|
|
90
92
|
msg.payload = !!msg.payload;
|
|
91
|
-
|
|
93
|
+
node_settings.last_value = msg.payload;
|
|
92
94
|
break;
|
|
93
95
|
|
|
94
96
|
case "set_permanent":
|
|
95
97
|
// Make sure it is bool
|
|
96
98
|
msg.payload = !!msg.payload;
|
|
97
|
-
|
|
99
|
+
node_settings.last_value = msg.payload;
|
|
98
100
|
isPermanent = msg.payload;
|
|
99
101
|
break;
|
|
100
102
|
|
|
@@ -106,16 +108,16 @@ module.exports = function (RED)
|
|
|
106
108
|
if (msg.payload == false)
|
|
107
109
|
{
|
|
108
110
|
// It already was off, so don't turn on
|
|
109
|
-
if (
|
|
111
|
+
if (node_settings.last_value == false)
|
|
110
112
|
return;
|
|
111
113
|
|
|
112
114
|
// If time is set to 0, then turn off immediately
|
|
113
115
|
if (helper.getTimeInMsFromString(msg.time_on ?? max_time_on) == 0)
|
|
114
|
-
|
|
116
|
+
node_settings.last_value = false;
|
|
115
117
|
}
|
|
116
118
|
else
|
|
117
119
|
{
|
|
118
|
-
|
|
120
|
+
node_settings.last_value = true;
|
|
119
121
|
}
|
|
120
122
|
break;
|
|
121
123
|
|
|
@@ -131,7 +133,7 @@ module.exports = function (RED)
|
|
|
131
133
|
if (msg.payload === false)
|
|
132
134
|
return;
|
|
133
135
|
|
|
134
|
-
|
|
136
|
+
node_settings.last_value = !node_settings.last_value;
|
|
135
137
|
break;
|
|
136
138
|
}
|
|
137
139
|
|
|
@@ -146,24 +148,24 @@ module.exports = function (RED)
|
|
|
146
148
|
switch (alarm_action)
|
|
147
149
|
{
|
|
148
150
|
case "ON":
|
|
149
|
-
|
|
151
|
+
node_settings.last_value = true;
|
|
150
152
|
break;
|
|
151
153
|
|
|
152
154
|
default:
|
|
153
155
|
case "OFF":
|
|
154
|
-
|
|
156
|
+
node_settings.last_value = false;
|
|
155
157
|
break;
|
|
156
158
|
}
|
|
157
159
|
}
|
|
158
160
|
|
|
159
161
|
if (alarm_active || helper.getTopicName(msg.topic) != "status")
|
|
160
|
-
node.send({ payload:
|
|
162
|
+
node.send({ payload: node_settings.last_value });
|
|
161
163
|
|
|
162
164
|
// Output is on, now
|
|
163
|
-
if (
|
|
165
|
+
if (node_settings.last_value && doRestartTimer)
|
|
164
166
|
startAutoOffIfNeeded(helper.getTimeInMsFromString(msg.time_on ?? max_time_on));
|
|
165
167
|
|
|
166
|
-
notifyCentral(
|
|
168
|
+
notifyCentral(node_settings.last_value);
|
|
167
169
|
}
|
|
168
170
|
|
|
169
171
|
let startAutoOffIfNeeded = origTimeMs =>
|
|
@@ -188,18 +190,18 @@ module.exports = function (RED)
|
|
|
188
190
|
stopAutoOff();
|
|
189
191
|
|
|
190
192
|
// 0 = Always on
|
|
191
|
-
if (timeMs <= 0 || isPermanent || isMotion || !
|
|
193
|
+
if (timeMs <= 0 || isPermanent || isMotion || !node_settings.last_value)
|
|
192
194
|
return;
|
|
193
195
|
|
|
194
196
|
max_time_on_timeout = setTimeout(() =>
|
|
195
197
|
{
|
|
196
198
|
max_time_on_timeout = null;
|
|
197
|
-
|
|
199
|
+
node_settings.last_value = false;
|
|
198
200
|
node.send({ payload: false });
|
|
199
201
|
notifyCentral(false);
|
|
200
202
|
|
|
201
203
|
setStatus();
|
|
202
|
-
|
|
204
|
+
smart_context.set(node.id, node_settings);
|
|
203
205
|
}, timeMs);
|
|
204
206
|
};
|
|
205
207
|
|
|
@@ -216,18 +218,18 @@ module.exports = function (RED)
|
|
|
216
218
|
{
|
|
217
219
|
if (alarm_active)
|
|
218
220
|
{
|
|
219
|
-
node.status({ fill: "red", shape: "dot", text:
|
|
221
|
+
node.status({ fill: "red", shape: "dot", text: helper.getCurrentTimeForStatus() + ": ALARM is active" });
|
|
220
222
|
}
|
|
221
|
-
else if (
|
|
223
|
+
else if (node_settings.last_value)
|
|
222
224
|
{
|
|
223
225
|
if (isPermanent || isMotion || timeout_end_date == null)
|
|
224
|
-
node.status({ fill: "green", shape: "dot", text:
|
|
226
|
+
node.status({ fill: "green", shape: "dot", text: helper.getCurrentTimeForStatus() + ": On" });
|
|
225
227
|
else if (max_time_on_timeout)
|
|
226
|
-
node.status({ fill: "yellow", shape: "ring", text:
|
|
228
|
+
node.status({ fill: "yellow", shape: "ring", text: helper.getCurrentTimeForStatus() + ": Wait " + helper.formatDateToStatus(timeout_end_date, "until") + " for auto off" });
|
|
227
229
|
}
|
|
228
230
|
else
|
|
229
231
|
{
|
|
230
|
-
node.status({ fill: "red", shape: "dot", text:
|
|
232
|
+
node.status({ fill: "red", shape: "dot", text: helper.getCurrentTimeForStatus() + ": Off" });
|
|
231
233
|
}
|
|
232
234
|
}
|
|
233
235
|
|
|
@@ -245,7 +247,7 @@ module.exports = function (RED)
|
|
|
245
247
|
}
|
|
246
248
|
|
|
247
249
|
// After node red restart, start also the timeout
|
|
248
|
-
if (
|
|
250
|
+
if (node_settings.last_value)
|
|
249
251
|
startAutoOffIfNeeded(helper.getTimeInMsFromString(max_time_on));
|
|
250
252
|
|
|
251
253
|
setStatus();
|
package/logic/logic.html
CHANGED
|
@@ -10,7 +10,9 @@
|
|
|
10
10
|
inverts: { value: "" },
|
|
11
11
|
invert_output: { value: false },
|
|
12
12
|
out_false: { value: '{"topic": ""}' },
|
|
13
|
+
out_false_type: { value: 'json' },
|
|
13
14
|
out_true: { value: '{"topic": ""}' },
|
|
15
|
+
out_true_type: { value: 'json' },
|
|
14
16
|
save_state: { value: true },
|
|
15
17
|
resend_on_start: { value: true }
|
|
16
18
|
},
|
|
@@ -66,12 +68,24 @@
|
|
|
66
68
|
|
|
67
69
|
$("#node-input-out_true").typedInput({
|
|
68
70
|
type: "json",
|
|
69
|
-
types: ["json"
|
|
71
|
+
types: ["json", {
|
|
72
|
+
value: "null",
|
|
73
|
+
label: "Nichts senden",
|
|
74
|
+
icon: "fa fa-times",
|
|
75
|
+
hasValue: false,
|
|
76
|
+
}],
|
|
77
|
+
typeField: "#node-input-out_true_type"
|
|
70
78
|
});
|
|
71
79
|
|
|
72
80
|
$("#node-input-out_false").typedInput({
|
|
73
81
|
type: "json",
|
|
74
|
-
types: ["json"
|
|
82
|
+
types: ["json", {
|
|
83
|
+
value: "null",
|
|
84
|
+
label: "Nichts senden",
|
|
85
|
+
icon: "fa fa-times",
|
|
86
|
+
hasValue: false,
|
|
87
|
+
}],
|
|
88
|
+
typeField: "#node-input-out_false_type"
|
|
75
89
|
});
|
|
76
90
|
|
|
77
91
|
$("#node-input-save_state").on("change", ev =>
|
|
@@ -137,10 +151,12 @@
|
|
|
137
151
|
<div class="form-row">
|
|
138
152
|
<label for="node-input-out_true"><i class="fa fa-check-circle"></i> Wahr</label>
|
|
139
153
|
<input type="text" id="node-input-out_true"/>
|
|
154
|
+
<input type="hidden" id="node-input-out_true_type">
|
|
140
155
|
</div>
|
|
141
156
|
<div class="form-row">
|
|
142
157
|
<label for="node-input-out_false"><i class="fa fa-times-circle"></i> Falsch</label>
|
|
143
158
|
<input type="text" id="node-input-out_false" />
|
|
159
|
+
<input type="hidden" id="node-input-out_false_type">
|
|
144
160
|
</div>
|
|
145
161
|
<div class="form-row">
|
|
146
162
|
<span><strong>Hinweis:</strong> <code>msg.payload</code> wird automatisch auf das Logik-Ergebnis gesetzt.</span>
|
package/logic/logic.js
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
module.exports = function (RED)
|
|
2
2
|
{
|
|
3
|
+
"use strict";
|
|
4
|
+
|
|
3
5
|
function LogicNode(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
|
// dynamic config
|
|
12
14
|
let logic = config.logic;
|
|
13
|
-
let out_true = helper.evaluateNodeProperty(RED, config.out_true, "json");
|
|
14
|
-
let out_false = helper.evaluateNodeProperty(RED, config.out_false, "json");
|
|
15
|
+
let out_true = helper.evaluateNodeProperty(RED, config.out_true, config.out_true_type || "json");
|
|
16
|
+
let out_false = helper.evaluateNodeProperty(RED, config.out_false, config.out_false_type || "json");
|
|
15
17
|
let logic_inputs = config.logic_inputs;
|
|
16
18
|
let inverts = config.inverts.split(",").map(n => parseInt(n));
|
|
17
19
|
let invert_output = config.invert_output;
|
|
@@ -19,7 +21,7 @@ module.exports = function (RED)
|
|
|
19
21
|
// runtime values
|
|
20
22
|
|
|
21
23
|
|
|
22
|
-
var
|
|
24
|
+
var node_settings = {
|
|
23
25
|
input_states: Array.from({ length: logic_inputs }).fill(false),
|
|
24
26
|
last_message: null,
|
|
25
27
|
};
|
|
@@ -27,12 +29,12 @@ module.exports = function (RED)
|
|
|
27
29
|
if (config.save_state)
|
|
28
30
|
{
|
|
29
31
|
// load old saved values
|
|
30
|
-
|
|
32
|
+
node_settings = Object.assign(node_settings, smart_context.get(node.id));
|
|
31
33
|
}
|
|
32
34
|
else
|
|
33
35
|
{
|
|
34
36
|
// delete old saved values
|
|
35
|
-
|
|
37
|
+
smart_context.del(node.id);
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
node.on("input", function (msg)
|
|
@@ -51,9 +53,9 @@ module.exports = function (RED)
|
|
|
51
53
|
}
|
|
52
54
|
|
|
53
55
|
if (inverts.includes(input))
|
|
54
|
-
|
|
56
|
+
node_settings.input_states[input - 1] = !msg.payload;
|
|
55
57
|
else
|
|
56
|
-
|
|
58
|
+
node_settings.input_states[input - 1] = !!msg.payload; // !! => Convert to boolean
|
|
57
59
|
|
|
58
60
|
setStatus();
|
|
59
61
|
let result = getResult();
|
|
@@ -61,23 +63,23 @@ module.exports = function (RED)
|
|
|
61
63
|
if (invert_output ? !result : result)
|
|
62
64
|
{
|
|
63
65
|
result = out_true;
|
|
64
|
-
result
|
|
66
|
+
if (result !== null)
|
|
67
|
+
result.payload = true;
|
|
65
68
|
}
|
|
66
69
|
else
|
|
67
70
|
{
|
|
68
71
|
result = out_false;
|
|
69
|
-
result
|
|
72
|
+
if (result !== null)
|
|
73
|
+
result.payload = false;
|
|
70
74
|
}
|
|
71
75
|
|
|
72
|
-
if (
|
|
73
|
-
{
|
|
74
|
-
nodeSettings.last_message = result;
|
|
75
|
-
|
|
76
|
+
if (result !== null && node_settings.last_message?.payload != result.payload)
|
|
76
77
|
node.send(result);
|
|
77
|
-
|
|
78
|
+
|
|
79
|
+
node_settings.last_message = result;
|
|
78
80
|
|
|
79
81
|
if (config.save_state)
|
|
80
|
-
|
|
82
|
+
smart_context.set(node.id, node_settings);
|
|
81
83
|
});
|
|
82
84
|
|
|
83
85
|
node.on("close", function ()
|
|
@@ -94,7 +96,7 @@ module.exports = function (RED)
|
|
|
94
96
|
result = true;
|
|
95
97
|
for (let i = 0; i < logic_inputs; i++)
|
|
96
98
|
{
|
|
97
|
-
const element =
|
|
99
|
+
const element = node_settings.input_states[i];
|
|
98
100
|
if (element == false)
|
|
99
101
|
{
|
|
100
102
|
result = false;
|
|
@@ -107,7 +109,7 @@ module.exports = function (RED)
|
|
|
107
109
|
result = false;
|
|
108
110
|
for (let i = 0; i < logic_inputs; i++)
|
|
109
111
|
{
|
|
110
|
-
const element =
|
|
112
|
+
const element = node_settings.input_states[i];
|
|
111
113
|
if (element == true)
|
|
112
114
|
{
|
|
113
115
|
result = true;
|
|
@@ -122,7 +124,7 @@ module.exports = function (RED)
|
|
|
122
124
|
|
|
123
125
|
for (let i = 0; i < logic_inputs; i++)
|
|
124
126
|
{
|
|
125
|
-
const element =
|
|
127
|
+
const element = node_settings.input_states[i];
|
|
126
128
|
if (element && oneTrue)
|
|
127
129
|
{
|
|
128
130
|
result = false;
|
|
@@ -145,7 +147,7 @@ module.exports = function (RED)
|
|
|
145
147
|
for (let i = 0; i < logic_inputs; i++)
|
|
146
148
|
{
|
|
147
149
|
let invert = inverts.includes(i + 1);
|
|
148
|
-
const element =
|
|
150
|
+
const element = node_settings.input_states[i];
|
|
149
151
|
|
|
150
152
|
state.push((invert ? "!" + (!element) : "" + element));
|
|
151
153
|
}
|
|
@@ -153,14 +155,14 @@ module.exports = function (RED)
|
|
|
153
155
|
let result = getResult();
|
|
154
156
|
let resultText = (invert_output ? "!" : "") + result;
|
|
155
157
|
|
|
156
|
-
node.status({ fill: "yellow", shape: "ring", text:
|
|
158
|
+
node.status({ fill: "yellow", shape: "ring", text: helper.getCurrentTimeForStatus() + ": [" + state.join(", ") + "] => " + resultText });
|
|
157
159
|
}
|
|
158
160
|
|
|
159
|
-
if (config.save_state && config.resend_on_start &&
|
|
161
|
+
if (config.save_state && config.resend_on_start && node_settings.last_message != null)
|
|
160
162
|
{
|
|
161
163
|
setTimeout(() =>
|
|
162
164
|
{
|
|
163
|
-
node.send(
|
|
165
|
+
node.send(node_settings.last_message);
|
|
164
166
|
}, 10000);
|
|
165
167
|
}
|
|
166
168
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
module.exports = function (RED)
|
|
2
2
|
{
|
|
3
|
+
"use strict";
|
|
4
|
+
|
|
3
5
|
function LongPressControlNode(config)
|
|
4
6
|
{
|
|
5
7
|
const node = this;
|
|
@@ -22,7 +24,7 @@ module.exports = function (RED)
|
|
|
22
24
|
{
|
|
23
25
|
if (msg.payload)
|
|
24
26
|
{
|
|
25
|
-
node.status({ fill: "yellow", shape: "ring", text:
|
|
27
|
+
node.status({ fill: "yellow", shape: "ring", text: helper.getCurrentTimeForStatus() + ": Wait for button release..." });
|
|
26
28
|
on_time = Date.now();
|
|
27
29
|
startAutoLongPress();
|
|
28
30
|
}
|
|
@@ -36,13 +38,13 @@ module.exports = function (RED)
|
|
|
36
38
|
|
|
37
39
|
if (pressTime < long_press_ms)
|
|
38
40
|
{
|
|
39
|
-
node.status({ fill: "green", shape: "dot", text:
|
|
41
|
+
node.status({ fill: "green", shape: "dot", text: helper.getCurrentTimeForStatus() + ": Last was short" });
|
|
40
42
|
if (short)
|
|
41
43
|
node.send([short, null]);
|
|
42
44
|
}
|
|
43
45
|
else
|
|
44
46
|
{
|
|
45
|
-
node.status({ fill: "green", shape: "dot", text:
|
|
47
|
+
node.status({ fill: "green", shape: "dot", text: helper.getCurrentTimeForStatus() + ": Last was long" });
|
|
46
48
|
if (long)
|
|
47
49
|
node.send([null, long]);
|
|
48
50
|
}
|
|
@@ -55,7 +57,7 @@ module.exports = function (RED)
|
|
|
55
57
|
max_time_on_timeout = setTimeout(() =>
|
|
56
58
|
{
|
|
57
59
|
on_time = null;
|
|
58
|
-
node.status({ fill: "green", shape: "dot", text:
|
|
60
|
+
node.status({ fill: "green", shape: "dot", text: helper.getCurrentTimeForStatus() + ": Last was long" });
|
|
59
61
|
node.send([null, long]);
|
|
60
62
|
}, long_press_ms);
|
|
61
63
|
};
|