node-red-contrib-velbus-2026 0.10.2 → 0.10.4

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.
@@ -29,6 +29,84 @@ separate duplicate-table bugs took to fully resolve.
29
29
 
30
30
  ---
31
31
 
32
+ ## v0.10.4 — 09/07/2026
33
+
34
+ ### README.md — fixed real staleness, now publicly visible on the Flow Library
35
+
36
+ - **Prompted by successfully getting listed on the Node-RED Flow Library**
37
+ (`flows.nodered.org/node/node-red-contrib-velbus-2026`) — checked the
38
+ rendered page and found the displayed README was genuinely stale, not a
39
+ caching artifact: `velbus-glass-panel` still said "26 types" (actually 29),
40
+ `velbus-button` still listed only the original 6 types (actually 12, plus
41
+ lock/unlock/status/naming capability added since), `velbus-sensor` didn't
42
+ mention `VMB6IN` or the new generic analogue reading, `velbus-clock`
43
+ didn't mention sunrise/sunset, and the tarball install example still
44
+ hardcoded `v0.8.1`.
45
+ - **Root cause:** `README.md` was fixed once, early on, during initial npm
46
+ publish prep — then never touched again despite `HANDOVER.md` and
47
+ `CHANGELOG_FORUM.md` being kept scrupulously current through every
48
+ subsequent change. This is the user-facing document (visible on both npm
49
+ and the Flow Library), arguably more consequential to get right than the
50
+ developer-facing ones, and it drifted the most.
51
+ - **Fixed the specific staleness, and the root cause of it recurring:**
52
+ the hardcoded tarball version number is now written as `vX.Y.Z` with an
53
+ explanatory note, rather than a literal version that will go stale again
54
+ next release exactly as it did this time.
55
+ - Added pointers to `HANDOVER.md`, `CHANGELOG_FORUM.md`, and
56
+ `coverage-roadmap.md` — none of which were linked from `README.md` at all
57
+ before, despite being genuinely useful to anyone landing on the repo.
58
+ - Also confirmed, while investigating: the earlier concern about Node-RED's
59
+ post-2022 scoped-package naming policy did **not** block Flow Library
60
+ approval — this package is listed successfully under its original
61
+ unscoped name.
62
+
63
+ ---
64
+
65
+ ## v0.10.3 — 09/07/2026
66
+
67
+ ### velbus-glass-panel — VMBEL edge colour control (set_edge_color)
68
+
69
+ - **Prompted by Stuart asking whether edge LED colours on `VMBEL` panels
70
+ could be controlled, or whether a raw-packet escape-hatch node (like the
71
+ original palette had) was needed instead.** Confirmed a real, well-defined
72
+ live-bus command exists — no raw-packet node needed for this case.
73
+ - **Scope deliberately split, per explicit decision:** `COMMAND_SET_PB_
74
+ BACKLIGHT` (`0xD4`) covers two different operations distinguished only by
75
+ DLC — "Set Custom Color" (`DLC=6`, *defines* a custom RGB palette slot)
76
+ and "Set Edge Color" (`DLC=4`, *applies* an already-defined colour).
77
+ Only the latter is implemented: defining new custom colours is
78
+ commissioning-time configuration, staying in VelbusLink's domain, same
79
+ reasoning as `VMB4LEDPWM-20`'s grouping mode and Program Step read/write
80
+ elsewhere in this project. See `HANDOVER.md` section 7.8b for the full
81
+ byte layout.
82
+ - **`hasEdgeLed` gated to the confirmed `VMBEL` family only** (12 of 29
83
+ glass panel types: `VMBEL1/2/4`, `VMBELO`, `VMBELPIR`, `VMBEL2PIR`, and
84
+ their `-20` siblings) — `VMBGP`-family panels have only a single-colour
85
+ front LED per button, genuinely different hardware, not just a missing
86
+ feature. Verified the command is byte-for-byte identical across every
87
+ `VMBEL` sub-family protocol PDF before implementing once. One vestigial
88
+ "Edge color inhibited" status bit found in `VMBGP1-20/2-20/4-20`'s own
89
+ `0xED` — confirmed as inherited documentation cruft, not evidence of real
90
+ edge-colour hardware on those panels.
91
+ - New `set_edge_color` command: `layers` (background/continuous/slow_blink/
92
+ fast_blink, any combination), `edges` (left/top/right/bottom, any
93
+ combination), `page` (1-8 or "all"), `palette` (default/custom), `index`
94
+ (0-31), `priority` (custom only), `blink`. Sending to a non-`VMBEL` panel
95
+ warns clearly and sends nothing, matching the established per-type
96
+ gating pattern used throughout this palette.
97
+ - Housekeeping: removed a stale "`VMBKP` has no node at all" entry from
98
+ `HANDOVER.md`'s known-open-issues — that was resolved back in v0.10.0
99
+ when `VMBKP` was folded into `velbus-button`, but the issue list was
100
+ never updated to reflect it.
101
+
102
+ Verified via the mock-RED harness: default palette, custom palette with
103
+ priority and blink flag, all-defaults shorthand, and rejection on a
104
+ non-`VMBEL` type — every case with hand-checked checksums and manually
105
+ verified bitfield encoding, not just visual review. Not yet sent to a real
106
+ bus.
107
+
108
+ ---
109
+
32
110
  ## v0.10.2 — 09/07/2026
33
111
 
34
112
  ### velbus-sensor — VMB4AN generic analogue reading (channels 9-12)
package/HANDOVER.md CHANGED
@@ -6,7 +6,7 @@ you're a new contributor, a new maintainer, or an AI assistant starting a fresh
6
6
  with no memory of previous work — this document should be sufficient on its own, together
7
7
  with the source code in this repository, to continue development competently.
