Skip to content

Add support for 720-based regulators#564

Open
burmistrzak wants to merge 43 commits intojohn30:masterfrom
burmistrzak:add-720-series
Open

Add support for 720-based regulators#564
burmistrzak wants to merge 43 commits intojohn30:masterfrom
burmistrzak:add-720-series

Conversation

@burmistrzak
Copy link
Copy Markdown

@burmistrzak burmistrzak commented Jan 30, 2026

This PR is a superset of #482, including register definitions for the following regulator models:

  • 15.720
  • 15.basv
  • 15.basv2
  • 15.basv3
  • 15.ctls2
  • 15.ctlv2
  • 15.ctlv3
  • 15.bass

If you have one of the aforementioned devices, feel free to give this unified configuration a try and report back!
There're still a few unsupported devices at the moment, specifically:

  • 15.ctlv*
  • 15.ctls*
  • 15.ctls3
  • 15.bass2
  • 15.bass3

*might not exist..?

In case you own one of them, please comment below with your setup details!

I also have incorporated (hopefully) all the recent discoveries made by @stadid, @chrizzzp & @jonesPD. 🤝
A fork of the CDN repo with pre-compiled definitions is available in English and German.

Testing & Validation

  1. Clone the CDN fork from https://github.com/burmistrzak/ebus.github.io
  2. Checkout dev branch (should be default)
  3. Set EBUSD_CONFIGPATH to <MOUNTPOINT>/ebus.github.io/dev/en
  4. Set EBUSD_MQTTVAR to e.g.:
    filter-direction=r|u|^w,filter-circuit=^bas*$,filter-non-circuit=^hmu*$,filter-name=^*,filter-non-name=^Z2|^Z3|^Hc2|^Hc3 (adjust to match your system)
  5. Restart ebusd container (or service).
  6. Check entities in HA and/or MQTT.
  7. Look out for errors and report them below.

@burmistrzak
Copy link
Copy Markdown
Author

@john30 Feel free to ping me when you've updated the web service. While I certainly have some concerns when it comes to this entire setup, I'll be happy to give it another try!

@john30
Copy link
Copy Markdown
Owner

john30 commented Apr 6, 2026

@burmistrzak
just checked: the temporary upload is currently limited to 8k due to the limited ram in the device. need to think how to extend that.
the reason for the download not happening is due to the new symlink structure, so basically it should work when you rename the file to the name before the new structure, i.e. 15.ctlv2.tsp

@john30
Copy link
Copy Markdown
Owner

john30 commented Apr 6, 2026

While I certainly have some concerns when it comes to this entire setup

@burmistrzak

I understand your concerns and actually I'm not that happy with it either as it consumes resources I'd rather not spend in the first place. However, the device memory is just too small and I'm already looking for other alternatives (like the ESP32-C5) that support PSRAM where all that is no issue any more.

In parallel I'm planning on adding the option to BYOD, i.e. to create your own version of the firmware online with the needed files bundled into it so that the device does not need an online service after that anymore. ok, same problem you might say but I don't see a lot of alternatives with all the limitations.

not having the firmware open source is for a good reason and I'm sure you understand that I don't want to spend my time answering tickets for other device manufacturers (which is already happening on ebusd btw) that actually expect me to do that for no benefit at all. and the amount of time I spend for everything around ebus is just crazy - basically every free minute I have and even stopping other private activities due to that.

how do I ensure the web service stays online - well just like I did for years and years with the ebusd config webservice (before I moved it to github pages). if the server is unreachable the devices would just continue to work as basically they only contact it to download newer versions of the definitions. once downloaded these are stored on the device anyway.

contingency/succession plan: just like for ebusd I would say. the amount of reasonable contribution is almost 0 there btw. all the source is on github anyway and a colleague of mine would be able to make it public in case I die (if you meant that).

protection: it is as protected as it can be I'd say, but of course sitting on a hosting provider with all its pros and cons.

guarantee: how much guarantee can be provided by a developer doing it for free? do I really need to answer that? anyway, I don't have any plans to drop the pure interface mode of ebusd-esp32 if that's what you meant. I recently spent almost a whole weekend to track down a frustrating issue generated by espressif for the Raspi GPIO communication, so I guess that should be enough proof of committment.

wrt development: as long as the firmware is closed it is rather impossible to have co-workers for it unless they can be trusted 100% as an NDA is just useless in that context

@d3vi1
Copy link
Copy Markdown

d3vi1 commented Apr 6, 2026

I've sent an email to John WRT what I found to be missing on the TSP side, in order to correctly implement our B524 discoveries into ebusd. It basically sums up to:

No instance parameterization

Multi-instance groups (HC, Zones, Radio Sensors) require full copy-paste duplication per instance. The current 15.ctlv2.tsp has 3 instances each for GG=0x02 and GG=0x03, totalling significant duplication. For groups like GG=0x09 (Radio Sensors VRC7xx) with up to 11 instances and 32 registers per instance, this would mean 352 duplicated model definitions. Some groups have dynamic number of instances (Primary Heating Generators have support for two devices on some VRC7xx series and eight devices on newer ones).

A parameterized @instances(0, 10) decorator on the group base model, would reduce the file from thousands of lines to hundreds.

No conditional/gated registers

