smart-nodes 0.6.7 → 0.7.1

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
@@ -252,3 +252,12 @@
252
252
 
253
253
  - Added crit temp change options to mixing-valve node.
254
254
  - Added UTC time usage in scheduler node.
255
+
256
+ ## Version 0.7.0:
257
+
258
+ - Added support of home assistant boolean values "on" and "off"
259
+ - BREAKING CHANGE: The forwarder node is only using set_forwarder and set_forwarder_state topics.
260
+
261
+ ## Version 0.7.1:
262
+
263
+ - Small bugfix in mode-selector node.
@@ -1 +1 @@
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}}
1
+ {"idn1":{"last_mode":"NO_MODES_DEFINED","last_position":0,"last_direction_up":false}}
@@ -8,6 +8,7 @@
8
8
  enabled: { value: true },
9
9
  always_forward_true: { value: false },
10
10
  always_forward_false: { value: false },
11
+ always_forward_other: { value: true },
11
12
  forward_last_on_enable: { value: false },
12
13
  save_state: { value: false },
13
14
  resend_on_start: { value: false },
@@ -62,6 +63,10 @@
62
63
  <input type="checkbox" id="node-input-always_forward_false" style="width: 20px;" />
63
64
  <label for="node-input-always_forward_false" style="width: calc(100% - 30px);" data-i18n="[html]forwarder.ui.always_forward_false"></label>
64
65
  </div>
66
+ <div class="form-row">
67
+ <input type="checkbox" id="node-input-always_forward_other" style="width: 20px;" />
68
+ <label for="node-input-always_forward_other" style="width: calc(100% - 30px);" data-i18n="[html]forwarder.ui.always_forward_other"></label>
69
+ </div>
65
70
  <hr/>
66
71
  <h4 style="margin: 0.5rem 0;" data-i18n="forwarder.ui.system_start"></h4>
67
72
  <div class="form-row">
@@ -42,6 +42,7 @@ module.exports = function (RED)
42
42
  // ##################
43
43
  let forward_true = config.always_forward_true;
44
44
  let forward_false = config.always_forward_false;
45
+ let forward_other = config.always_forward_other;
45
46
  let forward_last_on_enable = config.forward_last_on_enable;
46
47
 
47
48
 
@@ -85,18 +86,21 @@ module.exports = function (RED)
85
86
 
86
87
  if (real_topic != null)
87
88
  {
88
- if (real_topic.startsWith("set_state"))
89
- real_topic = real_topic.replace("set_state", "set");
89
+ if (real_topic == "set_forwarder_state")
90
+ real_topic = "set_forwarder";
90
91
 
91
- if (real_topic == "set_inverted")
92
+ if (real_topic == "set_forwarder_state_inverted")
93
+ real_topic = "set_forwarder_inverted";
94
+
95
+ if (real_topic == "set_forwarder_inverted")
92
96
  {
93
- real_topic = "set";
94
- msg.payload = !msg.payload;
97
+ real_topic = "set_forwarder";
98
+ msg.payload = !helper.toBool(msg.payload);
95
99
  }
96
100
 
97
- if (real_topic == "enable" || (real_topic == "set" && msg.payload))
101
+ if (real_topic == "enable" || (real_topic == "set_forwarder" && helper.toBool(msg.payload)))
98
102
  new_state = true;
99
- else if (real_topic == "disable" || (real_topic == "set" && !msg.payload))
103
+ else if (real_topic == "disable" || (real_topic == "set_forwarder" && !helper.toBool(msg.payload)))
100
104
  new_state = false;
101
105
  }
102
106
 
@@ -133,7 +137,7 @@ module.exports = function (RED)
133
137
 
134
138
  default:
135
139
  // Forward if enabled or forced
