The first Home Assistant integration purpose-built for hydronic underfloor heating systems.
While existing thermostats adapt radiator/TRV logic to UFH, this integration addresses UFH’s unique requirements: high thermal mass, slow response times, multi-zone coordination through shared heat sources, and valve scheduling to prevent rapid cycling.
Highlights
PID-Based Temperature Control
Tuned for concrete screed thermal response
Per-zone PID parameters (Kp, Ki, Kd) with anti-windup protection
EMA smoothing handles noisy wireless sensors (Zigbee, WiFi)
Multi-Zone Coordination
Zones aggregate demands for efficient boiler firing
Observation period scheduling (2-hour windows) prevents rapid valve cycling
Quota-based valve management allocates time based on PID duty cycle
Native Boiler Integration
Smart heat request signaling - waits for valves to fully open before firing
DHW priority handling - blocks new heating during hot water
Does this controller also account for hybrid systems with some rooms in the house being heated by radiators instead of UFH and thus requiring a different or possibly higher temperature of the boiler supply temp?
This integration does not control boiler supply temperatures, that falls outside the scope here. But in general, the control logic can be used for radiators if you wish.
Amazing project, thank you for sharing. I am testing this right now with one room.
Are you planning to implement more advanced optimization of PID paraameters based on historic performance? I am not sure how to manually optimize PID parameters to get to optimized results.
I’m planning to add heat accounting based on supply temperature. More details and opportunity to comment in GitHub. Any comments and challenges welcome.
Heating curve for outdoor temperature compensation (#76) — Dynamically calculates supply target temperature based on outdoor conditions using two-point linear interpolation. When an outdoor temperature sensor is configured, the system adjusts the supply target between warm and cold design points instead of using a fixed value. Includes a new controller-level supply target sensor entity.
Heat accounting with supply temperature normalization (#64) — Zones now accumulate quota weighted by actual heat delivery via a supply coefficient. When supply temperature is below target, zones consume quota slower and stay open longer. Includes a new supply coefficient sensor per zone and a flow binary sensor per zone. Configurable via a new “Heat Accounting” options flow step.
Quickstart guide (#68) — New task-oriented guide (docs/quickstart.md) walking users from installation to a working first zone.
Bug Fixes
Fix crash on config entry unload after in-place config reload (#65) — Stale listener callbacks caused ValueError: list.remove(x): x not in list on entry unload. Fixed by adding a dedicated shutdown() method registered once during setup.
Fix flaky test due to EMA floating-point precision (#81, #86) — Use pytest.approx() for float assertions where values pass through EMA smoothing.
Improvements
PID error icons changed to plus/minus (#66) — Replaced chevron icons (too similar to check icon) with mdi:thermometer-plus (cold) and mdi:thermometer-minus (warm).
Zone diagnostic entities hidden from dashboards — Zone sensors and binary sensors now have entity_registry_visible_default = False. Mode select and flush switch remain visible.
Entity recreation on config change — Changing supply temp, outdoor temp, or DHW entity in config now triggers a
full reload to recreate affected entities.
Refactoring / Internal
Storage format V2 (#78) — Coordinator state restructured with controller data nested under a controller key. PID keys renamed for consistency. Includes automatic V1 → V2 migration.
Entity declarations refactored to description-based patterns (#77) — All entity metadata and behavior defined in entity descriptions with generic entity classes using callbacks.