Some B524 registers are conditionally present: dormant registers (ACK + 0 bytes payload) when the associated feature is not configured (cooling, quick mode). Registers gated by fm5_config value (solar, cylinders only exist on installations with the VR71 functional module). Instance count depends on runtime discovery (number of heating circuits varies per installation)

TSP has no mechanism to express "this register only exists when condition X is met." Everything is unconditionally present. A @condition or @gate decorator would be valuable for representing the real hardware behavior.

No dual-opcode awareness within a group

GG=0x09 means completely different things on OP=0x02 (local radio sensor config / system quick mode write targets) vs OP=0x06 (remote radio device live data). The @base decorator handles this structurally (different opcode in the base), but there's no way to express that both address spaces share the same GG semantic domain. This is purely a documentation/authoring convention issue, not a functional blocker.

Generation-based gating

Different regulator generations (VRC 700 vs 720, wireless vs wired, different firmware versions) support different register subsets. Currently this is handled by separate TSP files (15.ctlv2.tsp vs 15.700.tsp). A shared base with device-conditional extensions would reduce maintenance burden as the register map grows.


Once some form of these is implemented, I can easily backport the 700 and 720 work discovered during the Helianthus development to ebusd in a human readable and maintainable fashion. Meanwhile, I'm working hard on a new edition of the VRC Explorer that has a much better integration of all 6 B524 opcodes. It should be ready by tomorrow and can be previewed in the wip/b524-opcode-namespace-split-integration branch.

@burmistrzak
Copy link
Copy Markdown
Author

@john30 I really appreciate you taking the time for a detailed response!

I understand your concerns and actually I'm not that happy with it either as it consumes resources I'd rather not spend in the first place. However, the device memory is just too small and I'm already looking for other alternatives (like the ESP32-C5) that support PSRAM where all that is no issue any more.

In parallel I'm planning on adding the option to BYOD, i.e. to create your own version of the firmware online with the needed files bundled into it so that the device does not need an online service after that anymore. ok, same problem you might say but I don't see a lot of alternatives with all the limitations.

Eh, flashing a fresh firmware just to e.g. test a new definition seems overkill, IMHO.
New hardware with PSRAM might be the best way forward. Can only do so much in software...

not having the firmware open source is for a good reason and I'm sure you understand that I don't want to spend my time answering tickets for other device manufacturers (which is already happening on ebusd btw) that actually expect me to do that for no benefit at all. and the amount of time I spend for everything around ebus is just crazy - basically every free minute I have and even stopping other private activities due to that.

I can see how random people constantly bothering you is affecting your life. Please take care of yourself!

Giving folks the benefit of the doubt, it's plausible that some might mistaken this entire operation to be your day job and/or primarily commercial in nature (and e.g. ebusd support part of an eAS purchase).
However, it's true that there isn't much separation (especially in branding) between the hardware (i.e. adapters) business and the FOSS project ebusd.

Maybe putting some distance between them by e.g. rebranding your hardware side hustle to eAS could be helpful here?
I'd also add a disclaimer to the eAS shop that makes clear that individual ebusd support has to be purchased/arranged separately.

guarantee: how much guarantee can be provided by a developer doing it for free? do I really need to answer that? anyway, I don't have any plans to drop the pure interface mode of ebusd-esp32 if that's what you meant. I recently spent almost a whole weekend to track down a frustrating issue generated by espressif for the Raspi GPIO communication, so I guess that should be enough proof of committment.

By guarantee I mean some sort of assurances that existing offline modes/features etc. can't be taken away or put behind a paywall. At the moment, you (or anyone else for that matter) could theoretically take the interface for a bunch of heating systems hostage and demand we "upgrade" to a subscription.
I'm not suggesting that's something you personally would actually do, but the possibility of such a scenario makes me just a little bit uneasy.

TL;DR Open sourcing the (core?) firmware would allow for free experimentation with more powerful hardware, introduce a solid alternative to pre-compiled blobs, limit your liability to hardware only, and open the doors for helping hands.

@chrizzzp
Copy link
Copy Markdown

chrizzzp commented Apr 7, 2026

@john30 @burmistrzak

  • the PrEnergy/Fuel are not valid for 720, right?

@john30 AFAIK, yes.

I'm not sure if @burmistrzak objected here (or agreed), on my 720/2 they are valid (fuel values remain zero for my HP system) with the following exceptions (removed):

PrEnergySum
PrFuelSum
  • the HwcBankHolidayStartPeriod does not exist on 720?

At least not at the same registers.

All *BankHoliday* registers are not working anymore on the 720 series of regulators (so start/end for HWC, Z1, Z2, Z3). I think the concept of 'bank holiday' has been removed completely in favor of the 'Holiday' settings (still present).

  • please explicitly check the timer writability as this was broken in the PR from my perspective. it is corrected now and partially rolled back as well for backward compatibilty
    ...

@chrizzzp Can you please check writability of timers?

Will do this shortly...

@chrizzzp
Copy link
Copy Markdown

chrizzzp commented Apr 7, 2026

@john30 @burmistrzak

  • please explicitly check the timer writability as this was broken in the PR from my perspective. it is corrected now and partially rolled back as well for backward compatibilty

Just checked:

  1. writing temperature-bound timers (z1, z2, z3) works
