smart-nodes 0.3.37 → 0.4.0

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.
Files changed (109) hide show
  1. package/CHANGELOG.md +62 -0
  2. package/README.md +35 -17
  3. package/central/central.html +26 -12
  4. package/central/central.js +84 -26
  5. package/central/locales/de-DE/central.json +1 -4
  6. package/central/locales/en-US/central.json +0 -3
  7. package/compare/compare.html +40 -24
  8. package/compare/compare.js +69 -29
  9. package/compare/locales/de-DE/compare.json +5 -7
  10. package/compare/locales/en-US/compare.json +18 -8
  11. package/counter/counter.html +64 -17
  12. package/counter/counter.js +43 -20
  13. package/counter/locales/de-DE/counter.json +6 -9
  14. package/counter/locales/en-US/counter.json +12 -16
  15. package/delay/delay.html +18 -88
  16. package/delay/delay.js +63 -20
  17. package/delay/locales/de-DE/delay.html +71 -0
  18. package/delay/locales/de-DE/delay.json +19 -0
  19. package/delay/locales/en-US/delay.html +76 -0
  20. package/delay/locales/en-US/delay.json +19 -0
  21. package/forwarder/forwarder.html +11 -42
  22. package/forwarder/forwarder.js +59 -18
  23. package/forwarder/locales/de-DE/forwarder.html +32 -0
  24. package/forwarder/locales/de-DE/forwarder.json +15 -0
  25. package/forwarder/locales/en-US/forwarder.html +32 -0
  26. package/forwarder/locales/en-US/forwarder.json +15 -0
  27. package/heating-curve/heating-curve.html +10 -51
  28. package/heating-curve/heating-curve.js +38 -13
  29. package/heating-curve/locales/de-DE/heating-curve.html +38 -0
  30. package/heating-curve/locales/de-DE/heating-curve.json +12 -0
  31. package/heating-curve/locales/en-US/heating-curve.html +38 -0
  32. package/heating-curve/locales/en-US/heating-curve.json +12 -0
  33. package/hysteresis/hysteresis.html +43 -65
  34. package/hysteresis/hysteresis.js +94 -68
  35. package/hysteresis/locales/de-DE/hysteresis.html +36 -0
  36. package/hysteresis/locales/de-DE/hysteresis.json +27 -0
  37. package/hysteresis/locales/en-US/hysteresis.html +36 -0
  38. package/hysteresis/locales/en-US/hysteresis.json +27 -0
  39. package/{light-control/light-control.html → light/light.html} +34 -144
  40. package/{light-control/light-control.js → light/light.js} +151 -32
  41. package/light/locales/de-DE/light.html +149 -0
  42. package/light/locales/de-DE/light.json +24 -0
  43. package/light/locales/en-US/light.html +148 -0
  44. package/light/locales/en-US/light.json +24 -0
  45. package/logic/locales/de-DE/logic.html +12 -0
  46. package/logic/locales/de-DE/logic.json +26 -0
  47. package/logic/locales/en-US/logic.html +12 -0
  48. package/logic/locales/en-US/logic.json +26 -0
  49. package/logic/logic.html +27 -40
  50. package/logic/logic.js +63 -29
  51. package/long-press/locales/de-DE/long-press.html +5 -0
  52. package/long-press/locales/de-DE/long-press.json +13 -0
  53. package/long-press/locales/en-US/long-press.html +5 -0
  54. package/long-press/locales/en-US/long-press.json +13 -0
  55. package/{long-press-control/long-press-control.html → long-press/long-press.html} +10 -14
  56. package/long-press/long-press.js +163 -0
  57. package/mixing-valve/locales/de-DE/mixing-valve.html +65 -0
  58. package/mixing-valve/locales/de-DE/mixing-valve.json +19 -0
  59. package/mixing-valve/locales/en-US/mixing-valve.html +66 -0
  60. package/mixing-valve/locales/en-US/mixing-valve.json +19 -0
  61. package/mixing-valve/mixing-valve.html +15 -79
  62. package/mixing-valve/mixing-valve.js +87 -61
  63. package/multi-press/locales/de-DE/multi-press.html +5 -0
  64. package/multi-press/locales/de-DE/multi-press.json +12 -0
  65. package/multi-press/locales/en-US/multi-press.html +5 -0
  66. package/multi-press/locales/en-US/multi-press.json +12 -0
  67. package/{multi-press-control/multi-press-control.html → multi-press/multi-press.html} +9 -13
  68. package/{multi-press-control/multi-press-control.js → multi-press/multi-press.js} +53 -5
  69. package/package.json +7 -7
  70. package/persistence.js +1 -0
  71. package/scene/locales/de-DE/scene.html +105 -0
  72. package/scene/locales/de-DE/scene.json +21 -0
  73. package/scene/locales/en-US/scene.html +107 -0
  74. package/scene/locales/en-US/scene.json +20 -0
  75. package/{scene-control/scene-control.html → scene/scene.html} +18 -121
  76. package/{scene-control/scene-control.js → scene/scene.js} +76 -26
  77. package/scheduler/locales/de-DE/scheduler.html +30 -0
  78. package/scheduler/locales/de-DE/scheduler.json +21 -0
  79. package/scheduler/locales/en-US/scheduler.html +30 -0
  80. package/scheduler/locales/en-US/scheduler.json +21 -0
  81. package/scheduler/scheduler.html +34 -64
  82. package/scheduler/scheduler.js +85 -53
  83. package/shutter/locales/de-DE/shutter.html +127 -0
  84. package/shutter/locales/de-DE/shutter.json +11 -0
  85. package/shutter/locales/en-US/shutter.html +133 -0
  86. package/shutter/locales/en-US/shutter.json +11 -0
  87. package/{shutter-control/shutter-control.html → shutter/shutter.html} +7 -133
  88. package/{shutter-control/shutter-control.js → shutter/shutter.js} +116 -56
  89. package/shutter-complex/locales/de-DE/shutter-complex.html +120 -0
  90. package/shutter-complex/locales/de-DE/shutter-complex.json +20 -0
  91. package/shutter-complex/locales/en-US/shutter-complex.html +120 -0
  92. package/shutter-complex/locales/en-US/shutter-complex.json +20 -0
  93. package/{shutter-complex-control/shutter-complex-control.html → shutter-complex/shutter-complex.html} +30 -133
  94. package/shutter-complex/shutter-complex.js +578 -0
  95. package/smart_helper.js +52 -9
  96. package/statistic/locales/de-DE/statistic.html +10 -0
  97. package/statistic/locales/de-DE/statistic.json +29 -0
  98. package/statistic/locales/en-US/statistic.html +10 -0
  99. package/statistic/locales/en-US/statistic.json +29 -0
  100. package/statistic/statistic.html +32 -36
  101. package/statistic/statistic.js +57 -28
  102. package/text-exec/locales/de-DE/text-exec.html +18 -0
  103. package/text-exec/locales/de-DE/text-exec.json +7 -0
  104. package/text-exec/locales/en-US/text-exec.html +18 -0
  105. package/text-exec/locales/en-US/text-exec.json +7 -0
  106. package/text-exec/text-exec.html +9 -25
  107. package/text-exec/text-exec.js +43 -2
  108. package/long-press-control/long-press-control.js +0 -76
  109. package/shutter-complex-control/shutter-complex-control.js +0 -442
