node-red-contrib-velbus-2026 0.9.3 → 0.10.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_FORUM.md +208 -0
- package/HANDOVER.md +175 -21
- package/lib/glass-panel-types.js +36 -0
- package/lib/sensor-types.js +19 -0
- package/nodes/velbus-button/velbus-button.html +71 -16
- package/nodes/velbus-button/velbus-button.js +226 -14
- package/nodes/velbus-clock/velbus-clock.html +21 -0
- package/nodes/velbus-clock/velbus-clock.js +36 -0
- package/nodes/velbus-dimmer/velbus-dimmer.html +9 -0
- package/nodes/velbus-dimmer/velbus-dimmer.js +66 -35
- package/nodes/velbus-glass-panel/velbus-glass-panel.html +2 -0
- package/nodes/velbus-glass-panel/velbus-glass-panel.js +4 -2
- package/nodes/velbus-scan/velbus-scan.js +34 -0
- package/nodes/velbus-sensor/velbus-sensor.html +1 -0
- package/package.json +1 -1
- package/velbus-2026-repo.bundle +0 -0
- package/velbus-2026-repo.bundle.1 +0 -0
package/CHANGELOG_FORUM.md
CHANGED
|
@@ -14,6 +14,214 @@ All feedback via GitHub issues, with examples and debug captures where possible.
|
|
|
14
14
|
|
|
15
15
|
---
|
|
16
16
|
|
|
17
|
+
## Field-confirmed — 09/07/2026
|
|
18
|
+
|
|
19
|
+
**v0.9.3 confirmed working against real hardware** (Stuart, his own home
|
|
20
|
+
installation). Both real VMBGPOD panels present on the bus (addresses 0x05
|
|
21
|
+
and 0x18/0x2C) now report correctly — `"module":"VMBGPOD"`, correct
|
|
22
|
+
suggested node, correct channel count — where a rescan previously showed
|
|
23
|
+
`unknown_0x28` twice. The only remaining unknown in the same scan is
|
|
24
|
+
`unknown_0x42` (VMBKP, address 0xFD on Stuart's bus) — expected and correct,
|
|
25
|
+
since that module genuinely has no node built yet. This closes out the
|
|
26
|
+
VMBGPOD saga (v0.9.2 → v0.9.3) with an actual confirmed result, not just
|
|
27
|
+
passing tests — worth the distinction given how much back-and-forth two
|
|
28
|
+
separate duplicate-table bugs took to fully resolve.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## v0.10.1 — 09/07/2026
|
|
33
|
+
|
|
34
|
+
### Two critical bugs found on real hardware — velbus-dimmer and velbus-glass-panel
|
|
35
|
+
|
|
36
|
+
**velbus-dimmer — `on`/`state` always wrong for original-series dimmers.**
|
|
37
|
+
Reported by Stuart: a VMBDMI at 75% dim showing `state:"off"`, `on:false`.
|
|
38
|
+
Root cause was a genuine misunderstanding of the protocol, not a small
|
|
39
|
+
off-by-one: `0xB8`'s `DATABYTE3` packs run-mode, error, load-type, and
|
|
40
|
+
temperature band **all into one status byte** (confirmed identical across
|
|
41
|
+
`protocol_vmbdmi.pdf`, `protocol_vmbdmi_r.pdf`, and `protocol_vmb4dc.pdf`).
|
|
42
|
+
The previous code treated this as if it were a separate mode-byte +
|
|
43
|
+
status-byte pair (the way relay modules genuinely have), and additionally
|
|
44
|
+
read `DATABYTE5` (LED indicator status — real values `0x00`/`0x80`/`0x40`/
|
|
45
|
+
`0x20`/`0x10`) as a second status word, checking its low 2 bits for
|
|
46
|
+
confirmation. Since none of the real LED status values have those bits
|
|
47
|
+
set, a dimmer in ordinary "normal running" mode — the overwhelmingly
|
|
48
|
+
common case — always fell through to `'off'`, regardless of actual dim
|
|
49
|
+
level. Also fixed in the same pass: the 24-bit current-delay timer was
|
|
50
|
+
being read as only 16 bits from the wrong byte offset, and `decodeThermal`
|
|
51
|
+
was being called on the LED byte instead of the real status byte (explains
|
|
52
|
+
why `thermal` always showed all zeros in the field report). `ledState` is
|
|
53
|
+
now correctly decoded and added to the payload. Verified against the exact
|
|
54
|
+
reported scenario plus inhibited/forced_on/disabled/thermal-alarm cases,
|
|
55
|
+
with the bit-field math for the packed status byte hand-checked.
|
|
56
|
+
|
|
57
|
+
**velbus-glass-panel — `0xEA` thermostat status has been silently crashing
|
|
58
|
+
since it was written.** Reported by Stuart via a `"velbus-bridge dispatch
|
|
59
|
+
error: currentTemp is not defined"` message appearing repeatedly while
|
|
60
|
+
testing a VMBGP2. Root cause: `currentTemp` and `targetTemp` were only ever
|
|
61
|
+
assigned as properties of the `payload` object literal, never declared as
|
|
62
|
+
their own variables — but the very next line referenced them as bare
|
|
63
|
+
identifiers in the `setStatus(...)` call. Because JS evaluates a function's
|
|
64
|
+
arguments before calling it, this threw a `ReferenceError` before
|
|
65
|
+
`node.send()` on the following line ever executed. **This means the
|
|
66
|
+
`type:"thermostat"` payload has likely never once been successfully
|
|
67
|
+
delivered for any thermostat-equipped glass panel** — the bridge's
|
|
68
|
+
dispatch-error handling caught the exception each time rather than
|
|
69
|
+
crashing the whole process, which is exactly why this went unnoticed for
|
|
70
|
+
so long rather than being immediately obvious. Fixed by declaring both as
|
|
71
|
+
proper local `const`s before use. Did a full sweep of every other packet
|
|
72
|
+
case in this file (button, module status, temperature, light sensor, memo
|
|
73
|
+
text, counter, name parts) via the mock harness afterward, specifically
|
|
74
|
+
exercising the OLED- and PIR-gated branches too — no other instances
|
|
75
|
+
found. Also swept every other node file for the same bare-identifier
|
|
76
|
+
`.toFixed()` pattern that caused this — one other match (`velbus-meteo`)
|
|
77
|
+
checked and confirmed already correct (properly prefixed with `payload.`).
|
|
78
|
+
|
|
79
|
+
Both verified via the mock-RED harness against the exact reported symptoms
|
|
80
|
+
before and after the fix — not just re-reading the corrected code. Not yet
|
|
81
|
+
re-confirmed on Stuart's real hardware.
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## v0.10.0 — 09/07/2026
|
|
86
|
+
|
|
87
|
+
### Coverage roadmap implementation — 9 new module types, velbus-button overhaul, velbus-clock sunrise/sunset
|
|
88
|
+
|
|
89
|
+
Following a full rationalization pass over every unaddressed Velbus module
|
|
90
|
+
type and feature (see `coverage-roadmap.md`), this implements everything
|
|
91
|
+
confirmed in scope. Every single item below was checked against its actual
|
|
92
|
+
protocol document before being added — several real divergences were caught
|
|
93
|
+
in the process that would otherwise have shipped silently wrong.
|
|
94
|
+
|
|
95
|
+
**velbus-button — substantial overhaul, not just new registry entries:**
|
|
96
|
+
- 7 new module types: VMB8IR, VMB4PD, VMB4RF, VMBRFR8S, VMBVP01, VMBKP, VMBIN.
|
|
97
|
+
- **Lock/unlock (0x12/0x13)** — confirmed present on 8 of the 12 total types
|
|
98
|
+
now covered; **NOT universal**, despite being asked for as "a key Velbus
|
|
99
|
+
feature." VMB8PB, VMB8IR, VMB4PD, and VMBVP01 genuinely lack this command
|
|
100
|
+
in their own protocol documents. Gated per-type (`hasLock`) — sending it to
|
|
101
|
+
an unsupported type now warns clearly on output 2 rather than silently
|
|
102
|
+
doing nothing.
|
|
103
|
+
- **Richer 0xED status decode** (locked/enabled/inverted/program-disabled) —
|
|
104
|
+
also NOT universal. VMB8PB's 0xED is a completely different, simpler
|
|
105
|
+
LED-only format; VMB4RF's status uses command byte 0xB4, not 0xED, with a
|
|
106
|
+
different field at DATABYTE4 ("learn transmitter mode"); VMBVP01's 0xED is
|
|
107
|
+
a third, shorter shape again. Gated per-type (`hasRichStatus`) — decoding
|
|
108
|
+
is skipped entirely for types that don't match, rather than risk
|
|
109
|
+
misreading whatever they actually send.
|
|
110
|
+
- **Channel names surfaced in event output** (0xF0/F1/F2) — found the
|
|
111
|
+
selector byte convention itself is inconsistent across types: some use a
|
|
112
|
+
bitmask (one bit per channel), others a literal 1-based number. These
|
|
113
|
+
produce the *same* byte value for channels 1-2, diverging only from
|
|
114
|
+
channel 3 onward — exactly the kind of thing that would pass casual
|
|
115
|
+
testing and then silently corrupt every name from channel 3 up. Verified
|
|
116
|
+
explicitly at channel 3 for both conventions before shipping.
|
|
117
|
+
- **VMBVP01 (DoorBird)** gets fixed semantic channel labels (Motion 1/2,
|
|
118
|
+
Bell 1/2, Door 1/2, Virtual button 1/2) — hardware-fixed functions, not
|
|
119
|
+
VelbusLink-configurable names, so not sourced from 0xF0-F2 at all.
|
|
120
|
+
- Output changed from 1 to 2 (events/status, warnings) — non-breaking for
|
|
121
|
+
existing flows, the new output simply has no wires by default.
|
|
122
|
+
- **Real mistake caught before shipping:** first pass had VMB4RF at 8
|
|
123
|
+
channels; its own status packet says "channel 1 to 4," matching its name.
|
|
124
|
+
Corrected to 4 before release, not after.
|
|
125
|
+
- **A second, more serious pre-existing bug found and fixed, unrelated to
|
|
126
|
+
today's additions:** `VMB4PB` and `VMB6PB-20` — two of the *original* five
|
|
127
|
+
button types, present since v0.5.2 — were registered under wrong type
|
|
128
|
+
bytes (`0x1C` and `0x20`) in this file's own registry. `0x1C` isn't a real
|
|
129
|
+
Velbus type byte at all; `0x20` actually belongs to `VMBGP4`, an unrelated
|
|
130
|
+
glass panel type. `velbus-scan.js` has always had the correct values
|
|
131
|
+
(`0x44`/`0x4C`) — only this file's internal lookup was wrong, meaning a
|
|
132
|
+
real `VMB4PB` or `VMB6PB-20`, correctly identified by a scan, would never
|
|
133
|
+
have matched this file's own type descriptor at all. Every type-specific
|
|
134
|
+
feature (and now, lock/unlock and rich status too) would have silently
|
|
135
|
+
never activated for these two types. Found by cross-referencing the
|
|
136
|
+
official type list while writing this changelog entry, not by design —
|
|
137
|
+
worth remembering that documentation review can surface real bugs too.
|
|
138
|
+
|
|
139
|
+
**velbus-sensor:** VMB6IN added. Confirmed simpler than its VMB7IN sibling,
|
|
140
|
+
not just a smaller version of it — no lock/unlock command exists for it at
|
|
141
|
+
all, and its 0xED module status is 5 bytes vs VMB7IN's 7. The existing
|
|
142
|
+
`body.length < 7` guard already skips it safely; no code change needed
|
|
143
|
+
beyond the registry entry itself.
|
|
144
|
+
|
|
145
|
+
**velbus-glass-panel:** VMBGP4PIR-2 (0x3E) and VMBGPTC (0x25) added.
|
|
146
|
+
- **Real mistake caught:** VMBGP4PIR-2's channels 5-8 have completely
|
|
147
|
+
different semantics from its 0x2D sibling despite the near-identical name
|
|
148
|
+
(Dark/Light output, Motion output, Light-depending-motion, Absence output
|
|
149
|
+
— not virtual/dark/light/motion). Copying the sibling's mapping would have
|
|
150
|
+
silently mislabeled four channels.
|
|
151
|
+
- VMBGPTC confirmed sharing its actual protocol document with VMBGPO
|
|
152
|
+
(0x21) — a thermostat-only variant of the same panel hardware, added to
|
|
153
|
+
the glass-panel registry rather than as thermostat-node-only, so
|
|
154
|
+
`velbus-thermostat` picks up its function automatically the same way it
|
|
155
|
+
already does for every other panel address.
|
|
156
|
+
|
|
157
|
+
**velbus-clock:** sunrise/sunset enable/disable (0xAE) added, same
|
|
158
|
+
global/local address pattern as the existing `set_alarm` — confirmed
|
|
159
|
+
identical packet body for both from the protocol PDF.
|
|
160
|
+
|
|
161
|
+
**velbus-scan:** all of the above added across its three independent tables
|
|
162
|
+
(`ALL_TYPES`/`NODE_SUGGESTION`/`MODULE_CHANNELS`) — the exact lesson from
|
|
163
|
+
the VMBGPOD saga (v0.9.2/v0.9.3), applied proactively this time rather than
|
|
164
|
+
discovered the hard way again. Also adds explicit `"Not supported"` scan
|
|
165
|
+
labels (rather than falling through to a bare name with no node) for
|
|
166
|
+
VMBDALI, VMBDALI-20, VMBLCDWB, VMCM3, VMBSIG, VMBSIG-20, and VMBSIG-21 —
|
|
167
|
+
recognized correctly in a scan, deliberately not built, by design rather
|
|
168
|
+
than oversight.
|
|
169
|
+
|
|
170
|
+
**Explicitly deferred, not built this round:** VMB1DM, VMBDME, and VMB1LED
|
|
171
|
+
(the dimmer-family additions) all turned out to use a genuinely different
|
|
172
|
+
single-channel `0xEE` status layout — distinct from both `velbus-dimmer`'s
|
|
173
|
+
own format and `velbus-dimmer-20`'s multi-channel bitmask format. This needs
|
|
174
|
+
real new decode logic, not a registry entry, and doesn't meet the
|
|
175
|
+
"minimal effort" bar set for this round. Parked rather than forced in.
|
|
176
|
+
|
|
177
|
+
**Verification:** every new packet format checked against its actual
|
|
178
|
+
protocol document (not inferred from a same-named sibling) before being
|
|
179
|
+
implemented; every new command exercised through the mock-RED harness with
|
|
180
|
+
hand-checked checksums; the channel-3 naming-convention divergence
|
|
181
|
+
specifically tested for both conventions, not just one; a full simulated
|
|
182
|
+
scan run across every new and "not supported" type confirmed correct
|
|
183
|
+
`suggestedNode`/`channels` output end to end. Not yet sent to a real bus.
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## v0.9.4 — 09/07/2026
|
|
188
|
+
|
|
189
|
+
### velbus-button — critical bug, live since v0.5.2: button events shifted by one byte
|
|
190
|
+
|
|
191
|
+
- **Found while scoping VMBKP's decode logic, not reported directly** — checking
|
|
192
|
+
`velbus-button.js` as a template surfaced that its `0x00` handler read
|
|
193
|
+
`body[0]`/`body[1]`/`body[2]` for pressed/released/long-pressed, when
|
|
194
|
+
`body[0]` is always the command byte itself (always `0x00`, per this
|
|
195
|
+
project's own most-repeated rule — see `HANDOVER.md` section 4.3). Every
|
|
196
|
+
field was reading one byte too early.
|
|
197
|
+
- **Real impact, not theoretical:** `pressed` was always empty (reading the
|
|
198
|
+
constant command byte), `released` was actually reporting what DATABYTE2
|
|
199
|
+
(the real "pressed" bitmask) contained, `longPressed` was reporting what
|
|
200
|
+
DATABYTE3 (the real "released" bitmask) contained, and the real
|
|
201
|
+
DATABYTE4 (long-press bitmask) was never read at all. The `on` field
|
|
202
|
+
followed the same corruption — it could report `true` on a release and
|
|
203
|
+
never correctly on an immediate press.
|
|
204
|
+
- **Confirmed live since `velbus-button`'s introduction in v0.5.2** — this
|
|
205
|
+
is not a new regression, it has been shipping incorrect button-event data
|
|
206
|
+
for the entire time this node has existed. `velbus-glass-panel`'s own
|
|
207
|
+
`0x00` handler was checked immediately afterward and confirmed **not**
|
|
208
|
+
affected — it already used the correct `body[1]`/`body[2]`/`body[3]`
|
|
209
|
+
indexing, so this was isolated to one file, not systemic.
|
|
210
|
+
- **Fixed and verified with a real repro, not just a corrected read of the
|
|
211
|
+
code:** built a mock-harness test that reproduces the exact failure first
|
|
212
|
+
(channel 3 pressed came back reported as "released") before applying the
|
|
213
|
+
fix, then re-ran the same test plus three more (release, long-press,
|
|
214
|
+
simultaneous multi-channel press) to confirm all four now report
|
|
215
|
+
correctly.
|
|
216
|
+
- **If you have flows depending on `velbus-button`'s `pressed`/`released`/
|
|
217
|
+
`longPressed` distinction** (rather than just the `on` boolean, or
|
|
218
|
+
scanning/discovery, which were unaffected), check them after updating —
|
|
219
|
+
behaviour that previously "worked" by only watching `on`, or by
|
|
220
|
+
compensating for the shift some other way in the flow itself, may now
|
|
221
|
+
behave differently now that the underlying data is actually correct.
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
17
225
|
## v0.9.3 — 09/07/2026
|
|
18
226
|
|
|
19
227
|
### velbus-scan — VMBGPOD still showed "unknown_0x28" after the v0.9.2 fix
|
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.
|
|
9
|
+
Current state at time of writing: **v0.10.1, 19 nodes, published on npm.**
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
@@ -106,7 +106,7 @@ lib/ Shared code — protocol utilities and per-module-fam
|
|
|
106
106
|
dimmer-types.js Original-series dimmer module type registry
|
|
107
107
|
dimmer-types-20.js V2 dimmer module type registry (incl. LED grouping mode / Device
|
|
108
108
|
Type table for VMB4LEDPWM-20)
|
|
109
|
-
glass-panel-types.js All
|
|
109
|
+
glass-panel-types.js All 29 glass panel module types in one registry (hasOled/hasPir/
|
|
110
110
|
hasOc/minMapVer flags per type)
|
|
111
111
|
pir-types.js / pir-types-20.js PIR sensor module type registries
|
|
112
112
|
sensor-types.js / sensor-types-20.js Sensor/meteo module type registries
|
|
@@ -262,6 +262,22 @@ implementing a new packet handler, always write out the DATABYTE-to-`body[]` ind
|
|
|
262
262
|
mapping explicitly as a comment before writing the parsing logic — it is not something
|
|
263
263
|
to trust from memory or infer quickly.
|
|
264
264
|
|
|
265
|
+
**The canonical real example: `velbus-button` shipped this exact bug from its very
|
|
266
|
+
first version (v0.5.2) until v0.9.4** — over 30 versions, undetected. Its `0x00`
|
|
267
|
+
handler read `body[0]`/`body[1]`/`body[2]` for pressed/released/long-pressed, when the
|
|
268
|
+
correct indices are `body[1]`/`body[2]`/`body[3]`. The practical effect: `pressed` was
|
|
269
|
+
always empty (silently reading the constant command byte), `released` actually reported
|
|
270
|
+
what was really the pressed bitmask, `longPressed` reported what was really the released
|
|
271
|
+
bitmask, and the real long-press data was never read at all. It went unnoticed for this
|
|
272
|
+
long specifically because `velbus-glass-panel`'s own, separately-written `0x00` handler
|
|
273
|
+
got the indexing right from the start, and nobody had directly exercised
|
|
274
|
+
`velbus-button`'s press/release distinction against real hardware — only its
|
|
275
|
+
scan/discovery path (`0xFF`/`0xB0`, handled entirely separately) had seen real traffic.
|
|
276
|
+
A bug in one packet handler is invisible from the outside if nothing forces that
|
|
277
|
+
specific handler to run against real data. If you're verifying a node, verify the
|
|
278
|
+
specific packet type you care about — passing scan/discovery doesn't imply anything
|
|
279
|
+
about a different command byte's handler in the same file.
|
|
280
|
+
|
|
265
281
|
### 4.4 Address format
|
|
266
282
|
|
|
267
283
|
Module addresses are stored as **hex strings in the editor's dropdown UI** (e.g.
|
|
@@ -284,18 +300,18 @@ or a string before assuming the parsing logic itself is wrong.
|
|
|
284
300
|
| `velbus-relay-20` | Velbus (outputs) | V2 relays: VMB1RYS-20, VMB4RYLD-20, VMB4RYNO-20 |
|
|
285
301
|
| `velbus-dimmer` | Velbus (outputs) | Original-series dimmers: VMBDMI, VMBDMI-R, VMB4DC |
|
|
286
302
|
| `velbus-dimmer-20` | Velbus (outputs) | V2 dimmers: VMB2DC-20, VMB8DC-20, VMB4LEDPWM-20 (incl. RGB/RGBW grouping mode) |
|
|
287
|
-
| `velbus-glass-panel` | Velbus (inputs) | All
|
|
303
|
+
| `velbus-glass-panel` | Velbus (inputs) | All 29 glass panel types (original + V2), buttons/OLED/PIR/open-collector as applicable per type |
|
|
288
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 |
|
|
289
|
-
| `velbus-button` | Velbus (inputs) |
|
|
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) |
|
|
290
306
|
| `velbus-pir` | Velbus (inputs) | Original-series PIR: VMBPIRO-10, VMBPIRM, VMBPIRC, VMBPIRO |
|
|
291
307
|
| `velbus-pir-20` | Velbus (inputs) | V2 PIR: VMBPIR-20, VMBPIRO-20 |
|
|
292
308
|
| `velbus-meteo` | Velbus (inputs) | Weather station: VMBMETEO |
|
|
293
|
-
| `velbus-sensor` | Velbus (inputs) | Original-series input/analogue: VMB7IN, VMB4AN |
|
|
309
|
+
| `velbus-sensor` | Velbus (inputs) | Original-series input/analogue: VMB7IN, VMB4AN, VMB6IN |
|
|
294
310
|
| `velbus-sensor-20` | Velbus (inputs) | V2 input: VMB8IN-20 |
|
|
295
311
|
| `velbus-blind` | Velbus (outputs) | VMB1BL, VMB2BL |
|
|
296
312
|
| `velbus-blind-s` | Velbus (outputs) | VMB1BLS, VMB2BLE, VMB2BLE-10 |
|
|
297
313
|
| `velbus-blind-20` | Velbus (outputs) | VMB2BLE-20 |
|
|
298
|
-
| `velbus-clock` | Velbus (outputs) | **No fixed module address.** Broadcasts system time/date/DST to the bus broadcast address (`0x00`),
|
|
314
|
+
| `velbus-clock` | Velbus (outputs) | **No fixed module address.** Broadcasts system time/date/DST to the bus broadcast address (`0x00`), sets clock alarms and sunrise/sunset enable state either globally (broadcast) or locally (a specific module, via a per-message address override) |
|
|
299
315
|
| `velbus-energy` | Velbus (inputs) | VMBPSUMNGR-20 — power supply manager: PSU load percentages, live wattage/voltage/amperage per rail, a warranty (hours-in-operation) counter, and PSU/warranty alarm status |
|
|
300
316
|
|
|
301
317
|
Palette group colours: **Velbus (inputs)** is teal (`#3A8C8C`), **Velbus (outputs)** is
|
|
@@ -331,23 +347,31 @@ blue (`#4A90D9`).
|
|
|
331
347
|
| 0x2F | VMBDMI-R | velbus-dimmer | n/a |
|
|
332
348
|
| 0x4B | VMB8DC-20 | velbus-dimmer-20 | n/a |
|
|
333
349
|
|
|
334
|
-
### Push buttons
|
|
335
|
-
| Type byte | Module |
|
|
336
|
-
|
|
337
|
-
| 0x01 | VMB8PB |
|
|
338
|
-
| 0x16 | VMB8PBU |
|
|
339
|
-
| 0x17 | VMB6PBN |
|
|
340
|
-
| 0x18 | VMB2PBN |
|
|
341
|
-
| 0x44 | VMB4PB | velbus-button |
|
|
342
|
-
| 0x4C | VMB6PB-20 | velbus-
|
|
343
|
-
|
|
344
|
-
|
|
350
|
+
### Push buttons (all → velbus-button, 12 types)
|
|
351
|
+
| Type byte | Module | Lock/unlock | Notes |
|
|
352
|
+
|---|---|---|---|
|
|
353
|
+
| 0x01 | VMB8PB | No | Simpler 0xED (LED status only), no lock command at all |
|
|
354
|
+
| 0x16 | VMB8PBU | Yes | |
|
|
355
|
+
| 0x17 | VMB6PBN | Yes | |
|
|
356
|
+
| 0x18 | VMB2PBN | — | Not yet cross-checked for lock support, treated conservatively |
|
|
357
|
+
| 0x44 | VMB4PB | Yes | **Type byte corrected 09/07/2026** — was wrongly keyed 0x1C in `velbus-button.js`'s own registry (not a real type byte at all); `velbus-scan.js` always had 0x44 right |
|
|
358
|
+
| 0x4C | VMB6PB-20 | Yes | **Type byte corrected 09/07/2026** — was wrongly keyed 0x20 (which is actually VMBGP4, a different module); `velbus-scan.js` always had 0x4C right |
|
|
359
|
+
| 0x0A | VMB8IR | No | IR receiver — presents fixed Velbus IR codes as button events |
|
|
360
|
+
| 0x0B | VMB4PD | No | LCD module — only the 4 button channels covered, not the LCD |
|
|
361
|
+
| 0x1A | VMB4RF | Yes | 4 channels (matches its name) — status uses 0xB4, not 0xED, so rich status is not decoded even though lock/unlock works |
|
|
362
|
+
| 0x30 | VMBRFR8S | Yes | |
|
|
363
|
+
| 0x33 | VMBVP01 | No | DoorBird — fixed semantic labels (Motion 1/2, Bell 1/2, Door 1/2, Virtual button 1/2), different/shorter 0xED not decoded |
|
|
364
|
+
| 0x42 | VMBKP | Yes | |
|
|
365
|
+
| 0x43 | VMBIN | Yes | Single channel |
|
|
366
|
+
|
|
367
|
+
### Glass panels (all → velbus-glass-panel, 29 types)
|
|
345
368
|
| Type byte | Module | OLED | PIR | Open collector | Min. map version |
|
|
346
369
|
|---|---|---|---|---|---|
|
|
347
370
|
| 0x1E | VMBGP1 | no | no | unconfirmed¹ | — |
|
|
348
371
|
| 0x1F | VMBGP2 | no | no | unconfirmed¹ | — |
|
|
349
372
|
| 0x20 | VMBGP4 | no | no | unconfirmed¹ | — |
|
|
350
373
|
| 0x21 | VMBGPO | yes | no | yes | 2 |
|
|
374
|
+
| 0x25 | VMBGPTC | yes | no | no | — |
|
|
351
375
|
| 0x28 | VMBGPOD | yes | no | no | — |
|
|
352
376
|
| 0x2D | VMBGP4PIR | no | yes | unconfirmed¹ | — |
|
|
353
377
|
| 0x34 | VMBEL1 | no | no | yes | 2 |
|
|
@@ -359,6 +383,7 @@ blue (`#4A90D9`).
|
|
|
359
383
|
| 0x3B | VMBGP2-2 | no | no | no² | — |
|
|
360
384
|
| 0x3C | VMBGP4-2 | no | no | no² | — |
|
|
361
385
|
| 0x3D | VMBGPOD-2 | yes | no | unconfirmed¹ | 2 |
|
|
386
|
+
| 0x3E | VMBGP4PIR-2 | no | yes | unconfirmed¹ | — |
|
|
362
387
|
| 0x47 | VMBEL2PIR | no | yes | yes | — |
|
|
363
388
|
| 0x4F | VMBEL1-20 | no | no | yes | — |
|
|
364
389
|
| 0x50 | VMBEL2-20 | no | no | yes | — |
|
|
@@ -372,6 +397,14 @@ blue (`#4A90D9`).
|
|
|
372
397
|
| 0x5C | VMBEL2PIR-20³ | no | yes | yes | — |
|
|
373
398
|
| 0x5F | VMBGP4PIR-20 | no | yes | unconfirmed¹ | — |
|
|
374
399
|
|
|
400
|
+
⁴ VMBGPTC (0x25) shares its actual protocol document with VMBGPO (0x21) — a
|
|
401
|
+
thermostat-only variant of the same touch panel hardware, not a separate
|
|
402
|
+
product. Type byte confirmed from the official type list, not spelled out
|
|
403
|
+
separately in the shared document's body. VMBGP4PIR-2 (0x3E) has genuinely
|
|
404
|
+
different channel 5-8 semantics from its 0x2D sibling despite the similar
|
|
405
|
+
name (Dark/Light output, Motion output, Light-depending-motion, Absence
|
|
406
|
+
output — not virtual/dark/light/motion) — confirmed directly, not assumed.
|
|
407
|
+
|
|
375
408
|
¹ Open-collector support unconfirmed against real hardware — see [section 13](#13-known-open-issues).
|
|
376
409
|
² Confirmed no open-collector commands in the protocol PDF, but not yet live-verified.
|
|
377
410
|
³ The official Velbus type list shows different module names at these two type bytes than
|
|
@@ -395,6 +428,7 @@ what this registry currently uses — flagged for verification, see
|
|
|
395
428
|
| 0x31 | VMBMETEO | velbus-meteo |
|
|
396
429
|
| 0x32 | VMB4AN | velbus-sensor |
|
|
397
430
|
| 0x4E | VMB8IN-20 | velbus-sensor-20 |
|
|
431
|
+
| 0x05 | VMB6IN | velbus-sensor — simpler sibling of VMB7IN, no lock/unlock at all, 5-byte 0xED (vs VMB7IN's 7) safely skipped by the existing length guard |
|
|
398
432
|
|
|
399
433
|
### Blind / shutter
|
|
400
434
|
| Type byte | Module | Node |
|
|
@@ -494,6 +528,36 @@ body[6] = error bitmask
|
|
|
494
528
|
body[7] = alarm/program byte
|
|
495
529
|
```
|
|
496
530
|
|
|
531
|
+
### 7.5a `0xB8` dimmer status — original series (VMBDMI, VMBDMI-R, VMB4DC)
|
|
532
|
+
|
|
533
|
+
**Not the same shape as 7.5 above, despite both being "dimmer status."**
|
|
534
|
+
Confirmed identical across all three original-series protocol PDFs — one
|
|
535
|
+
combined status byte, not separate mode/status bytes the way relay modules
|
|
536
|
+
or the V2 dimmer status have:
|
|
537
|
+
```
|
|
538
|
+
body[0] = 0xB8
|
|
539
|
+
body[1] = channel (VMBDMI/-R: always 0x01; VMB4DC: bitmask)
|
|
540
|
+
body[2] = status byte — MULTIPLE bit-fields packed together:
|
|
541
|
+
bits 0-1: run mode (00=normal, 01=inhibited, 10=forced_on, 11=disabled)
|
|
542
|
+
bits 2-3: error (VMBDMI/-R only — VMB4DC has no thermal section at all)
|
|
543
|
+
bit 4: load type (VMBDMI/-R only: 0=resistive, 1=inductive)
|
|
544
|
+
bits 5-7: temperature band (VMBDMI/-R only, 8 levels)
|
|
545
|
+
body[3] = dim value (0-100%)
|
|
546
|
+
body[4] = LED indicator status ONLY — unrelated to run state (0x00 off,
|
|
547
|
+
0x80 on, 0x40 slow blink, 0x20 fast blink, 0x10 very fast blink)
|
|
548
|
+
body[5-7] = 24-bit current delay time, MSB first
|
|
549
|
+
```
|
|
550
|
+
There is no separate `"forced_off"` status — that's a real, distinct
|
|
551
|
+
*command* (0x12) you can send, but the module reports its result through
|
|
552
|
+
the same four-value run-mode set above, same as relay's forced/inhibited
|
|
553
|
+
pattern conceptually, but packed into one byte here rather than two.
|
|
554
|
+
`on` is true for `forced_on`, or for `normal` mode with a nonzero dim
|
|
555
|
+
value — **not** simply "mode equals the literal string on," which was the
|
|
556
|
+
real bug (v0.10.1): a dimmer in ordinary normal-running mode — by far the
|
|
557
|
+
most common real-world state — was being read as `off` regardless of dim
|
|
558
|
+
level, because the code checked the LED status byte's low bits for
|
|
559
|
+
confirmation instead of using the dim value directly.
|
|
560
|
+
|
|
497
561
|
### 7.6 `0xA5` dim level — up to four channels packed per packet
|
|
498
562
|
```
|
|
499
563
|
body[0] = 0xA5, body[1] = channel, body[2] = level (0-254)
|
|
@@ -621,7 +685,7 @@ about why in the commit message.
|
|
|
621
685
|
|
|
622
686
|
- **Generational split.** Nodes generally split at the V2.0 boundary — one node for
|
|
623
687
|
original-series, a separate node for V2. **Exceptions:** `velbus-glass-panel` (one
|
|
624
|
-
node covers all
|
|
688
|
+
node covers all 29 types, both generations, via the type registry's per-type flags
|
|
625
689
|
rather than a code-level split), `velbus-thermostat` (covers the thermostat function
|
|
626
690
|
on any glass panel type), `velbus-meteo` (only one generation exists), and the blind
|
|
627
691
|
family (`velbus-blind` / `velbus-blind-s` / `velbus-blind-20`, split by actual protocol
|
|
@@ -775,6 +839,25 @@ orientation at the time of writing:
|
|
|
775
839
|
|
|
776
840
|
- **Field-tested against live hardware:** the core relay, dimmer, glass panel, and
|
|
777
841
|
thermostat nodes have real-hardware confirmation for their primary functions.
|
|
842
|
+
`VMBGPOD` (0x28) specifically confirmed 09/07/2026 against two real panels on
|
|
843
|
+
Stuart's own home bus, closing out the v0.9.2/v0.9.3 registry-gap saga with an
|
|
844
|
+
actual result rather than just a passing test.
|
|
845
|
+
- **`velbus-dimmer`'s `0xB8` status decode was fundamentally wrong from when it was
|
|
846
|
+
first written until v0.10.1** — see section 7.5a. A dimmer in ordinary "normal
|
|
847
|
+
running" mode always reported `off` regardless of actual dim level. Fixed and
|
|
848
|
+
verified via the mock harness against the exact reported scenario, but not yet
|
|
849
|
+
re-confirmed against Stuart's real VMBDMI.
|
|
850
|
+
- **`velbus-glass-panel`'s `0xEA` thermostat status has been silently crashing
|
|
851
|
+
since it was written, until v0.10.1** — see section 16's code style rules for
|
|
852
|
+
the full story. The `type:"thermostat"` payload has likely never once been
|
|
853
|
+
successfully delivered for any real thermostat-equipped panel. Fixed and swept
|
|
854
|
+
for the same pattern elsewhere in the file (none found), but not yet
|
|
855
|
+
re-confirmed against Stuart's real hardware.
|
|
856
|
+
- **`velbus-button` had a critical, real bug from its first version until v0.9.4** —
|
|
857
|
+
see section 4.3 for the full story. Its press/release/long-press decode is now
|
|
858
|
+
fixed and verified with a real repro, but has not yet been re-confirmed against a
|
|
859
|
+
live button press on real hardware (only via the mock harness) — worth doing
|
|
860
|
+
before trusting it fully, given how long the broken version went unnoticed.
|
|
778
861
|
- **Mock-harness verified only, not yet confirmed against a real bus:** `velbus-clock`
|
|
779
862
|
(both the time/date/DST broadcast and the `set_alarm` command), the
|
|
780
863
|
`velbus-dimmer-20` `get_device_type` read command, and `velbus-energy` in its
|
|
@@ -790,9 +873,10 @@ orientation at the time of writing:
|
|
|
790
873
|
## 13. Known open issues
|
|
791
874
|
|
|
792
875
|
- **`VMBKP` (0x42, "Keypad interface module") has no node at all.** Found scanning a
|
|
793
|
-
real installation (Stuart's home)
|
|
794
|
-
module
|
|
795
|
-
|
|
876
|
+
real installation (Stuart's home) — confirmed present at address `0xFD`, a real
|
|
877
|
+
module on a real bus, not a hypothetical. A genuinely new module type, not yet
|
|
878
|
+
scoped. Its protocol PDF (`protocol_vmbkp.pdf`, 28 pages) is substantial: channel
|
|
879
|
+
status, module status, and a full per-channel LED control layer
|
|
796
880
|
(clear/set/slow-blink/fast-blink/very-fast-blink), similar in spirit to `velbus-button`
|
|
797
881
|
but with LED feedback control `velbus-button` doesn't have. This needs the same
|
|
798
882
|
"how much work would this involve" scoping pass `velbus-energy` got before it was
|
|
@@ -826,6 +910,33 @@ orientation at the time of writing:
|
|
|
826
910
|
against the year's January/July offsets to infer whether daylight saving is active)
|
|
827
911
|
has only been sanity-checked in an environment where daylight saving never applies —
|
|
828
912
|
a genuine positive "DST is active" case hasn't been observed and confirmed correct.
|
|
913
|
+
- **`VMB1DM`, `VMBDME`, `VMB1LED` (dimmer-family additions) deferred, not built.**
|
|
914
|
+
All three use a genuinely different single-channel `0xEE` status layout
|
|
915
|
+
(mode/dim-value/LED/timer/config in one packet) — distinct from both
|
|
916
|
+
`velbus-dimmer`'s own `0xB8`-based format and `velbus-dimmer-20`'s
|
|
917
|
+
multi-channel bitmask `0xEE` format. Needs real new decode logic, not a
|
|
918
|
+
registry entry — see `coverage-roadmap.md` for the full reasoning.
|
|
919
|
+
- **Bus error counter (`0xDA`) — design settled, not built.** Confirmed
|
|
920
|
+
useful but explicitly framed as a rare edge case. Resolved design: every
|
|
921
|
+
node that registers for its own address already receives an unsolicited
|
|
922
|
+
`0xDA` broadcast if one occurs, so no new request command is needed —
|
|
923
|
+
just passive decoding, emitted only on a secondary output and only when
|
|
924
|
+
at least one counter is non-zero, so it never appears during normal
|
|
925
|
+
operation. Deliberately deferred since it touches most/all existing nodes
|
|
926
|
+
— a session of its own, not a quick addition.
|
|
927
|
+
- **OLED image writing — stretch goal, not built.** Pushing a custom B&W
|
|
928
|
+
1-bit bitmap to an OLED glass panel (e.g. swapping in a different-language
|
|
929
|
+
greeting for a visitor without opening VelbusLink) — genuine use case,
|
|
930
|
+
explicitly not urgent. `velbus-glass-panel` currently only reads memo text
|
|
931
|
+
(`0xAC`), no write path exists in either direction for display content.
|
|
932
|
+
- **`VMBDALI`/`VMBDALI-20`, `VMBLCDWB`, `VMCM3`, `VMBSIG`/`VMBSIG-20`/`VMBSIG-21`
|
|
933
|
+
— recognized, deliberately not supported.** These show their correct name
|
|
934
|
+
in a scan (not `unknown_0xNN`) with an explicit `"Not supported"` in place
|
|
935
|
+
of a suggested node, rather than silently falling through to `null`. DALI
|
|
936
|
+
is its own protocol layer beyond the gateway; the Signum types are a
|
|
937
|
+
proprietary HomeAssistant-based master clock, not interactable; VMBLCDWB
|
|
938
|
+
and VMCM3 are legacy/custom modules with no planned support. By design,
|
|
939
|
+
not oversight — see `coverage-roadmap.md` for the full per-type reasoning.
|
|
829
940
|
|
|
830
941
|
---
|
|
831
942
|
|
|
@@ -916,6 +1027,49 @@ git push --tags
|
|
|
916
1027
|
that node's own `.html` dropdown copy, and `velbus-scan.js`'s independent copy) —
|
|
917
1028
|
see section 3 for the full explanation. Missing one produces a symptom in a
|
|
918
1029
|
different part of the palette than wherever the type was actually added.
|
|
1030
|
+
- **Never assume a feature is universal across a module family — check each type's
|
|
1031
|
+
own protocol document.** Proven wrong repeatedly (09/07/2026) while adding
|
|
1032
|
+
lock/unlock and richer status decode to `velbus-button`: of 12 button-family
|
|
1033
|
+
types, 4 genuinely lack the lock/unlock command entirely (not "probably most
|
|
1034
|
+
don't" — specific, named exceptions); one type's status uses a completely
|
|
1035
|
+
different command byte (`0xB4` instead of `0xED`); the "which channel" selector
|
|
1036
|
+
byte in the name-request commands uses two incompatible conventions (bitmask vs.
|
|
1037
|
+
literal number) that happen to produce identical values for channels 1-2 and only
|
|
1038
|
+
diverge from channel 3 onward — exactly the kind of divergence that survives
|
|
1039
|
+
casual testing. When a person asks for a capability "because it's a key feature,"
|
|
1040
|
+
that's a reason to verify it broadly, not a reason to skip checking each type.
|
|
1041
|
+
- **Registry type-byte keys need the same verification as everything else** — don't
|
|
1042
|
+
assume an existing entry's key is correct just because it's already shipped.
|
|
1043
|
+
Found 09/07/2026: `VMB4PB` and `VMB6PB-20` had been keyed under wrong type bytes
|
|
1044
|
+
in `velbus-button.js`'s own registry since v0.5.2 (`0x1C`, which isn't a real
|
|
1045
|
+
Velbus type byte at all, and `0x20`, which actually belongs to `VMBGP4`) — while
|
|
1046
|
+
`velbus-scan.js` had always had the correct values. Cross-check against the
|
|
1047
|
+
official type list (section 15) periodically, not just when adding something new.
|
|
1048
|
+
- **Never reference a variable that was only ever assigned as an object property.**
|
|
1049
|
+
Real bug, live since the code was written (fixed v0.10.1): `velbus-glass-panel`'s
|
|
1050
|
+
`0xEA` handler built `currentTemp`/`targetTemp` only inside a `payload = {...}`
|
|
1051
|
+
object literal, then referenced them as bare identifiers on the very next line
|
|
1052
|
+
(`setStatus('...' + currentTemp.toFixed(1) + ...)`). Since JS evaluates a
|
|
1053
|
+
function's arguments before calling it, this threw a `ReferenceError` *before*
|
|
1054
|
+
`node.send()` on the following line — meaning the entire payload silently never
|
|
1055
|
+
went out, for as long as this code existed. The bridge's own dispatch-error
|
|
1056
|
+
handling caught the exception each time rather than crashing the process, which
|
|
1057
|
+
is exactly what let this go unnoticed rather than being immediately obvious.
|
|
1058
|
+
If a value is going into both a status/log string and a payload object, declare
|
|
1059
|
+
it as its own `const` first and use that name in both places — never build it
|
|
1060
|
+
only inside the object literal and assume you can reference it by name outside.
|
|
1061
|
+
- **Don't assume a "two-byte status" pattern applies to every module family.**
|
|
1062
|
+
Real bug, live since the code was written (fixed v0.10.1): the original-series
|
|
1063
|
+
dimmer's `0xB8` status was assumed to work like relay's genuine separate
|
|
1064
|
+
mode-byte + status-byte pair. In reality `VMBDMI`/`VMBDMI-R`/`VMB4DC` pack
|
|
1065
|
+
run-mode, error, load-type, and temperature into a *single* status byte
|
|
1066
|
+
(confirmed identical across all three protocol PDFs — see section 7.5a), and
|
|
1067
|
+
the code was additionally reading the LED indicator byte as if it were a second
|
|
1068
|
+
status word. The result: a dimmer in ordinary "normal running" mode — the most
|
|
1069
|
+
common real-world state — always reported `off` regardless of actual dim level.
|
|
1070
|
+
Same underlying lesson as the button-family capability work: check each
|
|
1071
|
+
module's own protocol document for its actual byte layout, don't port a pattern
|
|
1072
|
+
from a different (even superficially similar) module family.
|
|
919
1073
|
- **Thermostat commands go to the primary address only,** never a subaddress.
|
|
920
1074
|
- **Respect the 20ms minimum between `0xFC` writes** on original-series modules — this
|
|
921
1075
|
is real EEPROM wear, not an arbitrary rate limit.
|
package/lib/glass-panel-types.js
CHANGED
|
@@ -61,6 +61,24 @@ const GLASS_PANEL_TYPES = {
|
|
|
61
61
|
minMapVer: 2,
|
|
62
62
|
series: 'original',
|
|
63
63
|
},
|
|
64
|
+
0x25: {
|
|
65
|
+
// Added 09/07/2026. Shares its actual protocol document with VMBGPO
|
|
66
|
+
// (protocol_vmbgpo_vmbgptc.pdf) — a thermostat-only variant of the same
|
|
67
|
+
// touch panel hardware, not a separate product. Type byte 0x25 confirmed
|
|
68
|
+
// from the official Velbus type list, not spelled out separately in the
|
|
69
|
+
// body of the shared document (it only gives VMBGPO's H'21' as a worked
|
|
70
|
+
// example). hasOc set conservatively to false — the shared document has
|
|
71
|
+
// no "collector" mention at all for either variant, unlike whatever
|
|
72
|
+
// source justified VMBGPO's own hasOc:true above (a different document,
|
|
73
|
+
// not re-verified here — that entry is untouched).
|
|
74
|
+
name: 'VMBGPTC',
|
|
75
|
+
channels: 32,
|
|
76
|
+
hasOled: true,
|
|
77
|
+
hasPir: false,
|
|
78
|
+
hasOc: false,
|
|
79
|
+
minMapVer: null,
|
|
80
|
+
series: 'original',
|
|
81
|
+
},
|
|
64
82
|
0x28: {
|
|
65
83
|
name: 'VMBGPOD',
|
|
66
84
|
// Added 09/07/2026 — found as "unknown_0x28" scanning a real installation.
|
|
@@ -98,6 +116,24 @@ const GLASS_PANEL_TYPES = {
|
|
|
98
116
|
minMapVer: null,
|
|
99
117
|
series: 'original',
|
|
100
118
|
},
|
|
119
|
+
0x3E: {
|
|
120
|
+
// Added 09/07/2026. IMPORTANT: this is NOT the same channel 5-8 mapping
|
|
121
|
+
// as its 0x2D sibling above, despite the similar name — confirmed
|
|
122
|
+
// directly from protocol_vmbgp4pir_ed2.pdf, which gives an entirely
|
|
123
|
+
// different set of labels. Copying the 0x2D mapping here would have
|
|
124
|
+
// silently mislabeled four channels.
|
|
125
|
+
name: 'VMBGP4PIR-2',
|
|
126
|
+
channels: 8,
|
|
127
|
+
hasOled: false,
|
|
128
|
+
hasPir: true,
|
|
129
|
+
hasOc: null, // no mention found in this PDF either — same unconfirmed state as 0x2D
|
|
130
|
+
pirChannels: {
|
|
131
|
+
1: 'button1', 2: 'button2', 3: 'button3', 4: 'button4',
|
|
132
|
+
5: 'dark_light', 6: 'motion', 7: 'light_motion', 8: 'absence',
|
|
133
|
+
},
|
|
134
|
+
minMapVer: null,
|
|
135
|
+
series: 'original',
|
|
136
|
+
},
|
|
101
137
|
0x34: {
|
|
102
138
|
name: 'VMBEL1',
|
|
103
139
|
channels: 1,
|
package/lib/sensor-types.js
CHANGED
|
@@ -17,6 +17,14 @@
|
|
|
17
17
|
// nameStyle: 'bitmask'
|
|
18
18
|
// hasCounter: false
|
|
19
19
|
// hasAnalogue: true
|
|
20
|
+
//
|
|
21
|
+
// VMB6IN (0x05): 6 digital inputs, no pulse counters. Confirmed (09/07/2026)
|
|
22
|
+
// against protocol_vmb6in.pdf: no Lock channel/Unlock channel command at
|
|
23
|
+
// all (simpler than VMB7IN, not just a smaller version of it) — this
|
|
24
|
+
// node doesn't implement lock/unlock regardless, so no gating needed.
|
|
25
|
+
// nameStyle: 'bitmask' (confirmed: "00000001 = Input 1 / 00100000 = Input 6")
|
|
26
|
+
// Its 0xED module status is only 5 bytes (vs VMB7IN's 7) — the existing
|
|
27
|
+
// `body.length < 7` guard already skips it safely, no code change needed.
|
|
20
28
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
21
29
|
|
|
22
30
|
const SENSOR_TYPES = {
|
|
@@ -42,6 +50,17 @@ const SENSOR_TYPES = {
|
|
|
42
50
|
minMapVer: null,
|
|
43
51
|
series: 'original',
|
|
44
52
|
},
|
|
53
|
+
0x05: {
|
|
54
|
+
name: 'VMB6IN',
|
|
55
|
+
channels: 6,
|
|
56
|
+
counterCh: [],
|
|
57
|
+
hasCounter: false,
|
|
58
|
+
hasAnalogue: false,
|
|
59
|
+
lockStyle: null, // no lock/unlock command exists for this module at all
|
|
60
|
+
nameStyle: 'bitmask',
|
|
61
|
+
minMapVer: null,
|
|
62
|
+
series: 'original',
|
|
63
|
+
},
|
|
45
64
|
};
|
|
46
65
|
|
|
47
66
|
const SENSOR_TYPE_IDS = new Set(Object.keys(SENSOR_TYPES).map(k => parseInt(k)));
|