r -f Z1Timer_timeframes
1;1;1;1;1;1;1

r -f Z1Timer_Saturday0
07:30;23:30;20.0

w -c ctlv2 Z1Timer_Saturday "0;1;06:00;22:00;21.0"
empty

r -f Z1Timer_Saturday0
06:00;22:00;21.0
  1. writing temperature-independent timers (hwc, circulation) did not work
r -f CcTimer_Timeframes
0;0;0;0;0;0;0

r -f CcTimer_Saturday0
00:00;00:00

writing without temperature payload:
w -c ctlv2 CcTimer_Saturday "0;1;06:00;06:10"
empty

r -f CcTimer_Saturday0
00:00;00:00

writing with FFFF temperature payload:
w -c ctlv2 CcTimer_Saturday "0;1;06:00;06:10;FFFF"
empty

r -f CcTimer_Saturday0
00:00;00:00

Any advice here?

  1. the timers for cooling and - more importantly - the noise reduction mode of heat pumps are missing. The latter are routinely used to set the heat pump to lower power levels. Here's the example from the current PR:
r,,,SilentTimer_Config,silent timer Configuration,,,b555,a30004,value,,HEX:9,,,Configuration
r,,,SilentTimer_Timeframes,silent timer amount,,,b555,a40004,ign,,IGN:1,,,Amount of configured slots per weekday,slotcount,,UCH,,,number of slots on a day,slotcount_1,,UCH,,,number of slots on a day,slotcount_2,,UCH,,,number of slots on a day,slotcount_3,,UCH,,,number of slots on a day,slotcount_4,,UCH,,,number of slots on a day,slotcount_5,,UCH,,,number of slots on a day,slotcount_6,,UCH,,,number of slots on a day,ign_1,,IGN:1,,,
r,,,SilentTimer_Monday,silent timer monday read,,,b555,a500040000,ign,,IGN:1,,,,htm,,HTM,,,,htm_1,,HTM,,,,ign_1,,IGN:2,,,
w,,,SilentTimer_MondayWrite,silent timer monday write,,,b555,a600040000,slotindex,,UCH,,,index of a time slot,slotcount,,UCH,,,number of slots on a day,htm,,HTM,,,,htm_1,,HTM,,,,wtimeslotconst,,U2L,=65535,,constant value for writing a slot without target temperature
r,,,SilentTimer_Tuesday,silent timer tuesday read,,,b555,a500040100,ign,,IGN:1,,,,htm,,HTM,,,,htm_1,,HTM,,,,ign_1,,IGN:2,,,
w,,,SilentTimer_TuesdayWrite,silent timer tuesday write,,,b555,a600040100,slotindex,,UCH,,,index of a time slot,slotcount,,UCH,,,number of slots on a day,htm,,HTM,,,,htm_1,,HTM,,,,wtimeslotconst,,U2L,=65535,,constant value for writing a slot without target temperature
r,,,SilentTimer_Wednesday,silent timer wednesday read,,,b555,a500040200,ign,,IGN:1,,,,htm,,HTM,,,,htm_1,,HTM,,,,ign_1,,IGN:2,,,
w,,,SilentTimer_WednesdayWrite,silent timer wednesday write,,,b555,a600040200,slotindex,,UCH,,,index of a time slot,slotcount,,UCH,,,number of slots on a day,htm,,HTM,,,,htm_1,,HTM,,,,wtimeslotconst,,U2L,=65535,,constant value for writing a slot without target temperature
r,,,SilentTimer_Thursday,silent timer thursday read,,,b555,a500040300,ign,,IGN:1,,,,htm,,HTM,,,,htm_1,,HTM,,,,ign_1,,IGN:2,,,
w,,,SilentTimer_ThursdayWrite,silent timer thursday write,,,b555,a600040300,slotindex,,UCH,,,index of a time slot,slotcount,,UCH,,,number of slots on a day,htm,,HTM,,,,htm_1,,HTM,,,,wtimeslotconst,,U2L,=65535,,constant value for writing a slot without target temperature
r,,,SilentTimer_Friday,silent timer friday read,,,b555,a500040400,ign,,IGN:1,,,,htm,,HTM,,,,htm_1,,HTM,,,,ign_1,,IGN:2,,,
w,,,SilentTimer_FridayWrite,silent timer friday write,,,b555,a600040400,slotindex,,UCH,,,index of a time slot,slotcount,,UCH,,,number of slots on a day,htm,,HTM,,,,htm_1,,HTM,,,,wtimeslotconst,,U2L,=65535,,constant value for writing a slot without target temperature
r,,,SilentTimer_Saturday,silent timer saturday read,,,b555,a500040500,ign,,IGN:1,,,,htm,,HTM,,,,htm_1,,HTM,,,,ign_1,,IGN:2,,,
w,,,SilentTimer_SaturdayWrite,silent timer saturday write,,,b555,a600040500,slotindex,,UCH,,,index of a time slot,slotcount,,UCH,,,number of slots on a day,htm,,HTM,,,,htm_1,,HTM,,,,wtimeslotconst,,U2L,=65535,,constant value for writing a slot without target temperature
r,,,SilentTimer_Sunday,silent timer sunday read,,,b555,a500040600,ign,,IGN:1,,,,htm,,HTM,,,,htm_1,,HTM,,,,ign_1,,IGN:2,,,
w,,,SilentTimer_SundayWrite,silent timer sunday write,,,b555,a600040600,slotindex,,UCH,,,index of a time slot,slotcount,,UCH,,,number of slots on a day,htm,,HTM,,,,htm_1,,HTM,,,,wtimeslotconst,,U2L,=65535,,constant value for writing a slot without target temperature

