node-red-contrib-ccu 4.6.1 → 4.6.2

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,19 @@ 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.6.2 (2026-10-23)
9
+
10
+ ### Fixed
11
+
12
+ - **One event a few times a day was lost on the way from hmipserver, which
13
+ logged a `RpcIOException … Connection reset` for it.** hmipserver delivers
14
+ its events through a pooled HTTP keep-alive client whose idle timeout is
15
+ 1200 s and sends the next event on a pooled connection without checking it;
16
+ the XML-RPC callback server closed an idle connection after Node's default
17
+ 5 s, so at the idle boundary the event went out onto a socket this side was
18
+ closing. The callback server now keeps an idle connection open for 1300 s,
19
+ longer than the client pool does, so it is always the client that lets go.
20
+
8
21
  ## 4.6.1 (2026-10-22)
9
22
 
10
23
  ### Fixed
@@ -13,9 +26,8 @@ append commits automatically).
13
26
  maintenance channel's `STICKY_UNREACH`** went out as a `switch` with
14
27
  `device_class: problem`, a class only `binary_sensor` knows, and Home
15
28
  Assistant refused that component ("expected SwitchDeviceClass or one of
16
- 'outlet', 'switch'") while it created the device and its other entities
17
- (B-39). `STICKY_UNREACH` is no longer announced at all - the maintainer's
18
- decision: "UNREACH is enough" -, and a device class a platform does not
29
+ 'outlet', 'switch'") while it created the device and its other entities. `STICKY_UNREACH` is no longer announced at all
30
+ (UNREACH covers it), and a device class a platform does not
19
31
  accept is dropped from any component before it goes out. A test now checks
20
32
  every component of every device the shipped paramsets know against Home
21
33
  Assistant's device classes per platform.
@@ -44,7 +56,7 @@ append commits automatically).
44
56
  ### Fixed
45
57
 
46
58
  - **Home Assistant showed every entity of a device as "unavailable" for
47
- good** (B-38, reported by mail). The discovery configs name the device's
59
+ good** (reported by mail). The discovery configs name the device's
48
60
  `…:0/UNREACH` topic as its availability, and Home Assistant treats an
49
61
  entity as unavailable until that topic delivers a value. Only `ccu-mqtt`
50
62
  published UNREACH: when it changed, or once in its start-up burst of
@@ -64,8 +76,7 @@ append commits automatically).
64
76
 
65
77
  ### Fixed
66
78
 
67
- - **No HmIP-RF events for up to 10 minutes after hmipserver restarted**
68
- (B-37). hmipserver keeps its subscribers over a restart: it calls
79
+ - **No HmIP-RF events for up to 10 minutes after hmipserver restarted**. hmipserver keeps its subscribers over a restart: it calls
69
80
  `listDevices` and `newDevices` on them and answers their pings, but
70
81
  delivers no event to such a kept subscription until it is subscribed
71
82
  afresh. The liveness ping saw its PONG and was content, so the
@@ -80,7 +91,7 @@ append commits automatically).
80
91
  ### Fixed
81
92
 
82
93
  - **A burst of `getParamsetDescription Error: XML-RPC fault: Invalid device`
83
- at the first start after an update** (B-36). A device deleted from the CCU
94
+ at the first start after an update**. A device deleted from the CCU
84
95
  while Node-RED was not running stayed in the cached device table
85
96
  (`ccu_<host>.json`) and in the values cache (`ccu_values_<host>.json`).
86
97
  At the start its paramset descriptions were queued from the cached table;
@@ -105,7 +116,7 @@ append commits automatically).
105
116
  ### Added
106
117
 
107
118
  - **TLS and authentication for every connection to a CCU on the network**