8
8
 
9
- Current state at time of writing: **v0.10.2, 19 nodes, published on npm.**
9
+ Current state at time of writing: **v0.10.4, 19 nodes, published on npm.**
10
10
 
11
11
  ---
12
12
 
@@ -300,7 +300,7 @@ or a string before assuming the parsing logic itself is wrong.
300
300
  | `velbus-relay-20` | Velbus (outputs) | V2 relays: VMB1RYS-20, VMB4RYLD-20, VMB4RYNO-20 |
301
301
  | `velbus-dimmer` | Velbus (outputs) | Original-series dimmers: VMBDMI, VMBDMI-R, VMB4DC |
302
302
  | `velbus-dimmer-20` | Velbus (outputs) | V2 dimmers: VMB2DC-20, VMB8DC-20, VMB4LEDPWM-20 (incl. RGB/RGBW grouping mode) |
303
- | `velbus-glass-panel` | Velbus (inputs) | All 29 glass panel types (original + V2), buttons/OLED/PIR/open-collector as applicable per type |
303
+ | `velbus-glass-panel` | Velbus (inputs) | All 29 glass panel types (original + V2), buttons/OLED/PIR/open-collector as applicable per type. `VMBEL` family only (12 of the 29 types): `set_edge_color` applies an already-defined colour across layer/edge/page combinations — deliberately not palette *definition*, which stays in VelbusLink |
304
304
  | `velbus-thermostat` | Velbus (inputs) | Thermostat function on any glass panel module that has one — same address as the corresponding glass-panel node, coexists without conflict |
305
305
  | `velbus-button` | Velbus (inputs) | 12 types across original and V2 series (VMB8PB, VMB8PBU, VMB6PBN, VMB2PBN, VMB4PB, VMB6PB-20, VMB8IR, VMB4PD, VMB4RF, VMBRFR8S, VMBVP01, VMBKP, VMBIN) — plain button events for all; lock/unlock and richer status decode for the 8 types confirmed to support them; fixed semantic channel labels for VMBVP01 (DoorBird) |
306
306
  | `velbus-pir` | Velbus (inputs) | Original-series PIR: VMBPIRO-10, VMBPIRM, VMBPIRC, VMBPIRO |
@@ -606,6 +606,45 @@ body[3-5] = 24-bit raw value, MSB first
606
606
  (period mode: 0x000000 = short-circuited, 0xFFFFFF = open-circuit)
607
607
  ```
608
608
 
609
+ ### 7.8b `0xD4` — one command byte, two very different operations, `VMBEL` family only
610
+
611
+ `COMMAND_SET_PB_BACKLIGHT` (`0xD4`) covers **two genuinely different commands**,
612
+ distinguished only by `DLC` (data length), confirmed identical across every
613
+ `VMBEL` sub-family protocol PDF checked (`VMBEL1/2/4`, `VMBELO`, `VMBELPIR`,
614
+ and their `-20` siblings):
615
+
616
+ - **"Set Custom Color" (`DLC=6`)** — *defines* one of 32 custom colour
617
+ palette slots as an actual RGB (or white+saturation) value:
618
+ `[0xD4, paletteIndex(0-31), rgbOrWhiteFlag+saturation, red, green, blue]`.
619
+ **Deliberately not implemented** — defining new custom colours is
620
+ commissioning-time configuration, and per an explicit decision, stays in
621
+ VelbusLink's domain. Same reasoning as `VMB4LEDPWM-20`'s grouping mode and
622
+ Program Step read/write elsewhere in this project.
623
+ - **"Set Edge Color" (`DLC=4`)** — *applies* an already-defined colour
624
+ (default palette, or a custom slot VelbusLink has already programmed)
625
+ across a chosen combination of layer/edge/page. This one **is**
626
+ implemented (`velbus-glass-panel`'s `set_edge_color` command) — a
627
+ genuine live/runtime action, not palette editing:
628
+ ```
629
+ body[0] = 0xD4
630
+ body[1] = layer bitmask (bit0=background, bit1=continuous-feedback,
631
+ bit2=slow-blink-feedback, bit3=fast-blink-feedback) + bit7
632
+ (0=default palette, 1=custom palette)
633
+ body[2] = edge bitmask (bit0=left, bit1=top, bit2=right, bit3=bottom) +
634
+ page nibble (bits4-7: 0-7=pages 1-8, 8-15=all pages — the
635
+ protocol PDF states the entire 1000-1111 range means "all",
636
+ not just one value)
637
+ body[3] = blink flag (bit7) + priority (bits5-6, custom palette only:
638
+ 01=low, 10=mid, 11=high) + palette index (bits0-4, 0-31)
639
+ ```
640
+ **Gated to `hasEdgeLed` types only** — the `VMBEL` family, confirmed
641
+ `VMBGP`-family panels genuinely lack this (they have a single-colour
642
+ front LED per button, not side-firing edge lighting — a real hardware
643
+ difference, not just a missing feature). One vestigial "Edge color
644
+ inhibited" status *bit* appears in `VMBGP1-20/2-20/4-20`'s `0xED` module
645
+ status — almost certainly inherited from shared documentation with the
646
+ `VMBEL` family, not evidence those panels have real edge-colour hardware.
647
+
609
648
  ### 7.9 Thermostat commands — always to the primary address
610
649
  ```
611
650
  0xDB = comfort mode, 0xDC = day mode, 0xDD = night mode, 0xDE = safe mode
@@ -889,15 +928,6 @@ orientation at the time of writing:
889
928
 
890
929
  ## 13. Known open issues
891
930
 