@burmistrzak
Copy link
Copy Markdown
Author

I'm not sure if @burmistrzak objected here (or agreed), on my 720/2 they are valid (fuel values remain zero for my HP system) with the following exceptions (removed):

@chrizzzp Same. I assumed @john30 was referring to these *Sum registers. 😅

Regarding timers, current implementation is here

/** constant value for writing a slot without target temperature */
@constValue(0xffff)
scalar wTimeSlotConst extends U2L;
/** complete slot for writing without target temperature */
model wTimeSlotWithoutTemp {
slotIndex: slotIndex;
slotCount: slotCount;
slotTimeFrame: slotTimeFrame;
wTimeSlotConst: wTimeSlotConst;
}

I'd agree that having silent mode is essential.

@john30
Copy link
Copy Markdown
Owner

john30 commented Apr 8, 2026

No instance parameterization

...
A parameterized @instances(0, 10) decorator on the group base model, would reduce the file from thousands of lines to hundreds.

this usually can't be expressed so simple as the conversion needs to know where the part to be incremented sits, which could be the last or the first byte of an @ext decorator e.g. or something from an inherited r/w pair model.
as mentioned in my email, I've already started adding the option to use @inherit on union variants following a similar approach as the include construct. this way, copies of all models of a namespace can easily be declared.

No conditional/gated registers

TSP has no mechanism to express "this register only exists when condition X is met." Everything is unconditionally present. A @condition or @gate decorator would be valuable for representing the real hardware behavior.

TSP does not have that construct indeed, thats why I added this via the @condition and @conditionExt decorators to ebus-typespec. this is already used heavily in the files subject to this PR e.g.

No dual-opcode awareness within a group

GG=0x09 means completely different things on OP=0x02 (local radio sensor config / system quick mode write targets) vs OP=0x06 (remote radio device live data). The @base decorator handles this structurally (different opcode in the base), but there's no way to express that both address spaces share the same GG semantic domain. This is purely a documentation/authoring convention issue, not a functional blocker.

not entirely sure what you mean with this as it is not part of this PR as well. please share a concrete example or point to such.

Generation-based gating

Different regulator generations (VRC 700 vs 720, wireless vs wired, different firmware versions) support different register subsets. Currently this is handled by separate TSP files (15.ctlv2.tsp vs 15.700.tsp). A shared base with device-conditional extensions would reduce maintenance burden as the register map grows.

I totally agree and already pointed that out in earlier pull requests of this one.
with the @condition decorator this should be possible as well IMO but on the other hand it would make the defs rather overblown. maybe it would be better to split parts out, e.g. have timers in a separate file that is then included. this way, even a split main file might still be fine and produce less redundancy

@john30
Copy link
Copy Markdown
Owner

john30 commented Apr 8, 2026

Eh, flashing a fresh firmware just to e.g. test a new definition seems overkill, IMHO. New hardware with PSRAM might be the best way forward. Can only do so much in software...

not for testing of course, but for being independent of the device needing internet connection.

By guarantee I mean some sort of assurances that existing offline modes/features etc. can't be taken away or put behind a paywall. At the moment, you (or anyone else for that matter) could theoretically take the interface for a bunch of heating systems hostage and demand we "upgrade" to a subscription. I'm not suggesting that's something you personally would actually do, but the possibility of such a scenario makes me just a little bit uneasy.

well in doubt everyone can just use an older version of the firmware that does still have that feature, so even if I'd do something like that, it would still be possible to use the device as before. I really think you're a bit pessimistic here assuming I would intentionally block features just because I could. basically the same is true for a lot of projects I guess and I don't think there is any example for such in any of the work I've done in this context for the past 13 years...

TL;DR Open sourcing the (core?) firmware would allow for free experimentation with more powerful hardware, introduce a solid alternative to pre-compiled blobs, limit your liability to hardware only, and open the doors for helping hands.

yes, but then I can also just quit doing development there in the first place as a larger company could then just too quickly develop a new device and make a whole lot of money out of that (examples of that exist already, even with expectations to me doing their support). and recent examples of decompiling binaries just fit perfectly to the same scenario btw

@john30
Copy link
Copy Markdown
Owner

john30 commented Apr 8, 2026

  • the PrEnergy/Fuel are not valid for 720, right?
    I'm not sure if @burmistrzak objected here (or agreed), on my 720/2 they are valid (fuel values remain zero for my HP system) with the following exceptions (removed):

ok so those need to be kept then instead of being removed.

All *BankHoliday* registers are not working anymore on the 720 series of regulators (so start/end for HWC, Z1, Z2, Z3). I think the concept of 'bank holiday' has been removed completely in favor of the 'Holiday' settings (still present).

thanks for your feedback!

2. writing temperature-independent timers (hwc, circulation) did **not** work

hm, did that work with the former csv then? the csv message definition for writing didn't change for cc e.g.

