node-red-contrib-ccu 4.3.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-red-contrib-ccu",
3
- "version": "4.3.0",
3
+ "version": "4.4.1",
4
4
  "license": "MIT",
5
5
  "main": "none",
6
6
  "keywords": [
@@ -0,0 +1,106 @@
1
+ # B-17 — openccu-lite (a CCU without ReGaHSS)
2
+
3
+ **✅ done 2026-09-06** (`4.4.0`).
4
+
5
+ [openccu-lite](https://github.com/hobbyquaker/openccu-lite) is a Homematic
6
+ CCU firmware that drops ReGaHSS. The interface processes are the ones we
7
+ already talk to (`rfd` BidCos-RF/BIN-RPC, `hs485d`, `hmipserver`
8
+ XML-RPC) — but nothing listens on 8181/8183, `rega.exe`/`tclrega.exe` do
9
+ not exist, HM-Script is never interpreted, and there are no ReGa ids.
10
+ Everything this package took from the ReGa apart from names, rooms and
11
+ functions has no replacement there.
12
+
13
+ What it offers instead is `occulited`'s **metadata API**, a small JSON
14
+ store served under `/api/meta/v1/` behind the box's lighttpd, with a
15
+ Server-Sent-Events change stream. Its porting kit (`docs/porting-from-rega.md`,
16
+ `docs/PORTING-PROMPT.md`, `docs/meta-api.md` and the `fixtures/`
17
+ conformance corpus in the openccu-lite repository) is what this item
18
+ was implemented against.
19
+
20
+ ## The rule the port follows
21
+
22
+ Keep the ReGa code path, add a provider, detect at runtime. On a CCU3,
23
+ RaspberryMatic or OpenCCU nothing changes: the same configuration, the
24
+ same messages, the same cache files.
25
+
26
+ ## What was built
27
+
28
+ - **`nodes/lib/metaprovider.js`** — the counterpart of the `getRega*()`
29
+ methods. `detect()` is the feature test (`GET /api/meta/v1/version`,
30
+ no credential, 404 on a CCU). `MetaProvider` loads `GET /snapshot`,
31
+ then follows `GET /events/sse?since=<revision>`: `object.updated` and
32
+ `object.deleted` are applied to the in-memory document, everything
33
+ that can rewrite member paths (`node.*`, `enum.*`, `import`, an
34
+ explicit `resync`, a gap in the revisions) re-reads the snapshot.
35
+ `buildNames()` is pure and derives exactly what the rest of the code
36
+ already reads — `channelNames`, `channelRooms`, `channelFunctions`
37
+ keyed by the bare address (the API's ref is `<interface>.<address>`),
38
+ plus the `rooms` / `functions` name lists the editor asks for.
39
+ - **Rooms and functions are a tree** there (`room/eg/wohnzimmer`), not a
40
+ flat list. They are flattened to the arrays the nodes have always
41
+ published, ancestors included and most specific first, so a channel in
42
+ _Wohnzimmer_ below _Erdgeschoss_ matches a room filter on either name
43
+ and `msg.room` is still the room the user means.
44
+ - **Detection in the startup path** of `ccu-connection.js`: when the
45
+ ReGaHSS interface is ticked, the node probes once before deciding
46
+ between `startMeta()` and `getRegaData()`. The provider probes again
47
+ on every reconnect; three failed probes in a row hand control back to
48
+ the detection (a restored backup or a firmware swap under a running
49
+ Node-RED), and on the ReGa side a failing `getRegaData()` /
50
+ `refreshRegaData()` re-probes at most every five minutes. So a box
51
+ that changes kind is picked up in both directions without a redeploy.
52
+ - **Credential**: on the box the read-only local token
53
+ (`/usr/local/etc/occulite/local-token`) is read automatically, off the
54
+ box an _openccu-lite token_ field takes one created on the box's Users
55
+ page. `401`/`403` degrades to addresses-only, is logged once, and is
56
+ retried — never fatal. An _openccu-lite port_ field covers boxes whose
57
+ web server is not on 80/443 (it is also what the integration test
58
+ uses).
59
+ - **The ReGa-only nodes stay**: `ccu-sysvar`, `ccu-program`,
60
+ `ccu-script` and `ccu-poll` remain in the palette and in flows, the
61
+ connection logs one line about them when it starts, and every message
62
+ they get is rejected with `… are not available on this box
63
+ (openccu-lite has no ReGaHSS)` instead of breaking the connection.
64
+ - **No new dependency.** `node:http`/`node:https` rather than `fetch`,
65
+ because the connection node already offers "ignore invalid TLS
66
+ certificates", which `fetch` cannot express per request without
67
+ pulling in undici — and a Node stream is the natural shape for SSE.
68
+
69
+ ## Tests
70
+
71
+ 16 unit tests in `test/unit/metaprovider.test.js` (`npm run test:pure`):
72
+ `buildNames()` over the openccu-lite conformance corpus, copied verbatim
73
+ into `test/fixtures/openccu-lite/` (`valid-house`, `valid-empty`,
74
+ `valid-depth-8`), plus a fake `/api/meta/v1` server built from
75
+ `node:http` for detection (openccu-lite / a CCU's 404 / a 200 that is
76
+ not the metadata API / nothing listening), the 401 path, an event →
77
+ "names changed" round trip, the re-snapshot triggers, reconnects and the
78
+ "not an openccu-lite any more" hand-back. The existing ReGa specs are
79
+ untouched.
80
+
81
+ Verified against a real `occulited` (built from the openccu-lite
82
+ repository, `--listen 127.0.0.1:2132`, the `valid-house` fixture
83
+ imported) with `node-red-node-test-helper` driving a real
84
+ `ccu-connection` node: names, rooms and functions match the box; a
85
+ `PATCH /objects/{ref}` rename, a room rename and a `node.moved` all
86
+ reach `ccu.channelNames` / `ccu.channelRooms` in under 150 ms; the four
87
+ ReGa-only nodes error per message; `createMessage()` produces the same
88
+ `channelName` / `rooms` / `room` / `functions` / `function` fields as on
89
+ a CCU.
90
+
91
+ ## Findings handed back to openccu-lite
92
+
93
+ 1. `occulited`'s SSE endpoint does not flush the response header until
94
+ it has an event or a heartbeat to write, so an HTTP client cannot
95
+ tell "connected" from "still connecting" for up to 30 s. A client
96
+ that applies its ordinary request timeout to the open stream tears it
97
+ down on every cycle; this implementation arms a separate idle timeout
98
+ after the socket connects and reports "connected" once the snapshot
99
+ is in, not when the stream opens.
100
+ 2. The porting prompt's example is `fetch`, which cannot do per-request
101
+ TLS verification settings in Node — worth a sentence in the kit,
102
+ since every integration that offers "ignore invalid certificates"
103
+ hits it.
104
+
105
+ Original item: openccu-lite port — names, rooms and functions from the
106
+ metadata API instead of ReGaHSS, ReGa path unchanged, runtime detection.
@@ -18,6 +18,9 @@ the roadmap's contents index (marked ✅ there, linking here).
18
18
 
19
19
  **Backlog items**
20
20
 
21
+ - [B-17.md](B-17.md) — the openccu-lite port: names, rooms and
22
+ functions from the box's metadata API when it has no ReGaHSS ✅
23
+ 2026-09-06 (4.4.0).
21
24
  - [B-5.md](B-5.md) — ping toggle, value/age status lines, uncertain
22
25
  filter, trailing sysvar re-poll, RSSI guard ✅ 2026-09-04 (4.3.0;
23
26
  #44/#54/#52/#96/#166/#183/#124).