smart-nodes 0.6.1 → 0.6.3

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 CHANGED
@@ -151,7 +151,7 @@
151
151
 
152
152
  ## Version 0.4.17:
153
153
 
154
- - Fixed mixing valve position calculation.
154
+ - Fixed mixing-valve position calculation.
155
155
  - Fixed up_down message for central node.
156
156
 
157
157
  ## Version 0.4.18:
@@ -160,7 +160,7 @@
160
160
 
161
161
  ## Version 0.4.19:
162
162
 
163
- - Added min_change_time option to mixing valve node.
163
+ - Added min_change_time option to mixing-valve node.
164
164
 
165
165
  ## Version 0.4.20:
166
166
 
@@ -206,8 +206,8 @@
206
206
 
207
207
  - Improved light control percentage status text.
208
208
  - Fixed logic node when common outputs is configured but one value is set to "send nothing".
209
- - Mixing valve can now output as percentage directly or with open/close impulses.
210
- - Mixing valve tries to guess the best position, when getting enabled.
209
+ - mixing-valve can now output as percentage directly or with open/close impulses.
210
+ - mixing-valve tries to guess the best position, when getting enabled.
211
211
  - Added debug topic to all nodes, to see current values.
212
212
  - Added new node "mode-selector".
213
213
 
@@ -227,4 +227,13 @@
227
227
 
228
228
  ## Version 0.6.1:
229
229
 
230
- - Removed some ui limits of mixing valve.
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.
236
+
237
+ ## Version 0.6.3:
238
+
239
+ - Fixed bug, when disabling mixing-valve while it is opening, the off mode close was not handled. Same for closing and off mode open.
@@ -1 +1 @@
1
- {"idn1":{"temperature_outside":10,"last_flow_temperature":null}}
1
+ {"idn1":{"value":null,"last_message":null}}
@@ -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
 
@@ -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
 
@@ -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
 
@@ -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
  {
@@ -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
 
@@ -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
- }, smart_context.get(node.id));
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
- this.setpoint = parseFloat(this.setpoint ?? 10);
200
- this.hysteresis = parseFloat(this.hysteresis ?? 1);
201
- this.min = parseFloat(this.min ?? 10);
202
- this.max = parseFloat(this.max ?? 20);
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
 
@@ -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
- }, smart_context.get(node.id));
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({
@@ -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
- }, smart_context.get(node.id));
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
- min_change_time,
188
- min_temperature,
189
- min_temperature_position,
190
- max_temperature,
191
- max_temperature_position,
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
 
@@ -256,6 +214,7 @@ module.exports = function (RED)
256
214
  if (node_settings.alarm_active)
257
215
  return;
258
216
 
217
+ stopChanging();
259
218
  stopSampling();
260
219
  doOffMode();
261
220
  break;
@@ -294,16 +253,6 @@ module.exports = function (RED)
294
253
  {
295
254
  case "HEATING":
296
255
  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
256
  node_settings.valve_mode = msg.payload;
308
257
  setStatus();
309
258
  break;
@@ -312,18 +261,16 @@ module.exports = function (RED)
312
261
  helper.warn(this, "Invalid valve_mode: " + msg.payload);
313
262
  return;
314
263
  }
315
-
316
- startSampling();
317
264
  break;
318
265
 
319
266
  case "current_temperature":
320
267
  let new_temp = parseFloat(msg.payload);
321
268
  if (isNaN(new_temp) || !isFinite(new_temp))
322
269
  {
323
- // helper.warn(this, "Invalid payload for current_temperature: " + msg.payload);
270
+ // helper.warn(this, "Invalid payload for node_settings.current_temperature: " + msg.payload);
324
271
  return;
325
272
  }
326
- current_temperature = new_temp;
273
+ node_settings.current_temperature = new_temp;
327
274
  break;
328
275
 
329
276
  case "calibrate":
@@ -344,7 +291,7 @@ module.exports = function (RED)
344
291
  switch (alarm_action)
