smart-nodes 0.6.5 → 0.6.7

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
@@ -242,3 +242,13 @@
242
242
  ## Version 0.6.5:
243
243
 
244
244
  - Fixed light alarm mode, when status changed to an invalid.
245
+
246
+ ## Version 0.6.6:
247
+
248
+ - Counter can be configured in 0.1 steps. For smaller steps, use msg.payload value.
249
+ - Counter has a new topic refresh, to resend the last saved value.
250
+
251
+ ## Version 0.6.7:
252
+
253
+ - Added crit temp change options to mixing-valve node.
254
+ - Added UTC time usage in scheduler node.
package/README.md CHANGED
@@ -23,10 +23,10 @@ This smart nodes are still in development and can have breaking changes. So plea
23
23
 
24
24
  I spent a lots of hours in this project. If you like it, you can support my work in different ways:
25
25
 
26
- - Report bugs.
27
- - Create pull requests.
28
- - Name tipps and tricks if you see any improvement.
29
- - Donate via [Paypal](https://paypal.me/BergenSoft).
26
+ - Report bugs.
27
+ - Create pull requests.
28
+ - Name tipps and tricks if you see any improvement.
29
+ - Donate via [Paypal](https://paypal.me/BergenSoft).
30
30
 
31
31
  # Nodes
32
32
 
@@ -36,12 +36,12 @@ This node is able to control a light or a power outlet.
36
36
 
37
37
  ### **Features:**
38
38
 
39
- - Auto turn off the light after a fixed time.
40
- - Auto turn off the light with a custom time which is part of the message object.
41
- - Toggle light between on and off.
42
- - Can be activated by motion sensors.
43
- - Has an alarm on function to go to a specific state (on or off) when the alarm is activated.
44
- - Has an alarm off function to go to a specific (on, off, the last or the last sended) when the alarm is deactivated.
39
+ - Auto turn off the light after a fixed time.
40
+ - Auto turn off the light with a custom time which is part of the message object.
41
+ - Toggle light between on and off.
42
+ - Can be activated by motion sensors.
43
+ - Has an alarm on function to go to a specific state (on or off) when the alarm is activated.
44
+ - Has an alarm off function to go to a specific (on, off, the last or the last sended) when the alarm is deactivated.
45
45
 
46
46
  ## 2. Shutter control
47
47
 
@@ -50,12 +50,12 @@ There is no support for slats and it is also not planned as I don't need them, b
50
50
 
51
51
  ### **Features:**
52
52
 
53
- - One button control which switch between `up`, `stop`, `down`, `stop`.
54
- - Two button control for each direction `up and stop` and `down and stop`.
55
- - Send direct position the shutter should go to.
56
- - Stop shutter immediately.
57
- - Has an alarm on function to go to a specific state (Open or close) when the alarm is activated.
58
- - Has an alarm off function to restore a specific state when the alarm gets deaktivated.
53
+ - One button control which switch between `up`, `stop`, `down`, `stop`.
54
+ - Two button control for each direction `up and stop` and `down and stop`.
55
+ - Send direct position the shutter should go to.
56
+ - Stop shutter immediately.
57
+ - Has an alarm on function to go to a specific state (Open or close) when the alarm is activated.
58
+ - Has an alarm off function to restore a specific state when the alarm gets deaktivated.
59
59
 
60
60
  ## 3. Scene control
61
61
 
@@ -63,7 +63,7 @@ This node is tracking the state of multiple outputs and controls them by switchi
63
63
 
64
64
  ### **Features:**
65
65
 
66
- - An input message could name multiple scenes that should be iterated one by one by receiving the same message multiple times
66
+ - An input message could name multiple scenes that should be iterated one by one by receiving the same message multiple times
67
67
 
68
68
  ## 4. Central control
69
69
 
@@ -71,8 +71,8 @@ This node can control multiple light/scene controls or shutter controls at the s
71
71
 
72
72
  ### **Features:**
73
73
 
74
- - Take care that multiple light/scene controls are turned of if any of them is one before executing a toggle command. This is helpful to avoid turning one light on and the other off.
75
- - The same is used for shutters with the up_stop or down_stop commands. A toggle is not supported, it will only be forwarded.
74
+ - Take care that multiple light/scene controls are turned of if any of them is one before executing a toggle command. This is helpful to avoid turning one light on and the other off.
75
+ - The same is used for shutters with the up_stop or down_stop commands. A toggle is not supported, it will only be forwarded.
76
76
 
77
77
  ## 5. Long press control
78
78
 
@@ -81,7 +81,7 @@ The time can be configured in this node.
81
81
 
82
82
  ### **Features:**
83
83
 
84
- - Imediately send a message to the long press output when the time is reached. It is not waiting until the button is released.
84
+ - Imediately send a message to the long press output when the time is reached. It is not waiting until the button is released.
85
85
 
86
86
  ## 6. Multi press control
87
87
 
@@ -91,7 +91,7 @@ You can also choose 2-4 press detection.
91
91
 
92
92
  ### **Features:**
93
93
 
94
- - Imediately send a message to the last output when the max presses are reached. It is not waiting until the button is released.
94
+ - Imediately send a message to the last output when the max presses are reached. It is not waiting until the button is released.
95
95
 
96
96
  ## 7. Hysteresis
97
97
 
@@ -99,8 +99,8 @@ This node is checking if the input value reachs a defined value until the upper
99
99
 
100
100
  ### **Features:**
101
101
 
102
- - The state can be saved between NodeRed restarts.
103
- - The last message can automatically be sent 10 seconds after a deployment.
102
+ - The state can be saved between NodeRed restarts.
103
+ - The last message can automatically be sent 10 seconds after a deployment.
104
104
 
105
105
  ## 8. Logic
106
106
 
@@ -108,11 +108,11 @@ This node can be used for AND, OR and XOR logics. Inputs and outputs can be indi
108
108
 
109
109
  ### **Features:**
110
110
 
111
- - All input values could be individual converted as well as the output messsage.
112
- - A NOT logic is possible when selecting 1 input and convert the output.
113
- - The setpoint and hysteresis value can be changed in runtime.
114
- - The state can be saved between NodeRed restarts.
115
- - The last message can automatically be sent 10 seconds after a deployment.
111
+ - All input values could be individual converted as well as the output messsage.
112
+ - A NOT logic is possible when selecting 1 input and convert the output.
113
+ - The setpoint and hysteresis value can be changed in runtime.
114
+ - The state can be saved between NodeRed restarts.
115
+ - The last message can automatically be sent 10 seconds after a deployment.
116
116
 
117
117
  ## 9. Statistic
118
118
 
@@ -120,10 +120,10 @@ This node can be used for getting the following types of values: Minimum, Maximu
120
120
 
121
121
  ### **Features:**
122
122
 
123
- - All input values could be individual converted as well as the output messsage.
124
- - A NOT logic is possible when selecting 1 input and convert the output.
125
- - The state can be saved between NodeRed restarts.
126
- - The last message can automatically be sent 10 seconds after a deployment.
123
+ - All input values could be individual converted as well as the output messsage.
124
+ - A NOT logic is possible when selecting 1 input and convert the output.
125
+ - The state can be saved between NodeRed restarts.
126
+ - The last message can automatically be sent 10 seconds after a deployment.
127
127
 
128
128
  ## 10. Compare
129
129
 
@@ -131,9 +131,9 @@ This node can compare 2 values with the following operators: < <= == >= > !=
131
131
 
132
132
  ### **Features:**
133
133
 
134
- - Can compare also texts like js would do.
135
- - The state can be saved between NodeRed restarts.
136
- - The last message can automatically be sent 10 seconds after a deployment.
134
+ - Can compare also texts like js would do.
135
+ - The state can be saved between NodeRed restarts.
136
+ - The last message can automatically be sent 10 seconds after a deployment.
137
137
 
138
138
  ## 11. Delay
139
139
 
@@ -141,10 +141,10 @@ This node can delay incomming messages.
141
141
 
142
142
  ### **Features:**
143
143
 
144
- - Different times for `msg.payload = true` and `msg.payload = false`.
145
- - Delays can be changed in runtime.
146
- - The state can be saved between NodeRed restarts.
147
- - The last message can automatically be sent 10 seconds after a deployment.
144
+ - Different times for `msg.payload = true` and `msg.payload = false`.
145
+ - Delays can be changed in runtime.
146
+ - The state can be saved between NodeRed restarts.
147
+ - The last message can automatically be sent 10 seconds after a deployment.
148
148
 
149
149
  ## 12. Forwarder
150
150
 
@@ -152,9 +152,9 @@ This node can control if an incomming message should be forwarded or not.
152
152
 
153
153
  ### **Features:**
154
154
 
155
- - The forwarding can be enabled or disabled in runtime.
156
- - The state can be saved between NodeRed restarts.
157
- - The last message can automatically be sent 10 seconds after a deployment.
155
+ - The forwarding can be enabled or disabled in runtime.
156
+ - The state can be saved between NodeRed restarts.
157
+ - The last message can automatically be sent 10 seconds after a deployment.
158
158
 
159
159
  ## 13. Scheduler
160
160
 
@@ -162,11 +162,11 @@ This node can send a defined message on defined times.
162
162
 
163
163
  ### **Features:**
164
164
 
165
- - The weekdays and the time can be selected as a trigger.
166
- - Multiple trigger and messages can be defined in one node.
167
- - The scheduler can be activated or deactivated in runtime.
168
- - The state can be saved between NodeRed restarts.
169
- - The last message can automatically be sent 10 seconds after a deployment.
165
+ - The weekdays and the time can be selected as a trigger.
166
+ - Multiple trigger and messages can be defined in one node.
167
+ - The scheduler can be activated or deactivated in runtime.
168
+ - The state can be saved between NodeRed restarts.
169
+ - The last message can automatically be sent 10 seconds after a deployment.
170
170
 
171
171
  ## 14. Text execution
172
172
 
@@ -174,23 +174,23 @@ This node parses a text and performs actions to the selected and matching smart
174
174
 
175
175
  ### **Features:**
176
176
 
177
- - Control light and scenes (only on or off) in german and english.
178
- - Control shutter in german and english.
177
+ - Control light and scenes (only on or off) in german and english.
178
+ - Control shutter in german and english.
179
179
 
180
180
  ### Examples
181
181
 
182
182
  Text in [ Braces ] is optional<br/>
183
183
  Room names that has to be entered in the nodes are in `code` style.
184
184
 
185
- - Turn on [the light in] the `living room` and the `kitchen` off.
186
- - Open [the shutter in] the `kitchen` and turn `studio` off.
187
- - Close [the shutter in the] `sleeping` room.
188
- - `Living room` to 10 %.
189
- - Turn on `living room` except the `couch` light.
185
+ - Turn on [the light in] the `living room` and the `kitchen` off.
186
+ - Open [the shutter in] the `kitchen` and turn `studio` off.
187
+ - Close [the shutter in the] `sleeping` room.
188
+ - `Living room` to 10 %.
189
+ - Turn on `living room` except the `couch` light.
190
190
 
191
191
  ### **Features:**
192
192
 
193
- - Sends debug message to output.
193
+ - Sends debug message to output.
194
194
 
195
195
  ## 15. Mixing valve
196
196
 
@@ -198,9 +198,10 @@ This node can control a mixing valve to get the required tput temperature. It is
198
198
 
199
199
  ### **Features:**
200
200
 
201
- - Define target temperature.
202
- - Support heating and cooling.
203
- - Define off mode to do nothing, open or close the valve.
201
+ - Define target temperature.
202
+ - Support heating and cooling.
203
+ - Define off mode to do nothing, open or close the valve.
204
+ - Fast change if crit temp is exeeded.
204
205
 
205
206
  ## 16. Heating curve
206
207
 
@@ -208,9 +209,9 @@ This node calculates the needed flow temperature regarding to the target room te
208
209
 
209
210
  ### **Features:**
210
211
 
211
- - Define slope and offset values.
212
- - Limit flow temperature with min and max values.
213
- - Preview of different curves in the node editor.
212
+ - Define slope and offset values.
213
+ - Limit flow temperature with min and max values.
214
+ - Preview of different curves in the node editor.
214
215
 
215
216
  ## 17. Counter
216
217
 
@@ -218,9 +219,9 @@ This node countes up and down within a specified range.
218
219
 
219
220
  ### **Features:**
220
221
 
221
- - Define min, max and step values.
222
- - Set to a specific value.
223
- - Increment and decrement by default or by a given value.
222
+ - Define min, max and step values.
223
+ - Set to a specific value.
224
+ - Increment and decrement by default or by a given value.
224
225
 
225
226
  ## 18. Mode Selector
226
227
 
@@ -228,6 +229,6 @@ This node can define multiple modes which stores the last selected mode persiten
228
229
 
229
230
  ### **Features:**
230
231
 
231
- - Define custom modes.
232
- - The first mode is the default on first start.
233
- - Save last mode persistent and resend it at start, if wanted.
232
+ - Define custom modes.
233
+ - The first mode is the default on first start.
234
+ - Save last mode persistent and resend it at start, if wanted.
@@ -1 +1 @@
1
- {"idn1":{"last_value":false,"last_value_before_alarm":false,"last_value_sended":false,"alarm_active":false}}6666666666667,"alarm_active":false}}
1
+ {"idn1":{"last_position":0,"last_direction_up":true,"last_position_before_alarm":0,"alarm_active":false}}666666666666667,"alarm_active":false}}":false,"critical_temp_max":null,"crit_temp_change_percent":0,"last_direction_up":false,"last_position_before_alarm":0.006666666666666667}}
@@ -29,6 +29,7 @@
29
29
  $("#node-input-start")