@@ -7,29 +7,57 @@ module.exports = function (RED)
7
7
  const node = this;
8
8
  RED.nodes.createNode(node, config);
9
9
 
10
+ // ###################
11
+ // # Class constants #
12
+ // ###################
13
+
14
+
15
+ // #######################
16
+ // # Global help objects #
17
+ // #######################
10
18
  const smart_context = require("../persistence.js")(RED);
11
19
  const helper = require("../smart_helper.js");
12
20
 
13
- // used from text-exec node
21
+
22
+ // ############################
23
+ // # Used from text-exec node #
24
+ // ############################
14
25
  if (typeof config.exec_text_names == "string")
15
26
  node.exec_text_names = config.exec_text_names.split(",").map(n => n.trim().toLowerCase());
16
27
  else
17
28
  node.exec_text_names = [];
18
29
 
19
- // persistent values
20
- var node_settings = Object.assign({}, {
30
+
31
+ // #####################
32
+ // # persistent values #
33
+ // #####################
34
+ var node_settings = helper.cloneObject({
21
35
  last_position: 0, // 0 = opened, 100 = closed
22
36
  last_direction_up: true, // remember last direction for toggle action
23
37
  }, smart_context.get(node.id));
24
38
 
25
- // dynamic config
26
- let short_time_on_ms = config.short_time_on_ms || 200;
27
39
 
28
- // runtime values
29
- let is_running = false; // remember if shutter is running, this is only recognized when starting within this control or position 0% or 100% is reached.
30
- let max_time_on_timeout = null; // save timeout value to cancel auto timeout if needed
40
+ // ##################
41
+ // # Dynamic config #
42
+ // ##################
43
+ let short_time_on_ms = parseInt(config.short_time_on_ms || 200, 10);
44
+
45
+
46
+ // ##################
47
+ // # Runtime values #
48
+ // ##################
49
+
50
+ // Here the setTimeout return value is stored to stop the shutter.
51
+ // That means if it is null, the shutter is stopped.
52
+ let timeout = null;
53
+
54
+ // This is set to true if a command to start the shutter is recognized.
55
+ let is_running = false;
56
+
31
57
 
32
- // central handling
58
+ // #########################
59
+ // # Central node handling #
60
+ // #########################
33
61
  var event = "node:" + config.id;
34
62
  var handler = function (msg)
35
63
  {
@@ -37,43 +65,58 @@ module.exports = function (RED)
37
65
  }
38
66
  RED.events.on(event, handler);
39
67
 
40
- node.status({ fill: "red", shape: "dot", text: helper.getCurrentTimeForStatus() + ": Stopped at " + Math.round(node_settings.last_position) + "%" });
41
68
 
69
+ // ###############
70
+ // # Node events #
71
+ // ###############
42
72
  node.on("input", function (msg)
43
73
  {
44
74
  handleTopic(msg);
45
75
 
76
+ setStatus();
46
77
  smart_context.set(node.id, node_settings);
47
78
  });
48
79
 
49
80
  node.on("close", function ()
50
81
  {
51
- stopAutoOff();
82
+ startAction(ACTION_STOP);
52
83
  RED.events.off(event, handler);
53
84
  });
54
85
 
86
+
87
+ // #####################
88
+ // # Private functions #
89
+ // #####################
90
+
91
+ // This is the main function which handles all topics that was received.
55
92
  let handleTopic = msg =>
56
93
  {
94
+ helper.log("handle topic:");
95
+ helper.log(msg);
96
+
57
97
  var resultUpDown = null;
58
98
  var resultStop = null;
59
99
  var resultPosition = null;
60
100
 
61
- var real_topic = helper.getTopicName(msg.topic);
62
-
63
- // set default topic
64
- if (!["status", "status_position", "up_down", "up", "up_stop", "down", "down_stop", "stop", "toggle", "position", "short_up_down"].includes(real_topic))
65
- real_topic = "toggle";
101
+ let real_topic = helper.getRealTopic(msg.topic, "toggle", ["status", "status_position", "up_down", "up", "up_stop", "down", "down_stop", "stop", "toggle", "position", "short_up_down"]);
66
102
 
67
103
  // skip if button is released
68
104
  if (msg.payload === false && ["up", "up_stop", "down", "down_stop", "stop", "toggle"].includes(real_topic))
69
105
  return;
70
106
 
71
107
  // Correct next topic to avoid handling up_stop, down_stop or toggle separately.
72
- if ((max_time_on_timeout != null || is_running) && (real_topic == "up_stop" || real_topic == "down_stop" || real_topic == "toggle"))
108
+ if (real_topic == "short_up_down")
109
+ {
110
+ real_topic = msg.payload ? "down" : "up";
111
+ if (msg.time_on == null)
112
+ msg.time_on = short_time_on_ms;
113
+ }
114
+
115
+ if ((timeout != null || is_running) && (real_topic == "up_stop" || real_topic == "down_stop" || real_topic == "toggle"))
73
116
  {
74
117
  real_topic = "stop";
75
118
  }
76
- else if (max_time_on_timeout == null && !is_running)
119
+ else if (timeout == null && !is_running)
77
120
  {
78
121
  // shutter is not running, set next command depending on topic
79
122
  if (real_topic == "up_stop")
@@ -86,7 +129,7 @@ module.exports = function (RED)
86
129
  real_topic = "up";
87
130
  }
88
131
 
89
-
132
+ helper.log("handle real topic: " + real_topic);
90
133
  switch (real_topic)
91
134
  {
92
135
  case "status":
@@ -96,30 +139,18 @@ module.exports = function (RED)
96
139
 
97
140
  if (is_running && (msg.payload == 0 || msg.payload == 100))
98
141
  is_running = false;
99
-
100
- node.status({ fill: "yellow", shape: "ring", text: helper.getCurrentTimeForStatus() + ": Position status received: " + msg.payload + "%" });
101
142
  return;
102
143
 
103
- // This is only used to track starting of the shutter
104
144
  case "up_down":
145
+ // This is only used to track starting of the shutter
105
146
  node_settings.last_direction_up = !msg.payload;
106
147
  is_running = true;
107
-
108
- if (node_settings.last_direction_up)
109
- node.status({ fill: "green", shape: "dot", text: helper.getCurrentTimeForStatus() + ": Up" });
110
- else
111
- node.status({ fill: "green", shape: "dot", text: helper.getCurrentTimeForStatus() + ": Down" });
112
- return;
113
-
114
- case "short_up_down":
115
- handleTopic({ topic: msg.payload ? "down" : "up", time_on: msg.time_on ?? short_time_on_ms });
116
148
  return;
117
149
 
118
150
  case "up":
119
151
  node_settings.last_direction_up = true;
120
152
  is_running = true;
121
153
  resultUpDown = false;
122
- node.status({ fill: "green", shape: "dot", text: helper.getCurrentTimeForStatus() + ": Up" });
123
154
  startAutoOffIfNeeded(msg);
124
155
  break;
125
156
 
@@ -127,14 +158,12 @@ module.exports = function (RED)
127
158
  is_running = false;
128
159
  resultStop = true;
129
160
  stopAutoOff();
130
- node.status({ fill: "red", shape: "dot", text: helper.getCurrentTimeForStatus() + ": Stopped" });
131
161
  break;
132
162
 
133
163
  case "down":
134
164
  node_settings.last_direction_up = false;
135
165
  is_running = true;
136
166
  resultUpDown = true;
137
- node.status({ fill: "green", shape: "dot", text: helper.getCurrentTimeForStatus() + ": Down" });
138
167
  startAutoOffIfNeeded(msg);
139
168
  break;
140
169
 
@@ -145,67 +174,98 @@ module.exports = function (RED)
145
174
  if (value > 100) value = 100;
146
175
  // is_running = true; // Not guaranteed that the shutter starts running.
147
176
  resultPosition = value;
148
- node.status({ fill: "green", shape: "dot", text: helper.getCurrentTimeForStatus() + ": Set position to " + value + "%" });
149
177
  break;
150
178
  }
151
179
 
152
180
  if (resultUpDown != null)
153
181
  {
154
- node.send([{ payload: resultUpDown, topic: "up_down" }, null, null]);
182
+ node.send([{ payload: resultUpDown }, null, null]);
155
183
  notifyCentral(true);
156
184
  }
157
185
  else if (resultStop != null)
158
186
  {
159
- node.send([null, { payload: resultStop, topic: "stop" }, null]);
187
+ node.send([null, { payload: resultStop }, null]);
160
188
  notifyCentral(false);
161
189
  }
162
190
  else if (resultPosition != null)
163
191
  {
164
- node.send([null, null, { payload: resultPosition, topic: "position" }]);
192
+ node.send([null, null, { payload: resultPosition }]);
165
193
  }
166
194
  };
167
195
 
196
+ /**
197
+ * This function sets a timeout to stop the shutter after the defined time is over.
198
+ * @param {*} msg The original message object
199
+ */
168
200
  let startAutoOffIfNeeded = msg =>
169
201
  {
170
- if (!msg.time_on)
202
+ if (msg.time_on == null || msg.time_on == 0)
171
203
  return;
172
204
 
205
+ // calculate needed time
173
206
  let timeMs = helper.getTimeInMsFromString(msg.time_on);
174
- if (isNaN(timeMs))
207
+ if (isNaN(timeMs) || timeMs <= 0)
175
208
  {
176
- node.status({ fill: "red", shape: "dot", text: helper.getCurrentTimeForStatus() + ": Invalid time_on value send: '" + msg.time_on + "'" });
177
- return;
178
- }
179
-
180
- if (timeMs <= 0)
181
- {
182
- node.status({ fill: "red", shape: "dot", text: helper.getCurrentTimeForStatus() + ": time_on value has to be greater than 0" });
209
+ console.warn("Invalid msg.time_on value was sent.", msg);
183
210
  return;
184
211
  }
185
212
 
186
213
  // Stop if any timeout is set
187
214
  stopAutoOff();
188
215
 
189
- node.status({ fill: "yellow", shape: "ring", text: helper.getCurrentTimeForStatus() + ": Wait " + (timeMs / 1000).toFixed(1) + " sec for auto off" });
190
- max_time_on_timeout = setTimeout(() =>
216
+ timeout = setTimeout(() =>
191
217
  {
192
- node.status({ fill: "red", shape: "dot", text: helper.getCurrentTimeForStatus() + ": Stopped" });
193
218
  is_running = false;
219
+ timeout = null;
220
+
194
221
  node.send([null, { payload: true }, null]);
195
222
  notifyCentral(false);
223
+
224
+ smart_context.set(node.id, node_settings);
225
+
226
+ setStatus();
196
227
  }, timeMs);
197
228
  };
198
229
 
230
+ /**
231
+ * Stops the current running timeout
232
+ */
199
233
  let stopAutoOff = () =>
200
234
  {
201
- if (max_time_on_timeout != null)
235
+ if (timeout != null)
202
236
  {
203
- node.status({});
204
- clearTimeout(max_time_on_timeout);
205
- max_time_on_timeout = null;
237
+ clearTimeout(timeout);
238
+ timeout = null;
206
239
  }
207
240
  };
208
241
 
242
+ /**
243
+ * Set the current node status
244
+ */
245
+ let setStatus = () =>
246
+ {
247
+ let fill = "green";
248
+ let shape = (timeout != null || is_running) ? "ring" : "dot";
249
+
250
+ // collect all texts and join later with a comma
251
+ let texts = [];
252
+
253
+ if (timeout == null && !is_running)
254
+ texts.push("Stopped");
255
+ else if (node_settings.last_direction_up)
256
+ texts.push("Up");
257
+ else
258
+ texts.push("Down");
259
+
260
+ texts.push("Position: " + node_settings.last_position?.toFixed(0) + "%");
261
+
262
+ node.status({ fill, shape, text: helper.getCurrentTimeForStatus() + ": " + texts.join(", ") });
263
+ }
264
+
265
+ /**
266
+ * Notify all connected central nodes
267
+ * @param {boolean} state The state if the shutter is running
268
+ */
209
269
  let notifyCentral = state =>
210
270
  {
211
271
  if (!config.links)
@@ -213,8 +273,8 @@ module.exports = function (RED)
213
273
 
214
274
  config.links.forEach(link =>
215
275
  {
216
- // console.log(node.id + " -> " + link);
217
- // console.log({ source: node.id, state: state });
276
+ helper.log(node.id + " -> " + link);
277
+ helper.log({ source: node.id, state: state });
218
278
  RED.events.emit("node:" + link, { source: node.id, state: state });
219
279
  });
220
280
  };
@@ -0,0 +1,120 @@
1
+ <script type="text/html" data-help-name="smart_shutter-complex-control">
2
+ <p>
3
+ <b>Hinweis:</b> Diese Node wurde entwickelt, falls die KNX Rollladensteuerung nicht verwendet werden kann um man gezwungen ist 2 separate Ausgänge für Auf und Ab zu verwenden.
4
+ Es ist dabei sehr zu empfehlen, dass die Ausgänge sich gegenseitig verriegeln um ein gleichzeitiges Ansteuern zu verhindern. Für etwaige Schäden am Rollladen ist jeder selbst verantwortlich.
5
+ </p>
6
+ <p>
7
+ <b>Hinweis:</b> Smart Nodes verwenden Topics im Format <code>name#nummer</code>, damit können verschiedene Smart Nodes mit dem gleichen Topic angesteuert werden.<br/>
8
+ Diese Node verwendet nur den Teil <code>name</code>. <code>#</code> und <code>nummer</code> sind dabei optional.
9
+ </p>
10
+ <p>
11
+ Diese Node steuert Rollladen oder Jalousien.
12
+ Es gibt 3 Ausgänge die angesteuert werden können:
13
+ <ol>
14
+ <li><b>Auf:</b> <code>msg.payload = true;</code> startet den Rollladen um nach oben zu fahren und <code>msg.payload = false;</code> stoppt diesen wieder.</li>
15
+ <li><b>Ab:</b> <code>msg.payload = true;</code> startet den Rollladen um nach unten zu fahren und <code>msg.payload = false;</code> stoppt diesen wieder.</li>
16
+ <li><b>Status Position:</b> <code>msg.payload = 42;</code>Gibt den aktuellen Status der Rollladen aus. 0 = offen, 100 = geschlossen.</li>
17
+ </ol>
18
+ Die Ausgänge sind den jeweiligen KNX Gruppenadressen zuzuordnen.
19
+ </p>
20
+ <p>
21
+ Diese Node erwartet folgende Topics als Eingang:<br/>
22
+ <table>
23
+ <thead>
24
+ <tr>
25
+ <th>Topic</th>
26
+ <th>Beschreibung</th>
27
+ <th>msg.payload == false wird ignoriert</th>
28
+ </tr>
29
+ </thead>
30
+ <tbody>
31
+ <tr>
32
+ <td><code>up_stop</code></td>
33
+ <td>Sendet abwechselnd einen Stop- und einen Hochfahrbefehl.</td>
34
+ <td>Ja</td>
35
+ </tr>
36
+ <tr>
37
+ <td><code>up</code></td>
38
+ <td>Sendet einen Hochfahrbefehl, falls der Rollladen nicht bereits nach oben fährt. Ggf. wird vorher noch ein Stop-Befehl gesendet und die eingestellte Zeit gewartet.</td>
39
+ <td>Ja</td>
40
+ </tr>
41
+ <tr>
42
+ <td><code>down_stop</code></td>
43
+ <td>Sendet abwechselnd einen Stop- und einen Runterfahrbefehl.</td>
44
+ <td>Ja</td>
45
+ </tr>
46
+ <tr>
47
+ <td><code>down</code></td>
48
+ <td>Sendet einen Runterfahrbefehl, falls der Rollladen nicht bereits nach unten fährt. Ggf. wird vorher noch ein Stop-Befehl gesendet und die eingestellte Zeit gewartet.</td>
49
+ <td>Ja</td>
50
+ </tr>
51
+ <tr>
52
+ <td><code>up_down</code></td>
53
+ <td>Nimmt einen Befehl von Home Assistant entgegen und leitet die entsprechende Aktion ein.</td>
54
+ <td>Nein</td>
55
+ </tr>
56
+ <tr>
57
+ <td><code>stop</code></td>
58
+ <td>Sendet einen Stopbefehl.</td>
59
+ <td>Ja</td>
60
+ </tr>
61
+ <tr>
62
+ <td><code>position</code></td>
63
+ <td>Sendet einen Positionsbefehl. <code>msg.payload</code> sollte ein Wert zwischen 0 (offen) und 100 (geschlossen) haben.</td>
64
+ <td>Nein</td>
65
+ </tr>
66
+ <tr>
67
+ <td><code>alarm</code></td>
68
+ <td>Setzt den aktuellen Alarmzustand.</td>
69
+ <td>Nein</td>
70
+ </tr>
71
+ <tr>
72
+ <td><code>toggle</code> (default)</td>
73
+ <td>Schaltet den Rollladen abwechselnd auf hoch, stop, runter, stop.</td>
74
+ <td>Ja</td>
75
+ </tr>
76
+ </tbody>
77
+ </table>
78
+ </p>
79
+ <p>
80
+ Diese Node verwaltet die Laufzeit für den Rollladen selbst.
81
+ Es ist aber auch möglich, den Rollladen nach einer definierten Zeit automatisch abschalten zu lassen.
82
+ Beispiel: <code>msg = { "topic": "up", "time_on": 5000 }</code> oder <code>msg = { "topic": "up", "time_on": "5s" }</code><br/>
83
+ Diese Nachricht lässt den Rollladen für 5000 Millisekunden / 5 Sekunden nach oben fahren. Sollte es sich um eine Jalousie halten, werden die Lamellen entsprechend gedreht.
84
+ Als Einheit für die Zeit können folgende Werte verwendet werden:
85
+ <table>
86
+ <thead>
87
+ <tr>
88
+ <th>Einheit</th>
89
+ <th>Beschreibung</th>
90
+ </tr>
91
+ </thead>
92
+ <tbody>
93
+ <tr>
94
+ <td><code>ms</code> (default)</td>
95
+ <td>Millisekunden</td>
96
+ </tr>
97
+ <tr>
98
+ <td><code>s</code> oder <code>sec</code></td>
99
+ <td>Sekunden</td>
100
+ </tr>
101
+ <tr>
102
+ <td><code>m</code> oder <code>min</code></td>
103
+ <td>Minuten.</td>
104
+ </tr>
105
+ <tr>
106
+ <td><code>h</code></td>
107
+ <td>Stunden</td>
108
+ </tr>
109
+ </tbody>
110
+ </table>
111
+ </p>
112
+ <p>
113
+ Um mögliche Positionsabweichungen zu korrigieren läuft der Rollladen immer für mindestens 5 Sekunden, wenn nichts anderes in <code>msg.on_time</code> eingestellt wurde.
114
+ Dadurch kann der Rollladen auch noch weiter hochgefahren werden, falls er im System als offen erkannt wird, er aber in Wirklichkeit noch nicht ganz oben sein sollte.<br>
115
+ Manchmal kann es aber auch erwünscht sein, dass ein Rollladen bei 0 oder 100 % nicht nochmals startet. Dafür muss dann <code>msg.exact = true</code> gesetzt werden.
116
+ </p>
117
+ <p>
118
+ Die Angabe einer Zeit funktioniert nicht mit dem topic <b>position</b>.
119
+ </p>
120
+ </script>
@@ -0,0 +1,20 @@
1
+ {
2
+ "shutter": {
3
+ "ui": {
4
+ "name": "Name",
5
+ "text": "Text",
6
+ "controlled_by_words": "Diese Node kann über die eingegebenen Wörter gesteuert werden. Mehrere Wörter werden durch ein Komma getrennt.",
7
+ "time_up": "Zeit auf",
8
+ "time_down": "Zeit ab",
9
+ "pause_change": "Pause Wechsel",
10
+ "alarm_on": "Alarm Ein",
11
+ "alarm_off": "Alarm Aus",
12
+ "controlled_by_central": "Dieser Baustein wird von folgenden Zentralbausteinen gesteuert:",
13
+
14
+ "no_action": "Keine Aktion",
15
+ "up": "Hoch / Öffnen",
16
+ "down": "Runter / Schließen",
17
+ "last_position": "Letze Position"
18
+ }
19
+ }
20
+ }
@@ -0,0 +1,120 @@
1
+ <script type="text/html" data-help-name="smart_shutter-complex-control">
2
+ <p>
3
+ <b>Note:</b> This node was developed if the KNX roller shutter control cannot be used and you are forced to use 2 separate outputs for up and down.
4
+ It is highly recommended that the outputs lock each other to prevent simultaneous control. Everyone is responsible for any damage to the roller shutter.
5
+ </p>
6
+ <p>
7
+ <b>Note:</b> Smart nodes use topics in the format <code>name#number</code>, so that different smart nodes can be controlled with the same topic.<br />
8
+ This node only uses the <code>name</code> part. <code>#</code> and <code>number</code> are optional.
9
+ </p>
10
+ <p>
11
+ This node controls roller shutters or blinds.
12
+ There are 3 outputs that can be controlled:
13
+ <ol>
14
+ <li><b>Up:</b> <code>msg.payload = true;</code> starts the roller shutter to move up and <code>msg.payload = false;</code> stops it again. </li>
15
+ <li><b>Down:</b> <code>msg.payload = true;</code> starts the roller shutter to move down and <code>msg.payload = false;</code> stops it again. </li>
16
+ <li><b>Status Position:</b> <code>msg.payload = 42;</code>Shows the current status of the roller shutter. 0 = open, 100 = closed.</li>
17
+ </ol>
18
+ The outputs are assigned to the respective KNX group addresses.
19
+ </p>
20
+ <p>
21
+ This node expects the following topics as input:<br />
22
+ <table>
23
+ <thead>
24
+ <tr>
25
+ <th>Topic</th>
26
+ <th>Description</th>
27
+ <th>msg.payload == false is ignored</th>
28
+ </tr>
29
+ </thead>
30
+ <tbody>
31
+ <tr>
32
+ <td><code>up_stop</code></td>
33
+ <td>Sends a stop and a raise command alternately.</td>
34
+ <td>Yes</td>
35
+ </tr>
36
+ <tr>
37
+ <td><code>up</code></td>
38
+ <td>Sends a raise command if the roller shutter is not already moving up. If necessary, a stop command is sent beforehand and the set time is waited for.</td>
39
+ <td>Yes</td>
40
+ </tr>
41
+ <tr>
42
+ <td><code>down_stop</code></td>
43
+ <td>Sends a stop and a down command alternately.</td>
44
+ <td>Yes</td>
45
+ </tr>
46
+ <tr>
47
+ <td><code>down</code></td>
48
+ <td>Sends a down command if the roller shutter is not already moving down. If necessary, a stop command is sent beforehand and the set time is waited for.</td>
49
+ <td>Yes</td>
50
+ </tr>
51
+ <tr>
52
+ <td><code>up_down</code></td>
53
+ <td>Receives a command from Home Assistant and initiates the corresponding action.</td>
54
+ <td>No</td>
55
+ </tr>
56
+ <tr>
57
+ <td><code>stop</code></td>
58
+ <td>Sends a stop command.</td>
59
+ <td>Yes</td>
60
+ </tr>
61
+ <tr>
62
+ <td><code>position</code></td>
63
+ <td>Sends a position command. <code>msg.payload</code> should have a value between 0 (open) and 100 (closed).</td>
64
+ <td>No</td>
65
+ </tr>
66
+ <tr>
67
+ <td><code>alarm</code></td>
68
+ <td>Sets the current alarm state.</td>
69
+ <td>No</td>
70
+ </tr>
71
+ <tr>
72
+ <td><code>toggle</code> (default)</td>
73
+ <td>Switches the roller shutter alternately to up, stop, down, stop.</td>
74
+ <td>Yes</td>
75
+ </tr>
76
+ </tbody>
77
+ </table>
78
+ </p>
79
+ <p>
80
+ This node manages the running time for the roller shutter itself.
81
+ It is also possible to have the roller shutter switch off automatically after a defined time.
82
+ Example: <code>msg = { "topic": "up", "time_on": 5000 }</code> or <code>msg = { "topic": "up", "time_on": "5s" }</code><br />
83
+ This message causes the roller shutter to move up for 5000 milliseconds / 5 seconds. If it is a blind, the slats are rotated accordingly.
84
+ The following values can be used as a unit for time:
85
+ <table>
86
+ <thead>
87
+ <tr>
88
+ <th>Unit</th>
89
+ <th>Description</th>
90
+ </tr>
91
+ </thead>
92
+ <tbody>
93
+ <tr>
94
+ <td><code>ms</code> (default)</td>
95
+ <td>Milliseconds</td>
96
+ </tr>
97
+ <tr>
98
+ <td><code>s</code> or <code>sec</code></td>
99
+ <td>Seconds</td>
100
+ </tr>
101
+ <tr>
102
+ <td><code>m</code> or <code>min</code></td>
103
+ <td>Minutes.</td>
104
+ </tr>
105
+ <tr>
106
+ <td><code>h</code></td>
107
+ <td>Hours</td>
108
+ </tr>
109
+ </tbody>
110
+ </table>
111
+ </p>
112
+ <p>
113
+ To correct possible position deviations, the roller shutter always runs for at least 5 seconds if nothing else has been set in <code>msg.on_time</code>.
114
+ This means that the roller shutter can be raised even further if it is recognized as open in the system, but in reality it is not yet completely up.<br>
115
+ Sometimes it may also be desirable for a roller shutter not to start again at 0 or 100%. For this, <code>msg.exact = true</code> must be set.
116
+ </p>
117
+ <p>
118
+ Specifying a time does not work with the topic <b>position</b>.
119
+ </p>
120
+ </script>
@@ -0,0 +1,20 @@
1
+ {
2
+ "shutter": {
3
+ "ui": {
4
+ "name": "Name",
5
+ "text": "Text",
6
+ "controlled_by_words": "This node can be controlled using the words entered. Multiple words are separated by a comma.",
7
+ "time_up": "Time up",
8
+ "time_down": "Time down",
9
+ "pause_change": "Pause change",
10
+ "alarm_on": "Alarm On",
11
+ "alarm_off": "Alarm Off",
12
+ "controlled_by_central": "This module is controlled by the following central modules:",
13
+
14
+ "no_action": "No action",
15
+ "up": "Up / Open",
16
+ "down": "Down / Close",
17
+ "last_position": "Last position"
18
+ }
19
+ }
20
+ }