136
- if (node_settings.enabled || (forward_true && msg.payload) || (forward_false && !msg.payload))
140
+ if (node_settings.enabled || (forward_true && helper.toBool(msg.payload) === true) || (forward_false && helper.toBool(msg.payload) === false) || (forward_other && typeof msg.payload !== "boolean"))
137
141
  {
138
142
  node.send(helper.cloneObject(msg));
139
143
  node_settings.last_msg_was_sended = true;
@@ -27,11 +27,11 @@
27
27
  <td>Deaktiviert das Weiterleiten.</td>
28
28
  </tr>
29
29
  <tr>
30
- <td><code>set</code> oder <code>set_state</code></td>
30
+ <td><code>set_forwarder</code> oder <code>set_forwarder_state</code></td>
31
31
  <td>Aktiviert das Weiterleiten, wenn <code>msg.payload = true</code> oder deaktiviert das Weiterleiten, wenn <code>msg.payload = false</code>.</td>
32
32
  </tr>
33
33
  <tr>
34
- <td><code>set_inverted</code> oder <code>set_state_inverted</code></td>
34
+ <td><code>set_forwarder_inverted</code> oder <code>set_forwarder_state_inverted</code></td>
35
35
  <td>Aktiviert das Weiterleiten, wenn <code>msg.payload = false</code> oder deaktiviert das Weiterleiten, wenn <code>msg.payload = true</code>.</td>
36
36
  </tr>
37
37
  </tbody>
@@ -6,6 +6,7 @@
6
6
  "forward_last_on_enable": "Letzte nicht gesendete Nachricht senden,<br>wenn die Node aktiviert wird.",
7
7
  "always_forward_true": "Leite <code>msg.payload = true</code> immer weiter.",
8
8
  "always_forward_false": "Leite <code>msg.payload = false</code> immer weiter.",
9
+ "always_forward_other": "Leite alle anderen <code>msg.payload</code> Werte immer weiter.",
9
10
 
10
11
  "system_start": "Systemstart",
11
12
  "save_state": "Zustand speichern",
@@ -27,11 +27,11 @@
27
27
  <td>Disables forwarding.</td>
28
28
  </tr>
29
29
  <tr>
30
- <td><code>set</code> or <code>set_state</code></td>
30
+ <td><code>set_forwarder</code> or <code>set_forwarder_state</code></td>
31
31
  <td>Enables forwarding if <code>msg.payload = true</code> or disables forwarding if <code>msg.payload = false</code>.</td>
32
32
  </tr>
33
33
  <tr>
34
- <td><code>set_inverted</code> or <code>set_state_inverted</code></td>
34
+ <td><code>set_forwarder_inverted</code> or <code>set_forwarder_state_inverted</code></td>
35
35
  <td>Enables forwarding if <code>msg.payload = false</code> or disables forwarding if <code>msg.payload = true</code>.</td>
36
36
  </tr>
37
37
  </tbody>
@@ -4,8 +4,9 @@
4
4
  "name": "Name",
5
5
  "enabled": "Enabled",
6
6
  "forward_last_on_enable": "Send last unsent message when node is activated.",
7
- "always_forward_true": "Always forward <code>msg.payload = true</code> .",
8
- "always_forward_false": "Always forward <code>msg.payload = false</code> .",
7
+ "always_forward_true": "Always forward <code>msg.payload = true</code>.",
8
+ "always_forward_false": "Always forward <code>msg.payload = false</code>.",
9
+ "always_forward_other": "Always forward all other <code>msg.payload</code> values.",
9
10
 
10
11
  "system_start": "System start",
11
12
  "save_state": "Save state",
package/light/light.js CHANGED
@@ -117,7 +117,7 @@ module.exports = function (RED)
117
117
  real_topic = "set";
118
118
 
119
119
  if (mode == "BOOL")
120
- msg.payload = !msg.payload;
120
+ msg.payload = !helper.toBool(msg.payload);
121
121
  else if (mode == "PERCENTAGE")
122
122
  msg.payload = 100 - boolToInt(msg.payload);
123
123
  }
@@ -141,22 +141,22 @@ module.exports = function (RED)
141
141
 
142
142
  // Make sure it is bool or int
143
143
  if (mode == "BOOL")
144
- msg.payload = !!msg.payload;
144
+ msg.payload = helper.toBool(msg.payload);
145
145
  else if (mode == "PERCENTAGE")