30
30
  .css("max-width", "4rem")
31
31
  .spinner({
32
+ step: 0.1,
32
33
  change: function (event, ui)
33
34
  {
34
35
  var value = parseFloat(this.value);
@@ -40,6 +41,7 @@
40
41
  $("#node-input-step")
41
42
  .css("max-width", "4rem")
42
43
  .spinner({
44
+ step: 0.1,
43
45
  change: function (event, ui)
44
46
  {
45
47
  var value = parseFloat(this.value);
@@ -51,6 +53,7 @@
51
53
  $("#node-input-min")
52
54
  .css("max-width", "4rem")
53
55
  .spinner({
56
+ step: 0.1,
54
57
  change: function (event, ui)
55
58
  {
56
59
  var value = parseFloat(this.value);
@@ -62,6 +65,7 @@
62
65
  $("#node-input-max")
63
66
  .css("max-width", "4rem")
64
67
  .spinner({
68
+ step: 0.1,
65
69
  change: function (event, ui)
66
70
  {
67
71
  var value = parseFloat(this.value);
@@ -37,10 +37,10 @@ module.exports = function (RED)
37
37
  // ##################
38
38
  // # Dynamic config #
39
39
  // ##################
40
- let start = parseInt(config.start, 10);
41
- let step = parseInt(config.step, 10);
42
- let min = parseInt(config.min, 10);
43
- let max = parseInt(config.max, 10);
40
+ let start = parseFloat(config.start);
41
+ let step = parseFloat(config.step);
42
+ let min = parseFloat(config.min);
43
+ let max = parseFloat(config.max);
44
44
  let out_message = helper.evaluateNodeProperty(RED, config.out_message, config.out_message_type);
45
45
 
46
46
 
@@ -53,9 +53,8 @@ module.exports = function (RED)
53
53
  {
54
54
  handleTopic(msg);
55
55
 
56
- sendResult();
57
-
58
56
  setStatus();
57
+
59
58
  smart_context.set(node.id, node_settings);
60
59
  });
61
60
 
@@ -121,7 +120,11 @@ module.exports = function (RED)
121
120
 
122
121
  node_settings.value = temp_value;
123
122
  break;
124
-
123
+
124
+ case "refresh":
125
+ // Nothing to do, just resend the last message if value is set
126
+ break;
127
+
125
128
  default:
126
129
  node.error("Invalid topic: " + real_topic);
127
130
  return;
@@ -129,15 +132,9 @@ module.exports = function (RED)
129
132
 
130
133
  // Check value is in range
131
134
  node_settings.value = Math.min(max, Math.max(min, node_settings.value));
132
- }
133
-
134
- /**
135
- * Send the result to the output
136
- */
137
- let sendResult = () =>
138
- {
135
+
139
136
  // Nothing changed, nothing to do
140
- if (node_settings.value == node_settings.last_message?.payload)
137
+ if (real_topic != "refresh" && node_settings.value == node_settings.last_message?.payload)
141
138
  return;
142
139
 
143
140
  // if out_message is set, use this instead of the default message
@@ -61,7 +61,10 @@
61
61
  </tr>
62
62
  <tr>
63
63
  <td><code>current_temperature</code></td>
64
- <td>Setzt die aktuelle Temperatur auf <code>msg.payload</code> °C.</td>
64
+ <td>
65
+ Setzt die aktuelle Temperatur auf <code>msg.payload</code> °C.<br/>
66
+ Wird die eingestellte kritische Temperatur überschritten, schließt sich der Mischer sofort um den eingestellten prozentualen Wert.
67
+ </td>
65
68
  </tr>
66
69
  <tr>
67
70
  <td><code>alarm</code></td>
@@ -25,6 +25,8 @@
25
25
  "max_change_percent": "Max Änderung",
26
26
  "max_change_temp_difference": "Temperatur für max Änderung",
27
27
  "min_change_time": "Min Änderungsdauer",
28
+ "critical_temp_max": "Max kritische Temperatur",
29
+ "crit_temp_change_percent": "Änderung krit. Temperatur (%)",
28
30
  "controlled_by_central": "Dieser Baustein wird von folgenden Zentralbausteinen gesteuert:"
29
31
  }
30
32
  }
@@ -43,7 +43,10 @@
43
43
  </tr>
44
44
  <tr>
45
45
  <td><code>setpoint</code></td>
46
- <td>Overrides the setpoint with <code>msg.payload</code> °C.</td>
46
+ <td>
47
+ Overrides the setpoint with <code>msg.payload</code> °C.<br/>
48
+ If the configured critical temperature is exceeded, the mixer immediately moves toward the closed position by the configured percentage.
49
+ </td>
47
50
  </tr>
48
51
  <tr>
49
52
  <td><code>off_mode</code></td>
@@ -24,6 +24,8 @@
24
24
  "precision": "Precision",
25
25
  "max_change_percent": "Max change",
26
26
  "max_change_temp_difference": "Temp at max change",
27
+ "critical_temp_max": "Critical temperature (max)",
28
+ "crit_temp_change_percent": "Critical temp change (%)",
27
29
  "min_change_time": "Min change duration",
28
30
  "controlled_by_central": "This block is controlled by the following central blocks:"
29
31
  }
@@ -152,6 +152,8 @@
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
+ critical_temp_max: { value: 100 },
156
+ crit_temp_change_percent: { value: 0 },
155
157
  config_change_date: { value: "" },
156
158
  },
157
159
  inputs: 1,
@@ -344,6 +346,43 @@
344
346
  if (value !== this.value) $(this).spinner("value", value);
345
347
  },
346
348
  });
349
+
350
+ // New fields for critical temperature settings
351
+ $("#node-input-critical_temp_max")
352
+ .css("max-width", "4rem")
353
+ .spinner({
354
+ min: 0,
355
+ max: 100,
356
+ step: 1,
357
+ change: function (event, ui)
358
+ {
359
+ var value = parseFloat(this.value);
360
+ value = isNaN(value) ? 0.0 : value;
361
+ value = Math.max(value, parseFloat($(this).attr("aria-valuemin")));
362
+ value = Math.min(value, parseFloat($(this).attr("aria-valuemax")));
363
+ if (value !== this.value) $(this).spinner("value", value);
364
+ },
365
+ });
366
+ if ($("#node-input-critical_temp_max").val() === "")
367
+ $("#node-input-critical_temp_max").val("100");
368
+
369
+ $("#node-input-crit_temp_change_percent")
370
+ .css("max-width", "4rem")
371
+ .spinner({
372
+ min: 0,
373
+ max: 100,
374
+ step: 1,
375
+ change: function (event, ui)
376
+ {
377
+ var value = parseFloat(this.value);
378
+ value = isNaN(value) ? 0.0 : value;
379
+ value = Math.max(value, parseFloat($(this).attr("aria-valuemin")));
380
+ value = Math.min(value, parseFloat($(this).attr("aria-valuemax")));
381
+ if (value !== this.value) $(this).spinner("value", value);
382
+ },
383
+ });
384
+ if ($("#node-input-crit_temp_change_percent").val() === "")
385
+ $("#node-input-crit_temp_change_percent").val("0");
347
386
  },
348
387
  onadd: function ()
349
388
  {
@@ -412,6 +451,14 @@
412
451
  <label for="node-input-min_change_time" style="width: 250px;"><i class="fa fa-sliders"></i> <span data-i18n="mixing-valve.ui.min_change_time"></span></label>
413
452
  <input id="node-input-min_change_time" value="0" /> ms
414
453
  </div>
454
+ <div class="form-row">
455
+ <label for="node-input-critical_temp_max" style="width: 250px;"><i class="fa fa-thermometer-half"></i> <span data-i18n="mixing-valve.ui.critical_temp_max"></span></label>
456
+ <input id="node-input-critical_temp_max" value="100"/> °C
457
+ </div>
458
+ <div class="form-row">
459
+ <label for="node-input-crit_temp_change_percent" style="width: 250px;"><i class="fa fa-percent"></i> <span data-i18n="mixing-valve.ui.crit_temp_change_percent"></span></label>
460
+ <input id="node-input-crit_temp_change_percent" value="0"/> %
461
+ </div>
415
462
  <hr/>
416
463
  <span><i class="fa fa-link"></i> <span data-i18n="mixing-valve.ui.controlled_by_central"></span></span>
417
464
  <div class="form-row node-input-link-row node-input-link-rows"></div>
@@ -38,6 +38,8 @@ module.exports = function (RED)
38
38
  last_enabled_sended: null,
39
39
  alarm_active: false,
40
40
  config_change_date: config.config_change_date,
41
+ critical_temp_max: config.critical_temp_max,
42
+ crit_temp_change_percent: config.crit_temp_change_percent,
41
43
  }, smart_context.get(node.id, config.config_change_date));
42
44
 
43
45
  // Ensure correct types
@@ -46,6 +48,22 @@ module.exports = function (RED)
46
48
  if (isNaN(node_settings.setpoint) || !isFinite(node_settings.setpoint))
47
49
  node_settings.setpoint = 20;
48
50
 
51
+ if (!node_settings.critical_temp_max)
52
+ {
53
+ node_settings.critical_temp_max = null;
54
+ }
55
+ else
56
+ {
57
+ node_settings.critical_temp_max = parseFloat(node_settings.critical_temp_max);
58
+ if (isNaN(node_settings.critical_temp_max) || !isFinite(node_settings.critical_temp_max))
59
+ node_settings.critical_temp_max = null;
60
+ }
61
+
62
+ node_settings.crit_temp_change_percent = parseFloat(node_settings.crit_temp_change_percent);
63
+ if (isNaN(node_settings.crit_temp_change_percent) || !isFinite(node_settings.crit_temp_change_percent))
64
+ node_settings.crit_temp_change_percent = 0;
65
+
66
+
49
67
  // Remove old settings
50
68
  delete node_settings.precision;
51
69
  delete node_settings.max_change_percent;
@@ -271,6 +289,16 @@ module.exports = function (RED)
271
289
  return;
272
290
  }
273
291
  node_settings.current_temperature = new_temp;
292
+
293
+ // check if critical temperature is set and exceeded
294
+ if (node_settings.critical_temp_max !== null && node_settings.crit_temp_change_percent > 0 && node_settings.current_temperature > node_settings.critical_temp_max)
295
+ {
296
+ force_position = node_settings.last_position - node_settings.crit_temp_change_percent;
297
+ force_position = Math.max(force_position, 0);
298
+
299
+ stopSampling();
300
+ startSampling();
301
+ }
274
302
  break;
275
303
 
276
304
  case "calibrate":
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "smart-nodes",
3
- "version": "0.6.5",
3
+ "version": "0.6.7",
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",
@@ -35,4 +35,7 @@
35
35
  </tbody>
36
36
  </table>
37
37
  </p>
38
+ <p>
39
+ Hinweis: Sie können in der Node-Konfiguration "UTC Zeit verwenden" aktivieren, um UTC statt Lokalzeit zu nutzen. Der Status zeigt an, wenn UTC aktiv ist.
40
+ </p>
38
41
  </script>
@@ -15,7 +15,8 @@
15
15
  "thursday": "Donnerstag",
16
16
  "friday": "Freitag",
17
17
  "saturday": "Samstag",
18
- "sunday": "Sonntag"
18
+ "sunday": "Sonntag",
19
+ "use_utc": "UTC Zeit verwenden"
19
20
  }
