Building a fully custom smart heating system with Home Assistant - Part 1

Projects Nov 12, 2024

Over the last few years, gas and electricity has been getting rather expensive here in Wales...

This has meant that keeping our house warm, or at least warm enough to prevent condensation and mould during the colder months, was costing us north of £200/month in energy bills!
That's ridiculously expensive, and remained so even after switching to Octopus' cheapest energy tariff.

Strap in, it's time to embark on one HELL of a journey.
Why are we using so much gas, and how can we reduce that?


Contents:

For ease of reading, I've put some links here to the various parts of this project :)

The Existing Setup

Our house is a pretty typical Welsh terrace, built in the 1890s with solid brick walls of varying thicknesses.
It's been pretty thoroughly modernised with a (theoretically) very efficient central heating system; a modern condensing combi boiler, Hive smart controls and high efficiency radiators with TRVs in all rooms.

However, this was not working out.
Some rooms would be warmer or colder, some would not heat up, and some would cool down faster (due to those solid walls not being the best at keeping heat in).

This meant that we'd end up just turning the central thermostat in the kitchen up to make rooms somewhat comfortable if we were cold.

Condensation was an issue too, with some rooms having very wet walls during cold weather.
Again, this was either solved by turning up the thermostat, or by strategically ignoring the problem. (foreshadowing...)


What are our goals here, then?

Before any good project starts out, you need something to work towards!

So, I had two simple goals:

  • Reduce our gas usage as much as possible
  • Keep every room in the house at the same comfortable temperature

With that in mind, let's get cracking!


Maintenance time:

The first step was to make sure that the heating system was actually working at its best, as it hadn't had any basic maintenance in a while except a boiler service.

I started out by checking the boiler pressure, and was very glad I did...
The gauge was reading 0 bar, which doesn't tend to be a good sign!

So, next step was to re-pressurise it.
I turned the filling loop valves on, and nothing happened.

Wonderful.
This would be the first of many problems.

It turned out that the filling loop valves had seized, and that the plumber had broken them internally during the last service.
So, after some quick Youtube how-tos, those were replaced and the boiler pressurised!

This was actually a bit too much pressure, but I hadn't bled the radiators yet!

The next step was to bleed any air out of the radiators, as trapped air will cause them not to heat up as efficiently (or at all!).
I grabbed my bleed key and fired up the heating.

Problem number two then reared its head.
Some of the bleed valves were also stuck...

At this point I was cursing like a sailor, but I persevered.

I turned off each radiator using the lockshield and TRV, then removed the stuck bleed valves. Those were freed using penetrating oil, lubed up with some grease, then reinstalled.
I even added a bottle of corrosion inhibitor to one of the radiators whilst I was at it, to make sure the system was clean and free flowing inside.

Valves were turned back on, and the radiators bled out their air one by one.
The boiler was once again topped up to its stated 2 bar pressure, and the flow temperature set to 50C to ensure it works efficiently.

If the flow is too hot, the boiler won't condense the water in the outgoing gases, losing heat to the outdoors.
Too cold, and the radiators won't work efficiently.

I turned the heating back on, and we had success!
All of the radiators were warming up evenly!


The Measuring:

I do think I'm funny sometimes :) (also Lights' The Listening is a good album!)

To have any idea of how to save energy, I needed to get a baseline measurement of how much gas we were actually using.

I'd been playing around with Home Assistant and thought it would be the perfect tool for the job!

So, I added a custom integration for Hildebrand's Bright app, which could read our consumption from the smart meter DCC network, and the Hive integration so I could see when the heating was running.

We let the heating run its normal schedule over the next few days, and were horrified by the result.

66kWh worth of gas just for heating in a single day, with the thermostat set to 16.5C and boosted when necessary.
Jesus. The UK average is 38kWh!

Not only that, but we STILL had rooms that were too hot or cold!


When all you have is a hammer:

So naturally, I thought "Why not use HA to control the heating!"
We'd be able to heat each room to just the right temperature, and be able to control the boiler based on how many rooms needed heat.

But to do that I'd need some hardware.