345
292
  {
346
293
  case "OPEN":
347
- force_position = 100;;
294
+ force_position = 100;
348
295
  break;
349
296
 
350
297
  case "CLOSE":
@@ -467,10 +414,10 @@ module.exports = function (RED)
467
414
  let sample = () =>
468
415
  {
469
416
  // No current temperature available or in calibration => no action
470
- if (current_temperature === null || calibration_timeout !== null || !node_settings.enabled)
417
+ if (node_settings.current_temperature === null || calibration_timeout !== null || !node_settings.enabled)
471
418
  {
472
419
  helper.log(node, "No sample possible", {
473
- current_temperature,
420
+ current_temperature: node_settings.current_temperature,
474
421
  calibration_timeout,
475
422
  enabled: node_settings.enabled
476
423
  });
@@ -478,27 +425,9 @@ module.exports = function (RED)
478
425
  }
479
426
 
480
427
  // +/- 1°C => already good enough, do nothing
481
- let temp_diff = Math.abs(current_temperature - node_settings.setpoint);
428
+ let temp_diff = Math.abs(node_settings.current_temperature - node_settings.setpoint);
482
429
  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
430
  return;
501
- }
502
431
 
503
432
  // 0 °C diff => 0% change
504
433
  // for max_change_temp_difference (default: 20 °C) diff => max_change_percent (default: 2%) change
@@ -512,7 +441,7 @@ module.exports = function (RED)
512
441
 
513
442
  // calculate direction
514
443
  let adjustAction = ADJUST_CLOSE;
515
- if (current_temperature < node_settings.setpoint)
444
+ if (node_settings.current_temperature < node_settings.setpoint)
516
445
  {
517
446
  if (node_settings.valve_mode == "HEATING")
518
447
  adjustAction = ADJUST_OPEN;
@@ -705,29 +634,14 @@ module.exports = function (RED)
705
634
  }
706
635
  }
707
636
 
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
637
  let setStatus = () =>
724
638
  {
725
639
  if (calibration_timeout !== null)
726
640
  node.status({ fill: "yellow", shape: "ring", text: helper.getCurrentTimeForStatus() + ": In calibration" });
727
641
  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) + "%" });
642
+ 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
643
  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) + "%" });
644
+ 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
645
  }
732
646
 
733
647
  /**
@@ -749,22 +663,14 @@ module.exports = function (RED)
749
663
 
750
664
  if (node_settings.last_position === null)
751
665
  {
752
- if (output_mode === OUTPUT_MODE_OPEN_CLOSE)
753
- {
754
- // Start calibration after 10s
755
- setTimeout(calibrate, 10 * 1000);
756
- }
757
- else
758
- {
759
- node_settings.last_position = 0;
760
- }
666
+ node_settings.last_position = 50;
761
667
  }
762
668
  else if (node_settings.alarm_active)
763
669
  {
764
670
  switch (alarm_action)
765
671
  {
766
672
  case "OPEN":
767
- force_position = 100;;
673
+ force_position = 100;
768
674
  break;
769
675
 
770
676
  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
- this.mode_items = result.modes;
129
- this.outputs = this.mode_items.length;
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
- }, smart_context.get(node.id));
28
+ config_change_date: config.config_change_date,
29
+ }, smart_context.get(node.id, config.config_change_date));
29
30
 
30
31
 
31
32
  // ##################
@@ -119,7 +119,7 @@
119
119
  }
120
120
 
121
121
  showNeededMessages(node.max_presses);
122
- }
122
+ },
123
123
  });
124
124
 
125
125
  let showNeededMessages = value =>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "smart-nodes",
3
- "version": "0.6.1",
3
+ "version": "0.6.3",
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",
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 30 seconds if changes exists.
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
- }, 30 * 1000);
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,13 @@ 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
- return globalData["id" + id];
87
+ let data = globalData["id" + id];
88
+ if (data && data.config_change_date && data.config_change_date !== config_change_date)
89
+ return null;
90
+
91
+ return data;
86
92
  }
87
93
 
88
94
  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
- this.scenes = result.scenes;
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
- this.output_items = result.output_items;
436
- this.outputs = this.output_items.length;
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
- }, smart_context.get(node.id));
37
+ config_change_date: config.config_change_date,
38
+ }, smart_context.get(node.id, config.config_change_date));
38
39
 
39
40
 
40
41
  // ##################
@@ -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>
@@ -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
 
@@ -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
  })();
@@ -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
- }, smart_context.get(node.id));
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
- }, smart_context.get(node.id));
42
+ config_change_date: config.config_change_date,
43
+ }, smart_context.get(node.id, config.config_change_date));
43
44
 
44
45
 
45
46
  // ##########################
@@ -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
 
@@ -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