3. the timers for cooling and - more importantly - the noise reduction mode of heat pumps are missing. The latter are routinely used to set the heat pump to lower power levels. Here's the example from the current PR:

these are in the csv as well, so please check again (lines 555 and following of the generated csv).

@chrizzzp
Copy link
Copy Markdown

chrizzzp commented Apr 8, 2026

@john30

2. writing temperature-independent timers (hwc, circulation) did **not** work

hm, did that work with the former csv then? the csv message definition for writing didn't change for cc e.g.

3. the timers for cooling and - more importantly - the noise reduction mode of heat pumps are missing. The latter are routinely used to set the heat pump to lower power levels. Here's the example from the current PR:

these are in the csv as well, so please check again (lines 555 and following of the generated csv).

Ok, then we're not on the same line and talk about different CSVs. I used the 15.ctlv2.csv you linked here. This does not have the definitions for silent and cooling timers.

Could you point me to the CSVs you referred to so I can check all timers again?

@chrizzzp
Copy link
Copy Markdown

chrizzzp commented Apr 8, 2026

@burmistrzak

Regarding timers, current implementation is here

/** constant value for writing a slot without target temperature */
@constValue(0xffff)
scalar wTimeSlotConst extends U2L;
/** complete slot for writing without target temperature */
model wTimeSlotWithoutTemp {
slotIndex: slotIndex;
slotCount: slotCount;
slotTimeFrame: slotTimeFrame;
wTimeSlotConst: wTimeSlotConst;
}

I'd agree that having silent mode is essential.

Could you point me to the latest CSVs of this PR? It's a shame I still didn't invest time in figuring out don't know how to compile them myself... 🙈

@burmistrzak
Copy link
Copy Markdown
Author

well in doubt everyone can just use an older version of the firmware that does still have that feature, so even if I'd do something like that, it would still be possible to use the device as before. I really think you're a bit pessimistic here assuming I would intentionally block features just because I could. basically the same is true for a lot of projects I guess and I don't think there is any example for such in any of the work I've done in this context for the past 13 years...

@john30 I'm not pessimistic per se, but there've been enough examples of these stunts (bait & switch, rug-pulls, etc.) in the technology sector to justify at least some caution. Especially in cases where proprietary firmware and FOSS intermingle.

I'm a big advocate for right to own/repair and relying on closed-source firmware anywhere (from servers to dishwashers) is an inherent liability and restricts what folks able to do (repair, improve, etc.) with the things they've paid for.
Now, these are polished products from major manufacturers I'm talking about and not a hardware adapter used together with free software to reverse engineer another proprietary protocol...

IMHO, keeping the eAS firmware closed puts you in an awkward position where people to some extent expect support like they get when buying e.g. a smart lightbulb.
Adopting a FOSS license would again limit your liability to hardware failures and you could simply point to the firmware repo and say: «There's the code, feel free to fix it yourself or pay me to do it for you».

yes, but then I can also just quit doing development there in the first place as a larger company could then just too quickly develop a new device and make a whole lot of money out of that (examples of that exist already, even with expectations to me doing their support).

A corp can always out-spent the average individual, but that's the case regardless of firmware licensing. They either hire a room full of devs or throw a bunch of AI against the problem.
In such a scenario, you're cooked anyways.
Why would anyone pay more for basically the same product but with less QC and no proper support or warranty?

You rely on folks (like myself) who see the value in your work, are sympathetic to the overall cause and decide to buy your hardware (incl. token subscription) instead.

and recent examples of decompiling binaries just fit perfectly to the same scenario btw

Well, how does that saying go? Information wants to be free?
I'd argue that doing something like this in a clean room fashion for non-commercial purposes to empower users it is completely different than a corp doing it for financial gain. But that's just my opinion.

@burmistrzak
Copy link
Copy Markdown
Author

@chrizzzp There's no CSV. You'll have to compile it yourself. 😅

You need to pull the repo, checkout the merge564 branch and run npm install, followed by npm run compile. Make sure you have Git and NodeJS installed.

@john30
Copy link
Copy Markdown
Owner

john30 commented Apr 8, 2026

Ok, then we're not on the same line and talk about different CSVs. I used the 15.ctlv2.csv you linked here. This does not have the definitions for silent and cooling timers.

Could you point me to the CSVs you referred to so I can check all timers again?

those were for a different PR and not related to this one.
anyway, here you go:
15.720.csv

@chrizzzp
Copy link
Copy Markdown

chrizzzp commented Apr 13, 2026

Tested the timers from the above 15.720.csv: Confirmed writing works for both

  1. the temperature-bound timers (Z1...)
w -c ctlv2 Z1Timer_Friday "0;1;06:10;22:10;21"
empty

r -f Z1Timer_Friday0
06:10;22:10;21.0
  1. and the temperature-independent timers (tested with SilentTimer...).
w -c ctlv2 SilentTimer_Friday "0;1;01:00;24:00"
empty

r -f SilentTimer_Friday0
01:00;24:00