I started out by looking up the cheapest smart radiator valves, and what Zigbee stick to use to control them.
Hive also uses Zigbee, and I could integrate the existing thermostat into HA without using Hive's terrible app! Sweet!

Why should we need to pay a subscription for stats anyway, Hive??

So after some research, I ended up buying a few MOES branded Tuya TRV601 Zigbee TRVs from Aliexpress for roughly £12 each, and a Sonoff ZBDongle-E for £10.
I'd seen mixed reviews for these on the HA forums, but figured that if they could tell me the room temperature and turn the rads on and off, I'd be set.

A couple of weeks later, these showed up.

The valve's bottom, how naughty!

I got to work setting up the Zigbee stick with my Home Assistant VM, using Zigbee2MQTT as it supported these (and the Hive stuff) out of the box.

The setup was fairly painless; pass through the stick in Proxmox, install Z2M and the Mosquitto MQTT broker, then create a Zigbee network.
There's some good guides out there, this is not one of them!

I then set up one of the TRVs, installed it on the radiator in the front room, and connected it to HA.

A valve installed on the front room radiator!

Success! I set the temperature to 17C, and the valve to eco mode.

💡
These valves have two types of Auto mode, eco and comfort.
Eco turns 100% on when the room temp is 0.5C below the set point, and off 0.5C above it.
Comfort adjusts the valve from 0-100% depending how far away from the setpoint the room temp is, but this results in the valve being open for longer (which will ultimately use more gas!)

The rest of the valves (8 in total) were then set up, and appeared to work brilliantly! They opened and closed, and all the rooms stayed at the correct temperature when the boiler was running.

But after a few days of proving, we had yet more problems...


"They don't fucking work?!?!":

Well, I'd seen the mixed reviews, but I was not expecting this...

The valves seemed to have a mind of their own, changing their set temperatures to seemingly random values just after midnight when set to Auto.

Plus, the temperature recorded by the valves was badly skewed by the radiators being on.
Who'd have thought that a thermostat attached to a radiator would be affected by the radiator??

I'd seen people on the HA forums recommending a custom integration called Better Thermostat, which apparently corrected these issues using an external temperature sensor.

However, development seemed to have stalled, and I wasn't too keen on using someone else's integration with PLENTY of its own problems (including a bug where the target temperature would change!).

Seeing this, I decided the best course of action was to order some sensors and bash together my own system. Let's make these things WORK.


The Sensor-ening:

I once again hopped onto Aliexpress, and purchased 13 cheap little Tuya ZG-227Z temperature and humidity sensors, for about £30 all in.

They're tiny and unobtrusive, perfect for blending into the decor!

One of these was installed and connected up in every room, and now I could see the temperature and humidity. Neat!

But, it was here I noticed that either the TRV's internal sensors were WAY off, or these sensors were wrong.

I grabbed a handy Adjudicator (my very accurate darkroom thermometers), and discovered that each of the little sensors was bang on. Phew.

The Adjudicator! (yes I know my keyboard is minging!)

Now, it's time to get my hands dirty.


Templates aplenty:

At this point, I had decided how I was going to make this whole shebang work.

Each room will have its own Generic Thermostat in HA, using the external sensors for temperature and simply switching each valve on or off.

This should avoid the weirdness with keeping a set temperature!

The boiler will be turned on when a set number of rooms needs heat, and off when they've all reached temperature. Simples!

However, these valves only expose a climate entity to HA, not a switch.
That's no problem though, let's template a switch for each of them!

I started out by creating a fresh Template Switch in HA's Helpers tab.

The state of the switch is set using the following value template, which looks to see if the valve position is 100% or not.

#️⃣
{{ (states('sensor.bedroom_radiator_position') | float ) == 100 }}

Under 'Actions on turn on', set the radiator valve to heat. (100% open)

and under 'Actions on turn off', set it to off. (closed)

Add the switch to the radiator it controls, hit Submit, and now there's a lovely switch which opens and closes the TRV!

I then repeated that seven more times.
(this is going to turn into a bit of a theme...)

Tadaa! We have some working switches!

but naturally, there's yet another problem.


I can't Zigbeelieve it!

