A Home Assistant integration that reads and controls a Weishaupt heat pump (WBB, WWP, WSB and related models) over Modbus TCP.
This is a fork of OStrama/weishaupt_modbus. It differs from upstream on purpose:
- Modbus only. The experimental web-interface scraping is removed, together with its settings and entities. An entry that still carries web-interface settings is cleaned up on first start.
- One connection to the controller, shared. Since 2.0 the integration
borrows its Modbus unit from Home Assistant's own
modbusintegration instead of opening a socket of its own (see What changed in 2.0). - Entity ids are yours. The integration no longer rewrites entity ids on every start; a rename in Home Assistant stays.
- Two Home Assistant versions are tested on every change: the declared
minimum (
hacs.json) and the newest final release. - A test suite guards the register table: every register has a name in every language, every status value has a state text, no translation outlives its item.
If your heat pump has the separate Weishaupt Modbus module, this integration will not work. Weishaupt_CanApiJson may be what you are looking for.
Add this repository as a custom repository in HACS (category Integration)
and install it, or copy custom_components/weishaupt_modbus/ into the
custom_components/ directory of your Home Assistant configuration and
restart. Then add the integration:
Minimum Home Assistant version: 2026.9. Version 2.0 builds on the shared Modbus connection that arrived with 2026.9; older releases cannot load it.
The Weishaupt controller accepts a single Modbus TCP connection. Up to 1.x the
integration opened that connection itself, with its own reconnect logic and
block planner. Since 2.0 it asks Home Assistant's modbus integration for a
unit on the connection to the controller's address. Home Assistant keeps one
connection per endpoint and serialises everything that goes over it, so two
entries of this integration - or another integration asking for the same
endpoint - queue up behind one link instead of fighting over it. A hub from
the YAML modbus: configuration is not part of that: it opens a client of
its own, so pointing one at the same controller still costs the second
connection the controller does not have. The wire is handled by the
modbus-connection
library (tmodbus backend), which Home Assistant installs with its modbus
integration.
What stays the same: the entities, their unique ids and history, the entity
ids you chose, the options (poll interval, EEPROM write warning and limit), the
power map and the write counters. What is gone: this integration's own
pymodbus requirement, the pygal requirement (the preview picture is drawn
by the compile script, not at runtime), its reconnect and back-off logic, and
the five-register block limit - the controller serves each address band in
one read.
New in 2.0: a switch beside every setpoint the controller can switch off (see Configuration). New entities, nothing existing is renamed.
One state string changed: operating status 0 (undefined) used to be
published as ..._pvmode; it is ..._undefined now. An automation that
matched on that state needs the new name.
Upgrading: install 2.0 and restart. Existing entries migrate on first start (entry version 11); an entry keeps the host and port you configured. If the controller does not answer during setup, Home Assistant retries.
After the upgrade the recorder warns once per sensor whose unit changed: the three relabelled second-heat-source counters (hours and cycles had swapped names), the H1.x inputs (now °C, as the data-point list says) and a few unit-less rows (an empty unit became none). Open Developer tools -> Statistics, and for each listed entity choose to update the unit of the recorded statistics - the history is the register's and stays.
The only mandatory parameter is the address of your heat pump. The port is 502 unless you changed it on the heat pump.
- Prefix is part of every entity's unique id. Leave it alone unless you are migrating from another integration and want to keep the recorded history.
- Device postfix lets you add more than one heat pump. Leave it empty for a single pump; every further pump needs a postfix of its own, the flow refuses an empty or reused one.
Prefix and device postfix are part of every entity's unique id and cannot be changed afterwards: a change would orphan the recorded history of every entity and start the EEPROM write counters over. To rename, remove the entry and add it again.
- Heizkreis 2–5 enable the entities of additional heating circuits.
- Kennfeld file selects the power map for your model (see below).
Some setpoints can be switched off at the controller - the constant flow
temperatures, the summer/winter switchover and the SG-Ready boost. The
register then reports an "off" word instead of a temperature. Each of
these comes as a number and a switch (… active): the number reads
unknown while the setpoint is off, the switch turns it off and back on
(restoring the value it held before, or the lowest allowed one).
The poll interval (default 30 s) is an option, not part of the setup: open the integration's Options dialog to change it. A change reloads the integration.
A poll that fails keeps the last values; the entities go unavailable on the fourth failed poll in a row and come back with the next good one. A device that answers but refuses the system registers 30001-30006 is not treated as a heat pump with missing modules: that poll fails.
The heat power (Wärmeleistung) is calculated from the power request, the outside temperature and the flow temperature. That relation is model specific; the integration ships a precompiled grid per model, read from the graphs in the Weishaupt documentation:
weishaupt._wab8_kennfeld.jsonweishaupt_ls13_kennfeld.jsonweishaupt_wab11_kennfeld.jsonweishaupt_wbb12_kennfeld.jsonweishaupt_wbb20_kennfeld.jsonweishaupt_wbb_kennfeld.jsonweishaupt_wsb12_kennfeld.jsonweishaupt_wsb15_armd_kennfeld.jsonweishaupt_wsb6_kennfeld.jsonweishaupt_wsb8_armea_kennfeld.jsonweishaupt_wsb8_kennfeld.jsonweishaupt_wwp_ls_10_kennfeld.jsonweishaupt_wwp_ls_8_kennfeld.json
The two wwp_ls grids follow the "compressor frequency maximal" curves of the
outdoor-unit manuals (83306301, 83306401). Their 55 °C curve ends at -15 °C,
the operating limit; below it the value is carried on flat rather than
dropping to 0 W, which used to halve the interpolated power for 45 °C flow.
Known gap of another kind: the yearly energy registers (36104 and the other
… Jahr rows) answer but stay at 0 on every controller seen so far, even
after years of operation - the yearly total exists only on the display and
in the WEM portal. The yearly performance factor therefore has no value.
Pick the file matching your model. If yours is missing, copy the closest
one, adjust known_x, known_y and known_t from your documentation and
compile it once with .github/scripts/compile_kennfeld.py (needs numpy;
scipy gives a smoother curve, pygal draws the preview picture). The
integration only reads compiled grids and copies the picture next to the
grid under www/local/; a picture that carries script or links to the web
is refused. Contributions of new grids are welcome.
Modbus TCP has to be enabled on the heat pump: User → Settings (second page) → Modbus TCP
- Parameter: On
- Network: either the address of your Home Assistant host (only that host
may connect) or your network address, e.g.
192.168.178.0, to allow every host in it. The first is the safer choice. - Netmask: the netmask of your network, usually
255.255.255.0. - Port 502, slave address 1.
Modbus TCP has no authentication and no encryption. Keep the heat pump on a trusted local network and never expose port 502 to the internet.
Writes go to the heat pump's EEPROM, which Weishaupt rates for 100 000 writes over its lifetime. The integration never writes a value that is already set; keep automations that set values on a change, not on a schedule. Two diagnostic sensors on the system device count the writes that actually went out, in total and today. The Options dialog holds a warning threshold (default 50 writes a day, logged once when reached) and a daily limit (default off) beyond which writes are refused until the next day.
Tests need Linux (Home Assistant does not run natively on Windows; WSL2 is fine). Create a virtual environment with the test plugin and the runtime dependencies:
pip install -r requirements_test.txt # test plugin, ruff, mypy, pip-audit
pytest tests/ -q # the fast everyday run
pytest tests/ -q -m "" # everything, including the end-to-end testsBefore pushing, run every gate the CI runs:
PYTHON=/path/to/venv/bin/python .github/scripts/check.shtests/README.md explains the guards, the budgets and the mutation run, and
what to do when one of them turns red. Tests never touch a real controller:
the mock_modbus fixture replaces the connection Home Assistant's modbus
integration hands out with the library's in-memory unit.
The developers of this integration are not affiliated with Weishaupt. It was created in their spare time from publicly available information. Use is at your own risk; the developers are not liable for damage arising from it.