146
146
  msg.payload = boolToInt(msg.payload);
147
147
 
148
148
  // Output is already in the state of the status value and the timeout is running.
149
149
  // No need to restart the timeout.
150
- if (node_settings.last_value == msg.payload && timeout != null)
150
+ if (node_settings.last_value == helper.toBool(msg.payload) && timeout != null)
151
151
  doRestartTimer = false;
152
152
 
153
- node_settings.last_value = msg.payload;
153
+ node_settings.last_value = helper.toBool(msg.payload);
154
154
  current_output_state = node_settings.last_value;
155
155
  break;
156
156
 
157
157
  case "off":
158
158
  // If button is released, don't handle this message
159
- if (msg.payload === false)
159
+ if (helper.toBool(msg.payload) === false)
160
160
  return;
161
161
 
162
162
  isBlinking = false;
@@ -171,7 +171,7 @@ module.exports = function (RED)
171
171
 
172
172
  case "on":
173
173
  // If button is released, don't handle this message
174
- if (msg.payload === false)
174
+ if (helper.toBool(msg.payload) === false)
175
175
  return;
176
176
 
177
177
  isBlinking = false;
@@ -187,33 +187,33 @@ module.exports = function (RED)
187
187
  case "set":
188
188
  // Make sure it is bool or int
189
189
  if (mode == "BOOL")
190
- msg.payload = !!msg.payload;
190
+ msg.payload = helper.toBool(msg.payload);
191
191
  else if (mode == "PERCENTAGE")
192
192
  msg.payload = boolToInt(msg.payload);
193
193
 
194
194
  isBlinking = false;
195
195
 
196
- node_settings.last_value = msg.payload;
196
+ node_settings.last_value = helper.toBool(msg.payload);
197
197
  node_settings.last_value_sended = node_settings.last_value;
198
198
  break;
199
199
 
200
200
  case "set_permanent":
201
201
  // Make sure it is bool or int
202
202
  if (mode == "BOOL")
203
- msg.payload = !!msg.payload;
203
+ msg.payload = helper.toBool(msg.payload);
204
204
  else if (mode == "PERCENTAGE")
205
205
  msg.payload = boolToInt(msg.payload);
206
206
 
207
207
  isBlinking = false;
208
- isPermanent = !!msg.payload; // false or 0 => not permanent
208
+ isPermanent = helper.toBool(msg.payload);
209
209
 
210
- node_settings.last_value = msg.payload;
210
+ node_settings.last_value = helper.toBool(msg.payload);
211
211
  node_settings.last_value_sended = node_settings.last_value;
212
212
  break;
213
213
 
214
214
  case "motion":
215
215
  // Make sure it is bool
216
- msg.payload = !!msg.payload;
216
+ msg.payload = helper.toBool(msg.payload);
217
217
  isMotion = msg.payload;
218
218
  isBlinking = false;
219
219
 
@@ -248,7 +248,7 @@ module.exports = function (RED)
248
248
  isBlinking = false;
249
249
 
250
250
  // Make sure it is bool
251
- msg.payload = !!msg.payload;
251
+ msg.payload = helper.toBool(msg.payload);
252
252
 
253
253
  // No alarm change, do nothing
254
254
  if (node_settings.alarm_active == msg.payload)
@@ -321,7 +321,7 @@ module.exports = function (RED)
321
321
  case "toggle":
322
322
  default:
323
323
  // If button is released, don't handle this message
324
- if (msg.payload === false)
324
+ if (helper.toBool(msg.payload) === false)
325
325
  return;
326
326
 
327
327
  if (mode == "BOOL")
package/logic/logic.js CHANGED
@@ -91,9 +91,9 @@ module.exports = function (RED)
91
91
  }
92
92
 
93
93
  if (inverts.includes(real_topic_number))
94
- node_settings.input_states[real_topic_number - 1] = !msg.payload;
94
+ node_settings.input_states[real_topic_number - 1] = !helper.toBool(msg.payload);
95
95
  else
