node-red-contrib-ccu 4.2.0 → 4.3.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 (45) hide show
  1. package/CHANGELOG.md +96 -0
  2. package/HANDOFF.md +11 -3
  3. package/README.md +29 -0
  4. package/ROADMAP.md +112 -33
  5. package/nodes/ccu-alexa.html +3 -1
  6. package/nodes/ccu-connection.html +26 -0
  7. package/nodes/ccu-connection.js +87 -11
  8. package/nodes/ccu-display.js +29 -13
  9. package/nodes/ccu-get-value.html +3 -1
  10. package/nodes/ccu-mqtt.html +21 -4
  11. package/nodes/ccu-mqtt.js +126 -102
  12. package/nodes/ccu-rpc-event.html +6 -0
  13. package/nodes/ccu-rpc-event.js +31 -12
  14. package/nodes/ccu-set-value.html +38 -0
  15. package/nodes/ccu-set-value.js +59 -235
  16. package/nodes/ccu-signal.html +55 -1
  17. package/nodes/ccu-signal.js +52 -9
  18. package/nodes/ccu-switch.html +17 -4
  19. package/nodes/ccu-switch.js +28 -4
  20. package/nodes/ccu-sysvar.html +40 -1
  21. package/nodes/ccu-sysvar.js +78 -8
  22. package/nodes/ccu-value.html +27 -1
  23. package/nodes/ccu-value.js +69 -19
  24. package/nodes/lib/cast.js +59 -14
  25. package/nodes/lib/channelfilter.js +136 -0
  26. package/nodes/lib/dynconfig.js +81 -0
  27. package/nodes/lib/localccu.js +81 -0
  28. package/nodes/lib/message.js +6 -2
  29. package/nodes/lib/valuestatus.js +145 -0
  30. package/nodes/locales/de/ccu-display.html +17 -0
  31. package/nodes/locales/de/ccu-rpc-event.json +1 -0
  32. package/nodes/locales/de/ccu-sysvar.json +3 -2
  33. package/nodes/locales/de/ccu-value.json +2 -1
  34. package/nodes/locales/en-US/ccu-display.html +17 -0
  35. package/nodes/locales/en-US/ccu-rpc-event.json +3 -2
  36. package/nodes/locales/en-US/ccu-switch.html +12 -0
  37. package/nodes/locales/en-US/ccu-sysvar.json +3 -2
  38. package/nodes/locales/en-US/ccu-value.json +2 -1
  39. package/package.json +1 -1
  40. package/patch-certainonly.py +51 -0
  41. package/roadmap-archive/B-2.md +69 -0
  42. package/roadmap-archive/B-3.md +57 -0
  43. package/roadmap-archive/B-4.md +44 -0
  44. package/roadmap-archive/B-5.md +57 -0
  45. package/roadmap-archive/README.md +11 -0