20
21
  }
21
22
  }
@@ -35,4 +35,7 @@
35
35
  </tbody>
36
36
  </table>
37
37
  </p>
38
+ <p>
39
+ Note: You can choose to use UTC instead of local time by enabling "Use UTC time" in the node config. Status texts will indicate when UTC is active.
40
+ </p>
38
41
  </script>
@@ -15,7 +15,8 @@
15
15
  "thursday": "Thursday",
16
16
  "friday": "Friday",
17
17
  "saturday": "Saturday",
18
- "sunday": "Sunday"
18
+ "sunday": "Sunday",
19
+ "use_utc": "Use UTC time"
19
20
  }
20
21
  }
21
22
  }
@@ -37,6 +37,7 @@
37
37
  defaults: {
38
38
  name: { value: "" },
39
39
  enabled: { value: false },
40
+ use_utc: { value: false },
40
41
  schedules: {
41
42
  value: [],
42
43
  validate: function (v)
@@ -122,6 +123,7 @@
122
123
  $("#resend_on_start_row").hide();
123
124
  });
124
125
  $("#node-input-save_state").trigger("change");
126
+ // no special behaviour required for use_utc checkbox
125
127
 
126
128
  /**
127
129
  * prepare schedule
@@ -270,6 +272,7 @@
270
272
  oneditsave: function ()
271
273
  {
272
274
  let node = this;
275
+ node.use_utc = !!$("#node-input-use_utc").prop("checked");
273
276
 
274
277
  node.schedules = [];
275
278
 
@@ -314,6 +317,10 @@
314
317
  <input type="checkbox" id="node-input-enabled" style="width: 20px;" />
315
318
  <label for="node-input-enabled" style="width: 200px;" data-i18n="scheduler.ui.scheduler_enabled"></label>
316
319
  </div>
320
+ <div class="form-row">
321
+ <input type="checkbox" id="node-input-use_utc" style="width: 20px;" />
322
+ <label for="node-input-use_utc" style="width: calc(100% - 30px);" data-i18n="scheduler.ui.use_utc"></label>
323
+ </div>
317
324
  <div class="form-row" style="margin-bottom: 2px;">
318
325
  <p class="text-center"><i class="fa fa-list"></i> <strong data-i18n="scheduler.ui.schedules"></strong></p>
319
326
  </div>
@@ -6,6 +6,8 @@ module.exports = function (RED)
6
6
  {
7
7
  const node = this;
8
8
  RED.nodes.createNode(node, config);
9
+ // support use of UTC time (global option)
10
+ const useUtc = !!config.use_utc;
9
11
 
10
12
 
11
13
  // ###################
@@ -181,46 +183,70 @@ module.exports = function (RED)
181
183
  return null;
182
184
 
183
185
  let now = new Date();
186
+
187
+ // use UTC or local values
188
+ const nowHour = useUtc ? now.getUTCHours() : now.getHours();
189
+ const nowMinute = useUtc ? now.getUTCMinutes() : now.getMinutes();
190
+ const nowSecond = useUtc ? now.getUTCSeconds() : now.getSeconds();
191
+ const nowDay = useUtc ? now.getUTCDay() : now.getDay();
192
+
184
193
  let findNextDay = false;
185
194
 
186
195
  // check if the time has already passed today
187
- if (now.getHours() > schedule.hour)
196
+ if (nowHour > schedule.hour)
188
197
  {
189
198
  findNextDay = true;
190
199
  }
191
- else if (now.getHours() == schedule.hour)
200
+ else if (nowHour == schedule.hour)
192
201
  {
193
- if (now.getMinutes() > schedule.minute)
202
+ if (nowMinute > schedule.minute)
194
203
  {
195
204
  findNextDay = true;
196
205
  }
197
- else if (now.getMinutes() == schedule.minute)
206
+ else if (nowMinute == schedule.minute)
198
207
  {
199
- findNextDay = now.getSeconds() >= schedule.second;
208
+ findNextDay = nowSecond >= schedule.second;
200
209
  }
201
210
  }
202
211
 
203
212
  // find next day when the event should be raised
204
- let possibleDay = schedule.days.filter(d => findNextDay ? d > now.getDay() : d >= now.getDay());
213
+ let possibleDay = schedule.days.filter(d => findNextDay ? d > nowDay : d >= nowDay);
205
214
  if (possibleDay.length == 0)
206
215
  possibleDay = Math.min(...schedule.days);
207
216
  else
208
217
  possibleDay = Math.min(...possibleDay);
209
218
 
210
- let nextEvent = new Date(
211
- now.getFullYear(),
212
- now.getMonth(),
213
- now.getDate() + (
214
- findNextDay ?
215
- possibleDay <= now.getDay() ? 7 - now.getDay() + possibleDay : possibleDay - now.getDay()
216
- :
217
- possibleDay < now.getDay() ? 7 - now.getDay() + possibleDay : possibleDay - now.getDay()
218
- ),
219
- schedule.hour,
220
- schedule.minute,
221
- schedule.second
219
+ const dayOffset = (
220
+ findNextDay ?
221
+ (possibleDay <= nowDay ? 7 - nowDay + possibleDay : possibleDay - nowDay)
222
+ :
223
+ (possibleDay < nowDay ? 7 - nowDay + possibleDay : possibleDay - nowDay)
222
224
  );
223
225
 
226
+ let nextEvent;
227
+ if (useUtc)
228
+ {
229
+ nextEvent = new Date(Date.UTC(
230
+ now.getUTCFullYear(),
231
+ now.getUTCMonth(),
232
+ now.getUTCDate() + dayOffset,
233
+ schedule.hour,
234
+ schedule.minute,
235
+ schedule.second
236
+ ));
237
+ }
238
+ else
239
+ {
240
+ nextEvent = new Date(
241
+ now.getFullYear(),
242
+ now.getMonth(),
243
+ now.getDate() + dayOffset,
244
+ schedule.hour,
245
+ schedule.minute,
246
+ schedule.second
247
+ );
248
+ }
249
+
224
250
  // helper.log(node, {
225
251
  // i,
226
252
  // findNextDay,
@@ -256,7 +282,7 @@ module.exports = function (RED)
256
282
  node.status({
257
283
  fill: "red",
258
284
  shape: "dot",
259
- text: helper.getCurrentTimeForStatus() + ": Scheduler disabled"
285
+ text: helper.getCurrentTimeForStatus() + (useUtc ? " (UTC): " : ": ") + "Scheduler disabled"
260
286
  });
261
287
  }
262
288
  else if (nextEvent == null)
@@ -264,7 +290,7 @@ module.exports = function (RED)
264
290
  node.status({
265
291
  fill: "red",
266
292
  shape: "dot",
267
- text: helper.getCurrentTimeForStatus() + ": No events planned"
293
+ text: helper.getCurrentTimeForStatus() + (useUtc ? " (UTC): " : ": ") + "No events planned"
268
294
  });
269
295
  }
270
296
  else
@@ -276,7 +302,7 @@ module.exports = function (RED)
276
302
  node.status({
277
303
  fill: "yellow",
278
304
  shape: "dot",
279
- text: helper.getCurrentTimeForStatus() + ": Wait " + helper.formatMsToStatus(time, "until") + " to raise next event"
305
+ text: helper.getCurrentTimeForStatus() + (useUtc ? " (UTC): " : ": ") + "Wait " + helper.formatMsToStatus(time, "until") + " to raise next event"
280
306
  });
281
307
  }
282
308
  }