892
- - **`VMBKP` (0x42, "Keypad interface module") has no node at all.** Found scanning a
893
- real installation (Stuart's home) — confirmed present at address `0xFD`, a real
894
- module on a real bus, not a hypothetical. A genuinely new module type, not yet
895
- scoped. Its protocol PDF (`protocol_vmbkp.pdf`, 28 pages) is substantial: channel
896
- status, module status, and a full per-channel LED control layer
897
- (clear/set/slow-blink/fast-blink/very-fast-blink), similar in spirit to `velbus-button`
898
- but with LED feedback control `velbus-button` doesn't have. This needs the same
899
- "how much work would this involve" scoping pass `velbus-energy` got before it was
900
- built, not a quick bolt-on to an existing node.
901
931
  - **Open-collector support** on several glass panel types (marked "unconfirmed" in the
902
932
  registry in section 6) has not been verified against real hardware — the protocol PDFs
903
933
  are ambiguous or silent on some of these. Sending `0x01`/`0x02`/`0x03` open-collector
package/README.md CHANGED
@@ -52,8 +52,11 @@ npm install node-red-contrib-velbus-2026
52
52
  Via local tarball:
53
53
  ```bash
54
54
  cd ~/.node-red
55
- npm install /path/to/node-red-contrib-velbus-2026_v0.8.1.tar.gz
55
+ npm install /path/to/node-red-contrib-velbus-2026_vX.Y.Z.tar.gz
56
56
  ```
57
+ (replace `X.Y.Z` with whichever version tarball you have — deliberately not
58
+ hardcoded here, since a literal version number in this file has gone stale
59
+ every single time it's been written one before)
57
60
 
58
61
  ---
59
62
 
@@ -68,13 +71,13 @@ npm install /path/to/node-red-contrib-velbus-2026_v0.8.1.tar.gz
68
71
  ### Inputs (teal)
69
72
  | Node | Modules |
70
73
  |---|---|
71
- | `velbus-glass-panel` | All VMBEL and VMBGP variants — 26 types including OLED, PIR, and original series. Thermostat, LED control, open collector. |
74
+ | `velbus-glass-panel` | All VMBEL and VMBGP variants — 29 types including OLED, PIR, and original series. Thermostat, LED control, open collector. `VMBEL` family only: edge colour control (`set_edge_color`) — applies an already-defined colour across layer/edge/page combinations; defining new custom colours stays in VelbusLink. |
72
75
  | `velbus-thermostat` | Dedicated thermostat node for all glass panel modules. |
73
- | `velbus-button` | VMB8PB, VMB8PBU, VMB6PBN, VMB2PBN, VMB4PB, VMB6PB-20 |
76
+ | `velbus-button` | 12 types across original and V2 series: VMB8PB, VMB8PBU, VMB6PBN, VMB2PBN, VMB4PB, VMB6PB-20, VMB8IR, VMB4PD, VMB4RF, VMBRFR8S, VMBVP01, VMBKP, VMBIN. Lock/unlock and richer status decode where the specific type supports it (not universal); named channels in event output; fixed semantic labels for VMBVP01 (DoorBird). |
74
77
  | `velbus-pir` | VMBPIRM, VMBPIRC, VMBPIRO, VMBPIRO-10 |
75
78
  | `velbus-pir-20` | VMBPIR-20, VMBPIRO-20 |
76
79
  | `velbus-meteo` | VMBMETEO — wind, rain, light, temperature, alarm outputs |
77
- | `velbus-sensor` | VMB7IN (8 digital inputs + 4 pulse counters), VMB4AN (16-channel analogue/alarm) |
80
+ | `velbus-sensor` | VMB7IN (8 digital inputs + 4 pulse counters), VMB4AN (channels 1-8 alarm outputs + generic analogue reading on channels 9-12 — mode-aware but deliberately no engineering-unit conversion), VMB6IN (6 digital inputs) |
78
81
  | `velbus-sensor-20` | VMB8IN-20 (8 digital + 24 alarm channels via subaddresses, energy counters) |
79
82
 
80
83
  ### Outputs (blue)
@@ -87,7 +90,7 @@ npm install /path/to/node-red-contrib-velbus-2026_v0.8.1.tar.gz
87
90
  | `velbus-blind` | VMB1BL, VMB2BL — original series, stop/up/down only |
88
91
  | `velbus-blind-s` | VMB1BLS, VMB2BLE, VMB2BLE-10 — full position, lock, force, inhibit |
89
92
  | `velbus-blind-20` | VMB2BLE-20 — V2 series with CAN FD support |
90
- | `velbus-clock` | No fixed module — broadcasts time/date/DST to bus address `0x00`, plus global/local clock alarm (V2 series only) |
93
+ | `velbus-clock` | No fixed module — broadcasts time/date/DST to bus address `0x00`, plus global/local clock alarm and sunrise/sunset enable (V2 series only) |
91
94
  | `velbus-energy` | VMBPSUMNGR-20 — power supply manager: PSU load, live wattage/voltage/amperage, warranty counter, PSU alarms (V2 series only) |
92
95
 
93
96
  ---
@@ -122,6 +125,21 @@ at `/velbus`.
122
125
 
123
126
  Tested on a live 18-module installation including VMBEL4, VMBELO, VMBELPIR,
124
127
  VMBPIR-20, VMB1RYS, and VMB8DC-20. CAN FD modules confirmed working.
128
+ `VMBGPOD` specifically confirmed against two real panels on a separate
129
+ installation, after an earlier gap where it showed as `unknown` in a scan.
130
+
131
+ ---
132
+
133
+ ## Further documentation
134
+
135
+ - [`HANDOVER.md`](https://github.com/MDAR/node-red-contrib-velbus-2026/blob/main/HANDOVER.md) —
136
+ comprehensive technical reference for developing this palette: architecture, protocol
137
+ quirks found the hard way, per-node testing status, and known open issues. Written to
138
+ assume no prior context.
139
+ - [`CHANGELOG_FORUM.md`](https://github.com/MDAR/node-red-contrib-velbus-2026/blob/main/CHANGELOG_FORUM.md) —
140
+ full version-by-version development history, including *why* things changed, not just what.
141
+ - [`coverage-roadmap.md`](https://github.com/MDAR/node-red-contrib-velbus-2026/blob/main/coverage-roadmap.md) —
142
+ every Velbus module type and feature considered for this palette, what's in scope, and why.
125
143
 
126
144
  ---
127
145
 
@@ -0,0 +1,186 @@
1
+ # Coverage Roadmap — Rationalized 09/July/2026
2
+
3
+ **STATUS: Implemented in v0.10.0 (09/July/2026).** Everything marked "confirmed
4
+ and ready to build" below has been built, tested, and shipped — including
5
+ the type-byte fixes and real protocol divergences caught along the way (see
6
+ `CHANGELOG_FORUM.md` v0.10.0 for the full list). The two genuinely deferred
7
+ items (dimmer family, bus error counter) and the OLED stretch goal are now
8
+ tracked directly in `HANDOVER.md` section 13 going forward — this document
9
+ remains as the record of the original rationalization discussion, not the
10
+ place to look for current status.
11
+
12
+ Synthesized from a full pass over every Velbus module type and feature not yet
13
+ covered by this palette. Organized by what actually needs to happen, not by the
14
+ order it came up in discussion.
15
+
16
+ ---
17
+
18
+ ## 1. New types to add to existing nodes' registries
19
+
20
+ No new nodes required — each of these is a straightforward registry addition
21
+ to a node that already exists and already handles this exact command family.
22
+
23
+ | Type | Module | Target node | Note |
24
+ |---|---|---|---|
25
+ | 0x07 | VMB1DM | `velbus-dimmer` | Old, likely rare in the field, minimal effort |
26
+ | 0x14 | VMBDME | `velbus-dimmer` | |
27
+ | 0x0F | VMB1LED | `velbus-dimmer` | Confirmed via protocol PDF: "PWM LED strip dimmer module" — genuinely dimmer-family, not a separate concept |
28
+ | 0x0A | VMB8IR | `velbus-button` | Confirmed — just a button-event module |
29
+ | 0x0B | VMB4PD | `velbus-button` | Reclassified from "not supported" — confirmed as a 4-button interface |
30
+ | 0x1A | VMB4RF | `velbus-button` | Presents 8 button events to the bus, nothing more |
31
+ | 0x30 | VMBRFR8S | `velbus-button` | Same mechanism as VMB4RF |
32
+ | 0x33 | VMBVP01 | `velbus-button` | DoorBird video intercom OEM module — 8 button events |
33
+ | 0x42 | VMBKP | `velbus-button` | Already agreed — plus lock/unlock and richer status decode (section 3) |
34
+ | 0x43 | VMBIN | `velbus-button` | Single-channel input, EOL but real installed base |
35
+ | 0x05 | VMB6IN | `velbus-sensor` | Sibling of VMB7IN |
36
+ | 0x3E | VMBGP4PIR-2 | `velbus-glass-panel` | Original-series-2 sibling of the -20 already covered |
37
+ | 0x25 | VMBGPTC | `velbus-glass-panel` | Confirmed — shares its actual protocol PDF with VMBGPO (0x21), genuine glass-panel sibling |
38
+
39
+ **Resolved — `VMB1TC`/`VMB1TS`: out of scope, not "super easy."** Checked the
40
+ actual protocol: `VMB1TC` has its own distinct command vocabulary ("Sensor
41
+ zone number," "sensor time statistics request," "lock/unlock sensor local
42
+ control") that doesn't overlay onto the existing `velbus-thermostat` decode —
43
+ this would be real new command handling, not a registry entry. Per the
44
+ stated condition, this stays out of scope. Nothing in Velbus is genuinely
45
+ wireless (confirmed) other than 433MHz/IR modules, which translate to the
46
+ bus rather than living on it — so no "W"-variant type IDs to separately track.
47
+
48
+ **Resolved — `VMBLCDWB` (0x13):** confirmed as a pre-glass-panel thermostat
49
+ controller (Velleman product page: 4-button control with LCD display, 32
50
+ functions, time/date backup). Out of scope, name-only in section 2.
51
+
52
+ ---
53
+
54
+ ## 2. Scan-table "see it, don't support it" additions
55
+
56
+ Named correctly in a scan (not `unknown_0xNN`), explicit "Not supported" note
57
+ in place of a suggested node — no live node built.
58
+
59
+ | Type | Module | Note |
60
+ |---|---|---|
61
+ | 0x45 / 0x5A | VMBDALI / VMBDALI-20 | Real prevalence (12 VLP projects) but DALI is its own protocol layer beyond the gateway — explicit "Not supported" label requested |
62
+ | 0x13 | VMBLCDWB | Pre-glass-panel thermostat controller (4-button + LCD + time/date backup) — confirmed out of scope, name only |
63
+ | 0x3F | VMCM3 | Custom corporate-client module, function unknown — name only |
64
+ | 0x39 / 0x5B / 0x60 | VMBSIG / VMBSIG-20 / VMBSIG-21 | Custom HomeAssistant-based master clock, not interactable — already named in the scanner; **worth aligning to the same explicit "Not supported" note style as VMBDALI for consistency**, rather than leaving these as a bare name with no note at all |
65
+ | 0x40 | VMBUSBIP | Already correctly handled as-is — no use in this context beyond potentially being what the bridge itself connects to |
66
+
67
+ ---
68
+
69
+ ## 3. Feature additions to existing nodes
70
+
71
+ - **`velbus-clock`: add sunrise/sunset enable/disable (`0xAE`)** — part of the
72
+ same shared system block as time/date/DST/alarm, genuinely missing.
73
+ - **`velbus-button`: lock/unlock (`0x12`/`0x13`) + richer `0xED` status decode**
74
+ (locked/enabled/inverted/program-selection) — already agreed, applies as a
75
+ general button-family capability, not scoped to VMBKP alone.
76
+ - **`velbus-button`: surface channel names in the event output** — using the
77
+ existing `0xF0`/`0xF1`/`0xF2` pattern, so named-channel modules (VMBKP, and
78
+ potentially others) show real names, not just channel numbers, while every
79
+ existing numbered-only setup keeps working unchanged.
80
+
81
+ - **Bus error counter (`0xDA`) — resolved design, scoped as a follow-up, not
82
+ built today.** Confirmed genuinely useful, but explicitly framed as an edge
83
+ case: "the once in a blue moon bus error message will clear itself within
84
+ a second or two — including it in normal payload traffic will cause
85
+ confusion." Resolved design: every node that registers for its own address
86
+ already receives every packet addressed to it, including an unsolicited
87
+ `0xDA` broadcast if one occurs — so no new "request" command is needed, just
88
+ passive decoding. Add `0xDA` handling to every existing node, emitting
89
+ **only on the secondary output** (never mixed into the main status payload
90
+ on output 1), and **only when at least one counter is non-zero** — silent
91
+ during normal operation, so it never appears unless there's genuinely
92
+ something to see. Nodes that currently only have a single output would need
93
+ a second one added. **Scoped as its own follow-up given it touches most or
94
+ all existing nodes — not part of today's build.**
95
+
96
+ ---
97
+
98
+ ## 4. Deferred — logged as a stretch goal, not being built now
99
+
100
+ - **OLED image writing** (pushing a custom B&W 1-bit bitmap to an OLED glass
101
+ panel) — genuine use case raised (swapping in a different-language greeting
102
+ for a visitor without opening VelbusLink). **Confirmed: no solid reason to
103
+ build it now** — parked in `HANDOVER.md` as an explicit stretch goal rather
104
+ than an open question.
105
+
106
+ **Resolved — calibration data:** no concrete current need. Stays out of
107
+ scope alongside generic memory read/write, parked for if/when a real need
108
+ comes up rather than built speculatively.
109
+
110
+ ---
111
+
112
+ ## 5. Confirmed out of scope — no action
113
+
114
+ - **Generic memory read/write** — the foundation Program Step would sit on;
115
+ out of scope as a consequence of Program Step being out of scope.
116
+ - **Program Step read/write** — explicitly parked pending VelbusLink's own
117
+ Delphi rewrite; a strong candidate to become its own separate project
118
+ rather than living in this palette at all.
119
+ - **Cross-module "linked" LED control** — out of scope.
120
+ - **IR learn-and-replay, reframed correctly:** this was mischaracterized in
121
+ the original list — it isn't third-party IR code learning at all. The
122
+ glass-panel IR variants simply respond to Velbus-defined HEX codes and
123
+ present them as button events (up to 32), with codes 33-39 specifically
124
+ translated into heating temperature mode changes that `velbus-thermostat`
125
+ would see. Genuinely out of scope as a project, but worth remembering this
126
+ detail if the IR-capable glass panel variants (`VMBGPOD_IR` etc.) ever get
127
+ addressed — the 33-39 range needs the same special handling as any other
128
+ thermostat mode change, not treatment as plain numbered buttons.
129
+ - **DALI bridging** — out of scope, name-only per section 2.
130
+ - **Signum integration** — out of scope, name-only per section 2.
131
+
132
+ ---
133
+
134
+ ## 6. VMB4AN — groups 2/3 parked, large commitment
135
+
136
+ **Status: parked 09/07/2026, not scoped for near-term work.** `velbus-sensor`
137
+ currently only implements Group 1 of VMB4AN's three functional groups (alarm
138
+ outputs, channels 1-8, via the standard `0x00` button-style event — the same
139
+ path VMB7IN uses). The `isVMB4AN` flag already in the code is a placeholder
140
+ that's never actually consumed anywhere.
141
+
142
+ - **Group 2 — sensor inputs (channels 9-12).** Each channel supports 4
143
+ configurable operating modes (voltage 0-10V / current 4-20mA / resistance
144
+ PT100-1000 / period measurement), 4 presets (safe/night/day/comfort — same
145
+ naming as thermostat presets), a sleep timer, and configurable auto-send
146
+ behaviour (fixed interval, or threshold-based at 3.125%/6.25%/12.5%/25%
147
+ change). Reading a value and reading full settings are two separate
148
+ packets (`0xEA` status, `0xE8`+`0xE9` two-part settings, confirmed from
149
+ `protocol_vmb4an.pdf`).
150
+ - **Group 3 — analog outputs (channels 13-16).** Effectively a full dimmer
151
+ control surface bolted onto VMB4AN — same command bytes as `velbus-dimmer`
152
+ itself (`0x07` set value, `0x11` restore last value), percentage or 12-bit
153
+ precision, timer/forced-on/inhibit, even reusing `0xB8` for its status
154
+ (same byte as `VMBDMI`'s dimmer status — no real conflict, different
155
+ module addresses, just worth knowing Velbus reuses this byte across
156
+ contexts). **Deprioritized further:** not yet configurable natively in
157
+ VelbusLink, so unlikely to appear in any real installation regardless of
158
+ whether this palette supports it — low priority until that changes.
159
+ - **Comparable in size to `velbus-energy`** — a genuine second build, not a
160
+ quick addition. Revisit if/when there's a concrete need.
161
+
162
+ ---
163
+
164
+ ## 7. Final scope — everything below is confirmed and ready to build
165
+
166
+ **New registry entries** (sections 1 and 2 above) — 13 types added to
167
+ existing nodes' registries, 5 types added as scan-visible "not supported"
168
+ entries, no new nodes required for any of it.
169
+
170
+ **Feature additions to existing nodes:**
171
+ - `velbus-clock`: sunrise/sunset enable/disable (`0xAE`)
172
+ - `velbus-button`: lock/unlock (`0x12`/`0x13`), richer `0xED` status decode,
173
+ channel names surfaced in event output
174
+
175
+ **Explicitly deferred to a later session, design already settled:**
176
+ - Bus error counter (`0xDA`) — touches most/all existing nodes, scoped above
177
+
178
+ **Confirmed out of scope, no action ever:**
179
+ - Generic memory read/write, calibration data (no concrete need), Program
180
+ Step read/write, cross-module linked LED control, IR learn-and-replay (as
181
+ a feature — though see the 33-39 thermostat-mode detail above if the
182
+ IR-capable glass panel variants ever get addressed), DALI bridging, Signum
183
+ integration, `VMB1TC`/`VMB1TS` (genuinely not "easy"), `VMBLCDWB`.
184
+
185
+ **Logged as a stretch goal in `HANDOVER.md`, not built now:**
186
+ - OLED image writing
@@ -140,6 +140,7 @@ const GLASS_PANEL_TYPES = {
140
140
  hasOled: false,
141
141
  hasPir: false,
142
142
  hasOc: true, // Confirmed: VMBEL1/2/4 protocol PDF ed2 Nov 2024
143
+ hasEdgeLed: true, // VMBEL family confirmed - own protocol PDF has 'Set Edge Color' (0xD4)
143
144
  minMapVer: 2,
144
145
  series: 'original',
145
146
  },
@@ -149,6 +150,7 @@ const GLASS_PANEL_TYPES = {
149
150
  hasOled: false,
150
151
  hasPir: false,
151
152
  hasOc: true, // Confirmed: VMBEL1/2/4 protocol PDF ed2 Nov 2024
153
+ hasEdgeLed: true, // VMBEL family confirmed - own protocol PDF has 'Set Edge Color' (0xD4)
152
154
  minMapVer: 2,
153
155
  series: 'original',
154
156
  },
@@ -158,6 +160,7 @@ const GLASS_PANEL_TYPES = {
158
160
  hasOled: false,
159
161
  hasPir: false,
160
162
  hasOc: true, // Confirmed: VMBEL1/2/4 protocol PDF ed2 Nov 2024
163
+ hasEdgeLed: true, // VMBEL family confirmed - own protocol PDF has 'Set Edge Color' (0xD4)
161
164
  minMapVer: 2,
162
165
  series: 'original',
163
166
  },
@@ -167,6 +170,7 @@ const GLASS_PANEL_TYPES = {
167
170
  hasOled: true,
168
171
  hasPir: false,
169
172
  hasOc: true, // OLED/output variant — OC confirmed by protocol family
173
+ hasEdgeLed: true, // VMBEL family confirmed - own protocol PDF has 'Set Edge Color' (0xD4)
170
174
  minMapVer: 4,
171
175
  series: 'original',
172
176
  },
@@ -176,6 +180,7 @@ const GLASS_PANEL_TYPES = {
176
180
  hasOled: false,
177
181
  hasPir: true,
178
182
  hasOc: true, // PIR variant of VMBEL family — OC present
183
+ hasEdgeLed: true, // VMBEL family confirmed - own protocol PDF has 'Set Edge Color' (0xD4)
179
184
  pirChannels: {
180
185
  1: 'button1', 2: 'button2', 3: 'button3', 4: 'button4',
181
186
  5: 'virtual', 6: 'dark', 7: 'light', 8: 'motion',
@@ -225,6 +230,7 @@ const GLASS_PANEL_TYPES = {
225
230
  hasOled: false,
226
231
  hasPir: true,
227
232
  hasOc: true, // PIR variant of VMBEL family — OC present
233
+ hasEdgeLed: true, // VMBEL family confirmed - own protocol PDF has 'Set Edge Color' (0xD4)
228
234
  pirChannels: {
229
235
  1: 'button1', 2: 'button2',
230
236
  3: 'virtual', 4: 'dark', 5: 'light', 6: 'motion',
@@ -241,6 +247,7 @@ const GLASS_PANEL_TYPES = {
241
247
  hasOled: false,
242
248
  hasPir: false,
243
249
  hasOc: true, // Confirmed: VMBEL1/2/4 protocol PDF ed2 Nov 2024 covers -20 variants
250
+ hasEdgeLed: true, // VMBEL family confirmed - own protocol PDF has 'Set Edge Color' (0xD4)
244
251
  minMapVer: null,
245
252
  series: 'v2',
246
253
  },
@@ -250,6 +257,7 @@ const GLASS_PANEL_TYPES = {
250
257
  hasOled: false,
251
258
  hasPir: false,
252
259
  hasOc: true, // Confirmed: VMBEL1/2/4 protocol PDF ed2 Nov 2024 covers -20 variants
260
+ hasEdgeLed: true, // VMBEL family confirmed - own protocol PDF has 'Set Edge Color' (0xD4)
253
261
  minMapVer: null,
254
262
  series: 'v2',
255
263
  },
@@ -259,6 +267,7 @@ const GLASS_PANEL_TYPES = {
259
267
  hasOled: false,
260
268
  hasPir: false,
261
269
  hasOc: true, // Confirmed: VMBEL1/2/4 protocol PDF ed2 Nov 2024 covers -20 variants
270
+ hasEdgeLed: true, // VMBEL family confirmed - own protocol PDF has 'Set Edge Color' (0xD4)
262
271
  minMapVer: null,
263
272
  series: 'v2',
264
273
  },
@@ -268,6 +277,7 @@ const GLASS_PANEL_TYPES = {
268
277
  hasOled: true,
269
278
  hasPir: false,
270
279
  hasOc: true, // OLED/output variant — OC confirmed by protocol family
280
+ hasEdgeLed: true, // VMBEL family confirmed - own protocol PDF has 'Set Edge Color' (0xD4)
271
281
  minMapVer: null,
272
282
  series: 'v2',
273
283
  },
@@ -277,6 +287,7 @@ const GLASS_PANEL_TYPES = {
277
287
  hasOled: false,
278
288
  hasPir: true,
279
289
  hasOc: true, // PIR variant of VMBEL family — OC present
290
+ hasEdgeLed: true, // VMBEL family confirmed - own protocol PDF has 'Set Edge Color' (0xD4)
280
291
  pirChannels: {
281
292
  1: 'button1', 2: 'button2', 3: 'button3', 4: 'button4',
282
293
  5: 'virtual', 6: 'dark', 7: 'light', 8: 'motion',
@@ -326,6 +337,7 @@ const GLASS_PANEL_TYPES = {
326
337
  hasOled: false,
327
338
  hasPir: true,
328
339
  hasOc: true, // PIR variant of VMBEL family — OC present
340
+ hasEdgeLed: true, // VMBEL family confirmed - own protocol PDF has 'Set Edge Color' (0xD4)
329
341
  pirChannels: {
330
342
  1: 'button1', 2: 'button2',
331
343
  3: 'virtual', 4: 'dark', 5: 'light', 6: 'motion',
@@ -316,6 +316,56 @@
316
316
  <dt><code>{ "cmd": "led_set", "channel": 1 }</code></dt>
317
317
  <dd>Control button LED. Commands: <code>led_set</code>, <code>led_clear</code>, <code>led_slow</code>, <code>led_fast</code>, <code>led_vfast</code>.</dd>
318
318
 
319
+ <dt><code>set_edge_color</code> — <strong>VMBEL family only</strong> (VMBEL1/2/4, VMBELO,
320
+ VMBELPIR, and their -20 siblings — not VMBGP-family panels, which have only a
321
+ single-colour front LED per button, not side-firing edge lighting)</dt>
322
+ <dd>
323
+ Applies an <em>already-defined</em> colour — the module's default palette, or a
324
+ custom slot VelbusLink has already programmed — across a chosen combination of
325
+ layer(s), edge(s), and button page. <strong>Does not define new custom colours</strong> —
326
+ that stays in VelbusLink; this node only ever applies/switches between colours that
327
+ already exist on the module.
328
+ <pre>
329
+ { "cmd": "set_edge_color", "index": 5 }
330
+ // Simplest form — every field below is optional and defaults as shown.
331
+ // Applies default palette colour #5 to the background layer, all four
332
+ // edges, all button pages.
333
+
334
+ { "cmd": "set_edge_color",
335
+ "layers": ["background", "continuous"],
336
+ "edges": ["left", "top", "right", "bottom"],
337
+ "page": 1,
338
+ "palette": "default",
339
+ "index": 5 }
340
+ // Same as above but explicit — background AND continuous-feedback layers,
341
+ // all edges, button page 1 only.
342
+
343
+ { "cmd": "set_edge_color",
344
+ "layers": ["fast_blink"],
345
+ "edges": ["left"],
346
+ "page": "all",
347
+ "palette": "custom",
348
+ "index": 12,
349
+ "priority": "high",
350
+ "blink": true }
351
+ // Custom palette slot #12 (must already be programmed via VelbusLink),
352
+ // applied only to the fast-blink-feedback layer, left edge only, every
353
+ // button page, at highest override priority, with the blink flag set.
354
+ </pre>
355
+ <table style="width:100%; font-size:0.85em; border-collapse:collapse; margin-top:4px;">
356
+ <tr style="text-align:left; border-bottom:1px solid #ccc;"><th>Field</th><th>Values</th><th>Default if omitted</th></tr>
357
+ <tr><td><code>layers</code></td><td>array, any of: <code>background</code>, <code>continuous</code>, <code>slow_blink</code>, <code>fast_blink</code></td><td><code>["background"]</code></td></tr>
358
+ <tr><td><code>edges</code></td><td>array, any of: <code>left</code>, <code>top</code>, <code>right</code>, <code>bottom</code></td><td>all four</td></tr>
359
+ <tr><td><code>page</code></td><td><code>1</code>-<code>8</code>, or <code>"all"</code></td><td><code>"all"</code></td></tr>
360
+ <tr><td><code>palette</code></td><td><code>"default"</code> or <code>"custom"</code></td><td><code>"default"</code></td></tr>
361
+ <tr><td><code>index</code></td><td><code>0</code>-<code>31</code> (which palette slot to apply)</td><td><code>0</code></td></tr>
362
+ <tr><td><code>priority</code></td><td><code>"low"</code>/<code>"mid"</code>/<code>"high"</code> — <em>custom palette only</em>, ignored for default</td><td><code>"low"</code></td></tr>
363
+ <tr><td><code>blink</code></td><td><code>true</code>/<code>false</code></td><td><code>false</code></td></tr>
364
+ </table>
365
+ <p>Sending this to a non-VMBEL panel (e.g. VMBGP2) sends nothing and logs a clear
366
+ warning rather than silently failing.</p>
367
+ </dd>
368
+
319
369
  <dt><code>{ "cmd": "output_on" }</code> / <code>"output_off"</code></dt>
320
370
  <dd>Open collector output on/off.</dd>
321
371
 
@@ -38,6 +38,33 @@ const LED_CMD = {
38
38
  led_vfast: 0xF9,
39
39
  };
40
40
 
41
+ // ─────────────────────────────────────────────────────────────────────────────
42
+ // Edge colour constants — VMBEL family only (hasEdgeLed), confirmed identical
43
+ // byte layout across every VMBEL sub-family protocol PDF checked (VMBEL1/2/4,
44
+ // VMBELO, VMBELPIR, and their -20 siblings). Command byte 0xD4
45
+ // (COMMAND_SET_PB_BACKLIGHT) is shared with 'Set Custom Color' (defining new
46
+ // custom RGB palette entries) — deliberately NOT implemented here. Defining
47
+ // custom colours is commissioning-time configuration and stays in
48
+ // VelbusLink's domain, same reasoning as VMB4LEDPWM-20's grouping mode and
49
+ // Program Step read/write elsewhere in this project. Only 'Set Edge Color'
50
+ // (applying an already-defined colour — default palette, or a custom slot
51
+ // VelbusLink has already programmed) is in scope: a genuine live/runtime
52
+ // action, not palette editing.
53
+ // ─────────────────────────────────────────────────────────────────────────────
54
+ const EDGE_LAYER_BITS = {
55
+ background: 0x01,
56
+ continuous: 0x02,
57
+ slow_blink: 0x04,
58
+ fast_blink: 0x08,
59
+ };
60
+ const EDGE_SIDE_BITS = {
61
+ left: 0x01,
62
+ top: 0x02,
63
+ right: 0x04,
64
+ bottom: 0x08,
65
+ };
66
+ const EDGE_PRIORITY = { low: 0x01, mid: 0x02, high: 0x03 };
67
+
41
68
  // ─────────────────────────────────────────────────────────────────────────────
42
69
  // Channel bitmask helpers
43
70
  // ─────────────────────────────────────────────────────────────────────────────
@@ -91,6 +118,7 @@ module.exports = function(RED) {
91
118
  const typeDesc = (node.typeId !== null) ? (GLASS_PANEL_TYPES[node.typeId] || null) : null;
92
119
  const hasOled = typeDesc ? typeDesc.hasOled : false;
93
120
  const hasPir = typeDesc ? typeDesc.hasPir : false;
121
+ const hasEdgeLed = typeDesc ? !!typeDesc.hasEdgeLed : false;
94
122
  const hasOc = typeDesc ? !!typeDesc.hasOc : false;
95
123
  const pirCh = typeDesc ? (typeDesc.pirChannels || {}) : {};
96
124
 
@@ -421,6 +449,50 @@ module.exports = function(RED) {
421
449
  return;
422
450
  }
423
451
 
452
+ // ── Set edge colour (VMBEL family only) ─────────────────────────────
453
+ // Applies an already-defined colour (default palette, or a custom
454
+ // slot VelbusLink has already programmed) across a chosen combination
455
+ // of layer(s), edge(s), and button page. Does NOT define new custom
456
+ // colours — that stays in VelbusLink, see the constants comment above.
457
+ if (cmd === 'set_edge_color') {
458
+ if (!hasEdgeLed) {
459
+ node.warn('velbus-glass-panel: ' + (typeDesc ? typeDesc.name : 'this module type') +
460
+ ' has no edge lighting (VMBEL family only) — sending nothing.');
461
+ return;
462
+ }
463
+
464
+ const layers = Array.isArray(msg.payload.layers) ? msg.payload.layers : ['background'];
465
+ const edges = Array.isArray(msg.payload.edges) ? msg.payload.edges : ['left', 'top', 'right', 'bottom'];
466
+ const palette = msg.payload.palette === 'custom' ? 'custom' : 'default';
467
+ const index = Math.max(0, Math.min(31, parseInt(msg.payload.index) || 0));
468
+ const blink = !!msg.payload.blink;
469
+
470
+ let db2 = 0;
471
+ for (const l of layers) db2 |= (EDGE_LAYER_BITS[l] || 0);
472
+ if (palette === 'custom') db2 |= 0x80;
473
+
474
+ let db3 = 0;
475
+ for (const e of edges) db3 |= (EDGE_SIDE_BITS[e] || 0);
476
+ // Page: 1-8 map to nibble 0-7; 'all' (or omitted) uses 0xF, matching
477
+ // the protocol's own stated range (1000xxxx through 1111xxxx all
478
+ // mean "all pages" — 0xF is simply the clearest, most explicit value
479
+ // in that range to use).
480
+ const page = msg.payload.page;
481
+ const pageNibble = (page === undefined || page === 'all')
482
+ ? 0x0F
483
+ : Math.max(0, Math.min(7, parseInt(page) - 1));
484
+ db3 |= (pageNibble << 4) & 0xF0;
485
+
486
+ let db4 = index & 0x1F;
487
+ if (blink) db4 |= 0x80;
488
+ if (palette === 'custom') {
489
+ db4 |= (EDGE_PRIORITY[msg.payload.priority] || EDGE_PRIORITY.low) << 5;
490
+ }
491
+
492
+ node.bridge.send(pkt(0xFB, node.address, [0xD4, db2, db3, db4]));
493
+ return;
494
+ }
495
+
424
496
  // ── Open collector output ──────────────────────────────────────────
425
497
  if (cmd === 'output_on') {
426
498
  // COMMAND_SWITCH_RELAY_ON (0x02), channel byte = don't care (0xFF)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-red-contrib-velbus-2026",
3
- "version": "0.10.2",
3
+ "version": "0.10.4",
4
4
  "description": "Node-RED palette for Velbus building automation \u2014 relay, dimmer, glass panel, PIR, blind, sensor, meteo, clock nodes. Original and V2 (-20) series.",
5
5
  "keywords": [
6
6
  "node-red",
Binary file