@@ -0,0 +1,69 @@
1
+ # B-2 — Dynamic node configuration via msg
2
+
3
+ **✅ done 2026-09-04** (`4.3.0`) — issues #172, #71, #103, #80, #56,
4
+ #148, #185, #133.
5
+
6
+ The request arrived from every direction and was deliberately designed
7
+ once rather than patched per node (which is why PR #173's auto-subscribe
8
+ was closed rather than merged).
9
+
10
+ ## The mechanism
11
+
12
+ `msg.config` is an object whose properties override the receiving node's
13
+ own configuration **for that message only**. `nodes/lib/dynconfig.js`
14
+ builds the effective configuration; the stored one is never touched.
15
+
16
+ Why a namespace rather than flat properties everywhere: an event message
17
+ already carries `channel`, `datapoint`, `deviceType`, `rooms` and friends,
18
+ so honouring those on the signal or display node would let any message
19
+ coming from an event node silently retarget it. `msg.ccu` was the obvious
20
+ namespace but is taken — it holds the CCU host name — hence `msg.config`.
21
+
22
+ Each node passes the list of keys it accepts; anything else in
23
+ `msg.config` is ignored, so a stray property cannot reach node internals.
24
+ The flat mechanism the value/get-value/set-value nodes always had (fill in
25
+ fields left empty in the dialog from `msg.channel`, `msg.rooms`, …) is
26
+ unchanged and keeps working; `msg.config` wins over it.
27
+
28
+ ## Per node
29
+
30
+ - **set-value** — the whole filter plus `force`. This is also the fix for
31
+ #133: `setValues()` wrote message properties into `this.config`, so the
32
+ `if (!config[key])` guard skipped every later message and the node
33
+ stayed pinned to the first message's targets. The whitelist/blacklist
34
+ are keyed by the effective filter now, so an unchanged filter keeps the
35
+ caching benefit and a changed one is re-evaluated. The 200-line inline
36
+ matching chain moved to `nodes/lib/channelfilter.js` (pure, 14 tests),
37
+ which also fixed the device-name filter requiring the _channel_ to have
38
+ a ReGa name while comparing the _device_ name.
39
+ - **value** — `iface`, `channel`, `datapoint`. A message without a
40
+ payload writes nothing (the 4.0.0 guard) and now retargets the output
41
+ subscription, which is what #172 asked for. For a node with its own
42
+ channel/datapoint configured this is a no-op unless `msg.config`
43
+ overrides them, so no existing flow changes behaviour.
44
+ - **switch** — the source selection (`iface`/`channel`/`datapoint`/
45
+ `datapointProperty`/`sysvar`/`sysvarProperty`), so one node serves a
46
+ whole subflow (#103).
47
+ - **sysvar** — `name`, plus a typed input for _where the value comes
48
+ from_ (msg/flow/global/env) instead of always `msg.payload` (#56).
49
+ - **signal** — every command field including `soundList`/`dimmerList`,
50
+ which also accept a plain array of values instead of the editor's
51
+ list-of-objects shape (#148). The existing `<field>Type` typed inputs
52
+ keep working; `msg.config` wins over them.
53
+ - **display** — channel and the EP-WM55 settings, joining the lines,
54
+ colours and icons that were already overridable.
55
+
56
+ ## Subflows (#158)
57
+
58
+ Node-RED substitutes `${PARAMETER}` in a node's string properties before
59
+ the node is constructed, so subflow parameters already worked at runtime —
60
+ but the editor's channel autocomplete cleared any value that was not a
61
+ known channel address, wiping the placeholder every time the dialog was
62
+ opened. Fixed in the value, get-value, switch, signal and alexa editors.
63
+
64
+ Not done: an explicit `env` type on the filter fields of the event nodes.
65
+ The `${PARAMETER}` route covers the use case and the filters are read once
66
+ at construction, so a typed input would need runtime evaluation for little
67
+ gain. Revisit if someone asks.
68
+
69
+ Original item: | B-2 | Dynamic node configuration via msg — recurring theme #172, #71, #103, #80, #56, plus #148 (SOUNDFILE_LIST via msg), #158 (subflow env config) and #133 — the latter confirmed still broken in 4.0.0: `setValues()` writes msg values into `config` permanently, so the first message's filters stick. Design properly rather than merging PR #173's auto-subscribe | tracker |
@@ -0,0 +1,57 @@
1
+ # B-3 — ccu-mqtt node fixes and additions
2
+
3
+ **✅ done 2026-09-04** (`4.3.0`) — issues #115, #22, #167, plus the three
4
+ findings from ROADMAP §8.2 that the hm2mqtt 3.0 rewrite had confirmed.
5
+
6
+ ## Fixed
7
+
8
+ - **The writeable check never fired.** Both `putParam` and `putParamset`
9
+ tested `!(description.OPERATIONS) && 2`, which is `(!OPERATIONS) && 2` —
10
+ always falsy, since `OPERATIONS` is a non-zero number for every real
11
+ parameter. Read-only parameters were written regardless. Now
12
+ `!(OPERATIONS & 2)`, and the write is skipped.
13
+ - **`putParamset` cast against the wrong description.** It passed
14
+ `paramsetDescription[filter.param]` for every parameter; `filter.param`
15
+ only exists on the `putParam` topic, so it was `undefined` there and
16
+ the whole paramset went out uncast (strings where the CCU wanted
17
+ numbers or booleans). Each value is cast against its own description.
18
+ - **Enum names never worked.** The CCU returns them in `VALUE_LIST`, but
19
+ `lib/cast.js` and `lib/message.js` read `ENUM`, which no interface
20
+ process sends: all 9494 ENUM-typed datapoints in the shipped
21
+ `paramsets.json` carry `VALUE_LIST` and none carries `ENUM`. So
22
+ `msg.datapointEnum` and `msg.valueEnum` had always been `undefined`,
23
+ and writing e.g. `AUTO-MODE` to an enum datapoint fell through to the
24
+ numeric cast and produced `0`. `enumList()` reads `VALUE_LIST` with
25
+ `ENUM` as a fallback for hand-written data.
26
+ - **The divergent cast copy is gone.** `ccu-mqtt.paramCast` differed from
27
+ `lib/cast.js` only in clamping to MIN/MAX (and in producing `NaN` for
28
+ unparseable input, which XML-RPC cannot encode). `castValue` gained a
29
+ `clamp` option; the mqtt node passes it, the value nodes do not (#74).
30
+ - The empty-name topic bug (`hm/status//STATE` for channels without a
31
+ ReGa name) was already fixed in 4.2.0.
32
+
33
+ ## Added
34
+
35
+ - **`get`** (#115): `hm/get/<channel>/<datapoint>` republishes the last
36
+ known value on its status topic. An empty datapoint republishes every
37
+ datapoint of the channel. Fresh user interest in April 2026.
38
+ - **`rpc`** (#22): the topic was already in the dispatcher's table, but
39
+ the class had no `rpc()` method, so `typeof this[command] === 'function'`
40
+ was false and the message was silently dropped; `topicOutputRpc` was
41
+ never read at all. That is why both fields sat commented out in the
42
+ editor since 2018 — exposing them would have created two settings that
43
+ do nothing. Both are visible now; the result or the error is published
44
+ on the response topic, and the never-working default topic loses its
45
+ meaningless `${command}` segment (migrated on dialog open). An empty
46
+ topic disables a command.
47
+ - **#167**: `getRegaData()` (channel names, rooms, functions, groups) ran
48
+ once, in the connection constructor; the recurring poll only refreshed
49
+ variables and programs. A function added in the CCU WebUI was therefore
50
+ invisible until the flow was redeployed. New connection option
51
+ _names/rooms refresh_ (minutes, default 15, 0 = off) re-reads channel
52
+ names, rooms and functions from the ReGa poll's tail.
53
+
54
+ `resolveChannel()` now holds the channel-name/address resolution the four
55
+ command handlers each had inline.
56
+
57
+ Original item: | B-3 | Fix the ccu-mqtt node bugs verified in hm2mqtt ROADMAP §1.3 (see §8.2); also #115 get/update method (fresh user interest Apr 2026), #22 missing RPC-topic GUI, #167 stale rooms/functions | hm2mqtt |
@@ -0,0 +1,44 @@
1
+ # B-4 — Local-CCU detection
2
+
3
+ **✅ done 2026-09-04** (`4.3.0`).
4
+
5
+ When Node-RED runs on the CCU itself (RedMatic), the interface processes
6
+ can be reached directly on their 3xxxx ports — BINRPC for BidCos and
7
+ ReGa, and without the hop through the CCU's lighttpd proxy. The
8
+ connection node picked that up from:
9
+
10
+ ```js
11
+ const rfdConf = fs.readFileSync('/etc/lighttpd/conf.d/proxy.conf').toString();
12
+ if (rfdConf.match(/"port"\s+=>\s+32001/)) {
13
+ this.isLocal = true;
14
+ }
15
+ ```
16
+
17
+ On current firmware that file is a single line:
18
+
19
+ ```
20
+ include "/var/etc/lighttpd_proxy.conf"
21
+ ```
22
+
23
+ which itself only contains `include "/etc/lighttpd/conf.d/proxy_normal.conf"` —
24
+ the `"port" => 32001` markers are two levels down the include chain.
25
+ So the regex has not matched in years and every local install silently
26
+ went through the proxy on 1999/2000/2001/2010/9292.
27
+
28
+ Measured on a lab CCU3 with firmware 3.89.8: `proxy.conf` is the bare
29
+ include above, while 31999, 32001, 32010 and 39292 are all listening.
30
+
31
+ ## Fix
32
+
33
+ `nodes/lib/localccu.js` asks the kernel instead of parsing lighttpd's
34
+ configuration: a listener on rfd's direct port (32001, or the ReGa's 31999) is exactly the condition that makes using the direct ports
35
+ correct, and it cannot drift when eQ-3 reorganises the config files
36
+ again. `/proc/net/tcp` and `/proc/net/tcp6` are plain files, so the check
37
+ stays synchronous — the interface table is built in the constructor —
38
+ and on a host without `/proc` (Windows, macOS) it simply reports "not
39
+ local", which is the safe answer.
40
+
41
+ 8 unit tests, including the real `/proc/net/tcp` line format from the
42
+ 3.89.8 lab box.
43
+
44
+ Original item: | B-4 | Fix/remove the dead `isLocal` detection (`/etc/lighttpd/conf.d/proxy.conf` grep, `ccu-connection.js:346` — file is a stub on firmware ≥ 3.87, so local installs silently go through the proxy) | hm2mqtt §15.4 |
@@ -0,0 +1,57 @@
1
+ # B-5 — Ping checks, sysvar node properties and status
2
+
3
+ **✅ done 2026-09-04** (`4.3.0`) — issues #44, #54, #52, #124, #166, #96,
4
+ #56, #183.
5
+
6
+ A collection of small connection- and node-level items that had all been
7
+ open since 2019/2020.
8
+
9
+ - **#44 — configurable ping checks.** The connection node had a _ping
10
+ timeout_ field but no way to switch the check off: entering 0 fell
11
+ through `Number.parseInt(config.rpcPingTimeout, 10) || 60` back to 60
12
+ seconds. New _RPC ping_ checkbox (default on). Off means no periodic
13
+ ping and no timeout-triggered re-init for that connection — the honest
14
+ reading of "deactivate ping checks", with the consequence documented in
15
+ the dialog.
16
+ - **#54 / #52 — last value and its age under the node.** The connection
17
+ keeps `value`, `ts` and `lc` for every datapoint and system variable;
18
+ the nodes simply never showed them, and the sysvar node showed nothing
19
+ at all unless "emit value on start" was enabled.
20
+ `nodes/lib/valuestatus.js` renders `<value> (3m)` and re-renders on a timer whose
21
+ interval follows the resolution shown, so the line does not go stale
22
+ between events. Used by the sysvar node (which also seeds it from the
23
+ connection's cache when "emit value on start" is off) and the rpc-event
24
+ node (which shows the topic that last fired).
25
+ - **#96 — filter uncertain values.** The `uncertain` flag was already in
26
+ every message; there was no way to filter on it. `uncertain` is a
27
+ subscription filter property now, exposed as a _discard uncertain
28
+ values_ checkbox on the value and rpc-event nodes. It is only put into
29
+ the filter when the option is on, so existing subscriptions are
30
+ unaffected, and it is evaluated before `callCallback()`'s attribute
31
+ loop, which may break early for a whitelisted datapoint.
32
+ - **#166 — immediate sysvar echo lost under concurrency.** `setVariable()`
33
+ triggers a ReGa poll so the new value comes back without waiting for
34
+ the 30 s interval, but only `if (!this.regaPollPending)`, and
35
+ `regaPoll()` itself no-ops while one is in flight. Writing several
36
+ variables at once therefore left all but the first invisible for up to
37
+ a poll interval — exactly the reported symptom ("works for one
38
+ variable, not for several"). The request is remembered and exactly one
39
+ more poll runs when the current one finishes.
40
+ - **#183 — RSSI conversion guarded.** `dp.value -= 256` ran for every
41
+ RSSI_DEVICE/RSSI_PEER value from the ReGa poll, so a value that was
42
+ already signed, or the 0 that means "never received", became -318 or
43
+ -256. Now only for values above 127, matching hm2mqtt's guard. (The
44
+ XML-RPC event path needs no conversion.)
45
+ - **#124 — re-read variable descriptions on poll** was already fixed in
46
+ 2020 (commit 453f2b2, v3.2.1) and the issue merely never closed; the
47
+ remaining gap (`info` not selectable as a property) is noted below.
48
+ - **#56** — the sysvar node's configurable source property landed with
49
+ B-2, which owns the dialog change.
50
+
51
+ ## Not done
52
+
53
+ - `info` (a variable's description) is still not selectable as a single
54
+ property in the get-value/sysvar nodes; it is reachable through the
55
+ whole message. Left for whoever touches those property lists next.
56
+
57
+ Original item: | B-5 | Configurable ping checks (#44), sysvar node property/status improvements (#54, #56, #52 last-event status, #124 re-read descriptions on poll, #166 immediate sysvar echo, #96 uncertain-filter option) | tracker |
@@ -18,6 +18,17 @@ the roadmap's contents index (marked ✅ there, linking here).
18
18
 
19
19
  **Backlog items**
20
20
 
21
+ - [B-5.md](B-5.md) — ping toggle, value/age status lines, uncertain
22
+ filter, trailing sysvar re-poll, RSSI guard ✅ 2026-09-04 (4.3.0;
23
+ #44/#54/#52/#96/#166/#183/#124).
24
+ - [B-4.md](B-4.md) — local-CCU detection via a /proc/net/tcp listener
25
+ probe instead of the lighttpd config grep that had stopped matching ✅
26
+ 2026-09-04 (4.3.0).
27
+ - [B-3.md](B-3.md) — ccu-mqtt fixes plus the `get` and `rpc` commands and
28
+ the VALUE_LIST enum names ✅ 2026-09-04 (4.3.0; #115/#22/#167 and the
29
+ §8.2 findings).
30
+ - [B-2.md](B-2.md) — dynamic node configuration via `msg.config` ✅
31
+ 2026-09-04 (4.3.0; #172/#71/#103/#80/#56/#148/#185/#133/#158).
21
32
  - [B-14.md](B-14.md) — COMBINED_PARAMETER mapping for HmIP slat writes ✅
22
33
  2026-09-02 (#136/#154/#175, pending hardware confirmation).
23
34
  - [B-6.md](B-6.md) — binrpc rewrite without abandoned deps ✅ 2026-09-02