So, Zigbee is a mesh network.
That means that the devices connect to each other and relay messages between them, unlike WiFi which is usually point to point.

However, there are two types of Zigbee device, routers and end devices.

Routers are powered from the mains (or DC power supplies etc), and work to extend the network.
Battery powered end devices do not.

We now had 21 battery devices all connecting to my one Zigbee stick, and they were randomly disconnecting due to weak signal.

Fortunately though, I had yet to set up some Zigbee router devices!
In the kitchen and living room we had installed Zigbee LED strips under shelves and cabinets, and the Hive was still running on its own hub.

So, over the course of a couple of days, I set all of these up with Z2M/HA.
The Hive was a bit of a pain, but after following the guide on Z2M's wiki a couple of times, it worked.

Now at last, nothing was disconnecting! (and I consigned the Hive hub to a drawer, where it belongs)

I also set up a template switch for the Hive receiver, to enable me to switch the boiler on and off as well.

It seemed silly to buy another switch when I could just use what we already have!

This was pretty much identical to the TRVs, except that I had to switch it to Heat, wait 5sec, then set to 30C to start the boiler. (to let the thing slowly respond to commands)

It's a kludge, but it works!

Now, at last, it was time to get some working thermostats!


Automatic Thermostatic:

I now needed to set up HA's Generic Thermostat integration, with one for each room.
This of course meant making loads of them.

I chose to add these to HA's configuration.yaml file, as it allowed extra configuration variables to be set to fine tune them. (it also let me set them all up as a batch, saving my time!)

I'll go over the settings I used now:

