smart-nodes 0.6.0 → 0.6.2
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 +9 -0
- package/SmartNodesContext.json +1 -1
- package/compare/compare.html +7 -1
- package/compare/compare.js +2 -1
- package/counter/counter.html +8 -2
- package/counter/counter.js +2 -1
- package/delay/delay.html +7 -1
- package/delay/delay.js +2 -1
- package/forwarder/forwarder.html +7 -1
- package/forwarder/forwarder.js +3 -2
- package/heating-curve/heating-curve.html +6 -0
- package/heating-curve/heating-curve.js +3 -2
- package/hysteresis/hysteresis.html +9 -6
- package/hysteresis/hysteresis.js +3 -2
- package/light/light.html +7 -1
- package/light/light.js +2 -1
- package/logic/logic.html +8 -2
- package/logic/logic.js +2 -1
- package/mixing-valve/mixing-valve.html +10 -4
- package/mixing-valve/mixing-valve.js +21 -116
- package/mode-selector/mode-selector.html +6 -3
- package/mode-selector/mode-selector.js +2 -1
- package/multi-press/multi-press.html +1 -1
- package/package.json +2 -2
- package/persistence.js +22 -4
- package/scene/scene.html +7 -4
- package/scene/scene.js +2 -1
- package/scheduler/scheduler.html +4 -2
- package/scheduler/scheduler.js +2 -1
- package/shutter/shutter.html +7 -1
- package/shutter/shutter.js +2 -1
- package/shutter-complex/shutter-complex.html +7 -1
- package/shutter-complex/shutter-complex.js +2 -1
- package/statistic/statistic.html +8 -2
- package/statistic/statistic.js +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -224,3 +224,12 @@
|
|
|
224
224
|
- Reduced amount of messages sent by light node when it is in alarm mode.
|
|
225
225
|
- Fixed forwarder node causing an error when no topic was sent.
|
|
226
226
|
- Added Jest example for all nodes to be able to debug nodes in vscode.
|
|
227
|
+
|
|
228
|
+
## Version 0.6.1:
|
|
229
|
+
|
|
230
|
+
- Removed some ui limits of mixing valve.
|
|
231
|
+
|
|
232
|
+
## Version 0.6.2:
|
|
233
|
+
|
|
234
|
+
- Cached runtime config is revoked now, when new settings are applied in the web frontend.
|
|
235
|
+
- Removed feature from Mixing valve to automatically start with the best known position, because it hadn't worked as expected.
|
package/SmartNodesContext.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"idn1":{"
|
|
1
|
+
{"idn1":{"last_value":false,"last_value_before_alarm":false,"last_value_sended":false,"alarm_active":false,"enabled":false,"setpoint":20,"current_temperature":null,"last_position":50,"last_enabled_sended":null}}
|
package/compare/compare.html
CHANGED
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
send_only_change: { value: true },
|
|
18
18
|
outputs: { value: 1 },
|
|
19
19
|
save_state: { value: false },
|
|
20
|
-
resend_on_start: { value: false }
|
|
20
|
+
resend_on_start: { value: false },
|
|
21
|
+
config_change_date: { value: "" },
|
|
21
22
|
},
|
|
22
23
|
inputs: 1,
|
|
23
24
|
outputs: 1,
|
|
@@ -158,6 +159,11 @@
|
|
|
158
159
|
$("#node-input-value2_type").val("NOTHING");
|
|
159
160
|
}
|
|
160
161
|
},
|
|
162
|
+
oneditsave: function ()
|
|
163
|
+
{
|
|
164
|
+
let node = this;
|
|
165
|
+
node.config_change_date = (new Date()).toISOString();
|
|
166
|
+
},
|
|
161
167
|
});
|
|
162
168
|
</script>
|
|
163
169
|
|
package/compare/compare.js
CHANGED
|
@@ -29,11 +29,12 @@ module.exports = function (RED)
|
|
|
29
29
|
],
|
|
30
30
|
last_result: null,
|
|
31
31
|
last_message: null,
|
|
32
|
+
config_change_date: config.config_change_date,
|
|
32
33
|
};
|
|
33
34
|
|
|
34
35
|
// load or delete saved values
|
|
35
36
|
if (config.save_state)
|
|
36
|
-
node_settings = Object.assign(node_settings, smart_context.get(node.id));
|
|
37
|
+
node_settings = Object.assign(node_settings, smart_context.get(node.id, config.config_change_date));
|
|
37
38
|
else
|
|
38
39
|
smart_context.del(node.id);
|
|
39
40
|
|
package/counter/counter.html
CHANGED
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
out_message: { value: '{"topic": ""}' },
|
|
13
13
|
out_message_type: { value: 'json' },
|
|
14
14
|
save_state: { value: false },
|
|
15
|
-
resend_on_start: { value: false }
|
|
15
|
+
resend_on_start: { value: false },
|
|
16
|
+
config_change_date: { value: "" },
|
|
16
17
|
},
|
|
17
18
|
inputs: 1,
|
|
18
19
|
outputs: 1,
|
|
@@ -98,7 +99,12 @@
|
|
|
98
99
|
this.out_message_type = "NOTHING";
|
|
99
100
|
$("#node-input-out_message_type").val("NOTHING");
|
|
100
101
|
}
|
|
101
|
-
}
|
|
102
|
+
},
|
|
103
|
+
oneditsave: function ()
|
|
104
|
+
{
|
|
105
|
+
let node = this;
|
|
106
|
+
node.config_change_date = (new Date()).toISOString();
|
|
107
|
+
},
|
|
102
108
|
});
|
|
103
109
|
</script>
|
|
104
110
|
|
package/counter/counter.js
CHANGED
|
@@ -24,11 +24,12 @@ module.exports = function (RED)
|
|
|
24
24
|
var node_settings = {
|
|
25
25
|
value: null,
|
|
26
26
|
last_message: null,
|
|
27
|
+
config_change_date: config.config_change_date,
|
|
27
28
|
};
|
|
28
29
|
|
|
29
30
|
// load or delete saved values
|
|
30
31
|
if (config.save_state)
|
|
31
|
-
node_settings = Object.assign(node_settings, smart_context.get(node.id));
|
|
32
|
+
node_settings = Object.assign(node_settings, smart_context.get(node.id, config.config_change_date));
|
|
32
33
|
else
|
|
33
34
|
smart_context.del(node.id);
|
|
34
35
|
|
package/delay/delay.html
CHANGED
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
off_delay_unit: { value: "s" },
|
|
12
12
|
delay_only_on_change: { value: true },
|
|
13
13
|
save_state: { value: false },
|
|
14
|
-
resend_on_start: { value: false }
|
|
14
|
+
resend_on_start: { value: false },
|
|
15
|
+
config_change_date: { value: "" },
|
|
15
16
|
},
|
|
16
17
|
inputs: 1,
|
|
17
18
|
outputs: 1,
|
|
@@ -93,6 +94,11 @@
|
|
|
93
94
|
});
|
|
94
95
|
$("#node-input-save_state").trigger("change");
|
|
95
96
|
},
|
|
97
|
+
oneditsave: function ()
|
|
98
|
+
{
|
|
99
|
+
let node = this;
|
|
100
|
+
node.config_change_date = (new Date()).toISOString();
|
|
101
|
+
},
|
|
96
102
|
});
|
|
97
103
|
</script>
|
|
98
104
|
|
package/delay/delay.js
CHANGED
|
@@ -29,12 +29,13 @@ module.exports = function (RED)
|
|
|
29
29
|
on_delay_ms: helper.getTimeInMs(config.on_delay, config.on_delay_unit),
|
|
30
30
|
off_delay_ms: helper.getTimeInMs(config.off_delay, config.off_delay_unit),
|
|
31
31
|
last_message: null,
|
|
32
|
+
config_change_date: config.config_change_date,
|
|
32
33
|
};
|
|
33
34
|
|
|
34
35
|
if (config.save_state)
|
|
35
36
|
{
|
|
36
37
|
// load old saved values
|
|
37
|
-
node_settings = Object.assign(node_settings, smart_context.get(node.id));
|
|
38
|
+
node_settings = Object.assign(node_settings, smart_context.get(node.id, config.config_change_date));
|
|
38
39
|
|
|
39
40
|
switch (node_settings.last_message?.payload)
|
|
40
41
|
{
|
package/forwarder/forwarder.html
CHANGED
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
always_forward_false: { value: false },
|
|
11
11
|
forward_last_on_enable: { value: false },
|
|
12
12
|
save_state: { value: false },
|
|
13
|
-
resend_on_start: { value: false }
|
|
13
|
+
resend_on_start: { value: false },
|
|
14
|
+
config_change_date: { value: "" },
|
|
14
15
|
},
|
|
15
16
|
inputs: 1,
|
|
16
17
|
outputs: 1,
|
|
@@ -32,6 +33,11 @@
|
|
|
32
33
|
});
|
|
33
34
|
$("#node-input-save_state").trigger("change");
|
|
34
35
|
},
|
|
36
|
+
oneditsave: function ()
|
|
37
|
+
{
|
|
38
|
+
let node = this;
|
|
39
|
+
node.config_change_date = (new Date()).toISOString();
|
|
40
|
+
},
|
|
35
41
|
});
|
|
36
42
|
</script>
|
|
37
43
|
|
package/forwarder/forwarder.js
CHANGED
|
@@ -26,12 +26,13 @@ module.exports = function (RED)
|
|
|
26
26
|
var node_settings = {
|
|
27
27
|
enabled: config.enabled,
|
|
28
28
|
last_message: null,
|
|
29
|
-
last_msg_was_sended: true
|
|
29
|
+
last_msg_was_sended: true,
|
|
30
|
+
config_change_date: config.config_change_date,
|
|
30
31
|
};
|
|
31
32
|
|
|
32
33
|
// load or delete saved values
|
|
33
34
|
if (config.save_state)
|
|
34
|
-
node_settings = Object.assign(node_settings, smart_context.get(node.id));
|
|
35
|
+
node_settings = Object.assign(node_settings, smart_context.get(node.id, config.config_change_date));
|
|
35
36
|
else
|
|
36
37
|
smart_context.del(node.id);
|
|
37
38
|
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
offset: { value: 0 },
|
|
13
13
|
flow_max: { value: 75 },
|
|
14
14
|
flow_min: { value: 20 },
|
|
15
|
+
config_change_date: { value: "" },
|
|
15
16
|
},
|
|
16
17
|
inputs: 1,
|
|
17
18
|
outputs: 1,
|
|
@@ -109,6 +110,11 @@
|
|
|
109
110
|
drawCanvas();
|
|
110
111
|
|
|
111
112
|
},
|
|
113
|
+
oneditsave: function ()
|
|
114
|
+
{
|
|
115
|
+
let node = this;
|
|
116
|
+
node.config_change_date = (new Date()).toISOString();
|
|
117
|
+
},
|
|
112
118
|
});
|
|
113
119
|
|
|
114
120
|
let drawCanvas = () =>
|
|
@@ -27,8 +27,9 @@ module.exports = function (RED)
|
|
|
27
27
|
flow_min: config.flow_min,
|
|
28
28
|
flow_max: config.flow_max,
|
|
29
29
|
temperature_outside: 10,
|
|
30
|
-
last_flow_temperature: null
|
|
31
|
-
|
|
30
|
+
last_flow_temperature: null,
|
|
31
|
+
config_change_date: config.config_change_date,
|
|
32
|
+
}, smart_context.get(node.id, config.config_change_date));
|
|
32
33
|
|
|
33
34
|
|
|
34
35
|
// ##################
|
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
send_only_change: { value: true },
|
|
18
18
|
outputs: { value: 1 },
|
|
19
19
|
save_state: { value: false },
|
|
20
|
-
resend_on_start: { value: false }
|
|
20
|
+
resend_on_start: { value: false },
|
|
21
|
+
config_change_date: { value: "" },
|
|
21
22
|
},
|
|
22
23
|
inputs: 1,
|
|
23
24
|
outputs: 2,
|
|
@@ -196,11 +197,13 @@
|
|
|
196
197
|
{
|
|
197
198
|
let node = this;
|
|
198
199
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
200
|
+
node.setpoint = parseFloat(node.setpoint ?? 10);
|
|
201
|
+
node.hysteresis = parseFloat(node.hysteresis ?? 1);
|
|
202
|
+
node.min = parseFloat(node.min ?? 10);
|
|
203
|
+
node.max = parseFloat(node.max ?? 20);
|
|
204
|
+
|
|
205
|
+
node.config_change_date = (new Date()).toISOString();
|
|
206
|
+
},
|
|
204
207
|
});
|
|
205
208
|
</script>
|
|
206
209
|
|
package/hysteresis/hysteresis.js
CHANGED
|
@@ -30,13 +30,14 @@ module.exports = function (RED)
|
|
|
30
30
|
setpoint: parseFloat(config.setpoint ?? 10),
|
|
31
31
|
hysteresis: parseFloat(config.hysteresis ?? 1),
|
|
32
32
|
min: parseFloat(config.min ?? 10),
|
|
33
|
-
max: parseFloat(config.max ?? 20)
|
|
33
|
+
max: parseFloat(config.max ?? 20),
|
|
34
|
+
config_change_date: config.config_change_date,
|
|
34
35
|
};
|
|
35
36
|
|
|
36
37
|
if (config.save_state)
|
|
37
38
|
{
|
|
38
39
|
// load old saved values
|
|
39
|
-
node_settings = Object.assign(node_settings, smart_context.get(node.id));
|
|
40
|
+
node_settings = Object.assign(node_settings, smart_context.get(node.id, config.config_change_date));
|
|
40
41
|
|
|
41
42
|
switch (node_settings.last_result)
|
|
42
43
|
{
|
package/light/light.html
CHANGED
|
@@ -144,7 +144,8 @@
|
|
|
144
144
|
max_time_on_unit: { value: "s" },
|
|
145
145
|
alarm_action: { value: 'NOTHING' }, // NOTHING | ON | OFF
|
|
146
146
|
alarm_off_action: { value: 'NOTHING' }, // NOTHING | ON | OFF | LAST | LAST_SENDED
|
|
147
|
-
links: { value: [], type: "smart_central-control[]" }
|
|
147
|
+
links: { value: [], type: "smart_central-control[]" },
|
|
148
|
+
config_change_date: { value: "" },
|
|
148
149
|
},
|
|
149
150
|
inputs: 1,
|
|
150
151
|
outputs: 1,
|
|
@@ -236,6 +237,11 @@
|
|
|
236
237
|
{
|
|
237
238
|
this.links = [];
|
|
238
239
|
},
|
|
240
|
+
oneditsave: function ()
|
|
241
|
+
{
|
|
242
|
+
let node = this;
|
|
243
|
+
node.config_change_date = (new Date()).toISOString();
|
|
244
|
+
},
|
|
239
245
|
oneditresize: resizeNodeList
|
|
240
246
|
});
|
|
241
247
|
})();
|
package/light/light.js
CHANGED
|
@@ -36,7 +36,8 @@ module.exports = function (RED)
|
|
|
36
36
|
last_value_before_alarm: false,
|
|
37
37
|
last_value_sended: false,
|
|
38
38
|
alarm_active: false,
|
|
39
|
-
|
|
39
|
+
config_change_date: config.config_change_date,
|
|
40
|
+
}, smart_context.get(node.id, config.config_change_date));
|
|
40
41
|
|
|
41
42
|
|
|
42
43
|
// ##################
|
package/logic/logic.html
CHANGED
|
@@ -16,7 +16,8 @@
|
|
|
16
16
|
send_only_change: { value: true },
|
|
17
17
|
outputs: { value: 1 },
|
|
18
18
|
save_state: { value: false },
|
|
19
|
-
resend_on_start: { value: false }
|
|
19
|
+
resend_on_start: { value: false },
|
|
20
|
+
config_change_date: { value: "" },
|
|
20
21
|
},
|
|
21
22
|
inputs: 1,
|
|
22
23
|
outputs: 1,
|
|
@@ -139,7 +140,12 @@
|
|
|
139
140
|
$("#resend_on_start_row").hide();
|
|
140
141
|
});
|
|
141
142
|
$("#node-input-save_state").trigger("change");
|
|
142
|
-
}
|
|
143
|
+
},
|
|
144
|
+
oneditsave: function ()
|
|
145
|
+
{
|
|
146
|
+
let node = this;
|
|
147
|
+
node.config_change_date = (new Date()).toISOString();
|
|
148
|
+
},
|
|
143
149
|
});
|
|
144
150
|
|
|
145
151
|
let refreshInverts = inputs =>
|
package/logic/logic.js
CHANGED
|
@@ -26,12 +26,13 @@ module.exports = function (RED)
|
|
|
26
26
|
input_states: Array.from({ length: config.logic_inputs }).fill(false),
|
|
27
27
|
last_result: null,
|
|
28
28
|
last_message: null,
|
|
29
|
+
config_change_date: config.config_change_date,
|
|
29
30
|
};
|
|
30
31
|
|
|
31
32
|
|
|
32
33
|
// load or delete saved values
|
|
33
34
|
if (config.save_state)
|
|
34
|
-
node_settings = Object.assign(node_settings, smart_context.get(node.id));
|
|
35
|
+
node_settings = Object.assign(node_settings, smart_context.get(node.id, config.config_change_date));
|
|
35
36
|
else
|
|
36
37
|
smart_context.del(node.id);
|
|
37
38
|
|
|
@@ -152,6 +152,7 @@
|
|
|
152
152
|
min_change_time: { value: 100 },
|
|
153
153
|
links: { value: [], type: "smart_central-control[]" },
|
|
154
154
|
alarm_action: { value: "NOTHING" }, // NOTHING | OPEN | CLOSE
|
|
155
|
+
config_change_date: { value: "" },
|
|
155
156
|
},
|
|
156
157
|
inputs: 1,
|
|
157
158
|
outputs: 1,
|
|
@@ -267,7 +268,7 @@
|
|
|
267
268
|
],
|
|
268
269
|
}],
|
|
269
270
|
});
|
|
270
|
-
|
|
271
|
+
|
|
271
272
|
$("#node-input-alarm_action")
|
|
272
273
|
.css("max-width", "70%")
|
|
273
274
|
.typedInput({
|
|
@@ -302,7 +303,7 @@
|
|
|
302
303
|
.css("max-width", "4rem")
|
|
303
304
|
.spinner({
|
|
304
305
|
min: 1,
|
|
305
|
-
max:
|
|
306
|
+
max: 100,
|
|
306
307
|
change: function (event, ui)
|
|
307
308
|
{
|
|
308
309
|
var value = parseInt(this.value);
|
|
@@ -317,7 +318,7 @@
|
|
|
317
318
|
.css("max-width", "4rem")
|
|
318
319
|
.spinner({
|
|
319
320
|
min: 1,
|
|
320
|
-
max:
|
|
321
|
+
max: 100,
|
|
321
322
|
change: function (event, ui)
|
|
322
323
|
{
|
|
323
324
|
var value = parseInt(this.value);
|
|
@@ -332,7 +333,7 @@
|
|
|
332
333
|
.css("max-width", "4rem")
|
|
333
334
|
.spinner({
|
|
334
335
|
min: 0,
|
|
335
|
-
max:
|
|
336
|
+
max: 10000,
|
|
336
337
|
step: 100,
|
|
337
338
|
change: function (event, ui)
|
|
338
339
|
{
|
|
@@ -348,6 +349,11 @@
|
|
|
348
349
|
{
|
|
349
350
|
this.links = [];
|
|
350
351
|
},
|
|
352
|
+
oneditsave: function ()
|
|
353
|
+
{
|
|
354
|
+
let node = this;
|
|
355
|
+
node.config_change_date = (new Date()).toISOString();
|
|
356
|
+
},
|
|
351
357
|
oneditresize: resizeNodeList
|
|
352
358
|
});
|
|
353
359
|
})();
|
|
@@ -33,10 +33,12 @@ module.exports = function (RED)
|
|
|
33
33
|
setpoint: config.setpoint,
|
|
34
34
|
off_mode: config.off_mode,
|
|
35
35
|
valve_mode: config.valve_mode,
|
|
36
|
+
current_temperature: null,
|
|
36
37
|
last_position: null,
|
|
37
38
|
last_enabled_sended: null,
|
|
38
|
-
alarm_active: false
|
|
39
|
-
|
|
39
|
+
alarm_active: false,
|
|
40
|
+
config_change_date: config.config_change_date,
|
|
41
|
+
}, smart_context.get(node.id, config.config_change_date));
|
|
40
42
|
|
|
41
43
|
// Ensure correct types
|
|
42
44
|
node_settings.enabled = !!node_settings.enabled;
|
|
@@ -59,11 +61,6 @@ module.exports = function (RED)
|
|
|
59
61
|
let output_mode = config.output_mode || OUTPUT_MODE_OPEN_CLOSE;
|
|
60
62
|
let force_position = null;
|
|
61
63
|
let alarm_action = config.alarm_action || "NOTHING"; // NOTHING | OPEN | CLOSE
|
|
62
|
-
let min_temperature = null;
|
|
63
|
-
let min_temperature_position = null;
|
|
64
|
-
let max_temperature = null;
|
|
65
|
-
let max_temperature_position = null;
|
|
66
|
-
let temp_save_date = Date.now();
|
|
67
64
|
let precision = parseInt(config.precision || 1, 10);
|
|
68
65
|
let max_change_percent = parseInt(config.max_change_percent || 2, 10);
|
|
69
66
|
let max_change_temp_difference = parseInt(config.max_change_temp_difference || 20, 10);
|
|
@@ -86,9 +83,6 @@ module.exports = function (RED)
|
|
|
86
83
|
// Store the direction of the adjustment
|
|
87
84
|
let adjusting = null;
|
|
88
85
|
|
|
89
|
-
// Stores the current temperature which is used to determine the adjusting direction
|
|
90
|
-
let current_temperature = null;
|
|
91
|
-
|
|
92
86
|
// The start time of the adjustment to count the change
|
|
93
87
|
let adjusting_start_time = null;
|
|
94
88
|
|
|
@@ -112,7 +106,6 @@ module.exports = function (RED)
|
|
|
112
106
|
handleTopic(msg);
|
|
113
107
|
|
|
114
108
|
setStatus();
|
|
115
|
-
resetSavedTemperatures();
|
|
116
109
|
smart_context.set(node.id, node_settings);
|
|
117
110
|
});
|
|
118
111
|
|
|
@@ -179,16 +172,16 @@ module.exports = function (RED)
|
|
|
179
172
|
current_mode: calibration_timeout !== null ? "CALIBRATION" : (changing_timeout !== null ? (adjusting == ADJUST_OPEN ? "OPENING" : "CLOSING") : "IDLE"),
|
|
180
173
|
enabled: (node_settings.enabled ? "ENABLED" : "DISABLED"),
|
|
181
174
|
heating_mode: node_settings.valve_mode,
|
|
182
|
-
current_temperature,
|
|
175
|
+
current_temperature: node_settings.current_temperature,
|
|
183
176
|
output_mode,
|
|
184
177
|
precision,
|
|
185
178
|
max_change_percent,
|
|
186
179
|
max_change_temp_difference,
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
180
|
+
sampling_interval,
|
|
181
|
+
calibration_timeout,
|
|
182
|
+
changing_timeout,
|
|
183
|
+
adjusting,
|
|
184
|
+
adjusting_start_time,
|
|
192
185
|
});
|
|
193
186
|
break;
|
|
194
187
|
|
|
@@ -207,41 +200,6 @@ module.exports = function (RED)
|
|
|
207
200
|
return;
|
|
208
201
|
|
|
209
202
|
stopChanging();
|
|
210
|
-
|
|
211
|
-
// Set the most probable position
|
|
212
|
-
if (
|
|
213
|
-
min_temperature !== null &&
|
|
214
|
-
max_temperature !== null &&
|
|
215
|
-
min_temperature_position !== null &&
|
|
216
|
-
max_temperature_position !== null
|
|
217
|
-
)
|
|
218
|
-
{
|
|
219
|
-
let temp_range = max_temperature - min_temperature;
|
|
220
|
-
let pos_range = max_temperature_position - min_temperature_position;
|
|
221
|
-
|
|
222
|
-
if (
|
|
223
|
-
temp_range > 0 &&
|
|
224
|
-
pos_range !== 0 &&
|
|
225
|
-
node_settings.setpoint >= min_temperature &&
|
|
226
|
-
node_settings.setpoint <= max_temperature
|
|
227
|
-
)
|
|
228
|
-
{
|
|
229
|
-
let rel_pos;
|
|
230
|
-
if (node_settings.valve_mode === "HEATING")
|
|
231
|
-
{
|
|
232
|
-
// For HEATING, min_temperature_position is closed, max_temperature_position is open
|
|
233
|
-
rel_pos = min_temperature_position + ((node_settings.setpoint - min_temperature) / temp_range) * pos_range;
|
|
234
|
-
}
|
|
235
|
-
else
|
|
236
|
-
{
|
|
237
|
-
// For COOLING, max_temperature_position is closed, min_temperature_position is open
|
|
238
|
-
rel_pos = max_temperature_position + ((node_settings.setpoint - max_temperature) / -temp_range) * pos_range;
|
|
239
|
-
}
|
|
240
|
-
force_position = Math.min(Math.max(rel_pos, 0), 100);
|
|
241
|
-
helper.log(node, "Set force position to " + force_position.toFixed(1) + "% based on previous min/max temperature positions");
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
|
|
245
203
|
startSampling();
|
|
246
204
|
break;
|
|
247
205
|
|
|
@@ -294,16 +252,6 @@ module.exports = function (RED)
|
|
|
294
252
|
{
|
|
295
253
|
case "HEATING":
|
|
296
254
|
case "COOLING":
|
|
297
|
-
|
|
298
|
-
if (node_settings.valve_mode != msg.payload)
|
|
299
|
-
{
|
|
300
|
-
// When changing the mode, reset min/max temperature
|
|
301
|
-
min_temperature = null;
|
|
302
|
-
max_temperature = null;
|
|
303
|
-
min_temperature_position = null;
|
|
304
|
-
max_temperature_position = null;
|
|
305
|
-
}
|
|
306
|
-
|
|
307
255
|
node_settings.valve_mode = msg.payload;
|
|
308
256
|
setStatus();
|
|
309
257
|
break;
|
|
@@ -312,18 +260,16 @@ module.exports = function (RED)
|
|
|
312
260
|
helper.warn(this, "Invalid valve_mode: " + msg.payload);
|
|
313
261
|
return;
|
|
314
262
|
}
|
|
315
|
-
|
|
316
|
-
startSampling();
|
|
317
263
|
break;
|
|
318
264
|
|
|
319
265
|
case "current_temperature":
|
|
320
266
|
let new_temp = parseFloat(msg.payload);
|
|
321
267
|
if (isNaN(new_temp) || !isFinite(new_temp))
|
|
322
268
|
{
|
|
323
|
-
// helper.warn(this, "Invalid payload for current_temperature: " + msg.payload);
|
|
269
|
+
// helper.warn(this, "Invalid payload for node_settings.current_temperature: " + msg.payload);
|
|
324
270
|
return;
|
|
325
271
|
}
|
|
326
|
-
current_temperature = new_temp;
|
|
272
|
+
node_settings.current_temperature = new_temp;
|
|
327
273
|
break;
|
|
328
274
|
|
|
329
275
|
case "calibrate":
|
|
@@ -344,7 +290,7 @@ module.exports = function (RED)
|
|
|
344
290
|
switch (alarm_action)
|
|
345
291
|
{
|
|
346
292
|
case "OPEN":
|
|
347
|
-
force_position = 100
|
|
293
|
+
force_position = 100;
|
|
348
294
|
break;
|
|
349
295
|
|
|
350
296
|
case "CLOSE":
|
|
@@ -467,10 +413,10 @@ module.exports = function (RED)
|
|
|
467
413
|
let sample = () =>
|
|
468
414
|
{
|
|
469
415
|
// No current temperature available or in calibration => no action
|
|
470
|
-
if (current_temperature === null || calibration_timeout !== null || !node_settings.enabled)
|
|
416
|
+
if (node_settings.current_temperature === null || calibration_timeout !== null || !node_settings.enabled)
|
|
471
417
|
{
|
|
472
418
|
helper.log(node, "No sample possible", {
|
|
473
|
-
current_temperature,
|
|
419
|
+
current_temperature: node_settings.current_temperature,
|
|
474
420
|
calibration_timeout,
|
|
475
421
|
enabled: node_settings.enabled
|
|
476
422
|
});
|
|
@@ -478,27 +424,9 @@ module.exports = function (RED)
|
|
|
478
424
|
}
|
|
479
425
|
|
|
480
426
|
// +/- 1°C => already good enough, do nothing
|
|
481
|
-
let temp_diff = Math.abs(current_temperature - node_settings.setpoint);
|
|
427
|
+
let temp_diff = Math.abs(node_settings.current_temperature - node_settings.setpoint);
|
|
482
428
|
if (temp_diff < precision)
|
|
483
|
-
{
|
|
484
|
-
if (!node_settings.alarm_active)
|
|
485
|
-
{
|
|
486
|
-
// Found a good position for the current setpoint
|
|
487
|
-
// Update min/max temperature
|
|
488
|
-
if (min_temperature === null || current_temperature < min_temperature)
|
|
489
|
-
{
|
|
490
|
-
min_temperature = current_temperature;
|
|
491
|
-
min_temperature_position = node_settings.last_position;
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
if (max_temperature === null || current_temperature > max_temperature)
|
|
495
|
-
{
|
|
496
|
-
max_temperature = current_temperature;
|
|
497
|
-
max_temperature_position = node_settings.last_position;
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
429
|
return;
|
|
501
|
-
}
|
|
502
430
|
|
|
503
431
|
// 0 °C diff => 0% change
|
|
504
432
|
// for max_change_temp_difference (default: 20 °C) diff => max_change_percent (default: 2%) change
|
|
@@ -512,7 +440,7 @@ module.exports = function (RED)
|
|
|
512
440
|
|
|
513
441
|
// calculate direction
|
|
514
442
|
let adjustAction = ADJUST_CLOSE;
|
|
515
|
-
if (current_temperature < node_settings.setpoint)
|
|
443
|
+
if (node_settings.current_temperature < node_settings.setpoint)
|
|
516
444
|
{
|
|
517
445
|
if (node_settings.valve_mode == "HEATING")
|
|
518
446
|
adjustAction = ADJUST_OPEN;
|
|
@@ -705,29 +633,14 @@ module.exports = function (RED)
|
|
|
705
633
|
}
|
|
706
634
|
}
|
|
707
635
|
|
|
708
|
-
let resetSavedTemperatures = () =>
|
|
709
|
-
{
|
|
710
|
-
let now = Date.now();
|
|
711
|
-
|
|
712
|
-
// Reset saved temperatures after 7 days, to avoid using too old data
|
|
713
|
-
if (now - temp_save_date >= 7 * 24 * 60 * 60 * 1000)
|
|
714
|
-
{
|
|
715
|
-
temp_save_date = now;
|
|
716
|
-
min_temperature = null;
|
|
717
|
-
min_temperature_position = null;
|
|
718
|
-
max_temperature = null;
|
|
719
|
-
max_temperature_position = null;
|
|
720
|
-
}
|
|
721
|
-
}
|
|
722
|
-
|
|
723
636
|
let setStatus = () =>
|
|
724
637
|
{
|
|
725
638
|
if (calibration_timeout !== null)
|
|
726
639
|
node.status({ fill: "yellow", shape: "ring", text: helper.getCurrentTimeForStatus() + ": In calibration" });
|
|
727
640
|
else if (changing_timeout != null)
|
|
728
|
-
node.status({ fill: node_settings.enabled ? "green" : "red", shape: "ring", text: helper.getCurrentTimeForStatus() + ": " + (node_settings.alarm_active ? "ALARM - " : "") + (node_settings.valve_mode == "HEATING" ? "🔥" : "❄️") + " " + (adjusting == ADJUST_OPEN ? "Opening" : "Closing") + ", Set: " + helper.toFixed(node_settings.setpoint, 1) + "°C, Cur: " + helper.toFixed(current_temperature, 1) + "°C, Pos: " + helper.toFixed(node_settings.last_position, 1) + "%" });
|
|
641
|
+
node.status({ fill: node_settings.enabled ? "green" : "red", shape: "ring", text: helper.getCurrentTimeForStatus() + ": " + (node_settings.alarm_active ? "ALARM - " : "") + (node_settings.valve_mode == "HEATING" ? "🔥" : "❄️") + " " + (adjusting == ADJUST_OPEN ? "Opening" : "Closing") + ", Set: " + helper.toFixed(node_settings.setpoint, 1) + "°C, Cur: " + helper.toFixed(node_settings.current_temperature, 1) + "°C, Pos: " + helper.toFixed(node_settings.last_position, 1) + "%" });
|
|
729
642
|
else
|
|
730
|
-
node.status({ fill: node_settings.enabled ? "green" : "red", shape: "dot", text: helper.getCurrentTimeForStatus() + ": " + (node_settings.alarm_active ? "ALARM - " : "") + (node_settings.valve_mode == "HEATING" ? "🔥" : "❄️") + " Set: " + helper.toFixed(node_settings.setpoint, 1) + "°C, Cur: " + helper.toFixed(current_temperature, 1) + "°C, Pos: " + helper.toFixed(node_settings.last_position, 1) + "%" });
|
|
643
|
+
node.status({ fill: node_settings.enabled ? "green" : "red", shape: "dot", text: helper.getCurrentTimeForStatus() + ": " + (node_settings.alarm_active ? "ALARM - " : "") + (node_settings.valve_mode == "HEATING" ? "🔥" : "❄️") + " Set: " + helper.toFixed(node_settings.setpoint, 1) + "°C, Cur: " + helper.toFixed(node_settings.current_temperature, 1) + "°C, Pos: " + helper.toFixed(node_settings.last_position, 1) + "%" });
|
|
731
644
|
}
|
|
732
645
|
|
|
733
646
|
/**
|
|
@@ -749,22 +662,14 @@ module.exports = function (RED)
|
|
|
749
662
|
|
|
750
663
|
if (node_settings.last_position === null)
|
|
751
664
|
{
|
|
752
|
-
|
|
753
|
-
{
|
|
754
|
-
// Start calibration after 10s
|
|
755
|
-
setTimeout(calibrate, 10 * 1000);
|
|
756
|
-
}
|
|
757
|
-
else
|
|
758
|
-
{
|
|
759
|
-
node_settings.last_position = 0;
|
|
760
|
-
}
|
|
665
|
+
node_settings.last_position = 50;
|
|
761
666
|
}
|
|
762
667
|
else if (node_settings.alarm_active)
|
|
763
668
|
{
|
|
764
669
|
switch (alarm_action)
|
|
765
670
|
{
|
|
766
671
|
case "OPEN":
|
|
767
|
-
force_position = 100
|
|
672
|
+
force_position = 100;
|
|
768
673
|
break;
|
|
769
674
|
|
|
770
675
|
case "CLOSE":
|
|
@@ -41,7 +41,8 @@
|
|
|
41
41
|
outputs: { value: 1 },
|
|
42
42
|
mode_items: { value: ["MODE1", "MODE2"] },
|
|
43
43
|
update_only_changed_outputs: { value: true },
|
|
44
|
-
resend_on_start: { value: false }
|
|
44
|
+
resend_on_start: { value: false },
|
|
45
|
+
config_change_date: { value: "" },
|
|
45
46
|
},
|
|
46
47
|
inputs: 1,
|
|
47
48
|
outputs: 1,
|
|
@@ -125,8 +126,10 @@
|
|
|
125
126
|
// Set modes
|
|
126
127
|
var items = $("#node-input-property-modes").editableList("items");
|
|
127
128
|
var result = getModes(items);
|
|
128
|
-
|
|
129
|
-
|
|
129
|
+
node.mode_items = result.modes;
|
|
130
|
+
node.outputs = node.mode_items.length;
|
|
131
|
+
|
|
132
|
+
node.config_change_date = (new Date()).toISOString();
|
|
130
133
|
},
|
|
131
134
|
oneditresize: resizeDialog
|
|
132
135
|
});
|
|
@@ -25,7 +25,8 @@ module.exports = function (RED)
|
|
|
25
25
|
// #####################
|
|
26
26
|
var node_settings = helper.cloneObject({
|
|
27
27
|
last_mode: null,
|
|
28
|
-
|
|
28
|
+
config_change_date: config.config_change_date,
|
|
29
|
+
}, smart_context.get(node.id, config.config_change_date));
|
|
29
30
|
|
|
30
31
|
|
|
31
32
|
// ##################
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "smart-nodes",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.2",
|
|
4
4
|
"description": "Controls light, shutters and more. Includes common used logic and statistic nodes to control your home.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"node-red",
|
|
@@ -48,11 +48,11 @@
|
|
|
48
48
|
"hysteresis": "hysteresis/hysteresis.js",
|
|
49
49
|
"statistic": "statistic/statistic.js",
|
|
50
50
|
"counter": "counter/counter.js",
|
|
51
|
+
"mode-selector": "mode-selector/mode-selector.js",
|
|
51
52
|
"scheduler": "scheduler/scheduler.js",
|
|
52
53
|
"delay": "delay/delay.js",
|
|
53
54
|
"central": "central/central.js",
|
|
54
55
|
"mixing-valve": "mixing-valve/mixing-valve.js",
|
|
55
|
-
"mode-selector": "mode-selector/mode-selector.js",
|
|
56
56
|
"heating-curve": "heating-curve/heating-curve.js",
|
|
57
57
|
"text-exec": "text-exec/text-exec.js"
|
|
58
58
|
}
|
package/persistence.js
CHANGED
|
@@ -21,6 +21,8 @@ module.exports = function (_RED)
|
|
|
21
21
|
const userDir = (_RED.settings && _RED.settings.userDir) ? _RED.settings.userDir : process.cwd();
|
|
22
22
|
const filePath = pathLib.join(userDir, 'SmartNodesContext.json');
|
|
23
23
|
|
|
24
|
+
// console.log(filePath);
|
|
25
|
+
|
|
24
26
|
let globalData = {};
|
|
25
27
|
|
|
26
28
|
if (fs.existsSync(filePath))
|
|
@@ -39,13 +41,13 @@ module.exports = function (_RED)
|
|
|
39
41
|
}
|
|
40
42
|
}
|
|
41
43
|
|
|
42
|
-
// Autosave each
|
|
44
|
+
// Autosave each 15 seconds if changes exists.
|
|
43
45
|
let interval = setInterval(() =>
|
|
44
46
|
{
|
|
45
47
|
if (hasChanges)
|
|
46
48
|
save();
|
|
47
49
|
|
|
48
|
-
},
|
|
50
|
+
}, 15 * 1000);
|
|
49
51
|
|
|
50
52
|
// Prevent the interval from keeping the process alive (important for Jest)
|
|
51
53
|
if (interval && typeof interval.unref === "function")
|
|
@@ -80,9 +82,25 @@ module.exports = function (_RED)
|
|
|
80
82
|
save();
|
|
81
83
|
}
|
|
82
84
|
|
|
83
|
-
function get(id)
|
|
85
|
+
function get(id, config_change_date)
|
|
84
86
|
{
|
|
85
|
-
|
|
87
|
+
let data = globalData["id" + id];
|
|
88
|
+
if (id == "7e5e332f362a43fb")
|
|
89
|
+
{
|
|
90
|
+
log({
|
|
91
|
+
old_config_change_date: data.config_change_date,
|
|
92
|
+
new_config_change_date: config_change_date
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (data && data.config_change_date && data.config_change_date !== config_change_date)
|
|
97
|
+
{
|
|
98
|
+
console.log("id = " + id + " - config change date mismatch, ignoring stored data.");
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
return data;
|
|
86
104
|
}
|
|
87
105
|
|
|
88
106
|
function del(id)
|
package/scene/scene.html
CHANGED
|
@@ -226,7 +226,8 @@
|
|
|
226
226
|
scenes: {
|
|
227
227
|
value: [{ name: "", outputs: "" }],
|
|
228
228
|
},
|
|
229
|
-
links: { value: [], type: "smart_central-control[]" }
|
|
229
|
+
links: { value: [], type: "smart_central-control[]" },
|
|
230
|
+
config_change_date: { value: "" },
|
|
230
231
|
},
|
|
231
232
|
inputs: 1,
|
|
232
233
|
outputs: 1,
|
|
@@ -427,13 +428,15 @@
|
|
|
427
428
|
// Set scenes
|
|
428
429
|
var items = $("#node-input-property-scenes").editableList("items");
|
|
429
430
|
var result = getScenes(items);
|
|
430
|
-
|
|
431
|
+
node.scenes = result.scenes;
|
|
431
432
|
|
|
432
433
|
// Set outputs
|
|
433
434
|
var items = $("#node-input-property-outputs").editableList("items");
|
|
434
435
|
var result = getOutputs(items);
|
|
435
|
-
|
|
436
|
-
|
|
436
|
+
node.output_items = result.output_items;
|
|
437
|
+
node.outputs = node.output_items.length;
|
|
438
|
+
|
|
439
|
+
node.config_change_date = (new Date()).toISOString();
|
|
437
440
|
},
|
|
438
441
|
onadd: function ()
|
|
439
442
|
{
|
package/scene/scene.js
CHANGED
|
@@ -34,7 +34,8 @@ module.exports = function (RED)
|
|
|
34
34
|
// #####################
|
|
35
35
|
var node_settings = helper.cloneObject({
|
|
36
36
|
last_values: [], // light is on or off for a scene
|
|
37
|
-
|
|
37
|
+
config_change_date: config.config_change_date,
|
|
38
|
+
}, smart_context.get(node.id, config.config_change_date));
|
|
38
39
|
|
|
39
40
|
|
|
40
41
|
// ##################
|
package/scheduler/scheduler.html
CHANGED
|
@@ -100,7 +100,8 @@
|
|
|
100
100
|
},
|
|
101
101
|
},
|
|
102
102
|
save_state: { value: false },
|
|
103
|
-
resend_on_start: { value: false }
|
|
103
|
+
resend_on_start: { value: false },
|
|
104
|
+
config_change_date: { value: "" },
|
|
104
105
|
},
|
|
105
106
|
inputs: 1,
|
|
106
107
|
outputs: 1,
|
|
@@ -266,7 +267,6 @@
|
|
|
266
267
|
return s;
|
|
267
268
|
}
|
|
268
269
|
},
|
|
269
|
-
|
|
270
270
|
oneditsave: function ()
|
|
271
271
|
{
|
|
272
272
|
let node = this;
|
|
@@ -298,6 +298,8 @@
|
|
|
298
298
|
node.schedules.push(schedule);
|
|
299
299
|
}
|
|
300
300
|
});
|
|
301
|
+
|
|
302
|
+
node.config_change_date = (new Date()).toISOString();
|
|
301
303
|
},
|
|
302
304
|
});
|
|
303
305
|
</script>
|
package/scheduler/scheduler.js
CHANGED
|
@@ -26,12 +26,13 @@ module.exports = function (RED)
|
|
|
26
26
|
var node_settings = {
|
|
27
27
|
enabled: config.enabled,
|
|
28
28
|
last_message: null,
|
|
29
|
+
config_change_date: config.config_change_date,
|
|
29
30
|
};
|
|
30
31
|
|
|
31
32
|
|
|
32
33
|
// load or delete saved values
|
|
33
34
|
if (config.save_state)
|
|
34
|
-
node_settings = Object.assign(node_settings, smart_context.get(node.id));
|
|
35
|
+
node_settings = Object.assign(node_settings, smart_context.get(node.id, config.config_change_date));
|
|
35
36
|
else
|
|
36
37
|
smart_context.del(node.id);
|
|
37
38
|
|
package/shutter/shutter.html
CHANGED
|
@@ -140,7 +140,8 @@
|
|
|
140
140
|
name: { value: "" },
|
|
141
141
|
exec_text_names: { value: "" },
|
|
142
142
|
short_time_on_ms: { value: 200 },
|
|
143
|
-
links: { value: [], type: "smart_central-control[]" }
|
|
143
|
+
links: { value: [], type: "smart_central-control[]" },
|
|
144
|
+
config_change_date: { value: "" },
|
|
144
145
|
},
|
|
145
146
|
inputs: 1,
|
|
146
147
|
outputs: 3,
|
|
@@ -176,6 +177,11 @@
|
|
|
176
177
|
{
|
|
177
178
|
this.links = [];
|
|
178
179
|
},
|
|
180
|
+
oneditsave: function ()
|
|
181
|
+
{
|
|
182
|
+
let node = this;
|
|
183
|
+
node.config_change_date = (new Date()).toISOString();
|
|
184
|
+
},
|
|
179
185
|
oneditresize: resizeNodeList
|
|
180
186
|
});
|
|
181
187
|
})();
|
package/shutter/shutter.js
CHANGED
|
@@ -34,7 +34,8 @@ module.exports = function (RED)
|
|
|
34
34
|
var node_settings = helper.cloneObject({
|
|
35
35
|
last_position: 0, // 0 = opened, 100 = closed
|
|
36
36
|
last_direction_up: true, // remember last direction for toggle action
|
|
37
|
-
|
|
37
|
+
config_change_date: config.config_change_date,
|
|
38
|
+
}, smart_context.get(node.id, config.config_change_date));
|
|
38
39
|
|
|
39
40
|
|
|
40
41
|
// ##################
|
|
@@ -145,7 +145,8 @@
|
|
|
145
145
|
revert_time_ms: { value: 100 },
|
|
146
146
|
alarm_action: { value: 'NOTHING' }, // NOTHING | UP | DOWN
|
|
147
147
|
alarm_off_action: { value: 'NOTHING' }, // NOTHING | ON | OFF | LAST
|
|
148
|
-
links: { value: [], type: "smart_central-control[]" }
|
|
148
|
+
links: { value: [], type: "smart_central-control[]" },
|
|
149
|
+
config_change_date: { value: "" },
|
|
149
150
|
},
|
|
150
151
|
inputs: 1,
|
|
151
152
|
outputs: 3,
|
|
@@ -250,6 +251,11 @@
|
|
|
250
251
|
{
|
|
251
252
|
this.links = [];
|
|
252
253
|
},
|
|
254
|
+
oneditsave: function ()
|
|
255
|
+
{
|
|
256
|
+
let node = this;
|
|
257
|
+
node.config_change_date = (new Date()).toISOString();
|
|
258
|
+
},
|
|
253
259
|
oneditresize: resizeNodeList
|
|
254
260
|
});
|
|
255
261
|
})();
|
|
@@ -39,7 +39,8 @@ module.exports = function (RED)
|
|
|
39
39
|
last_direction_up: true, // remember last direction for toggle action
|
|
40
40
|
last_position_before_alarm: 0, // remember position to restore on alarm off event
|
|
41
41
|
alarm_active: false, // remember if alarm is on or off
|
|
42
|
-
|
|
42
|
+
config_change_date: config.config_change_date,
|
|
43
|
+
}, smart_context.get(node.id, config.config_change_date));
|
|
43
44
|
|
|
44
45
|
|
|
45
46
|
// ##########################
|
package/statistic/statistic.html
CHANGED
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
out_message: { value: '{"topic": ""}' },
|
|
11
11
|
out_message_type: { value: 'json' },
|
|
12
12
|
save_state: { value: false },
|
|
13
|
-
resend_on_start: { value: false }
|
|
13
|
+
resend_on_start: { value: false },
|
|
14
|
+
config_change_date: { value: "" },
|
|
14
15
|
},
|
|
15
16
|
inputs: 1,
|
|
16
17
|
outputs: 1,
|
|
@@ -93,7 +94,12 @@
|
|
|
93
94
|
this.out_message_type = "NOTHING";
|
|
94
95
|
$("#node-input-out_message_type").val("NOTHING");
|
|
95
96
|
}
|
|
96
|
-
}
|
|
97
|
+
},
|
|
98
|
+
oneditsave: function ()
|
|
99
|
+
{
|
|
100
|
+
let node = this;
|
|
101
|
+
node.config_change_date = (new Date()).toISOString();
|
|
102
|
+
},
|
|
97
103
|
});
|
|
98
104
|
</script>
|
|
99
105
|
|
package/statistic/statistic.js
CHANGED
|
@@ -25,12 +25,13 @@ module.exports = function (RED)
|
|
|
25
25
|
var node_settings = {
|
|
26
26
|
values: [],
|
|
27
27
|
last_message: null,
|
|
28
|
+
config_change_date: config.config_change_date,
|
|
28
29
|
};
|
|
29
30
|
|
|
30
31
|
|
|
31
32
|
// load or delete saved values
|
|
32
33
|
if (config.save_state)
|
|
33
|
-
node_settings = Object.assign(node_settings, smart_context.get(node.id));
|
|
34
|
+
node_settings = Object.assign(node_settings, smart_context.get(node.id, config.config_change_date));
|
|
34
35
|
else
|
|
35
36
|
smart_context.del(node.id);
|
|
36
37
|
|