108
- (task 5, #27). With _TLS/SSL_ on, all XML-RPC interfaces are reached over
119
+ (#27). With _TLS/SSL_ on, all XML-RPC interfaces are reached over
109
120
  the CCU's TLS ports (42000, 42001, 42010, 49292; CCU-Jack 2122), the ReGaHSS
110
121
  over 48181 and openccu-lite's metadata api over 443; with _Authentication_
111
122
  on, the username and password go out as HTTP basic auth on every call, the
@@ -126,7 +137,7 @@ append commits automatically).
126
137
  certificates_, the CCU's self-signed certificate is refused, as before.
127
138
 
128
139
  - **One topic template in every node that emits, the value node's input
129
- takes the emitted shape** (task 6, #39 @psi-4ward). The `get value` node has a _Topic_
140
+ takes the emitted shape** (#39 @psi-4ward). The `get value` node has a _Topic_
130
141
  field now, the same `${…}` template as rpc-event, value, sysvar, program,
131
142
  rpc and script; empty (the default, and every existing flow) leaves
132
143
  `msg.topic` as it came in. The value node's input accepts a datapoint
@@ -140,7 +151,7 @@ append commits automatically).
140
151
  rpc-event, value and get value the placeholders.
141
152
 
142
153
  - **Help texts for every node in German and English, as locale files**
143
- (task 7, #58). The help moved from inline blocks in the node files into
154
+ (#58). The help moved from inline blocks in the node files into
144
155
  `nodes/locales/de/` and `nodes/locales/en-US/`, the layout Node-RED
145
156
  documents for node help: the runtime serves one language's text per
146
157
  request through the same lookup as its own nodes (`de` and `de-DE` both
@@ -158,7 +169,7 @@ append commits automatically).
158
169
  ### Fixed
159
170
 
160
171
  - **Writing one party-mode datapoint of an HmIP thermostat reset the other
161
- two** (task 2, #156 @ben-5555, #161 @lolli78). An HmIP eTRV/WTH takes
172
+ two** (#156 @ben-5555, #161 @lolli78). An HmIP eTRV/WTH takes
162
173
  `PARTY_TIME_START`, `PARTY_TIME_END` and `PARTY_SET_POINT_TEMPERATURE` only
163
174
  together: a `setValue` of one of them put the others back to
164
175
  `1999_11_30 00:00`, so party or holiday mode could not be set from the
@@ -170,7 +181,7 @@ append commits automatically).
170
181
  Date, an ISO string or epoch milliseconds; they are formatted for the device
171
182
  in local time. Any other datapoint of the channel is written as before. The
172
183
  older HM thermostats (`PARTY_MODE_SUBMIT`) are not covered.
173
- - **A callback call with an unknown interface id ended Node-RED** (B-32).
184
+ - **A callback call with an unknown interface id ended Node-RED**.
174
185
  Anything on the system can connect to the connection's callback ports on
175
186
  the loopback; a `system.listMethods` without parameters, an `event` with an
176
187
  id that is not one of ours, or a `newDevices` list with a malformed entry
@@ -180,7 +191,7 @@ append commits automatically).
180
191
  `system.listMethods`) and logged at debug; a throw inside a handler is
181
192
  logged as an error and answered instead of ending the process.
182
193
  - **A metadata api detection that timed out at start left the connection in
183
- ReGa mode for good** (B-28). On openccu-lite the connection asks
194
+ ReGa mode for good**. On openccu-lite the connection asks
184
195
  `GET /api/meta/v1/version` once at start; when that probe ran into its 5 s
185
196
  timeout - on a Raspberry Pi 3 Node-RED's own start blocks the event loop
186
197
  long enough for that at every start, on a busy system now and then - the
@@ -191,8 +202,7 @@ append commits automatically).
191
202
  the detection is repeated after 1, 2, 4, 8 s and then every 15 s (up to 20
192
203
  times, then the five-minute rule again), and the failing ReGa poll asks for
193
204
  a re-detection too. A CCU's 404 is still a conclusive "no".
194
- - **After an hmipserver restart HmIP-RF events stopped for up to ten minutes**
195
- (B-29). hmipserver forgets its clients when it restarts and does not tell
205
+ - **After an hmipserver restart HmIP-RF events stopped for up to ten minutes**. hmipserver forgets its clients when it restarts and does not tell
196
206
  them: the `init` had succeeded, nothing failed, and the events simply stopped
197
207
  until the 600 s silence timeout called `init` again. The connection now
198
208
  pings HmIP-RF after 30 s without an event and, when no event (the PONG)
@@ -203,7 +213,7 @@ append commits automatically).
203
213
  events are back well within a minute. An interface that never delivered an
204
214
  event since its `init` is not re-subscribed on a missing PONG alone.
205
215
  - **A queued write of the same set point was dropped after the actuator had
206
- been operated by hand** (B-19, #151 @vigeland). The value node's _Queue_ compared the
216
+ been operated by hand** (#151 @vigeland). The value node's _Queue_ compared the
207
217
  new value with the value cache, and the cache of a control channel
208
218
  (HmIP-FROLL/BROLL `:4`, the status lives in `:3`) holds the echo of our own
209
219
  last write for good - a blind moved by hand reports no new set point there,
@@ -217,7 +227,7 @@ append commits automatically).
217
227
  ### Security
218
228
 
219
229
  - **The CCU password and the openccu-lite token were stored in plain text in
220
- `flows.json`** and went out with every exported flow (B-31). Both are
230
+ `flows.json`** and went out with every exported flow. Both are
221
231
  Node-RED credentials now (`flows_cred.json`, encrypted, never exported).
222
232
  A flow written before this version still carries them as plain properties:
223
233
  the connection uses them once, moves them into the credentials and warns;
@@ -226,8 +236,7 @@ append commits automatically).
226
236
 
227
237
  ### Changed
228
238
 
229
- - **The device table follows the CCU, and can be re-read by hand** (task 9,
230
- #146 @guny74, #181 @vore). A device or channel the CCU reports with another TYPE,
239
+ - **The device table follows the CCU, and can be re-read by hand** (#146 @guny74, #181 @vore). A device or channel the CCU reports with another TYPE,
231
240
  VERSION or FIRMWARE than the cache holds replaces the cached entry, leaves
232
241
  its old type list and gets its datapoints fetched again - a channel whose
233
242
  type changed in place kept its old datapoints before, until the cache file
@@ -237,14 +246,14 @@ append commits automatically).
237
246
  reports what changed. The editor's channel pickers no longer empty the
238
247
  configured channel when the connection is still initialising: they show
239
248
  _loading device data_ and ask again.
240
- - **An interface without devices is watched too** (task 9, old B-11). The
249
+ - **An interface without devices is watched too**. The
241
250
  ping watchdog returned early for an interface with no devices in the
242
251
  cache, so such an interface never pinged and never re-initialised after a
243
252
  CCU reboot. It pings now, and re-initialises after the ping timeout once
244
253
  it has ever delivered an event (a PONG counts) - a process that answers no
245
254
  ping at all is not asked to `init` every timeout.
246
255
  - **The `listDevices` answer to hmipserver lists the CCU's virtual remote
247
- control (HmIP-RCV-1) again** (task 13). It was left out since CCU3 firmware
256
+ control (HmIP-RCV-1) again**. It was left out since CCU3 firmware
248
257
  3.43.15 (2019), whose hmipserver failed on an answer that held it; current
249
258
  hmipservers take it, and without it every `init` made hmipserver log a
250
259
  _handleIDMigration_ warning and send the whole virtual remote (52
@@ -262,8 +271,7 @@ append commits automatically).
262
271
  proxy ports (XML-RPC instead of BIN-RPC for BidCos) until the next restart.
263
272
  A loopback host on a system that has the CCU's interface list
264
273
  (`/etc/config/InterfacesList.xml`) is now taken as local as well.
265
- - **Waiting for an interface process that is still starting is no warning**
266
- (task 12). Before the interface was ever connected, a refused connection
274
+ - **Waiting for an interface process that is still starting is no warning**. Before the interface was ever connected, a refused connection
267
275
  is one info line (_"HmIP-RF not listening yet (connect ECONNREFUSED),
268
276
  waiting for it - retrying in 1 s"_); another transport error, or a refused
269
277
  connection after the interface had been connected, is still a warning, and
@@ -272,7 +280,7 @@ append commits automatically).
272
280
  ### Changed
273
281
 
274
282
  - **A failed `init` is retried after 1 s, 2 s, 4 s and 8 s, then every 15 s**
275
- (task 12; was 2, 4, 8, 16 s, then every 30 s), the schedule of hm2mqtt.js and
283
+ (was 2, 4, 8, 16 s, then every 30 s), the schedule of hm2mqtt.js and
276
284
  the Homematic Manager.
277
285
 
278
286
  ## 4.4.4 (2026-09-17)
@@ -280,7 +288,7 @@ append commits automatically).
280
288
  ### Fixed
281
289
 
282
290
  - **An interface stayed without events for minutes, or for good, when its
283
- process did not answer the first `init`** (task 11). A failed `init` at
291
+ process did not answer the first `init`**. A failed `init` at
284
292
  start (connection refused, timeout) was only retried by the ping
285
293
  supervision, which does nothing without cached devices and waits the ping
286
294
  timeout otherwise: 60 s, and 600 s for HmIP-RF. A Node-RED that starts
@@ -298,8 +306,7 @@ append commits automatically).
298
306
 
