node-red-contrib-ccu 4.4.4 → 4.5.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 (60) hide show
  1. package/CHANGELOG.md +175 -0
  2. package/README.md +35 -0
  3. package/nodes/ccu-alexa.html +12 -14
  4. package/nodes/ccu-connection.html +63 -95
  5. package/nodes/ccu-connection.js +812 -115
  6. package/nodes/ccu-get-value.html +18 -15
  7. package/nodes/ccu-get-value.js +16 -0
  8. package/nodes/ccu-homeassistant.html +0 -48
  9. package/nodes/ccu-mqtt.html +0 -8
  10. package/nodes/ccu-poll.html +0 -17
  11. package/nodes/ccu-program.html +0 -53
  12. package/nodes/ccu-rpc-event.html +0 -34
  13. package/nodes/ccu-rpc.html +0 -64
  14. package/nodes/ccu-script.html +0 -8
  15. package/nodes/ccu-set-value.html +0 -62
  16. package/nodes/ccu-set-value.js +6 -11
  17. package/nodes/ccu-signal.html +0 -64
  18. package/nodes/ccu-switch.html +12 -24
  19. package/nodes/ccu-sysvar.html +0 -64
  20. package/nodes/ccu-value.html +23 -95
  21. package/nodes/ccu-value.js +8 -2
  22. package/nodes/lib/initretry.js +46 -9
  23. package/nodes/lib/localccu.js +21 -3
  24. package/nodes/lib/metaprovider.js +47 -19
  25. package/nodes/lib/party.js +103 -0
  26. package/nodes/lib/topic.js +22 -1
  27. package/nodes/lib/transport.js +80 -0
  28. package/nodes/locales/de/ccu-alexa.html +4 -0
  29. package/nodes/locales/de/ccu-connection.html +103 -0
  30. package/nodes/locales/de/ccu-get-value.html +16 -0
  31. package/nodes/locales/de/ccu-homeassistant.html +23 -0
  32. package/nodes/locales/de/ccu-mqtt.html +21 -0
  33. package/nodes/locales/de/ccu-poll.html +8 -0
  34. package/nodes/locales/de/ccu-program.html +26 -0
  35. package/nodes/locales/de/ccu-rpc-event.html +32 -0
  36. package/nodes/locales/de/ccu-rpc.html +31 -0
  37. package/nodes/locales/de/ccu-script.html +13 -0
  38. package/nodes/locales/de/ccu-set-value.html +46 -0
  39. package/nodes/locales/de/ccu-signal.html +29 -0
  40. package/nodes/locales/de/ccu-switch.html +18 -0
  41. package/nodes/locales/de/ccu-sysvar.html +43 -0
  42. package/nodes/locales/de/ccu-value.html +98 -0
  43. package/nodes/locales/de/ccu-value.json +1 -0
  44. package/nodes/locales/en-US/ccu-alexa.html +4 -0
  45. package/nodes/locales/en-US/ccu-connection.html +41 -0
  46. package/nodes/locales/en-US/ccu-get-value.html +13 -0
  47. package/nodes/locales/en-US/ccu-homeassistant.html +23 -0
  48. package/nodes/locales/en-US/ccu-mqtt.html +21 -0
  49. package/nodes/locales/en-US/ccu-poll.html +7 -0
  50. package/nodes/locales/en-US/ccu-program.html +25 -0
  51. package/nodes/locales/en-US/ccu-rpc-event.html +31 -0
  52. package/nodes/locales/en-US/ccu-rpc.html +30 -0
  53. package/nodes/locales/en-US/ccu-script.html +13 -0
  54. package/nodes/locales/en-US/ccu-set-value.html +45 -0
  55. package/nodes/locales/en-US/ccu-signal.html +29 -0
  56. package/nodes/locales/en-US/ccu-switch.html +6 -0
  57. package/nodes/locales/en-US/ccu-sysvar.html +42 -0
  58. package/nodes/locales/en-US/ccu-value.html +81 -0
  59. package/nodes/locales/en-US/ccu-value.json +1 -0
  60. package/package.json +1 -1
@@ -12,7 +12,8 @@
12
12
  datapoint: {value: ''},
13
13
  datapointProperty: {value: 'value'},
14
14
  setProp: {value: 'payload'},
15
- setPropType: {value: 'msg'}
15
+ setPropType: {value: 'msg'},
16
+ topic: {value: ''}
16
17
  },
17
18
  inputs: 1,
18
19
  outputs: 1,
@@ -47,6 +48,7 @@
47
48
  let ifacesLoaded = false;
48
49
  let ifacesPending = false;
49
50
  let ifaceLoadRetries = 5;
51
+ let channelLoadRetries = 30;
50
52
 