BTW

  • the current definitions contain only one time slot/frame per day (e.g. Z1Timer_Friday0). This might not be enough for many use cases (esp. DHW circulation), I suggest to define at least three time slots/frame per day for all timers or to use indexed reading (-i option) to reduce the amount of required definitions, as suggested here: VRC 720 configuration: understanding and managing Heating Zone time slots stadid/ebusd-configuration#3 (comment) as up to 11 time slots can be defined per day
  • there is a nomenclature discrepancy concerning time slots / time frames (the timer definitions use time slot, other definitions use time frame: e.g. Z1Timer_Timeframes), BTW Vaillant uses the term 'time period" in the regulator

@chrizzzp
Copy link
Copy Markdown

chrizzzp commented Apr 13, 2026

Concerning this PR some HWC-related suggestions:

The following ExtHWC-related definitions should not be bound to the condition hc1exthwcactive=1, since hc1exthwcactive=1 is a dynamic runtime status indicator, that turns on only if the external DHW circuit is currently in operation (i.e. producing hot water).

[hc1exthwcactive=1]r,,,Hc1ExtHwcTempDesired,External hot water desired temperature heating circuit 1,,,b524,020002000900,ign,,IGN:4,,,,value,,EXP,,°C,temperature
[hc1exthwcactive=1]w,,,Hc1ExtHwcTempDesired,External hot water desired temperature heating circuit 1,,,b524,020102000900,value,,EXP,,°C,temperature
...
[hc1exthwcactive=1]r,,,Hc1ExtHwcOpMode,External hot water operation mode heating circuit 1,,,b524,020002001300,ign,,IGN:4,,,,value,,UIN,0=off;1=auto;2=manual,,
[hc1exthwcactive=1]w,,,Hc1ExtHwcOpMode,External hot water operation mode heating circuit 1,,,b524,020102001300,value,,UIN,0=off;1=auto;2=manual,,

Instead these definitions should be bound the condition: [hc1circuittype=3], which is a static configuration setting. The same applies to the corresponding hc2, hc3 settings.

Another issue:
My setup involves such a hc with circuit type 3 (=water=DHW=extHWC) although I don't have an original DHW circuit (i.e. I don't use the circuit to actually produce hot water, but to heat up my buffer cylinder for the heating). This means HwcEnabled = 0 (permanently off), but external DHW circuits can still be defined as active.

However, some of the HWC-related basic settings apply also to the 'external DHW circuit' (e.g. MaxCylinderChargeTime and and HwcLockTime). Unfortunately, these definitions are not available when the condition [HwcEnabled=1] is not met.
So could they be bound also to the condition e.g. [hc1circuittype=3] or just be unconditional?

@burmistrzak
Copy link
Copy Markdown
Author

@chrizzzp Just checked, myVaillant allows max. three time slots per day. 👀

@chrizzzp
Copy link
Copy Markdown

chrizzzp commented Apr 13, 2026

And here are a few additions to the 15.720.csv (basic regulator settings):

*r,,,,,,B524,02000000,,,IGN:4,,,
*w,,,,,,B524,02010000,,,,,,
r;w,,TariffPrimHeaterLow,,,,,1100,,,UIN,,,Primary heater low tariff value
r;w,,TariffPrimHeaterNormal,,,,,1200,,,UIN,, ,Primary heater normal tariff value
r;w,,MultiInputSetting,multifunction input configuration,,,,6A00,,,UIN,0=not connected;1=1x circulation;2=photovoltaics;3=Ext.Cooling,,
r,,EnergyHeatingThisMonthMirror,,,,,C200,,,ULG,,,
r,,EnergyHeatingLastMonthMirror,,,,,C300,,,ULG,,,
r,,EnergyHeatingHWCTotalMirror,,,,,C500,,,ULG,,,
r,,EnergyHeatingHCTotalMirror,,,,,C600,,,ULG,,,

@stadid
Copy link
Copy Markdown
Contributor

stadid commented Apr 13, 2026

@chrizzzp Just checked, myVaillant allows max. three time slots per day. 👀

For 720 series regulators:
max 12 time slots per day for heating
max 3 time slots per day for DHW
max 3 time slots per day for DHW circulation

@john30
Copy link
Copy Markdown
Owner

john30 commented Apr 15, 2026

Tested the timers from the above 15.720.csv: Confirmed writing works for both

thanks for testing!