299
307
  ### Fixed
300
308
 
301
- - **Node-RED at 100 % CPU and unresponsive while ReGaHSS is unreachable**
302
- (B-27). binrpc up to 4.2.0 armed a new reconnect timer for both the `error`
309
+ - **Node-RED at 100 % CPU and unresponsive while ReGaHSS is unreachable**. binrpc up to 4.2.0 armed a new reconnect timer for both the `error`
303
310
  and the `close` event of every refused connect, so the number of attempts to
304
311
  the ReGaHSS port 31999 doubled every 2.5 s without bound: about 7,000 refused
305
312
  connects per second, 30,000 pending timers and 68 million connects in under
@@ -317,7 +324,7 @@ append commits automatically).
317
324
  ### Fixed
318
325
 
319
326
  - **`getRegaVariables Error: socket hang up` every few minutes on a CCU**
320
- (B-18, [RedMatic #601](https://github.com/rdmtc/RedMatic/issues/601)
327
+ ([RedMatic #601](https://github.com/rdmtc/RedMatic/issues/601)
321
328
  follow-up). Since 4.3.0 a local install talks to ReGaHSS itself on port 8183. ReGaHSS answers HTTP/1.1 without `Connection: close` — and then
322
329
  closes the connection 0.4–7 ms after every response (measured on a
323
330
  CCU3 3.89.8, median 0.55 ms). `homematic-rega` 2.0 (since 4.0.0) sent
@@ -374,7 +381,7 @@ hang up` — became an **unhandled rejection**, which Node >= 15 turns
374
381
 
375
382
  ### Added
376
383
 
377
- - **Dynamic node configuration through `msg.config`** (roadmap B-2). Put
384
+ - **Dynamic node configuration through `msg.config`**. Put
378
385
  an object in `msg.config` and its properties override that node's own
379
386
  configuration for that one message; the stored configuration is never
380
387
  modified, so the next message starts from the dialog settings again.
@@ -449,7 +456,6 @@ hang up` — became an **unhandled rejection**, which Node >= 15 turns
449
456
  `/etc/lighttpd/conf.d/proxy.conf` for a port number; on current
450
457
  firmware that file is a one-line include and the port markers live two
451
458
  levels down. It now looks for a listener on the direct port instead.
452
- (Roadmap B-4)
453
459
  - Writing several system variables at once left all but the first
454
460
  invisible until the next scheduled ReGa poll (30 s by default): the
455
461
  immediate re-poll each write triggers was dropped while another poll
@@ -481,7 +487,7 @@ hang up` — became an **unhandled rejection**, which Node >= 15 turns
481
487
  presence, smoke, water), event (keys), lock (KeyMatic), sensor (energy,
482
488
  weather, maintenance) plus, optionally, disabled-by-default entities for
483
489
  every other datapoint. Unchecking a device removes it from Home
484
- Assistant on the next deploy. (Roadmap B-16)
490
+ Assistant on the next deploy.
485
491
  - ccu-mqtt: the setValue topic accepts Home Assistant's command words —
486
492
  `OPEN`, `CLOSE`, `STOP`, `ON`, `OFF` on LEVEL and `AUTO-MODE`,
487
493
  `MANU-MODE`, `BOOST-MODE`, `COMFORT-MODE`, `LOWERING-MODE` on the
@@ -21,6 +21,10 @@ const {InitRetry, retryDelay} = require('./lib/initretry.js');
21
21
  const xmlrpc = require('homematic-xmlrpc');
22
22
  const binrpc = require('binrpc');
23
23
 
24
+ /** how long the XML-RPC callback server keeps an idle keep-alive connection open: longer than
25
+ * hmipserver's HTTP client pool (1200 s), so the pool never reuses a connection this side closed */
26
+ const KEEP_ALIVE_TIMEOUT_MS = 1300 * 1000;
27
+
24
28
  const pkg = require(path.join(__dirname, '..', 'package.json'));
25
29
 
26
30
  // B-37: how long after our init the process's listDevices/newDevices still belong to it -
@@ -2862,6 +2866,17 @@ module.exports = function (RED) {
2862
2866
  this.logger.info(protocol === 'binrpc' ? 'binrpc' : 'xmlrpc', 'server listening on', url);
2863
2867
  this.serverError[iface] = null;
2864
2868
  });
2869
+ if (this.servers[protocol].httpServer) {
2870
+ // hmipserver delivers its events through a pooled HTTP keep-alive client whose idle
2871
+ // timeout is 1200 s, and sends the next event on a pooled connection without
2872
+ // checking it. Node closes an idle keep-alive connection after 5 s by default, so
2873
+ // at the idle boundary the two raced: the event went out onto a socket this side was
2874
+ // closing, hmipserver logged "Connection reset" and the event was lost, a few times a
2875
+ // day. The callback server keeps an idle connection longer than the client pool
2876
+ // does, so it is always the client that lets go.
2877
+ this.servers[protocol].httpServer.keepAliveTimeout = KEEP_ALIVE_TIMEOUT_MS;
2878
+ this.servers[protocol].httpServer.headersTimeout = KEEP_ALIVE_TIMEOUT_MS + 5000;
2879
+ }
2865
2880
 
2866
2881
  // Todo binrpc module: emit error event on server object to eliminate the reach-in
2867
2882
  const errorEmitter = protocol === 'binrpc' ? this.servers[protocol].server : this.servers[protocol];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-red-contrib-ccu",
3
- "version": "4.6.1",
3
+ "version": "4.6.2",
4
4
  "license": "MIT",
5
5
  "main": "none",
6
6
  "keywords": [