96
- node_settings.input_states[real_topic_number - 1] = !!msg.payload; // !! => Convert to boolean
96
+ node_settings.input_states[real_topic_number - 1] = helper.toBool(msg.payload);
97
97
 
98
98
  let result = getResult();
99
99
 
@@ -70,7 +70,7 @@ module.exports = function (RED)
70
70
  */
71
71
  let handleTopic = msg =>
72
72
  {
73
- if (msg.payload)
73
+ if (helper.toBool(msg.payload))
74
74
  {
75
75
  on_time = Date.now();
76
76
  startAutoLongPress();
@@ -175,11 +175,11 @@ module.exports = function (RED)
175
175
  if (real_topic == "set_inverted")
176
176
  {
177
177
  real_topic = "set";
178
- msg.payload = !msg.payload;
178
+ msg.payload = !helper.toBool(msg.payload);
179
179
  }
180
180
 
181
181
  if (real_topic == "set")
182
- real_topic = (!!msg.payload) ? "enable" : "disable";
182
+ real_topic = helper.toBool(msg.payload) ? "enable" : "disable";
183
183
 
184
184
  switch (real_topic)
185
185
  {
@@ -307,7 +307,7 @@ module.exports = function (RED)
307
307
 
308
308
  case "alarm":
309
309
  // Make sure it is bool
310
- msg.payload = !!msg.payload;
310
+ msg.payload = helper.toBool(msg.payload);
311
311
 
312
312
  // No alarm change -> nothing to do
313
313
  if (node_settings.alarm_active == msg.payload)
@@ -84,8 +84,10 @@ module.exports = function (RED)
84
84
  if (msg.payload == null)
85
85
  return;
86
86
 
87
- if (typeof msg.payload === "boolean")
87
+ if (typeof msg.payload === "boolean" || msg.payload === "on" || msg.payload === "off")
88
88
  {
89
+ msg.payload = helper.toBool(msg.payload);
90
+
89
91
  // Syntax: set_mode#MODE_NAME and payload is boolean
90
92
  // If payload is true, set to MODE_NAME
91
93
  // if payload is false, set to default mode
@@ -55,7 +55,7 @@ module.exports = function (RED)
55
55
  // ###############
56
56
  node.on("input", function (msg)
57
57
  {
58
- if (msg.payload)
58
+ if (helper.toBool(msg.payload))
59
59
  startTimeout();
60
60
  });
61
61
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "smart-nodes",
3
- "version": "0.6.7",
3
+ "version": "0.7.1",
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/scene/scene.js CHANGED
@@ -123,7 +123,7 @@ module.exports = function (RED)
123
123
 
124
124
  case "status":
125
125
  // Make sure it is bool
126
- msg.payload = !!msg.payload;
126
+ msg.payload = helper.toBool(msg.payload);
127
127
  node_settings.last_values[number] = msg.payload;
128
128
 
129
129
  notifyCentral();
@@ -145,7 +145,7 @@ module.exports = function (RED)
145
145
 
146
146
  case "set":
147
147
  // Make sure it is bool
148
- msg.payload = !!msg.payload;
148
+ msg.payload = helper.toBool(msg.payload);
149
149
  node_settings.last_values = new Array(config.outputs).fill(msg.payload);
150
150
 
151
151
  // This happens because of splitting by _ for scenes
@@ -155,7 +155,7 @@ module.exports = function (RED)
155
155
 
156
156
  case "scene":
157
157
  // Skip if button is released;
158
- if (msg.payload === false)
158
+ if (helper.toBool(msg.payload) === false)
159
159
  return;
160
160
 
161
161
  if (typeof scenes === "undefined")
@@ -204,7 +204,7 @@ module.exports = function (RED)
204
204
 
205
205
  case "toggle":
206
206
  // Skip if button is released;
207
- if (msg.payload === false)
207
+ if (helper.toBool(msg.payload) === false)
208
208
  return;
209
209
 
210
210
  node_settings.last_values = new Array(config.outputs).fill(currentScene == 0);
@@ -111,11 +111,11 @@ module.exports = function (RED)
111
111
  if (real_topic == "set_inverted")
112
112
  {
113
113
  real_topic = "set";
114
- msg.payload = !msg.payload;
114
+ msg.payload = !helper.toBool(msg.payload);
115
115
  }
116
116
 
117
117
  if (real_topic == "set")
118
- real_topic = (!!msg.payload) ? "enable" : "disable";
118
+ real_topic = helper.toBool(msg.payload) ? "enable" : "disable";
119
119
 
120
120
  switch (real_topic)
121
121
  {
@@ -107,7 +107,7 @@ module.exports = function (RED)
107
107
  // Correct next topic to avoid handling up_stop, down_stop or toggle separately.
108
108
  if (real_topic == "short_up_down")
109
109
  {
110
- real_topic = msg.payload ? "down" : "up";
110
+ real_topic = helper.toBool(msg.payload) ? "down" : "up";
111
111
  if (msg.time_on == null)
112
112
  msg.time_on = short_time_on_ms;
113
113
  }
@@ -150,7 +150,7 @@ module.exports = function (RED)
150
150
 
151
151
  case "up_down":
152
152
  // This is only used to track starting of the shutter
153
- node_settings.last_direction_up = !msg.payload;
153
+ node_settings.last_direction_up = !helper.toBool(msg.payload);
154
154
  is_running = true;
155
155
  return;
156
156
 
@@ -125,13 +125,13 @@ module.exports = function (RED)
125
125
  let real_topic = helper.getRealTopic(msg.topic, "toggle", ["up", "up_stop", "down", "down_stop", "stop", "toggle", "up_down", "position", "alarm"]);
126
126
 
127
127
  // skip if button is released
128
- if (msg.payload === false && ["up", "up_stop", "down", "down_stop", "stop", "toggle"].includes(real_topic))
128
+ if (helper.toBool(msg.payload) === false && ["up", "up_stop", "down", "down_stop", "stop", "toggle"].includes(real_topic))
129
129
  return;
130
130
 
131
131
  // Convert up_down from HA UI to next command
132
132
  if (real_topic == "up_down")
133
133
  {
134
- if (msg.payload)
134
+ if (helper.toBool(msg.payload))
135
135
  real_topic = "down";
136
136
  else
137
137
  real_topic = "up";
@@ -192,13 +192,13 @@ module.exports = function (RED)
192
192
  case "position":
193
193
  startAction(ACTION_POSITION, msg.payload ?? null);
194
194
  break;
195
-
195
+
196
196
  case "status_up":
197
197
  // TODO: if status changed from false to true, start time measurement to calculate position
198
198
  // if status changed from true to false, stop time measurement and save position
199
199
  // if alarm is active, check if current action is allowed and stop if not
200
200
  break;
201
-
201
+
202
202
  case "status_down":
203
203
  // TODO: if status changed from false to true, start time measurement to calculate position
204
204
  // if status changed from true to false, stop time measurement and save position
@@ -207,7 +207,7 @@ module.exports = function (RED)
207
207
 
208
208
  case "alarm":
209
209
  // Make sure it is bool
210
- msg.payload = !!msg.payload;
210
+ msg.payload = helper.toBool(msg.payload);
211
211
 
212
212
  // No alarm change, do nothing
213
213
  if (node_settings.alarm_active == msg.payload)
package/smart_helper.js CHANGED
@@ -1,5 +1,23 @@
1
1
  module.exports = {
2
2
 
3
+ toBool(value)
4
+ {
5
+ if (typeof value == "boolean")
6
+ return value;
7
+
8
+ if (typeof value == "string")
9
+ {
10
+ value = value.toLowerCase();
11
+ if (value == "true" || value == "yes" || value == "on")
12
+ return true;
13
+
14
+ if (value == "false" || value == "no" || value == "off")
15
+ return false;
16
+ }
17
+
18
+ return null;
19
+ },
20
+
3
21
  /**
4
22
  * This functions converts a value into the given type.
5
23
  * If a type is unknown the NodeRed function is used for conversation.