* the current definitions contain only one time slot/frame per day (e.g. Z1Timer_Friday0). This might not be enough for many use cases (esp. DHW circulation), I suggest to define at least three time slots/frame per day for all timers or to use indexed reading (-i option) to reduce the amount of required definitions, as suggested here: [VRC 720 configuration: understanding and managing Heating Zone time slots stadid/ebusd-configuration#3 (comment)](https://github.com/stadid/ebusd-configuration/pull/3#issue-2169827331) as up to 11 time slots can be defined per day

I recognized that during the review and expected that to be intentional. so if it wasn't then these should get rolled back as well I guess

* there is a nomenclature discrepancy concerning time slots / time frames (the timer definitions use time slot, other definitions use time frame: e.g. Z1Timer_Timeframes), BTW Vaillant uses the term 'time period" in the regulator

wrt the slotCountWeek template usage I only see "*_Timeframes" in the old tsp and the new, so where do you see the discrepancy exactly?

@chrizzzp
Copy link
Copy Markdown

chrizzzp commented Apr 15, 2026

I recognized that during the review and expected that to be intentional. so if it wasn't then these should get rolled back as well I guess

Yes, roll back to three time slots or - maybe more efficient - have a single read time slot predefined (e.g. Monday0) and add a definition that allows indexed reading of any number of time slots:

e.g.

[hc1circuittype=1]r,,,Z1Timer_Monday,timer heating monday indexed read 1,,,b555,a5000000,index,m,UCH,,,,htm,,HTM,,,,htm_1,,HTM,,,,slottemp,,UIN,10,°C,desired temperature of a slot
  • there is a nomenclature discrepancy concerning time slots / time frames (the timer definitions use time slot, other definitions use time frame: e.g. Z1Timer_Timeframes), BTW Vaillant uses the term 'time period" in the regulator

wrt the slotCountWeek template usage I only see "*_Timeframes" in the old tsp and the new, so where do you see the discrepancy exactly?

This is what I meant, it's rather a naming inconsistency. Therefore I suggest to rename "*_Timeframes" to "*_Timeslots".

@john30
Copy link
Copy Markdown
Owner

john30 commented Apr 18, 2026

@chrizzzp ok I've addressed your suggestions in d581175, 0d63db7, 10b51ed, and 74360dd. I've also made TariffAuxHeater writable as it would be unreasonable otherwise (maybe you can confirm that?).

now to your other findings:

r;w,,MultiInputSetting,multifunction input configuration,,,,6A00,,,UIN,0=not connected;1=1x circulation;2=photovoltaics;3=Ext.Cooling,,

does that depend on some setup, so is this specific for yours e.g. or would this be available always?

r,,EnergyHeatingThisMonthMirror,,,,,C200,,,ULG,,,
r,,EnergyHeatingLastMonthMirror,,,,,C300,,,ULG,,,
r,,EnergyHeatingHWCTotalMirror,,,,,C500,,,ULG,,,
r,,EnergyHeatingHCTotalMirror,,,,,C600,,,ULG,,,

if these are "mirrors", where would the non-mirrored value be then? is this related to e.g. PrFuelSumHcThisMonth and which unit do these have (probably kWh)?

@john30
Copy link
Copy Markdown
Owner

john30 commented Apr 19, 2026

added the MultiInputSetting as well and merged to master in 4875c46
only thing missing are these mirror energy counters (presumably), therefore kept open

@chrizzzp
Copy link
Copy Markdown

chrizzzp commented Apr 19, 2026

@john30

I investigated more into the Tariff-related definitions. To implement it properly we need a few more definitions, e.g. I just discoverd the tariff timer (for dual tariff operations in trivalence hybrid manager mode, actually quite a neat feature as it considers energy cost and heat demand) and the the register that defines the backup heater type (gas or electrical). I'm currently trying to find the register that specifies single/dual tariff selection, so the tariff timer can be bound to dual tariff as a condition. I will compile my findings here very soon...

@chrizzzp
Copy link
Copy Markdown

chrizzzp commented Apr 19, 2026

OK, here are the updated definitons for the tariff settings. Unfortunately, I could not identify the register for single/dual tariff selection. However, I suggest to make all these definitions conditional to:

[HybridManager=0]
(triVAl mode of hybrid manager, definiton already in the config).

EDIT: The following registers were confirmed to be writable.

*r,,,,,,B524,02000000,,,IGN:4,,,
*w,,,,,,B524,02010000,,,,,,
r;w,,TariffBackupHeater,,,,,1000,,,UIN,, ,Secondary heater tariff value
r;w,,TariffPrimHeaterLow,,,,,1100,,,UIN,,,Primary heater dual tariff low tariff value
r;w,,TariffPrimHeaterHighSingle,,,,,1200,,,UIN,,,Primary heater single tariff value/dual tariff high value
r;w,,BackupHeaterType,,,,,1300,,,UCH,0=Condensing;1=Non-Condensing;2=Electrical,,in hybrid manager trival mode only

According to the VRC720 manual, BackupHeaterType 0 and 1 are specific to gas boilers (Condensing = "Brennwert" in german). The Vaillant manual uses the term "Backup Boiler" instead of "Backup Heater". Not sure if we aim for consistency here with Vaillant nomenclature.

Here are the Tariff timer definitions: should be conditional to the dual tariff, but as mentioned I didn't find this register yet.

(sorry for the mix of old and new CSV definitions)

r,,,TariffTimer_Timeslots,Tariff timer amount,,,b555,a40006,ign,,IGN:1,,,Amount of configured slots per weekday,slotcount,,UCH,,,number of slots on a day,slotcount_1,,UCH,,,number of slots on a day,slotcount_2,,UCH,,,number of slots on a day,slotcount_3,,UCH,,,number of slots on a day,slotcount_4,,UCH,,,number of slots on a day,slotcount_5,,UCH,,,number of slots on a day,slotcount_6,,UCH,,,number of slots on a day,ign_1,,IGN:1,,,
r,,,TariffTimer_Monday0,Tariff timer monday 1,,,b555,a500060000,ign,,IGN:1,,,,htm,,HTM,,,,htm_1,,HTM,,,,ign_1,,IGN:2,,,
w,,,TariffTimer_Monday,Tariff timer monday,,,b555,a6000600,slotindex,,UCH,,,index of a time slot,slotcount,,UCH,,,number of slots on a day,htm,,HTM,,,,htm_1,,HTM,,,,wtimeslotconst,,U2L,=65535,,constant value for writing a slot without target temperature
r,,,TariffTimer_Tuesday0,Tariff timer tuesday 1,,,b555,a500060100,ign,,IGN:1,,,,htm,,HTM,,,,htm_1,,HTM,,,,ign_1,,IGN:2,,,
w,,,TariffTimer_Tuesday,Tariff timer tuesday,,,b555,a6000601,slotindex,,UCH,,,index of a time slot,slotcount,,UCH,,,number of slots on a day,htm,,HTM,,,,htm_1,,HTM,,,,wtimeslotconst,,U2L,=65535,,constant value for writing a slot without target temperature
r,,,TariffTimer_Wednesday0,Tariff timer wednesday 1,,,b555,a500060200,ign,,IGN:1,,,,htm,,HTM,,,,htm_1,,HTM,,,,ign_1,,IGN:2,,,
w,,,TariffTimer_Wednesday,Tariff timer wednesday,,,b555,a6000602,slotindex,,UCH,,,index of a time slot,slotcount,,UCH,,,number of slots on a day,htm,,HTM,,,,htm_1,,HTM,,,,wtimeslotconst,,U2L,=65535,,constant value for writing a slot without target temperature
r,,,TariffTimer_Thursday0,Tariff timer thursday 1,,,b555,a500060300,ign,,IGN:1,,,,htm,,HTM,,,,htm_1,,HTM,,,,ign_1,,IGN:2,,,
w,,,TariffTimer_Thursday,Tariff timer thursday,,,b555,a6000603,slotindex,,UCH,,,index of a time slot,slotcount,,UCH,,,number of slots on a day,htm,,HTM,,,,htm_1,,HTM,,,,wtimeslotconst,,U2L,=65535,,constant value for writing a slot without target temperature
r,,,TariffTimer_Friday0,Tariff timer friday 1,,,b555,a500060400,ign,,IGN:1,,,,htm,,HTM,,,,htm_1,,HTM,,,,ign_1,,IGN:2,,,
w,,,TariffTimer_Friday,Tariff timer friday,,,b555,a6000604,slotindex,,UCH,,,index of a time slot,slotcount,,UCH,,,number of slots on a day,htm,,HTM,,,,htm_1,,HTM,,,,wtimeslotconst,,U2L,=65535,,constant value for writing a slot without target temperature
r,,,TariffTimer_Saturday0,Tariff timer saturday 1,,,b555,a500060500,ign,,IGN:1,,,,htm,,HTM,,,,htm_1,,HTM,,,,ign_1,,IGN:2,,,
w,,,TariffTimer_Saturday,Tariff timer saturday,,,b555,a6000605,slotindex,,UCH,,,index of a time slot,slotcount,,UCH,,,number of slots on a day,htm,,HTM,,,,htm_1,,HTM,,,,wtimeslotconst,,U2L,=65535,,constant value for writing a slot without target temperature
r,,,TariffTimer_Sunday0,Tariff timer sunday 1,,,b555,a500060600,ign,,IGN:1,,,,htm,,HTM,,,,htm_1,,HTM,,,,ign_1,,IGN:2,,,
w,,,TariffTimer_Sunday,Tariff timer sunday,,,b555,a6000606,slotindex,,UCH,,,index of a time slot,slotcount,,UCH,,,number of slots on a day,htm,,HTM,,,,htm_1,,HTM,,,,wtimeslotconst,,U2L,=65535,,constant value for writing a slot without target temperature

The manual states up to 12 tariff time slots can be defined, so I suggest to add indexed reading also for this timer (sorry not done yet for the above snippet).

@chrizzzp
Copy link
Copy Markdown

chrizzzp commented Apr 19, 2026

@john30

... only thing missing are these mirror energy counters (presumably), therefore kept open

OK, I had to revise the b524 mirrored energy statistics a little. Some were not assigned correctly (which I hadn't checked before) and I found more.

All values are in kWh.

They are mirrored/collected once per day (I think at midnight) from - I assume - the b516 energy statistics (and converted from Wh to kWh). That's why I suggest a new naming with reference to the b516 Stat* energy values.

*r,,,,,,B524,02000000,,,IGN:4,,,
*w,,,,,,B524,02010000,,,,,,
r,,StatMirrorElectricEnergyHcLastYear,,,,,C000,,,ULG,,kWh,
r,,StatMirrorElectricEnergyHcThisYear,,,,,C100,,,ULG,,kWh,
r,,StatMirrorElectricEnergySumThisMonth,,,,,C200,,,ULG,,kWh,
r,,StatMirrorElectricEnergySumLastMonth,,,,,C300,,,ULG,,kWh,
r,,StatMirrorElectricEnergySumThisYear,,,,,C400,,,ULG,,kWh,
r,,StatMirrorElectricEnergySumLastYear,,,,,C500,,,ULG,,kWh,
r,,StatMirrorElectricEnergySumTotal,,,,,C600,,,ULG,,kWh,

I haven't checked yet if they are writable, but I assume yes.

These values correspond to the energy values that can be queried from the VRC720 regulator UI. There must be more values (including HWC and more HC and probably solar, environmental and fuel stats).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants