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 +10 -0
- package/README.md +68 -67
- package/SmartNodesContext.json +1 -1
- package/counter/counter.html +4 -0
- package/counter/counter.js +12 -15
- package/mixing-valve/locales/de-DE/mixing-valve.html +4 -1
- package/mixing-valve/locales/de-DE/mixing-valve.json +2 -0
- package/mixing-valve/locales/en-US/mixing-valve.html +4 -1
- package/mixing-valve/locales/en-US/mixing-valve.json +2 -0
- package/mixing-valve/mixing-valve.html +47 -0
- package/mixing-valve/mixing-valve.js +28 -0
- package/package.json +1 -1
- package/scheduler/locales/de-DE/scheduler.html +3 -0
- package/scheduler/locales/de-DE/scheduler.json +2 -1
- package/scheduler/locales/en-US/scheduler.html +3 -0
- package/scheduler/locales/en-US/scheduler.json +2 -1
- package/scheduler/scheduler.html +7 -0
- package/scheduler/scheduler.js +47 -21
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
|
-
-
|
|
27
|
-
-
|
|
28
|
-
-
|
|
29
|
-
-
|
|
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
|
-
-
|
|
40
|
-
-
|
|
41
|
-
-
|
|
42
|
-
-
|
|
43
|
-
-
|
|
44
|
-
-
|
|
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
|
-
-
|
|
54
|
-
-
|
|
55
|
-
-
|
|
56
|
-
-
|
|
57
|
-
-
|
|
58
|
-
-
|
|
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
|
-
-
|
|
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
|
-
-
|
|
75
|
-
-
|
|
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
|
-
-
|
|
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
|
-
-
|
|
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
|
-
-
|
|
103
|
-
-
|
|
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
|
-
-
|
|
112
|
-
-
|
|
113
|
-
-
|
|
114
|
-
-
|
|
115
|
-
-
|
|
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
|
-
-
|
|
124
|
-
-
|
|
125
|
-
-
|
|
126
|
-
-
|
|
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
|
-
-
|
|
135
|
-
-
|
|
136
|
-
-
|
|
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
|
-
-
|
|
145
|
-
-
|
|
146
|
-
-
|
|
147
|
-
-
|
|
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
|
-
-
|
|
156
|
-
-
|
|
157
|
-
-
|
|
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
|
-
-
|
|
166
|
-
-
|
|
167
|
-
-
|
|
168
|
-
-
|
|
169
|
-
-
|
|
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
|
-
-
|
|
178
|
-
-
|
|
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
|
-
-
|
|
186
|
-
-
|
|
187
|
-
-
|
|
188
|
-
-
|
|
189
|
-
-
|
|
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
|
-
-
|
|
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
|
-
-
|
|
202
|
-
-
|
|
203
|
-
-
|
|
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
|
-
-
|
|
212
|
-
-
|
|
213
|
-
-
|
|
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
|
-
-
|
|
222
|
-
-
|
|
223
|
-
-
|
|
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
|
-
-
|
|
232
|
-
-
|
|
233
|
-
-
|
|
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.
|
package/SmartNodesContext.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"idn1":{"
|
|
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}}
|
package/counter/counter.html
CHANGED
|
@@ -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);
|
package/counter/counter.js
CHANGED
|
@@ -37,10 +37,10 @@ module.exports = function (RED)
|
|
|
37
37
|
// ##################
|
|
38
38
|
// # Dynamic config #
|
|
39
39
|
// ##################
|
|
40
|
-
let start =
|
|
41
|
-
let step =
|
|
42
|
-
let min =
|
|
43
|
-
let max =
|
|
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>
|
|
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>
|
|
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
package/scheduler/scheduler.html
CHANGED
|
@@ -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>
|
package/scheduler/scheduler.js
CHANGED
|
@@ -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 (
|
|
196
|
+
if (nowHour > schedule.hour)
|
|
188
197
|
{
|
|
189
198
|
findNextDay = true;
|
|
190
199
|
}
|
|
191
|
-
else if (
|
|
200
|
+
else if (nowHour == schedule.hour)
|
|
192
201
|
{
|
|
193
|
-
if (
|
|
202
|
+
if (nowMinute > schedule.minute)
|
|
194
203
|
{
|
|
195
204
|
findNextDay = true;
|
|
196
205
|
}
|
|
197
|
-
else if (
|
|
206
|
+
else if (nowMinute == schedule.minute)
|
|
198
207
|
{
|
|
199
|
-
findNextDay =
|
|
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 >
|
|
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
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
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
|
}
|