51
53
  if (!this.setProp) {
52
54
  this.setProp = 'payload';
@@ -135,7 +137,16 @@
135
137
 
136
138
  const nodeId = $nodeInputCcuConfig.val();
137
139
  const url = 'ccu?config=' + nodeId + '&type=channels&iface=' + $nodeInputIface.val();
138
- $.getJSON(url, d => {
140
+ $.getJSON(url, (d, _status, xhr) => {
141
+ // task 9: an empty list while the connection is still initialising is "not yet",
142
+ // not "nothing" - keep what is configured, say so, and ask again
143
+ if (Object.keys(d).length === 0 && xhr.getResponseHeader('X-CCU-Loading') && channelLoadRetries-- > 0) {
144
+ $nodeInputChannel.attr('placeholder', 'loading device data ...');
145
+ setTimeout(loadConfig, 2000);
146
+ return;
147
+ }
148
+
149
+ $nodeInputChannel.removeAttr('placeholder');
139
150
  data = d;
140
151
  autocompleteChannel();
141
152
  autocompleteDatapoint();
@@ -197,7 +208,7 @@
197
208
 
198
209
  // ${ENV} placeholders are substituted by Node-RED before the node is
199
210
  // constructed (subflow parameters, #158) - do not clear them
200
- if (!/^\$\{[^}]+\}$/.test($nodeInputChannel.val()) && !data[$nodeInputChannel.val().split(' ')[0]]) {
211
+ if (Object.keys(data).length > 0 && !/^\$\{[^}]+\}$/.test($nodeInputChannel.val()) && !data[$nodeInputChannel.val().split(' ')[0]]) {
201
212
  $nodeInputChannel.val('');
202
213
  $nodeInputDatapoint.val('');
203
214
  }
@@ -472,19 +483,11 @@
472
483
  <input type="text" id="node-input-setProp" placeholder="payload" style="width:250px;">
473
484
  <input type="hidden" id="node-input-setPropType">
474
485
  </div>
486
+ <div class="form-row">
487
+ <label for="node-input-topic"><i class="icon-tasks"></i> Topic</label>
488
+ <input type="text" id="node-input-topic" placeholder="empty: msg.topic stays as it came in">
489
+ </div>
475
490
  <div id="dialog-select-datapoint" title="Select Channel, Datapoint and Property">
476
491
  <div id="config-lookup-tree"></div>
477
492
  </div>
478
493
  </script>
479
-
480
- <script type="text/x-red" data-help-name="ccu-get-value" lang="en-US">
481
- <p>This Node outputs the current state of a datapoint or a ccu variable on any incoming message.</p>
482
- </script>
483
-
484
- <script type="text/x-red" data-help-name="ccu-display" lang="de-DE">
485
- <p>Dieser Node gibt bei jeder eingehenden Message den aktuellen zwischengespeicherten Zustand eines Datenpunktes oder einer CCU Systemvariable aus.</p>
486
- <h3>Konfiguration</h3>
487
- Um über die eingehende Message die Attribute <code>iface</code>, <code>channel</code>, <code>datapoint</code> und <code>sysvar</code> setzen zu können müssen die entsprechenden Konfigurationsoptionen leer gelassen werden.
488
- <h3>Input</h3>
489
- <h3>Output</h3>
490
- </script>
@@ -1,3 +1,5 @@
1
+ const {topicReplace} = require('./lib/topic.js');
2
+
1
3
  module.exports = function (RED) {
2
4
  class CcuGetValue {
3
5
  constructor(config) {
@@ -6,6 +8,9 @@ module.exports = function (RED) {
6
8
  this.ccu = RED.nodes.getNode(config.ccuConfig);
7
9
  this.setProp = config.setProp || 'payload';
8
10
  this.setPropType = config.setPropType || 'msg';
11
+ // task 6 (#39): the same topic template as the other emitting nodes; empty
12
+ // (the default, and every flow from before) leaves msg.topic as it came in
13
+ this.topic = config.topic || '';
9
14
 
10
15
  if (!this.ccu) {
11
16
  return;
@@ -39,8 +44,18 @@ module.exports = function (RED) {
39
44
  }
40
45
  }
41
46
 
47
+ // the cached object the topic placeholders are taken from (iface, channel,
48
+ // channelName, datapoint, ... for a datapoint; name, iface, ... for a variable)
49
+ const source = value;
50
+ const setTopic = () => {
51
+ if (this.topic) {
52
+ message.topic = topicReplace(this.topic, source);
53
+ }
54
+ };
55
+
42
56
  if (config.setPropType === 'cmsg') {
43
57
  Object.assign(message, value);
58
+ setTopic();
44
59
  send(message);
45
60
  this.status({fill: 'green', shape: 'ring', text: String(value.payload)});
46
61
  done();
@@ -55,6 +70,7 @@ module.exports = function (RED) {
55
70
 
56
71
  this.status({fill: 'green', shape: 'ring', text: String(value)});
57
72
 
73
+ setTopic();
58
74
  if (config.setPropType === 'msg') {
59
75
  RED.util.setMessageProperty(message, config.setProp, value);
60
76
  if (send) {
@@ -284,51 +284,3 @@
284
284
  </div>
285
285
  </div>
286
286
  </script>
287
-
288
- <script type="text/x-red" data-help-name="ccu-homeassistant" lang="de-DE">
289
- <p>Veröffentlicht Home-Assistant-MQTT-Discovery-Konfigurationen für ausgewählte Geräte.</p>
290
- <p>Der Node ist ein Begleiter zum <b>ccu-mqtt</b>-Node: er übernimmt dessen Topic-Vorlagen und
291
- Payload-Format, so dass die Discovery-Konfigurationen auf die Topics zeigen, die ccu-mqtt bereits
292
- veröffentlicht bzw. entgegennimmt. Status und Befehle laufen weiterhin über ccu-mqtt.</p>
293
- <h3>Verkabelung</h3>
294
- <p>Den Ausgang mit demselben <b>mqtt out</b>-Node verbinden wie den ccu-mqtt-Node. Der Node sendet
295
- <code>msg.topic</code>, <code>msg.payload</code> und <code>msg.retain</code>.</p>
296
- <h3>Geräteauswahl</h3>
297
- <p>Nur angehakte Geräte werden an Home Assistant gemeldet (ein HA-Gerät pro Homematic-Gerät).
298
- Wird ein zuvor angehaktes Gerät abgehakt, sendet der Node beim nächsten Deploy eine leere
299
- Konfiguration, die das Gerät in Home Assistant entfernt.</p>
300
- <h3>Entitäten</h3>
301
- <p>Schalter, Dimmer (light), Rollladen/Jalousie (cover), Thermostate (climate), Kontakte/Bewegung/
302
- Rauch/Wasser (binary_sensor), Tasten (event), KeyMatic (lock), Energie/Wetter (sensor). Mit der
303
- Option <i>weitere Datenpunkte</i> werden alle übrigen Datenpunkte als standardmäßig deaktivierte
304
- Entitäten mitgeliefert.</p>
305
- <h3>Eingang</h3>
306
- <p>Jede eingehende Nachricht veröffentlicht die Discovery-Konfigurationen erneut.</p>
307
- <h3>Voraussetzungen</h3>
308
- <p>Home Assistant ≥ 2024.11 (gerätebasierte Discovery). Die Verfügbarkeit der Geräte wird aus dem
309
- UNREACH-Datenpunkt des Wartungskanals abgeleitet.</p>
310
- </script>
311
-
312
- <script type="text/x-red" data-help-name="ccu-homeassistant" lang="en-US">
313
- <p>Publishes Home Assistant MQTT discovery configurations for selected devices.</p>
314
- <p>The node is a companion to the <b>ccu-mqtt</b> node: it reuses that node's topic templates and
315
- payload format, so the discovery configs point at the topics ccu-mqtt already publishes and
316
- consumes. State and commands keep flowing through ccu-mqtt.</p>
317
- <h3>Wiring</h3>
318
- <p>Connect the output to the same <b>mqtt out</b> node as the ccu-mqtt node. The node sends
319
- <code>msg.topic</code>, <code>msg.payload</code> and <code>msg.retain</code>.</p>
320
- <h3>Device selection</h3>
321
- <p>Only checked devices are announced to Home Assistant (one HA device per Homematic device).
322
- Unchecking a previously checked device publishes an empty config on the next deploy, which
323
- removes the device from Home Assistant.</p>
324
- <h3>Entities</h3>
325
- <p>Switches, dimmers (light), blinds/shutters (cover), thermostats (climate), contacts/motion/
326
- smoke/water (binary_sensor), keys (event), KeyMatic (lock), energy/weather (sensor). With the
327
- <i>other datapoints</i> option every remaining datapoint is included as an entity that is
328
- disabled by default.</p>
329
- <h3>Input</h3>
330
- <p>Any incoming message republishes the discovery configs.</p>
331
- <h3>Requirements</h3>
332
- <p>Home Assistant ≥ 2024.11 (device-based discovery). Device availability is derived from the
333
- UNREACH datapoint of the maintenance channel.</p>
334
- </script>
@@ -155,11 +155,3 @@
155
155
  }
156
156
  </style>
157
157
  </script>
158
-
159
- <script type="text/x-red" data-help-name="ccu-mqtt" lang="de-DE">
160
- <p>Vereinfacht die Anbindung einer CCU an MQTT.</p>
161
- </script>
162
-
163
- <script type="text/x-red" data-help-name="ccu-mqtt" lang="en-US">
164
- <p>Ease the connection of a CCU to MQTT.</p>
165
- </script>
@@ -33,20 +33,3 @@
33
33
  </div>
34
34
 
35
35
  </script>
36
-
37
- <script type="text/x-red" data-help-name="ccu-poll" lang="de-DE">
38
- <p>Führt einen sofortigen Poll von ReGaHSS Systemvariablen durch.</p>
39
- <p>Dieser Node ist dazu vorgesehen die Änderung von Systemvariablen mit möglichst geringer Verzögerung zu empfangen.
40
- Hierzu kann man ein Programm auf der CCU anlegen dass bei Änderung von Variablen einen virtuellen Taster betätigt.
41
- In Node-RED wird dann ein <i>rpc event</i> oder <i>value</i> Node so konfiguriert dass er diese
42
- "Tastenbetätigungen" empfängt und über den <i>ccu poll</i> Node eine Aktualisierung der Variablenwerte auslöst.
43
- </p>
44
- </script>
45
-
46
- <script type="text/x-red" data-help-name="ccu-poll" lang="en-US">
47
- <p>Triggers an immediate polling of Sysvars from ReGaHSS.</p>
48
- <p>This node is intended to receive changes of variables with lower latency. You can create a CCU Program that
49
- reacts to variable changes by pressing a virtual button, this virtual button presses can then be received by a
50
- <i>value</i> or <i>rpc event</i> node that triggers an update of the variables through the <i>ccu poll</i>
51
- node.</p>
52
- </script>
@@ -85,56 +85,3 @@
85
85
  </div>
86
86
  <div class="form-tips" data-i18n="ccu-program.tip"></div>
87
87
  </script>
88
-
89
- <script type="text/x-red" data-help-name="ccu-program" lang="de-DE">
90
- <p>Führt ein ReGaHSS Programm aus.</p>
91
- <h3>Inputs</h3>
92
- <dl class="message-properties">
93
- <dt>payload
94
- <span class="property-type">*</span>
95
- </dt>
96
- <dd>
97
- Ist der Payload vom Typ boolean wird das Programm bei <code>true</code> aktiviert und ausgeführt und bei
98
- <code>false</code> deaktiviert. In allen anderen Fällen (Payload ist z.B. ein leerer String) wird das
99
- Programm ausgeführt.
100
- </dd>
101
- </dl>
102
- <h3>Outputs</h3>
103
- <ol class="node-ports">
104
- <li>Output
105
- <dl class="message-properties">
106
- <dt>payload <span class="property-type">string</span></dt>
107
- <dd>
108
- Im Payload ist der Zeitstempel der letzten Programmausführung (Attribut <code>ts</code>) sowie
109
- die Information ob ein Programm aktiv oder inaktiv ist (Attribut <code>active</code>) enthalten.
110
- </dd>
111
- </dl>
112
- </li>
113
- </ol>
114
- </script>
115
-
116
- <script type="text/x-red" data-help-name="ccu-program" lang="en-US">
117
- <p>Executes a ReGaHSS program.</p>
118
- <h3>Inputs</h3>
119
- <dl class="message-properties">
120
- <dt>payload
121
- <span class="property-type">*</span>
122
- </dt>
123
- <dd>
124
- If the payload is of type boolean the program gets (de)activated. On activation it is executed also. In all
125
- other cases the program will be executed.
126
- </dd>
127
- </dl>
128
- <h3>Outputs</h3>
129
- <ol class="node-ports">
130
- <li>Output
131
- <dl class="message-properties">
132
- <dt>payload <span class="property-type">string</span></dt>
133
- <dd>
134
- The payload contains a timestamp of the last program run (property <code>ts</code> and the
135
- information if the program is activated (property <code>active</code>).
136
- </dd>
137
- </dl>
138
- </li>
139
- </ol>
140
- </script>
@@ -159,7 +159,6 @@
159
159
  data.nameChannels = {};
160
160
  data.nameDevices = {};
161
161
 
162
-
163
162
  Object.keys(data.channelRooms).forEach(channel => {
164
163
  const room = data.channelRooms[channel];
165
164
  const device = channel.split(':')[0];
@@ -298,7 +297,6 @@
298
297
  }
299
298
  }
300
299
 
301
-
302
300
  function checkDatapoint(datapoint) {
303
301
  let deviceCheck = false;
304
302
  let channelCheck = false;
@@ -609,35 +607,3 @@
609
607
  <input type="text" id="node-input-name">
610
608
  </div>
611
609
  </script>
612
-
613
- <script type="text/x-red" data-help-name="ccu-rpc-event" lang="de-DE">
614
- <p>Gibt RPC Events aus.</p>
615
- <h3>Konfiguration</h3>
616
- <ul>
617
- <li><b>CCU</b>: Die zu verwendende CCU-Konfiguration.</li>
618
- <li><b>topic</b>: <code>msg.topic</code> ausgehender Nachrichten. Kann mit Platzhaltern konfiguriert werden.</li>
619
- <li><b>interface</b>: Die Schnittstelle über welche die gewüschten Geräte angebunden sind. <code>*</code> erlaubt Events aller verbundenen Schnittstellen.</li>
620
- <li><b>room</b>: Raum Filter. Beispiel: <code>Wohnzimmer</code>.</li>
621
- <li><b>function</b>: Gewerk Filter. Beispiel: <code>Taster</code></li>
622
- <li><b>device</b>: Die Seriennummer der Homematic Komponente. Beispiel: <code>OEQ1662328</code></li>
623
- <li><b>deviceName</b>: Der in der CCU vergebene Name der Homematic Komponente. Beispiel: <code>Rauchmelder Arbeitszimmer</code>; alle Rauchemelder über RegEx: <code>Rauchmelder.*</code></li>
624
- <li><b>deviceType</b>: Die Typen-Bezeichnung der Homematic Komponente. Beispiel: <code>HM-Sec-SD-2</code></li>
625
- <li><b>channel</b>: Die Kanaladresse bestehend aus Serien- und Kanalnummer. Beispiel: <code>OEQ1245312:4</code></li>
626
- <li><b>channelName</b>: Der in der CCU vergebene Kanalname. Beispiel: <code>Bad Lichte Decke PIR</code></li>
627
- <li><b>channelType</b>: Der Typ des Kanals. Beispiel: <code>VIRTUAL_KEY</code> oder <code>DIMMER</code></li>
628
- <li><b>channelIndex</b>: Der Index des Kanals. Beispiel: <code>2</code>
629
- <li><b>datapoint</b>: Der Datenpunkt des Kanals. Beispiel: <code>PRESS_SHORT</code> oder <code>ACTUAL_TEMPERATURE</code>.</li>
630
- <li><b>Nur geänderte Werte ausgeben</b> - Ein Event wird nur dann erzeugt, wenn sich der Wert seit dem letztn Event verändert hat.</li>
631
- <li><b>Während WORKING keine Werte ausgeben</b> - Es gibt Aktoren, z.B. Dimmer oder Rolladen, die während einer Rampe (Öffnen/Schließen eines Rollladen, Dimmen einer Lampe) fortwährend den aktuellen Zustand ausgeben. Um nur den End-Status auszugeben kann diese Option benutzt werden. Gebräuchlich auch bei Verwendung mit Dashboard-Nodes um "springende" Slider zu verhindern.</li>
632
- <li><b>Beim Start letzten bekannten Wert ausgeben</b> - Wenn Node-RED gestartet wird, dann wird der letzte Wert (sofern in der ReGaHSS bekannt) ausgegeben. Z.B. um beim Start einen korrekten Wert an das Dashboard zu übergeben. <b>Achtung:</b> Wird durch die ausgegebene Nachricht im weiteren Verlauf des Flows ein Homematic Wert gesetzt wirkt sich jedes (Full-)Deployment negativ auf den DutyCycle aus.</li>
633
- </ul>
634
-
635
- <h3>Output</h3>
636
- <!-- TODO -->
637
-
638
- <!-- TODO Funktionsweise Filter erläutern -->
639
- </script>
640
-
641
- <script type="text/x-red" data-help-name="ccu-rpc-event" lang="en-US">
642
- <p>Outputs RPC events.</p>
643
- </script>
@@ -171,67 +171,3 @@
171
171
  <span data-i18n="ccu-rpc.tip3"></span>
172
172
  </div>
173
173
  </script>
174
-
175
-
176
- <script type="text/x-red" data-help-name="ccu-rpc" lang="de-DE">
177
- <p>Führt eine RPC Methode aus und gibt das Ergebnis zurück.</p>
178
- <h3>Inputs</h3>
179
- <dl class="message-properties">
180
- <dt>topic
181
- <span class="property-type">String</span>
182
- </dt>
183
- <dd>
184
- Die Methode die aufgerufen werden soll. Siehe <a href="https://www.eq-3.de/Downloads/eq3/download%20bereich/hm_web_ui_doku/HM_XmlRpc_API.pdf">XMLRPC API Dokumentation</a>
185
- </dd>
186
- <dt>payload
187
- <span class="property-type">Array|String</span>
188
- </dt>
189
- <dd>
190
- Ein Array oder ein in einem JSON-string enthaltenes Array von Parametern die für den RPC Methodenaufruf
191
- genutzt werden.
192
- </dd>
193
-
194
- </dl>
195
- <h3>Outputs</h3>
196
- <ol class="node-ports">
197
- <li>Output
198
- <dl class="message-properties">
199
- <dt>payload <span class="property-type">array</span></dt>
200
- <dd>
201
- Die Rückgabe des RPC Methodenaufrufs.
202
- </dd>
203
- </dl>
204
- </li>
205
- </ol>
206
- </script>
207
-
208
- <script type="text/x-red" data-help-name="ccu-rpc" lang="en-US">
209
- <p>Executes a RPC method and outputs the return value.</p>
210
- <h3>Inputs</h3>
211
- <dl class="message-properties">
212
- <dt>topic
213
- <span class="property-type">String</span>
214
- </dt>
215
- <dd>
216
- The method that should be called
217
- </dd>
218
- <dt>payload
219
- <span class="property-type">Array|String</span>
220
- </dt>
221
- <dd>
222
- An array or an JSON string containing an array of parameters for the rpc call.
223
- </dd>
224
-
225
- </dl>
226
- <h3>Outputs</h3>
227
- <ol class="node-ports">
228
- <li>Output
229
- <dl class="message-properties">
230
- <dt>payload <span class="property-type">array</span></dt>
231
- <dd>
232
- The return value of the rpc call.
233
- </dd>
234
- </dl>
235
- </li>
236
- </ol>
237
- </script>
@@ -44,11 +44,3 @@
44
44
  <div class="form-tips"><span data-i18n="ccu-script.tip"></span></div>
45
45
 
46
46
  </script>
47
-
48
- <script type="text/x-red" data-help-name="ccu-script" lang="de-DE">
49
- <p>Führt ein ReGaHSS Script auf der CCU aus und gibt die Rückgabe aus.</p>
50
- </script>
51
-
52
- <script type="text/x-red" data-help-name="ccu-script" lang="en-US">
53
- <p>Executes a ReGaHSS Script on the CCU and returns the output.</p>
54
- </script>
@@ -158,7 +158,6 @@
158
158
  data.nameChannels = {};
159
159
  data.nameDevices = {};
160
160
 
161
-
162
161
  Object.keys(data.channelRooms).forEach(channel => {
163
162
  const room = data.channelRooms[channel];
164
163
  const device = channel.split(':')[0];
@@ -298,7 +297,6 @@
298
297
  }
299
298
  }
300
299
 
301
-
302
300
  function checkDatapoint(datapoint) {
303
301
  let deviceCheck = false;
304
302
  let channelCheck = false;
@@ -481,7 +479,6 @@
481
479
  });
482
480
  }
483
481
 
484
-
485
482
  Object.keys(lists).forEach(key => {
486
483
  if (key === 'channelIndex') {
487
484
  lists[key].sort((a, b) => Number(a) > Number(b));
@@ -608,62 +605,3 @@
608
605
  </p>
609
606
  </div>
610
607
  </script>
611
-
612
-
613
-
614
- <script type="text/x-red" data-help-name="ccu-set-value" lang="de-DE">
615
- <p>Ansteuerung von mehreren Geräten auf einmal.</p>
616
- <h3>Konfiguration</h3>
617
- <ul>
618
- <li><b></b>: </li>
619
- <li><b></b>: </li>
620
- <li><b></b>: </li>
621
- <li><b></b>: </li>
622
- <li><b></b>: </li>
623
- </ul>
624
-
625
- <h3>Input</h3>
626
-
627
-
628
- <h3>Dynamische Konfiguration</h3>
629
- <p><code>msg.config</code> ist ein Objekt, dessen Eigenschaften die Konfiguration dieses Nodes für genau diese Nachricht überschreiben. Die gespeicherte Konfiguration bleibt unverändert.</p>
630
- <ul>
631
- <li><code>iface</code></li>
632
- <li><code>rooms</code></li>
633
- <li><code>functions</code></li>
634
- <li><code>device</code></li>
635
- <li><code>deviceType</code></li>
636
- <li><code>deviceName</code></li>
637
- <li><code>channel</code></li>
638
- <li><code>channelType</code></li>
639
- <li><code>channelIndex</code></li>
640
- <li><code>channelName</code></li>
641
- <li><code>datapoint</code></li>
642
- <li><code>force</code></li>
643
- <li><code>sowie die zugehörigen <code>...Rx</code>-Selektoren</code></li>
644
- </ul>
645
- <p>Zusätzlich füllen gleichnamige Eigenschaften der Nachricht selbst (<code>msg.rooms</code> usw.) leer gelassene Felder — so war es schon immer.</p>
646
- </script>
647
-
648
- <script type="text/x-red" data-help-name="ccu-set-value" lang="en-US">
649
- <p>Control multiple devices at once.</p>
650
-
651
- <h3>Dynamic configuration</h3>
652
- <p><code>msg.config</code> is an object whose properties override this node's configuration for that one message. The stored configuration is never modified.</p>
653
- <ul>
654
- <li><code>iface</code></li>
655
- <li><code>rooms</code></li>
656
- <li><code>functions</code></li>
657
- <li><code>device</code></li>
658
- <li><code>deviceType</code></li>
659
- <li><code>deviceName</code></li>
660
- <li><code>channel</code></li>
661
- <li><code>channelType</code></li>
662
- <li><code>channelIndex</code></li>
663
- <li><code>channelName</code></li>
664
- <li><code>datapoint</code></li>
665
- <li><code>force</code></li>
666
- <li><code>and the matching <code>...Rx</code> selectors</code></li>
667
- </ul>
668
- <p>Properties of the message itself (<code>msg.rooms</code> and so on) also fill in fields left empty in the dialog, as they always did.</p>
669
- </script>
@@ -102,18 +102,13 @@ module.exports = function (RED) {
102
102
  }
103
103
 
104
104
  datapointsOf(this.ccu, iface, address, config).forEach((dp) => {
105
- const datapointName = iface + '.' + address + '.' + dp;
106
- const currentValue = this.ccu.values[datapointName] && this.ccu.values[datapointName].value;
107
105
  count += 1;
108
- if (
109
- dp.startsWith('PRESS_') ||
110
- typeof currentValue === 'undefined' ||
111
- currentValue !== message.payload
112
- ) {
113
- this.ccu
114
- .setValueQueued(iface, address, dp, message.payload, false, config.force)
115
- .catch(() => {});
116
- }
106
+ // the queue dedupes against the value cache itself (B-19: force and
107
+ // the echo of our own write get through; the pre-check here used to
108
+ // drop a forced write whenever the cache already held the value)
109
+ this.ccu
110
+ .setValueQueued(iface, address, dp, message.payload, false, config.force)
111
+ .catch(() => {});
117
112
  });
118
113
  });
119
114
  });
@@ -617,7 +617,6 @@
617
617
  <input id="node-input-dimmerLevelType" type="hidden">
618
618
  </div>
619
619
 
620
-
621
620
  <div class="form-row SUBMIT ACOUSTIC_SIGNAL_VIRTUAL_RECEIVER DIMMER_VIRTUAL_RECEIVER BSL_DIMMER_VIRTUAL_RECEIVER">
622
621
  <label for="node-input-rampTimeUnit"><i class=""></i> Rampenzeit </label>
623
622
  <select id="node-input-rampTimeUnit" style="width: calc(35% - 5px)">
@@ -629,7 +628,6 @@
629
628
  <input id="node-input-rampTimeValueType" type="hidden">
630
629
  </div>
631
630
 
632
-
633
631
  <div class="form-row SUBMIT ALARM_SWITCH_VIRTUAL_RECEIVER ACOUSTIC_SIGNAL_VIRTUAL_RECEIVER DIMMER_VIRTUAL_RECEIVER BSL_DIMMER_VIRTUAL_RECEIVER">
634
632
  <label for="node-input-durationUnit"><i class=""></i> Dauer </label>
635
633
  <select id="node-input-durationUnit" style="width: calc(35% - 5px)">
@@ -641,66 +639,4 @@
641
639
  <input id="node-input-durationValueType" type="hidden">
642
640
  </div>
643
641
 
644
-
645
-
646
- </script>
647
-
648
- <script type="text/x-red" data-help-name="ccu-signal" lang="de-DE">
649
- <p>Senden von LED- und Tonsignalen an Displaytaster und Funk-Gongs.</p>
650
-
651
- <h3>Dynamische Konfiguration</h3>
652
- <p><code>msg.config</code> ist ein Objekt, dessen Eigenschaften die Konfiguration dieses Nodes für genau diese Nachricht überschreiben. Die gespeicherte Konfiguration bleibt unverändert.</p>
653
- <ul>
654
- <li><code>iface</code></li>
655
- <li><code>channel</code></li>
656
- <li><code>channelType</code></li>
657
- <li><code>chime</code></li>
658
- <li><code>led</code></li>
659
- <li><code>signal</code></li>
660
- <li><code>volume</code></li>
661
- <li><code>repeat</code></li>
662
- <li><code>repetitions</code></li>
663
- <li><code>durationUnit</code></li>
664
- <li><code>durationValue</code></li>
665
- <li><code>rampTimeUnit</code></li>
666
- <li><code>rampTimeValue</code></li>
667
- <li><code>acousticAlarmSelection</code></li>
668
- <li><code>opticalAlarmSelection</code></li>
669
- <li><code>dimmerLevel</code></li>
670
- <li><code>dimmerColor</code></li>
671
- <li><code>dimmerList</code></li>
672
- <li><code>soundLevel</code></li>
673
- <li><code>soundList</code></li>
674
- </ul>
675
- <p><code>soundList</code> und <code>dimmerList</code> akzeptieren auch ein einfaches Array von Werten, z.B. <code>msg.config.soundList = [1, 2]</code>.</p>
676
- </script>
677
-
678
- <script type="text/x-red" data-help-name="ccu-signal" lang="en-US">
679
- <p>Send LED- and Sound-Signals.</p>
680
-
681
- <h3>Dynamic configuration</h3>
682
- <p><code>msg.config</code> is an object whose properties override this node's configuration for that one message. The stored configuration is never modified.</p>
683
- <ul>
684
- <li><code>iface</code></li>
685
- <li><code>channel</code></li>
686
- <li><code>channelType</code></li>
687
- <li><code>chime</code></li>
688
- <li><code>led</code></li>
689
- <li><code>signal</code></li>
690
- <li><code>volume</code></li>
691
- <li><code>repeat</code></li>
692
- <li><code>repetitions</code></li>
693
- <li><code>durationUnit</code></li>
694
- <li><code>durationValue</code></li>
695
- <li><code>rampTimeUnit</code></li>
696
- <li><code>rampTimeValue</code></li>
697
- <li><code>acousticAlarmSelection</code></li>
698
- <li><code>opticalAlarmSelection</code></li>
699
- <li><code>dimmerLevel</code></li>
700
- <li><code>dimmerColor</code></li>
701
- <li><code>dimmerList</code></li>
702
- <li><code>soundLevel</code></li>
703
- <li><code>soundList</code></li>
704
- </ul>
705
- <p><code>soundList</code> and <code>dimmerList</code> also accept a plain array of values, e.g. <code>msg.config.soundList = [1, 2]</code>.</p>
706
642
  </script>
@@ -114,6 +114,7 @@
114
114
  let ifacesLoaded = false;
115
115
  let ifacesPending = false;
116
116
  let ifaceLoadRetries = 5;
117
+ let channelLoadRetries = 30;
117
118
 
118
119
  $('.form-row.datapoint').hide();
119
120
  $('.form-row.sysvar').hide();
@@ -180,7 +181,16 @@
180
181
  }
181
182
  const nodeId = $nodeInputCcuConfig.val();
182
183
  const url = 'ccu?config=' + nodeId + '&type=channels&iface=' + $nodeInputIface.val();
183
- $.getJSON(url, d => {
184
+ $.getJSON(url, (d, _status, xhr) => {
185
+ // task 9: an empty list while the connection is still initialising is "not yet",
186
+ // not "nothing" - keep what is configured, say so, and ask again
187
+ if (Object.keys(d).length === 0 && xhr.getResponseHeader('X-CCU-Loading') && channelLoadRetries-- > 0) {
188
+ $nodeInputChannel.attr('placeholder', 'loading device data ...');
189
+ setTimeout(loadConfig, 2000);
190
+ return;
191
+ }
192
+
193
+ $nodeInputChannel.removeAttr('placeholder');
184
194
  data = d;
185
195
  autocompleteChannel();
186
196
  autocompleteDatapoint();
@@ -241,7 +251,7 @@
241
251
 
242
252
  // ${ENV} placeholders are substituted by Node-RED before the node is
243
253
  // constructed (subflow parameters, #158) - do not clear them
244
- if (!/^\$\{[^}]+\}$/.test($nodeInputChannel.val()) && !data[$nodeInputChannel.val().split(' ')[0]]) {
254
+ if (Object.keys(data).length > 0 && !/^\$\{[^}]+\}$/.test($nodeInputChannel.val()) && !data[$nodeInputChannel.val().split(' ')[0]]) {
245
255
  $nodeInputChannel.val('');
246
256
  $nodeInputDatapoint.val('');
247
257
  }
@@ -733,7 +743,6 @@
733
743
  })();
734
744
  </script>
735
745
 
736
-
737
746
  <script type="text/x-red" data-template-name="ccu-switch" lang="en-US">
738
747
  <div class="form-row">
739
748
  <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="ccu-switch.label.name"></span></label>
@@ -796,24 +805,3 @@
796
805
  </div>
797
806
 
798
807
  </script>
799
-
800
- <script type="text/x-red" data-help-name="ccu-switch" lang="de-DE">
801
- <p>Nachricht abhängig von einem Zustand eines Aktors oder einer Systemvariablen weiterleiten.</p>
802
- <h3>Details</h3>
803
- <p>Der ccu switch Node verhält sich ähnlich wie der switch Node von Node-RED. Er leitet eine Nachricht abhängig von einem Zustand eines Aktors oder einer Systemvariablen weiter, wahlweise auch je nach Zustand an unterschiedliche Ausgänge.</p>
804
- <h4>Dokumentation</h4>
805
- <a target="_blank" href="https://github.com/rdmtc/RedMatic/wiki/CCU-Nodes#ccu-switch-node">ccu switch node im RedMatic Wiki</a>
806
-
807
- <h3>Dynamische Konfiguration</h3>
808
- <p><code>msg.config</code> ist ein Objekt, dessen Eigenschaften die Konfiguration dieses Nodes für genau diese Nachricht überschreiben. Die gespeicherte Konfiguration bleibt unverändert.</p>
809
- <ul>
810
- <li><code>iface</code></li>
811
- <li><code>channel</code></li>
812
- <li><code>datapoint</code></li>
813
- <li><code>datapointProperty</code></li>
814
- <li><code>sysvar</code></li>
815
- <li><code>sysvarProperty</code></li>
816
- </ul>
817
- </script>
818
-
819
-