node-red-contrib-ccu 4.4.0 → 4.4.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
@@ -5,6 +5,34 @@ Notable changes to node-red-contrib-ccu. Format follows
5
5
  user-visible symptom and the cause, not the commit list (the release notes
6
6
  append commits automatically).
7
7
 
8
+ ## 4.4.1 (2026-09-07)
9
+
10
+ ### Fixed
11
+
12
+ - **Node-RED could be killed by a failed ReGaHSS write, seconds after
13
+ start** ([RedMatic #601](https://github.com/rdmtc/RedMatic/issues/601)).
14
+ A write to a system variable that arrives before the variable list is
15
+ known is deferred into a queue and flushed once the first
16
+ `getRegaVariables` completes. That flush dropped the resulting promise,
17
+ so a rejected write — ReGaHSS closing the connection, `Error: socket
18
+ hang up` — became an **unhandled rejection**, which Node >= 15 turns
19
+ into an uncaught exception: the whole Node-RED process exited with
20
+ status 1 and its supervisor restarted it into the same crash. The
21
+ rejection is now caught and logged.
22
+
23
+ This became reachable in 4.3.0: the rewritten local-CCU detection made
24
+ `isLocal` true again on RedMatic boxes (it had silently stopped
25
+ matching on current firmware), which moves ReGa traffic from lighttpd
26
+ on 8181 to ReGaHSS directly on 8183. lighttpd absorbed a busy ReGaHSS;
27
+ the direct port simply closes the connection.
28
+
29
+ - The same floating-promise pattern in `ccu-mqtt`: `setVariable`,
30
+ `programActive` and `programExecute` triggered over MQTT dropped their
31
+ promises too, and now report through the node's error output instead of
32
+ taking the process down.
33
+ - `regaPoll`'s `finally` chain is caught as well, so a throw in the
34
+ follow-up scheduling cannot escape as an unhandled rejection.
35
+
8
36
  ## 4.4.0 (2026-09-06)
9
37
 
10
38
  ### Added
package/HANDOFF.md CHANGED
@@ -28,6 +28,20 @@ Lab addresses and credentials are intentionally **not** in this file
28
28
  re-poll, RSSI guard). All four archived. Branch `b-2-b-5` merged with
29
29
  `--no-ff`; 145 pure tests, 23 integration specs green on all four CI
30
30
  legs.
31
+ - **4.4.0 released 2026-09-06** (tag v4.4.0, npm latest = 4.4.0):
32
+ B-17, the openccu-lite port. `nodes/lib/metaprovider.js` takes names,
33
+ rooms and functions from the box's metadata API (`/api/meta/v1`
34
+ snapshot + SSE) when `GET /api/meta/v1/version` answers; a CCU
35
+ answers 404 and the ReGa path is byte-for-byte what it was. Two
36
+ optional connection fields (openccu-lite token, port); on the box the
37
+ token comes from `/usr/local/etc/occulite/local-token`. sysvar,
38
+ program, script and poll stay in the palette and error per message.
39
+ 16 unit tests plus a verification against a real `occulited` built
40
+ from ../openccu-lite (see roadmap-archive/B-17.md). Branch
41
+ `b-17-openccu-lite` merged with `--no-ff` and deleted. **Open: no test
42
+ on real openccu-lite hardware, and the connection dialog with the two
43
+ new fields has not been opened in a browser.** RedMatic's own port
44
+ needs `node-red-contrib-ccu@^4.4.0`.
31
45
  - Issue tracker: 36 → **19 open**. The 17 issues 4.3.0 fixes were
32
46
  commented and closed after the release (#172 #71 #103 #80 #56 #148
33
47
  #133 #115 #22 #167 #44 #54 #52 #96 #166 #183 #51, plus comments on the
@@ -1593,7 +1593,10 @@ module.exports = function (RED) {
1593
1593
  this.regaPollAgain = false;
1594
1594
  this.refreshRegaDataIfDue();
1595
1595
  }
1596
- });
1596
+ })
1597
+ // a throw inside the finally above would otherwise be an
1598
+ // unhandled rejection, see #601
1599
+ .catch((error) => this.logger.error('regaPoll', error));
1597
1600
  }
1598
1601
  }
1599
1602
 
@@ -1784,10 +1787,17 @@ module.exports = function (RED) {
1784
1787
  Object.keys(this.setVariableQueueTimeout).forEach((name) =>
1785
1788
  clearTimeout(this.setVariableQueueTimeout[name]),
1786
1789
  );
1787
- Object.keys(this.setVariableQueue).reduce(
1788
- (p, name) => p.then((_) => this.setVariable(name, this.setVariableQueue[name])),
1789
- Promise.resolve(),
1790
- );
1790
+ // #601: a rejected write here used to be an
1791
+ // unhandled rejection, which Node >= 15 turns into
1792
+ // an uncaught exception - it killed the whole
1793
+ // process seconds after start whenever ReGaHSS
1794
+ // dropped the connection (RedMatic #601).
1795
+ Object.keys(this.setVariableQueue)
1796
+ .reduce(
1797
+ (p, name) => p.then((_) => this.setVariable(name, this.setVariableQueue[name])),
1798
+ Promise.resolve(),
1799
+ )
1800
+ .catch((error) => this.logger.error('deferred setVariable', error));
1791
1801
  }
1792
1802
 
1793
1803
  resolve();
package/nodes/ccu-mqtt.js CHANGED
@@ -405,13 +405,22 @@ module.exports = function (RED) {
405
405
  return;
406
406
  }
407
407
 
408
+ // #601: these promises used to float - a rejection (e.g. ReGaHSS
409
+ // closing the connection) became an unhandled rejection and took
410
+ // the whole Node-RED process down.
408
411
  if (this.ccu.sysvar[filter.name]) {
409
- this.ccu.setVariable(filter.name, payload);
412
+ this.ccu
413
+ .setVariable(filter.name, payload)
414
+ .catch((error) => this.error('setVariable ' + filter.name + ': ' + error.message));
410
415
  } else if (this.ccu.program[filter.name]) {
411
416
  if (typeof payload === 'boolean') {
412
- this.ccu.programActive(filter.name, payload);
417
+ this.ccu
418
+ .programActive(filter.name, payload)
419
+ .catch((error) => this.error('programActive ' + filter.name + ': ' + error.message));
413
420
  } else {
414
- this.ccu.programExecute(filter.name);
421
+ this.ccu
422
+ .programExecute(filter.name)
423
+ .catch((error) => this.error('programExecute ' + filter.name + ': ' + error.message));
415
424
  }
416
425
  } else {
417
426
  this.error('no sysvar or program with name ' + filter.name + ' found');
package/nodes/ccu-poll.js CHANGED
@@ -23,7 +23,8 @@ module.exports = function (RED) {
23
23
  return;
24
24
  }
25
25
 
26
- this.ccu.regaPoll(); // TODO catch errors
26
+ // regaPoll() returns nothing and handles its own errors (#601)
27
+ this.ccu.regaPoll();
27
28
  done();
28
29
  });
29
30
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-red-contrib-ccu",
3
- "version": "4.4.0",
3
+ "version": "4.4.1",
4
4
  "license": "MIT",
5
5
  "main": "none",
6
6
  "keywords": [