#️⃣
name: (name of the room)
unique_id: (I used an online UUID generator for this)
heater: (the template switch for that room's TRV I set up earlier)
target_sensor: (the temperature sensor in that room)
min_temp: 10 (the lowest possible set temperature)
max_temp: 25 (the highest possible set temperature)
ac_mode: false (tells HA that we're heating, not cooling)
cold_tolerance: 0.5 (turn on when 0.5C below set temp)
hot_tolerance: 0 (turn off exactly at the set temp)
initial_hvac_mode: "heat" (when HA restarts, turn it on)
precision: 0.1 (precision for the room temp)
target_temp_step: 0.5 (set the temp in 0.5C steps)
eco_temp: 15.5 (I'll get to this in Part 2)

I wrote up all of these in notepad++, then copied the entire block into configuration.yaml

One HA reboot later, and TADAA!

a troupe of thermostats

We have a whole bunch of thermostats, which after a day duly kept their set temperatures!

Sweet!

Now, let's make these able to control the boiler.


"It's getting cold in here, so turn the boiler on:"

"I am, getting so cold, I'm gonna put more clothes on!"

Excuse my musical interlude, it's now time to set up how we're controlling the boiler!

Earlier on, I wrote that the boiler should be turned on when a set number of rooms need heating.
To do that, we're going to need a way of counting which rooms are calling for heat.

Templates to the rescue again!

This time, I'm going to use a template sensor.

So, back in HA's Helpers tab, I created a new template sensor called Heating Calls.

This sensor uses a state template to count all climate type entities which are currently heating, then exclude the Hive receiver (Boiler Thermostat) and the TRVs' native Climate entities (all called Room Radiator) to avoid duplicates being counted.

I'll leave the template below;

#️⃣
{{ states.climate | rejectattr('entity_id', 'search', "radiator") | rejectattr('entity_id', 'search', "boiler") | selectattr('attributes.hvac_action','eq','heating') | list | length }}

Save that, and we have a lovely sensor!

Now we need a way to set our threshold of rooms calling for heat, before the boiler gets turned on.

I used an Input Number helper for this, with the maximum being the number of rooms in the house.

You may have noticed that I only have 8 TRVs, yet I have 12 rooms/thermostats.
Brilliant observation, Watson!

For rooms that do not yet have a smart TRV, I still set up a Generic Thermostat, but these only turn on a dummy Template Switch helper.

That way, those rooms still count towards the total number of heating calls! Neat!


"Computer, give me heat!"

Now let's get that boiler on!

For this, I'm going to use a pair of automations.
One to turn the boiler on when the heating call threshold is reached, and one to switch it off when there are none.

I created the first automation using a template trigger, to check if the number of heating calls is over the threshold, then turn the boiler switch on.

That template is below;

#️⃣
{{ states('sensor.heating_calls') | float(0) >= states('input_number.heating_call_threshold') | float(0) }}

Then, we need it to turn off when there's no more heating to be done.

The second automation has a template triggering when there are no heating calls.
It also checks to make sure the boiler is actually on beforehand :)

#️⃣
{{ states('sensor.heating_calls') | float(0) == 0 }}

Save that too and would you know it, we now have a working heating system!
Hooray!!

I then added all of the room thermostats to a new dashboard, and it almost looks like we're done!

Hold on, what's in Knobs & Dials?

But wait, there's more!

So now we have a working heating system, what else could there be to do?
Well, there's a couple of tweaks!

What about disabling the heating if it's unseasonably warm outside, or if we need to turn it off for any other reason (leaks etc)

So, I created an input boolean helper called Heating System Switch

Then, another input number called Heating On Temperature.
The heating will be able to run below this temperature, and off when it's above it.

Then, a template binary sensor helper called Heating Weather Switch, to see if the temperature outside (from the OpenWeatherMap integration) is below the Heating On Temp.

Then I added both of these to the Boiler On automation;

and FINALLY, I added the new controls to a tab on my heating dashboard called Knobs & Dials.

Ignore the default temperature, that does nothing (yet)

I used Mushroom custom cards to make this look pretty, and gave the new Sections layout a spin :)

and with that, we're done! (for NOW!)


But, does it work?

If you remember at the beginning of this post novel, I said that there were two goals.

To save gas, and to keep the house comfortable.

So, does all of this overcomplicated mess work, after faffing with it all summer?

YES!!!

The weather started to cool down in mid October, and everything kicked in as expected. It all works perfectly!

Every room gets nicely warm and STAYS warm!

Even better, our daily gas usage has dropped by over 50%!!
Holy shit!

I started this project with the house burning upwards of 66kWh of gas per day.
After all of this it's averaging a much more reasonable 30kWh!!

Mission accomplished!


So, it's the end?

This project has been a wild ride, hasn't it!
and if you're still reading this, THANK YOU!

But this project isn't over yet...

Fitting temperature and humidity sensors in each room has had the unfortunate side effect of highlighting how badly insulated and soggy this house is.

The joys of a century plus old house!

The rooms towards the back of the house lose heat FAST, and actually have ended up being the two that trigger the heating to come on most often!

We'd assumed that these rooms were lacking loft insulation above them, and our assumptions turned out to be correct.
None whatsoever, apart from a small section at the front of the house...

Thankfully we qualified for the Great British Insulation Scheme, so soon we shall be insulated!

But as part of this, some issues with my heating setup were flagged by an energy assessor.
Ideally it needs Weather or Load Compensation (alongside the insulation), to dynamically change the flow temperatures to save even more gas.
So, I'll be adding that soon...

Plus we need to balance the radiators again, after the damp proofing works...
I'll get round to it, I promise!

Damp?

During this project, the house has undergone SERIOUS works to remedy a severe damp problem. Walls were falling apart, there was mould, it was BAD.
Thankfully this has now been rectified, and the house is once again dry.

However, another issue that both the energy assessment and the damp proofers flagged was ventilation.
Those high humidity levels? Caused by insufficient ventilation.

So, we've started to also install new ventilation units, with heat recovery!
(which leads to an upcoming post about those!)


Fin.

So, there we have it for Part 1.

Again, THANK YOU SO MUCH for reading this madness!

There will of course be a Part 2 to this saga soon, including:

  • OpenTherm control for the boiler, to implement load/weather compensation
  • More TRVs, to make every radiator (except one) smart
  • A smart Eco Mode, to adjust temperatures to avoid condensation
  • Basic presence detection, so rooms are automatically set to Eco if we're not in
  • Get the valves' built in window detection to maybe work?

so, stick around for that!

I hope you've found this interesting :)
Now, go get yourself a brew, you deserve it!

Tags

nycto

Finding my own creative solutions to things, and just generally messing about is what I do :)