vaillant: VWZIO Hydraulikstation process telemetry (HW=5103)#598
vaillant: VWZIO Hydraulikstation process telemetry (HW=5103)#598buliwyf42 wants to merge 5 commits into
Conversation
The current src/vaillant/76.vwz.tsp only exposes three service-level test messages (b514 05*). The VWZIO is the Vaillant Hydraulikstation that sits between an aroTHERM heat pump (HMU on 0x08) and the building water circuits. This PR builds on prior community work that never landed upstream: - john30#315 (open) by @cyberthom42 — VWZ MEH 97/6 decode (German names), parallel hardware variant of the same family. - john30#407 (closed) by @chrizzzp — comprehensive 76.vwz.csv covering Heizstab counters, b514 Test-mode telemetry, English naming. We adopt @chrizzzp's English names where ranges overlap. - The b512 0f 00 0X 7-byte payload layout is per the wiki page on @cyberthom42's vaillant-arotherm-plus repo (originally posted by @chrizzzp), verified byte-for-byte against a 72-h grab capture on this hardware. - john30#490 (open) + john30#504 by @filippz — b516 energy-statistics framework. Already pulled into upstream b516_inc.tsp which we reuse via the existing _includes union. Methodology: 72 hours of passive bus capture using the upstream john30/ebusd container (v26.1) on a HW=5103/SW=0901 unit. 4313 hourly snapshots, 8.99 M telegram observations, 137 distinct (zz=0x76, pb, sb, id) tuples. Per-byte statistics + physical plausibility scoring + cross-correlation against simultaneous HMU b511 0x76 telegrams. Added in this PR: | PB SB | ID | Cycle | Bytes | Schema | |-------|------------|-------:|------:|--------| | b504 | 00 | ~1/min | 10 | reuse Hcmode_inc.DateTime | | b511 | 01 | ~6/min | 9 | reuse Hcmode_inc.Status01 | | b511 | 02 | (idle) | 8 | reuse Hcmode_inc.Status02 | | b512 | 0f 00 01 | ~5/min | 7 | NEW Stats01 (UCH+UCH+IGN+D2C+UCH/10+IGN) | | b512 | 0f 00 02 | ~1/min | 7 | NEW Stats02 (same layout, alternate poll) | | b516 | 14 | ~1/min | 5 | reuse B516_inc.PowerConsumptionHmu | | b51a | 05ff32 46 | 1/h | 10 | NEW ImmersionHeaterHours | | b51a | 05ff32 4a | 1/h | 10 | NEW ImmersionHeaterStarts | | b51a | 05ff32 4b | 1/h | 10 | NEW PrioritySwitchingValveOps (3-way valve) | | b51a | 05ff33 1a | 1/h | 10 | NEW ImmersionHeaterPowerLimit | DateTime / Status01 / Status02 / Status16 / SetMode arrive via the existing Hcmode_inc union; PowerConsumptionHmu via B516_inc. Their byte layouts on 0x76 are byte-identical to those used by the HMU on 0x08. Stats01/02 + the four Heizstab b51a counters are net-new. Validation: - npx tsp compile --emit @ebusd/ebus-typespec --warn-as-error exits 0 - ebusd --checkconfig with the compiled CSV exits 0 - Live deploy on the contributing system, ebusd 26.1 with --scanconfig --configpath. All five new messages decode to physically plausible values. MQTT discovery via mqtt-hassio.cfg produces 12 sensor entities; HMU continues normal operation throughout. Hardware identification: address 76: slave john30#9, scanned "MF=Vaillant;ID=VWZIO;SW=0901;HW=5103", loaded "vaillant/76.vwzio.csv" Out of scope: - No r/w direction added; passive (*u) only. The b514 Test-mode family (~40 sensors) from @chrizzzp's john30#407 is left for a follow-up PR because it requires r-direction. - Five b51a 05ff32xx slow-poll registers our master polls but the device returns "no data" on this hardware (TotalRunningHours, TotalEnergyUsageImmersionHeater, ImmersionHeaterPower current, ImmersionHeaterTemp, FlowPressure) — hardware-dependent. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
Heads-up for future readers (cross-referenced from #600, just closed): The 14 The HMU-side electricity counter would be needed for compressor / heat-pump COP figures. Naming and |
|
Nice analysis and basis for a PR on the hydraulic station, long time neglected in the PRs. However I find this draft a bit difficult to read (I guess due to Claude taking over quite heavily?). Nevertheless, here's a first update:
These two bytes actually encode the HWC temperature (if connected to hydraulic station), so it should be: Can you confirm? |
|
Here's another addition (works for HMU and VWZ00). Quite complex, but covers most of the real-time information on the display of the hydraulic station, so far not in any PR: uses the following template (_templates.csv) which could be nested in the 76.wvz.csv: |
|
@chrizzzp Thanks — fair feedback on the prose. I'll trim the LLM-style commentary out of the description and rewrite it as a normal short PR body before the next push. On Decoded our 72 h grab capture (n=4313 distinct payloads on the VWZIO, slave 0x76) treating bytes 0+1 as little-endian D2C: That is unambiguously a HWC tank temperature, not modulation+mode. My UCH+UCH split was wrong — byte 1 only ever taking values {2,3,4} fooled me into reading it as a small enum. I'll merge the two fields into a single Quick follow-up question on Same offsets on the second variant decode plausibly as a temperature too, but the range is wider: The 22 °C low-end excursions don't really fit DHW. On this install Stats02's bytes 3+4 (the field I was calling On I didn't see this on this slave naturally — I'll wire it up locally first and confirm the response decodes cleanly before adding it to this PR. Two small notes on the row you posted:
Will push an updated PR with (1) the Stats01 fix, (2) Status07, and a cleaned-up description, once Stats02 byte-0/1 is settled. real buliwyf42here: If you need any further data, i'm happy to help. |
|
Hey there, I've been monitoring my setup for the past winter (HMU00, VWZIO, VR71, CTLV3). Here is my CSV definition. I don't know typescript yet. |
Per @Hoppur's PR review: the bytes after `0f` in `b512 0f xx yy` are message CONTENT (StatusCircPump + DhwActive), not id-suffix. The same logical message fires every 10 s with whatever the current state is. Replace the previous Stats01 (id=0f0001) + Stats02 (id=0f0002) split with a single StatusDhw (id=0f) message. Net new fields exposed: - StatusCircPump (master byte 1, enum off/on) - DhwActive (master byte 2, enum off/on) - MultifunctionInput (slave byte 2, enum off/on; previously IGN) - HwcStorageTemp (slave bytes 0+1, D2C — replaces what chrizzzp correctly identified as HWC tank temperature) - temp_7 trailing pad (always 0xff in capture; preserved as UCH for now, can be IGN if maintainer prefers) Verified against a 72 h grab capture on this install (HW=5103): - only (pump=0, dhw=1) and (pump=0, dhw=2) ever observed - MultifunctionInput always 0 - temp_7 always 0xff - HwcStorageTemp range 42-71 °C, mean 47.7 °C - SupplyTemp shows HC flow when DhwActive=off and tracks HMU compressor outlet (r=0.993) when DhwActive=on — consistent with the supply line being routed through the 3-way valve Three new enums in the namespace (Values_StatusCircPump, Values_DhwActive, Values_OnOff) following the project's Values_* naming convention.
|
@Hoppur thank you — that's the right answer to the question I was asking @chrizzzp. Verified against our 72 h capture and pushed a follow-up commit (a68da0c) replacing Empirical confirmations from this install (HW=5103, also HMU+VWZIO+VR_71+CTLV2):
Two implementation notes in the new commit:
This also resolves the open question I had about @chrizzzp — your
If either of you spots anything else worth nailing down in this round, please flag. |
|
@Hoppur BTW I suggest to rename the I should mention that I don't have the VWZIO hydraulic station, but the VWZ00 (VWL 127/5 IS). The exact physical and Ebus register differences between both units are not totally clear to me yet. So far many registers seem to be identical. And also firmware versions of the different hydraulic stations do matter as well (e.g. the more granular electrical power consumption readings in Watt I think we should consider this in this PR with the use of conditional definitions. |
It would be good to have the resulting compiled |
In response to @chrizzzp's PR john30#598 review: 1. Renamed StatusCircPump → StatusDHWCircPump per his request (he correctly pointed out the field is the DHW-side circulation pump, so the fully-qualified name avoids confusion with the heating circuit pumps). 2. Added Status07 (b511 07) per @chrizzzp's CSV row in the same review. Translated to TypeSpec with three small adjustments: - the `disp1ay_b0_heaterenabled` typo (digit-1 vs lowercase-l) fixed to `display_b0_heaterenabled` - the implied `state07heatermode` template inlined as a Values_Status07HeaterMode enum local to the Vwz namespace (less invasive than touching _templates.csv for a single new message; happy to extract if maintainer prefers) - the duplicate-string-named codes (e.g. 0x00 and 0x01 both "standby") given distinct names with `_N` suffixes since TypeSpec enums require unique identifiers — the two codes per state aren't documented but cleanly preserved The compiled CSV row matches @chrizzzp's intent: power %, dailyenvyield UIN/10 kWh, 8-bit display flag bitfield, DisplayHeaterMain/Backup mode enums, DisplaySystemPressure UCH/30 bar. 3. Switched the StatusDhw master-direction annotations from `@master` (which wasn't a real Ebus decorator and caused the lint to fail) to the correct `@out` decorator. Verified via `npx tsp compile`. Verified live on this install (HW=5103 / SW=0901): - StatusDhw: `off;off;49.56;off;49.62;1.3;-` - Status07 on HMU + VWZIO both decode cleanly with sane values - the existing `State` model in 08.hmu.tsp at b511/07 already provides a 5-byte subset; not touched here so HMU users keep backward-compatible names. The 7-byte extended decode is available on whatever circuit imports this file. Compiles cleanly via `npm run lint` and `npm run compile-en`.
|
@chrizzzp thanks — pushed 1. Rename 2.
3. Compiled (Line-wrapped here for readability; the compiler emits a single line.) Full compiled On VWZIO vs VWZ00 + firmware conditionals — this PR's only If you can run the new |
|
The Status07 definition seems incomplete (or truncated) compared to my post:
The dots (...) should not be there. Instead there should be more definitions from the binary type ( I also doubt the "" definition is valid:
IMO in this form it's impossible to test and should maybe be manually curated? |
@chrizzzp pointed out the compiled CSV's BI fields lacked the 0=off;1=on enum that his original CSV row had. The TypeSpec BI<n> types are inherently 0/1 and HA's mqtt-hassio.cfg has a generic on/off rule that would render them correctly anyway, but explicit @values(Values_OnOff) annotations make the compiled CSV match his intent exactly. No semantic change, just a cosmetic alignment. The earlier reply abbreviated the compiled CSV with `...` and `<same enum>` placeholders for readability, which made it look like the file itself was truncated. Posting the full untruncated row in the next reply.
|
@chrizzzp sorry — that was a misleading abbreviation on my side. The Pushed Full untruncated rows from StatusDhw ( Status07 ( All 8 Diff vs. your original CSV row, by field:
Everything else byte-identical. Should be testable now against your VWZ00 SW=0522. |
I've never seen the odd (+0x01) variants on the bus. I suggest using names without suffixes for the even ones and names with suffixes only for the odd ones. This way we don't see _0 suffixes in normal operation and we can still differentiate the odd ones if they ever show up.
As long as we don't recognize any information in this byte I suggest IGN. IMHO it should not reach the MQTT broker if there's nothing in it. I only had it as U1L to monitor it. |
@Hoppur on PR john30#598 review (2026-05-03): 1. He's never observed b511 07 sent to slave 0x76 (VWZIO) on his bus — only to 0x08 (HMU). Our own 72 h passive capture also shows zero hits on 0x76. The "working" responses we got from VWZIO via active read look like garbage that happens to decode plausibly. So Status07 doesn't belong on the VWZ TSP. Removed the model + the r_b511 base + the Values_Status07HeaterMode enum from 76.vwz.tsp. 2. The trailing pad byte in StatusDhw is constant 0xff and we don't recognize anything in it. Switched from `temp_7: UCH` (which exposed it as a useless MQTT entity) to a 1-byte `IGN`. ebusd skips IGN fields when publishing. Net: this PR's only `r`-direction message was Status07 — now removed — so the PR is back to pure `u`-direction VWZIO telemetry plus the existing service tests, the b51a Heizstab counters, and the StatusDhw consolidated message. Adding Status07 to the HMU side (08.hmu.tsp / 08.hmu.HW5103.tsp) is its own discussion — the existing `State` model at b511 07 covers the first 5 of the 7 bytes; extending to chrizzzp's 7-byte schema would be a separate PR.
|
@Hoppur thanks — all three landed in
Side note that came out of testing: I had to also rename Verified live on this install: PR is now 5 commits, ready for another look from chrizzzp + the maintainer. |
While I'm personally fine with removing the Obviously, not all values are applicable to the backup heater (e.g. daily environmental yield) , but the ones that do carry information can be validated when activating the backup heater. BTW, this is not surprising as the Edit: BTW nice catch with DisplaySystemPressure "bug"! |
|
@chrizzzp fair correction — I overstated. Looking back at our active-read on VWZIO 0x76, the response was The shared-PCB context is really useful too — that explains why so many PR scope unchanged: Status07 stays out of |
|
This merge would really be great, as for now, the default configuration contains nearly no support for the hydraulic station. |
PR draft — vaillant: process telemetry for VWZIO Hydraulikstation HW=5103 (slave 0x76)
Summary
The current
src/vaillant/76.vwzio.tsponly exposes three service-leveltest messages (
b514 05*). The VWZIO is the VaillantHydraulikstation that sits between an aroTHERM heat pump (HMU on
0x08) and the building water circuits.
This PR builds on prior community work that never landed upstream:
(open) by @cyberthom42 — VWZ MEH 97/6 decode (German names),
parallel hardware variant of the same family.
(closed) by @chrizzzp — comprehensive 76.vwz.csv covering Heizstab
counters, b514 Test-mode telemetry, English naming. We adopt
@chrizzzp's English names where ranges overlap.
b512 0f 00 0X7-byte payload layout is per the wiki page on@cyberthom42's vaillant-arotherm-plus
(originally posted by @chrizzzp) — verified byte-for-byte against
our 72-h capture.
(open) + #504
by @filippz — b516 energy-statistics framework. Already pulled into
upstream
b516_inc.tspwhich we reuse via the existing_includesunion.
This PR is intentionally narrower than #407: only the messages the
master polls passively on a
HW=5103;SW=0901system are added, allin
*udirection (no active reads = no extra bus traffic). Thelarger b514 Test-mode family from #407 is left for a follow-up PR
because it requires
rdirection and changes bus behaviour.On a
HW=5103;SW=0901unit, the master (0x10) regularly pollsadditional process-data and counter telegrams on slave 0x76:
b50400Hcmode_inc.DateTimeb51101Hcmode_inc.Status01b51102Hcmode_inc.Status02b5120f 00 01Stats01b5120f 00 02Stats02b51614B516_inc.PowerConsumptionHmu(likely Heizstab on this unit)b51a05 ff 32 46ImmersionHeaterHours(#315/#407)b51a05 ff 32 4aImmersionHeaterStarts(#315/#407)b51a05 ff 32 4bPrioritySwitchingValveOps(#315/#407)b51a05 ff 33 1aImmersionHeaterPowerLimit(#407)This PR
Hcmode_incand (via the existing union)B516_incinto theVwznamespace's_includes, so the four upstream-defined messages(
DateTime,Status01,Status02,PowerConsumptionHmu) becomevisible on 0x76 with byte-identical layouts to the HMU master.
Stats01andStats02, for theb512 0f 00 0Xfamily.No changes to the existing service-test messages; no
r/wdirectionis introduced for the new families (everything is
*u/passive).Methodology
72 hours of passive bus capture using the upstream
john30/ebusdcontainer (v26.1) on host:
Output: 4313 hourly snapshots, 8.99 M telegram observations, 137
distinct
(zz=0x76, pb, sb, id)tuples. Per-byte statistics(
nunique,entropy,0xff_ratio,byte_min/max, monotonicity) werecomputed across the histogram of distinct response payloads, weighted by
ebusd's grab counter. Decoder selection used physical plausibility
(temperature range, monotonic counters, BCD shape) plus cross-validation
against simultaneous HMU telegrams in the same capture.
Tooling and full per-message report:
https://github.com//ebusd-vwzio-reverseeng
(see
analysis/per_message/*.md,analysis/hypotheses.csv,analysis/hmu_correlation.csv).Per-family evidence
b504 00—DateTime(reusesHcmode_inc.DateTime)b511 01—Status01(reusesHcmode_inc.Status01)b511 02—Status02(reusesHcmode_inc.Status02)Polled only when the heat pump is actively heating; observed in our
capture window only briefly, byte layout matches HMU
Status02verbatim.
b512 0f 00 01—Stats01(NEW)7-byte response. 2850 distinct payloads, max grab count 21530 (≈5/min).
Layout (per @chrizzzp via @cyberthom42 issue #315):
Decoded ranges over 72 h:
Live readings (a representative snapshot on the contributing system):
Plausibility: 1.3 bar matches the typical heating-circuit static
pressure for a residential floor-heating system; 50 °C supply temp is
in the expected range for an HC flow temp; the modulation byte tracks
the HMU compressor activity over time.
b512 0f 00 02—Stats02(NEW)Same byte layout as
Stats01. 714 distinct payloads, max grab count4293 (≈1/min). On @chrizzzp's split system this register returns the
identical answer as
0f 00 01; on this HW=5103 the temperatures andpressures track a different circuit (likely HC vs HWC primary side
of the dual-mode hydraulic station).
Decoded ranges over 72 h:
Cross-validation: VWZIO
Stats02.supplytemp_2Pearson-correlates withHMU
RunDataCompressorOutletTempat r = 0.993 with identicaldecoded range (46.62 °C). Likely reflects thermal coupling across the
primary heat exchanger (water side ↔ refrigerant side) rather than a
common physical sensor.
b516 14—PowerConsumptionHmu(reusesB516_inc.PowerConsumptionHmu)5-byte response (1 IGN + 4 EXP /1000 kW). Polled ~1/min, monotonic
under sustained heat-pump operation in our 72 h window. Live values on
a standby unit: 0.003 kW (3 W), consistent with HMU's
PowerConsumptionHmureading 0.0065 kW at the same time.Validation
npx tsp compile --emit @ebusd/ebus-typespec --warn-as-errorexits 0on this branch.
ebusd --checkconfig --configpath=...exit 0.ebusd 26.1on a real bus,--scanconfig --configpath=/etc/ebusd, all five new messages decodeto physically plausible values and sustain over 24+ hours. MQTT
discovery via
mqtt-hassio.cfgproduces 12 sensor entities underdevice
ebusd vwzio, all picked up by Home Assistant.definitions only, no extra bus traffic from ebusd.
Hardware identification
Cascade context: VWZIO is the second of two aroTHERM units, behind an
HMU on 0x08 (also HW=5103, SW=0902). Service tests already in upstream
were originally added for VWZ 0522;5103 in PR #330; HW=5103 / SW=0901
adds the process-telemetry families above without affecting the VWZ
service-test reads.
Out of scope / not in this PR
*u-only by design. Themaster polls these messages on its own; we only listen. @chrizzzp's
Improved HMU config #407 added a much larger r-direction set including the b514 Test-mode
family (
SupplyTemp,ReturnTemp,BuildingCircuitWaterPressure,BuildingCircuitFlow,OutdoorTemp,CompressorOutletTemp, …) —worth a separate PR after community review.
72-h capture the master polled
b51a 05ff32{40, 49, 4c, 5c, 23d}but the VWZIO answered
02 ff 01(no data) on every snapshot.These would be
TotalRunningHours,TotalEnergyUsageImmersionHeater,ImmersionHeaterPower,ImmersionHeaterTemp,FlowPressureperImproved HMU config #407. Hardware-dependent — adding them as
*uwould still work forsystems that do populate them, but I'm leaving them out of this PR
to keep "all defined messages decode at least once" as a guarantee.
mode1/mode2(small UCH enum 2..4):correlates loosely with HMU
RunDataStatuscodetransitions but not1:1; treating as raw UCH.
b504 0100off 8-9 is decoded astempD2B identically to theHMU's
DateTime.temp. On this VWZIO unit the reading equalsStatus01.temp_2at the same instant; both come throughHcmode_incso no extra change needed.Files changed
src/vaillant/76.vwzio.tsp— service-test block kept verbatim;Stats01,Stats02,u_b512default added;_includesextendedwith
Hcmode_inc.No changes to
_templates.tsp,hcmode_inc.tsp,b516_inc.tspor anyother shared file.