My Central Heating Solution using Thermal Actuators

If you have time, would it be possible if you could show how you were able to retrieve your ‘heating profiles’ stored in a JSON file and used to schedule heating?


Pm me tonight and I’ll post you my setup.
It is based on node-red

Just a random thought…

You wouldn’t happen to be lucky enough to already have a mechanical gas meter with the rotating gear with the magnet inside, that just needs the reed switch add-on?

IE, is there a funny little notch on the bottom right hand side, just below the decimal digit.
With a different colour gear rotating very close to the edge?

Unfortunalty the gas meter is inside a box in where I cant get in. so I wouldn´t know.
They should be force to build the same wireless meters as for water. In that way we wouldnt have to mess around with cables, cam, switches etc…

1 Like

The delta should be around 15%, if possible you should lower the pump flow rate. This detla is needed for condensing the exhaust gasses, improving the efficiency!

Edit: oops, that is for modulating gas heaters, not for oil based heaters.

Thought I’d add a little update. Been in the house for a few weeks now, and got all 16 heating zones up and running.

In addition to the 3 Sonoff 4ch in the cupboard in my office (feeding 9 zones), I’ve also got another 2 near my boiler, which feed the other 7 zones.

I’ve also added a Sonoff Basic, which is my “call-for-heat”, which piggy-backs onto the existing basic RF thermostat, which I’ve got set to a chilly 10°C as a bit of a backup! (I could have easily run this from the spare channel on one of the 4ch Sonoff’s below, but I had the spare Sonoff Basic, and I couldn’t be bothered to run a cable up the wall!)

I’ve still got the hot water on a basic timer (below the Sonoff Basic) - if I really feel the need in the future I may incorporate that into openHAB too!

All radiators (apart from one, in an airing cupboard) have their thermal actuators fitted.

This is the status of each zone + boiler over the last 7 days.

I’ve had to tweak the position of a couple of temperature sensors (Wemos D1 Mini with DHT22) sitting on surfaces in some rooms, trying to find a position where they’re not too close nor too far away from the radiators, so the temperature they’re reading is closer to what you feel when using the room. Still need to make something to put them in, either 3d print something or repurpose an old ornament so they blend in!

In the bathroom, shower room and en-suite, I’ve repurposed some in-ceiling PIR housings, which I’m powering via PoE and some PoE to 5v micro USB splitters (

In the first few days, I had to tweak the the target temperature rules a little, but I’ve not touched anything for a couple of weeks now, as there’s been no further complaints from the others in the house! I’ve also had to change the pumps from a fixed speed to an automatic speed setting, as when only a couple of radiators were flowing, they were making a whooshing noise with the water flowing through them so quickly!

“Grumpy” has a habit of having his door pushed open by the dog when he’s asleep, so I’ve got some Shelly door sensors on their way, which will then allow me to disable the heating in that room if the door is open for a period of time - that should help prevent trying to heat the world too much! I’ve also added a manual “override” switch, which I’ve exposed on an “Admin” sitemap, and it too works on Groups, so you can have multiple items triggering the override Group - this could be door sensors, presence detection, outside temperature, sun position - the limit is your imagination.

My main rule is now as follows:

import org.eclipse.smarthome.model.script.ScriptServiceUtil

val String filename = "heating_mode.rules"
val Number hysteresis = 0.2 

// ========================
// check Current temps and enables/disables actuators

rule "Check heating actuators every 5 minutes"
	Time cron "5 0/5 * * * ?" or
	Item gHeatingTargetTemp received update
	if (HeatingOverride.state == OFF) {
		var Number hylow = 0
		var Number hyhigh = 0
		gHeatingTargetTemp.members.forEach[ temp | 
			if (temp.state !== NULL || temp.state !== UNDEF) 
				hylow = (temp.state as Number) - hysteresis 
				hyhigh  = (temp.state as Number) + hysteresis
				var String GroupName =, 4)
				var nums = gTemperature.allMembers.filter[ i | i.state !== NULL && i.state !== UNDEF && + "Temp") ]
				if (nums.size > 0) {
					var avg =[state as Number].reduce[ result, value | result = (result + value) ] / nums.size
					val override = ScriptServiceUtil.getItemRegistry.getItem("g" + GroupName + "Heating_Override")
					gHeatingActuators.members.filter[ i | + "Heating_Actuator")].forEach [ i |
						var newState = i.state
						if (avg <= hylow)  {
							newState = ON
						if (avg >= hyhigh || override.state == ON) {	
							newState = OFF
						if (i.state !== newState) { 

rule "Boiler Call For Heat"
	Item gHeatingActuators received update
	if (HeatingOverride.state == OFF) {

(The rest of the rules is as it was in the first post - just with a few more zones defined!)

And my .items file:

// POR = Porch
// HAL = Hallway
// LNG = Lounge
// LRM = Living Room
// DRM = Dining Room
// KIT = Kitchen
// PLA = Playroom
// KNL = Kennel
// SHW = Shower Room
// BRW = Brewery
// TOP = Top Room
// GAR = Garage
// MEZ = Mezzanine

// GAB = Garry & Alex Bedroom
// MEB = Megan Bedroom
// JVB = Jim & Val Bedroom
// OFF = Office
// BAT = Bathroom
// LAN = Landing
// ENS = En-Suite

// If this switch is ON, the actuators won't be updated by the rule - use for testing etc
Switch HeatingOverride  "Disable Automatic Heating Actuators" 
// Individual room override groups
Group:Switch:OR(ON, OFF) gHeatingOverride "Heating Override Active" <lock>
Group:Switch:OR(ON, OFF) gPOR_Heating_Override "Porch - Disable Automatic Heating" <lock>
Group:Switch:OR(ON, OFF) gLNG_Heating_Override "Lounge - Disable Automatic Heating" <lock>
Group:Switch:OR(ON, OFF) gLRM_Heating_Override "Living Room - Disable Automatic Heating" <lock>
Group:Switch:OR(ON, OFF) gDRM_Heating_Override "Dining Room - Disable Automatic Heating" <lock>
Group:Switch:OR(ON, OFF) gPLA_Heating_Override "Playroom - Disable Automatic Heating" <lock>
Group:Switch:OR(ON, OFF) gKNL_Heating_Override "Grumpy Grotto - Disable Automatic Heating" <lock>
Group:Switch:OR(ON, OFF) gSHW_Heating_Override "Shower Room - Disable Automatic Heating" <lock>
Group:Switch:OR(ON, OFF) gBRW_Heating_Override "Brewery - Disable Automatic Heating" <lock>
Group:Switch:OR(ON, OFF) gTOP_Heating_Override "Top Room - Disable Automatic Heating" <lock>
Group:Switch:OR(ON, OFF) gGAR_Heating_Override "Garage - Disable Automatic Heating" <lock>
Group:Switch:OR(ON, OFF) gGAB_Heating_Override "Garry/Alex Bedroom - Disable Automatic Heating" <lock>
Group:Switch:OR(ON, OFF) gMEB_Heating_Override "Megan Bedroom - Disable Automatic Heating" <lock>
Group:Switch:OR(ON, OFF) gJVB_Heating_Override "Jim/Val Bedroom - Disable Automatic Heating" <lock>
Group:Switch:OR(ON, OFF) gOFF_Heating_Override "Office - Disable Automatic Heating" <lock>
Group:Switch:OR(ON, OFF) gBAT_Heating_Override "Bathroom - Disable Automatic Heating" <lock>
Group:Switch:OR(ON, OFF) gENS_Heating_Override "En-Suite - Disable Automatic Heating" <lock>
// Individual room override items
Switch	POR_Heating_Override "Porch - Disable Automatic Heating"    <lock>  (gPOR_Heating_Override)
Switch	LNG_Heating_Override "Lounge - Disable Automatic Heating"       <lock>  (gLNG_Heating_Override)
Switch	LRM_Heating_Override "Living Room - Disable Automatic Heating"      <lock>  (gLRM_Heating_Override)
Switch	DRM_Heating_Override "Dining Room - Disable Automatic Heating"     <lock>   (gDRM_Heating_Override)
Switch	PLA_Heating_Override "Playroom - Disable Automatic Heating"    <lock>   (gPLA_Heating_Override) 
Switch	KNL_Heating_Override "Grumpy Grotto - Disable Automatic Heating"       <lock>   (gKNL_Heating_Override)
Switch	SHW_Heating_Override "Shower Room - Disable Automatic Heating"    <lock>    (gSHW_Heating_Override) 
Switch	BRW_Heating_Override "Brewery - Disable Automatic Heating"    <lock>    (gBRW_Heating_Override) 
Switch	TOP_Heating_Override "Top Room - Disable Automatic Heating"    <lock>   (gTOP_Heating_Override)
Switch	GAR_Heating_Override "Garage - Disable Automatic Heating"     <lock>    (gGAR_Heating_Override)
Switch	GAB_Heating_Override "Garry/Alex Bedroom - Disable Automatic Heating"      <lock>   (gGAB_Heating_Override)
Switch	MEB_Heating_Override "Megan Bedroom - Disable Automatic Heating"       <lock>   (gMEB_Heating_Override)
Switch	JVB_Heating_Override "Jim/Val Bedroom - Disable Automatic Heating"    <lock>    (gJVB_Heating_Override) 
Switch	OFF_Heating_Override "Office - Disable Automatic Heating"     <lock>    (gOFF_Heating_Override)  
Switch	BAT_Heating_Override "Bathroom - Disable Automatic Heating"    <lock>   (gBAT_Heating_Override) 
Switch	ENS_Heating_Override "En-Suite - Disable Automatic Heating"    <lock>   (gENS_Heating_Override) 

// Groups
Group:Number:AVG gTemperature "Household Average Temperature [%.1f °C]"	<temperature>
Group:Number:AVG gHumidity "Household Average Humidity [%.1f %%]"	<humidity>

// Temp sensors
Number POR_Temp1 "Porch Temperature [%.1f °C]" 			        <temperature> 	(gChart, gTemperature, gPOR_Thermostat, gDeviceStatuses)  ["CurrentTemperature"] 	{mqtt="<[mosquitto:esp-por-1/env/temperature:state:default]", expire="30m"}
Number LNG_Temp1 "Lounge Temperature [%.1f °C]" 			    <temperature> 	(gChart, gTemperature, gLNG_Thermostat, gDeviceStatuses)  ["CurrentTemperature"] 	{mqtt="<[mosquitto:esp-lng-1/env/temperature:state:default]", expire="30m"}
Number LRM_Temp1 "Living Room Temperature [%.1f °C]" 			<temperature> 	(gChart, gTemperature, gLRM_Thermostat, gDeviceStatuses)  ["CurrentTemperature"] 	{mqtt="<[mosquitto:esp-lrm-1/env/temperature:state:default]", expire="30m"}
Number DRM_Temp1 "Dining Room Temperature [%.1f °C]" 			<temperature> 	(gChart, gTemperature, gDRM_Thermostat, gDeviceStatuses)  ["CurrentTemperature"] 	{mqtt="<[mosquitto:esp-dng-1/env/temperature:state:default]", expire="30m"}
Number PLA_Temp1 "Playroom Temperature [%.1f °C]" 			    <temperature> 	(gChart, gTemperature, gPLA_Thermostat, gDeviceStatuses)  ["CurrentTemperature"] 	{mqtt="<[mosquitto:esp-pla-1/env/temperature:state:default]", expire="30m"}
Number KNL_Temp1 "Kennel Temperature [%.1f °C]"				 	<temperature> 	(gChart, gTemperature, gKNL_Thermostat, gDeviceStatuses)  ["CurrentTemperature"] 	{mqtt="<[mosquitto:esp-knl-1/env/temperature:state:default]", expire="30m"}
Number SHW_Temp1 "Shower Room Temperature [%.1f °C]" 	        <temperature> 	(gChart, gTemperature, gSHW_Thermostat, gDeviceStatuses)  ["CurrentTemperature"] 	{mqtt="<[mosquitto:esp-shw-1/env/temperature:state:default]", expire="30m"}
Number BRW_Temp1 "Brewery Temperature [%.1f °C]" 	            <temperature> 	(gChart, gTemperature, gBRW_Thermostat, gDeviceStatuses)  ["CurrentTemperature"] 	{mqtt="<[mosquitto:esp-brw-1/env/temperature:state:default]", expire="30m"}
Number TOP_Temp1 "Top Room Temperature [%.1f °C]" 	            <temperature> 	(gChart, gTemperature, gTOP_Thermostat, gDeviceStatuses)  ["CurrentTemperature"] 	{mqtt="<[mosquitto:esp-top-1/env/temperature:state:default]", expire="30m"}
Number GAR_Temp1 "Garage Temperature [%.1f °C]" 	            <temperature> 	(gChart, gTemperature, gGAR_Thermostat, gDeviceStatuses)  ["CurrentTemperature"] 	{mqtt="<[mosquitto:esp-gar-1/env/temperature:state:default]", expire="30m"}
Number MEZ_Temp1 "Mezzanine Temperature [%.1f °C]" 	            <temperature> 	(gChart)  ["CurrentTemperature"] 	{mqtt="<[mosquitto:esp-mez-1/env/temperature:state:default]"}

Number GAB_Temp1 "Garry/Alex Bedroom Temperature [%.1f °C]" 	<temperature> 	(gChart, gTemperature, gGAB_Thermostat, gDeviceStatuses)  ["CurrentTemperature"] 	{mqtt="<[mosquitto:esp-gab-1/env/temperature:state:default]", expire="30m"}
Number MEB_Temp1 "Megan Bedroom Temperature [%.1f °C]" 			<temperature> 	(gChart, gTemperature, gMEB_Thermostat, gDeviceStatuses)  ["CurrentTemperature"] 	{mqtt="<[mosquitto:esp-meb-1/env/temperature:state:default]", expire="30m"}
Number JVB_Temp1 "Jim/Val Bedroom Temperature [%.1f °C]"		<temperature> 	(gChart, gTemperature, gJVB_Thermostat, gDeviceStatuses)  ["CurrentTemperature"] 	{mqtt="<[mosquitto:esp-jvb-1/env/temperature:state:default]", expire="30m"}
Number OFF_Temp1 "Office Temperature [%.1f °C]" 				<temperature> 	(gChart, gTemperature, gOFF_Thermostat, gDeviceStatuses)  ["CurrentTemperature"] 	{mqtt="<[mosquitto:esp-off-1/env/temperature:state:default]", expire="30m"}
Number BAT_Temp1 "Bathroom Temperature [%.1f °C]" 				<temperature> 	(gChart, gTemperature, gBAT_Thermostat, gDeviceStatuses)  ["CurrentTemperature"] 	{mqtt="<[mosquitto:esp-bat-1/env/temperature:state:default]", expire="30m"}
Number ENS_Temp1 "En-Suite Temperature [%.1f °C]" 				<temperature> 	(gChart, gTemperature, gENS_Thermostat, gDeviceStatuses)  ["CurrentTemperature"] 	{mqtt="<[mosquitto:esp-ens-1/env/temperature:state:default]", expire="30m"}

// Humidity sensors
Number POR_Humidity1 "Porch Humidity [%.1f %%]" 			    <humidity> 	(gChart, gPOR_Thermostat)    ["CurrentHumidity"] 	{mqtt="<[mosquitto:esp-por-1/env/humidity:state:default]"}
Number LNG_Humidity1 "Lounge Humidity [%.1f %%]" 			    <humidity> 	(gChart, gLNG_Thermostat)    ["CurrentHumidity"] 	{mqtt="<[mosquitto:esp-lng-1/env/humidity:state:default]"}
Number LRM_Humidity1 "Living Room Humidity [%.1f %%]" 			<humidity> 	(gChart, gLRM_Thermostat)    ["CurrentHumidity"] 	{mqtt="<[mosquitto:esp-lrm-1/env/humidity:state:default]"}
Number DRM_Humidity1 "Dining Room Humidity [%.1f %%]" 			<humidity> 	(gChart, gDNG_Thermostat)    ["CurrentHumidity"] 	{mqtt="<[mosquitto:esp-dng-1/env/humidity:state:default]"}
Number PLA_Humidity1 "Playroom Humidity [%.1f %%]" 			    <humidity> 	(gChart, gPLA_Thermostat)    ["CurrentHumidity"] 	{mqtt="<[mosquitto:esp-pla-1/env/humidity:state:default]"}
Number KNL_Humidity1 "Kennel Humidity [%.1f %%]"				<humidity> 	(gChart, gKNL_Thermostat)    ["CurrentHumidity"] 	{mqtt="<[mosquitto:esp-knl-1/env/humidity:state:default]"}
Number SHW_Humidity1 "Shower Room Humidity [%.1f %%]" 	        <humidity> 	(gChart, gSHW_Thermostat)    ["CurrentHumidity"] 	{mqtt="<[mosquitto:esp-shw-1/env/humidity:state:default]"}
Number BRW_Humidity1 "Brewery Humidity [%.1f %%]" 	            <humidity> 	(gChart, gBRW_Thermostat)    ["CurrentHumidity"] 	{mqtt="<[mosquitto:esp-brw-1/env/humidity:state:default]"}
Number TOP_Humidity1 "Top Room Humidity [%.1f %%]" 	            <humidity> 	(gChart, gTOP_Thermostat)    ["CurrentHumidity"] 	{mqtt="<[mosquitto:esp-top-1/env/humidity:state:default]"}
Number GAR_Humidity1 "Garage Humidity [%.1f %%]" 	            <humidity> 	(gChart, gGAR_Thermostat)    ["CurrentHumidity"] 	{mqtt="<[mosquitto:esp-gar-1/env/humidity:state:default]"}
Number MEZ_Humidity1 "Mezzanine Humidity [%.1f %%]" 	        <humidity> 	(gChart)    ["CurrentHumidity"] 	{mqtt="<[mosquitto:esp-mez-1/env/humidity:state:default]"}

Number GAB_Humidity1 "Garry/Alex Bedroom Humidity [%.1f %%]" 	<humidity> 	(gChart, gGAB_Thermostat)    ["CurrentHumidity"] 	{mqtt="<[mosquitto:esp-gab-1/env/humidity:state:default]"}
Number MEB_Humidity1 "Megan Bedroom Humidity [%.1f %%]" 		<humidity> 	(gChart, gMEB_Thermostat)    ["CurrentHumidity"] 	{mqtt="<[mosquitto:esp-meb-1/env/humidity:state:default]"}
Number JVB_Humidity1 "Jim/Val Bedroom Humidity [%.1f %%]"		<humidity> 	(gChart, gJVB_Thermostat)    ["CurrentHumidity"] 	{mqtt="<[mosquitto:esp-jvb-1/env/humidity:state:default]"}
Number OFF_Humidity1 "Office Humidity [%.1f %%]" 				<humidity> 	(gChart, gOFF_Thermostat)    ["CurrentHumidity"] 	{mqtt="<[mosquitto:esp-off-1/env/humidity:state:default]"}
Number BAT_Humidity1 "Bathroom Humidity [%.1f %%]" 				<humidity> 	(gChart, gBAT_Thermostat)    ["CurrentHumidity"] 	{mqtt="<[mosquitto:esp-bat-1/env/humidity:state:default]"}
Number ENS_Humidity1 "En-Suite Humidity [%.1f %%]" 				<humidity> 	(gChart, gENS_Thermostat)    ["CurrentHumidity"] 	{mqtt="<[mosquitto:esp-gab-1/env/humidity:state:default]"} // For now duplicate Bedroom humidity

// Switch items used for actuators
Group:Switch:OR(ON, OFF) gHeatingActuators "The heating should be [%s]" <fire> (gHeating)

// Thermal Actuators
Switch POR_Heating_Actuator "Porch Heating [%s]"	            <radiator>	(gHeatingActuators, gHistory)		{ mqtt=">[mosquitto:cmnd/sonoff-heating-1/POWER2:command:*:default], <[mosquitto:stat/sonoff-heating-1/POWER2:state:default]", autoupdate="false"}
Switch LNG_Heating_Actuator "Lounge Heating [%s]"	            <radiator>	(gHeatingActuators, gHistory)		{ mqtt=">[mosquitto:cmnd/sonoff-heating-1/POWER1:command:*:default], <[mosquitto:stat/sonoff-heating-1/POWER1:state:default]", autoupdate="false"}
Switch LRM_Heating_Actuator "Living Room Heating [%s]"	        <radiator>	(gHeatingActuators, gHistory)		{ mqtt=">[mosquitto:cmnd/sonoff-heating-1/POWER4:command:*:default], <[mosquitto:stat/sonoff-heating-1/POWER4:state:default]", autoupdate="false"}
Switch DRM_Heating_Actuator "Dining Room Heating [%s]"          <radiator>	(gHeatingActuators, gHistory)		{ mqtt=">[mosquitto:cmnd/sonoff-heating-4/POWER4:command:*:default], <[mosquitto:stat/sonoff-heating-4/POWER4:state:default]", autoupdate="false"}
Switch PLA_Heating_Actuator "Playroom Heating [%s]"             <radiator>	(gHeatingActuators, gHistory)		{ mqtt=">[mosquitto:cmnd/sonoff-heating-5/POWER3:command:*:default], <[mosquitto:stat/sonoff-heating-5/POWER3:state:default]", autoupdate="false"}
Switch KNL_Heating_Actuator "Kennel Heating [%s]"               <radiator>	(gHeatingActuators, gHistory)		{ mqtt=">[mosquitto:cmnd/sonoff-heating-5/POWER2:command:*:default], <[mosquitto:stat/sonoff-heating-5/POWER2:state:default]", autoupdate="false"}
Switch SHW_Heating_Actuator "Shower Room Heating [%s]"          <radiator>	(gHeatingActuators, gHistory)		{ mqtt=">[mosquitto:cmnd/sonoff-heating-4/POWER1:command:*:default], <[mosquitto:stat/sonoff-heating-4/POWER1:state:default]", autoupdate="false"}
Switch BRW_Heating_Actuator "Brewery Heating [%s]"              <radiator>	(gHeatingActuators, gHistory)		{ mqtt=">[mosquitto:cmnd/sonoff-heating-5/POWER1:command:*:default], <[mosquitto:stat/sonoff-heating-5/POWER1:state:default]", autoupdate="false"}
Switch TOP_Heating_Actuator "Top Room Heating [%s]"             <radiator>	(gHeatingActuators, gHistory)		{ mqtt=">[mosquitto:cmnd/sonoff-heating-4/POWER2:command:*:default], <[mosquitto:stat/sonoff-heating-4/POWER2:state:default]", autoupdate="false"}
Switch GAR_Heating_Actuator "Garage Heating [%s]"               <radiator>	(gHeatingActuators, gHistory)		{ mqtt=">[mosquitto:cmnd/sonoff-heating-4/POWER3:command:*:default], <[mosquitto:stat/sonoff-heating-4/POWER3:state:default]", autoupdate="false"}

Switch GAB_Heating_Actuator "Garry/Alex Bedroom Heating [%s]"	<radiator>	(gHeatingActuators, gHistory)		{ mqtt=">[mosquitto:cmnd/sonoff-heating-2/POWER2:command:*:default], <[mosquitto:stat/sonoff-heating-2/POWER2:state:default]", autoupdate="false"}
Switch MEB_Heating_Actuator "Megan Bedroom Heating [%s]"	    <radiator>	(gHeatingActuators, gHistory)		{ mqtt=">[mosquitto:cmnd/sonoff-heating-1/POWER3:command:*:default], <[mosquitto:stat/sonoff-heating-1/POWER3:state:default]", autoupdate="false"}
Switch JVB_Heating_Actuator "Jim & Val Bedroom Heating [%s]"	<radiator>	(gHeatingActuators, gHistory)		{ mqtt=">[mosquitto:cmnd/sonoff-heating-2/POWER4:command:*:default], <[mosquitto:stat/sonoff-heating-2/POWER4:state:default]", autoupdate="false"}
Switch OFF_Heating_Actuator "Office Heating [%s]"	            <radiator>	(gHeatingActuators, gHistory)		{ mqtt=">[mosquitto:cmnd/sonoff-heating-3/POWER1:command:*:default], <[mosquitto:stat/sonoff-heating-3/POWER1:state:default]", autoupdate="false"}
Switch BAT_Heating_Actuator "Bathroom Heating [%s]"	            <radiator>	(gHeatingActuators, gHistory)		{ mqtt=">[mosquitto:cmnd/sonoff-heating-2/POWER3:command:*:default], <[mosquitto:stat/sonoff-heating-2/POWER3:state:default]", autoupdate="false"}
Switch ENS_Heating_Actuator "En-Suite Heating [%s]"	            <radiator>	(gHeatingActuators, gHistory)		{ mqtt=">[mosquitto:cmnd/sonoff-heating-2/POWER1:command:*:default], <[mosquitto:stat/sonoff-heating-2/POWER1:state:default]", autoupdate="false"}

// Boiler control
Switch Boiler_Call_For_Heat "Boiler [%s]"   <fire>     (gHistory)  { mqtt=">[mosquitto:cmnd/sonoff-heating-boiler/POWER:command:*:default], <[mosquitto:stat/sonoff-heating-boiler/POWER1:state:default]", autoupdate="false"}

// Current target temperatures
Group:Number gHeatingTargetTemp (gHeating)
Number POR_Heating_TargetTemp "Porch Target [%.1f °C]"          <heating> 	(gHeatingTargetTemp, gHistory, gPOR_Thermostat)  ["TargetTemperature"]
Number LNG_Heating_TargetTemp "Lounge Target [%.1f °C]"         <heating> 	(gHeatingTargetTemp, gHistory, gLNG_Thermostat)  ["TargetTemperature"]
Number LRM_Heating_TargetTemp "Living Room Target [%.1f °C]"    <heating> 	(gHeatingTargetTemp, gHistory, gLRM_Thermostat)  ["TargetTemperature"]
Number DRM_Heating_TargetTemp "Dining Room Target [%.1f °C]"    <heating> 	(gHeatingTargetTemp, gHistory, gDRM_Thermostat)  ["TargetTemperature"]
Number PLA_Heating_TargetTemp "Playroom Target [%.1f °C]"       <heating> 	(gHeatingTargetTemp, gHistory, gPLA_Thermostat)  ["TargetTemperature"]
Number KNL_Heating_TargetTemp "Kennel Target [%.1f °C]"         <heating> 	(gHeatingTargetTemp, gHistory, gKNL_Thermostat)  ["TargetTemperature"]
Number SHW_Heating_TargetTemp "Shower Room Target [%.1f °C]"    <heating> 	(gHeatingTargetTemp, gHistory, gSHW_Thermostat)  ["TargetTemperature"]
Number BRW_Heating_TargetTemp "Brewery Target [%.1f °C]"        <heating> 	(gHeatingTargetTemp, gHistory, gBRW_Thermostat)  ["TargetTemperature"]
Number TOP_Heating_TargetTemp "Top Room Target [%.1f °C]"       <heating> 	(gHeatingTargetTemp, gHistory, gTOP_Thermostat)  ["TargetTemperature"]
Number GAR_Heating_TargetTemp "Garage Target [%.1f °C]"         <heating> 	(gHeatingTargetTemp, gHistory, gGAR_Thermostat)  ["TargetTemperature"]

Number GAB_Heating_TargetTemp "Garry/Alex Bedroom Target [%.1f °C]" <heating> 	(gHeatingTargetTemp, gHistory, gGAB_Thermostat)  ["TargetTemperature"]
Number MEB_Heating_TargetTemp "Megan Bedroom Target [%.1f °C]"   <heating> 	(gHeatingTargetTemp, gHistory, gMEB_Thermostat)  ["TargetTemperature"]
Number JVB_Heating_TargetTemp "Jim/Val Bedroom Target [%.1f °C]" <heating> 	(gHeatingTargetTemp, gHistory, gJVB_Thermostat)  ["TargetTemperature"]
Number OFF_Heating_TargetTemp "Office Target [%.1f °C]"         <heating> 	(gHeatingTargetTemp, gHistory, gOFF_Thermostat)  ["TargetTemperature"]
Number BAT_Heating_TargetTemp "Bathroom Target [%.1f °C]"       <heating> 	(gHeatingTargetTemp, gHistory, gBAT_Thermostat)  ["TargetTemperature"]
Number ENS_Heating_TargetTemp "En-Suite Target [%.1f °C]"       <heating> 	(gHeatingTargetTemp, gHistory, gENS_Thermostat)  ["TargetTemperature"]

// Heating Modes
String Heating_Mode "Global Heating Mode [MAP(]" <heating>
Switch Heating_UpdateHeaters "Send Target Temperatures to Heaters"

// Presets  
Group Heating_PresetNormal_Group (gHeating)
Number POR_Heating_PresetTempNormal "Porch Heating Preset (Normal Mode) [%.1f °C]" <heating> (Heating_PresetNormal_Group)
Number LNG_Heating_PresetTempNormal "Lounge Heating Preset (Normal Mode) [%.1f °C]" <heating> (Heating_PresetNormal_Group)
Number LRM_Heating_PresetTempNormal "Living Room Heating Preset (Normal Mode) [%.1f °C]" <heating> (Heating_PresetNormal_Group)
Number DRM_Heating_PresetTempNormal "Dining Room Heating Preset (Normal Mode) [%.1f °C]" <heating> (Heating_PresetNormal_Group)
Number PLA_Heating_PresetTempNormal "Playroom Heating Preset (Normal Mode) [%.1f °C]" <heating> (Heating_PresetNormal_Group)
Number KNL_Heating_PresetTempNormal "Kennel Heating Preset (Normal Mode) [%.1f °C]" <heating> (Heating_PresetNormal_Group)
Number SHW_Heating_PresetTempNormal "Shower Room Heating Preset (Normal Mode) [%.1f °C]" <heating> (Heating_PresetNormal_Group)
Number BRW_Heating_PresetTempNormal "Brewery Heating Preset (Normal Mode) [%.1f °C]" <heating> (Heating_PresetNormal_Group)
Number TOP_Heating_PresetTempNormal "Top Room Heating Preset (Normal Mode) [%.1f °C]" <heating> (Heating_PresetNormal_Group)
Number GAR_Heating_PresetTempNormal "Garage Heating Preset (Normal Mode) [%.1f °C]" <heating> (Heating_PresetNormal_Group)
Number GAB_Heating_PresetTempNormal "Garry/Alex Bedroom Heating Preset (Normal Mode) [%.1f °C]" <heating> (Heating_PresetNormal_Group)
Number MEB_Heating_PresetTempNormal "Megan Bedroom Heating Preset (Normal Mode) [%.1f °C]" <heating> (Heating_PresetNormal_Group)
Number JVB_Heating_PresetTempNormal "Jim/Val Bedroom Heating Preset (Normal Mode) [%.1f °C]" <heating> (Heating_PresetNormal_Group)
Number OFF_Heating_PresetTempNormal "Office Heating Preset (Normal Mode) [%.1f °C]" <heating> (Heating_PresetNormal_Group)
Number BAT_Heating_PresetTempNormal "Bathroom Heating Preset (Normal Mode) [%.1f °C]" <heating> (Heating_PresetNormal_Group)
Number ENS_Heating_PresetTempNormal "En-Suite Heating Preset (Normal Mode) [%.1f °C]" <heating> (Heating_PresetNormal_Group)

// Groups (needed for Google Assistant)
Group gPOR_Thermostat "Porch Thermostat" <heating>	["Thermostat"]
Group gLNG_Thermostat "Lounge Thermostat" <heating>	["Thermostat"]
Group gLRM_Thermostat "Living Room Thermostat" <heating>	["Thermostat"]
Group gDRM_Thermostat "Dining Room Thermostat" <heating>	["Thermostat"]
Group gPLA_Thermostat "Playroom Thermostat" <heating>	["Thermostat"]
Group gKNL_Thermostat "Grumpy Grotto Thermostat" <heating>	["Thermostat"]
Group gSHW_Thermostat "Shower Room Thermostat" <heating>	["Thermostat"]
Group gBRW_Thermostat "Brewery Thermostat" <heating>	["Thermostat"]
Group gTOP_Thermostat "Top Room Thermostat" <heating>	["Thermostat"]
Group gGAR_Thermostat "Garage Thermostat" <heating>	["Thermostat"]
Group gGAB_Thermostat "Garry/Alex Bedroom Thermostat" <heating>	["Thermostat"]
Group gMEB_Thermostat "Megan Bedroom Thermostat" <heating>	["Thermostat"]
Group gJVB_Thermostat "Jim/Val Bedroom Thermostat" <heating>	["Thermostat"]
Group gOFF_Thermostat "Office Thermostat" <heating>	["Thermostat"]
Group gBAT_Thermostat "Bathroom Thermostat" <heating>	["Thermostat"]
Group gENS_Thermostat "En-Suite Thermostat" <heating>	["Thermostat"]

Switch Grotto_Door "Grotto Door [%s]" <door>   (gKNL_Heating_Override)  { mqtt="<[mosquitto:shelly/sensor/state:state:default]" }

You’ll notice that I have also exposed all of this to Google, so I can now also get and set temperatures with Google Assistant, such as “set the temperature in the lounge to 22” and “what is the temperature in the garage”

I’ve also utilised Design Patterns: Generic Is Alive to send me an alert via myopenHAB if any of the sensors stop reporting for 30 minutes.

I’m really glad I’ve done this all, I’ve got a fully customised system, which doesn’t rely on any cloud services (but uses them to augment it), and so far over the last few weeks, the rooms have been just the right temperatures when they need to be - as it starts getting colder here in the UK, I’ll be thankful for that, and hopefully I’ve got the rules just about right - but if not, it’s a matter of seconds to tweak the rules once I’ve used the sitemap or Google Assistant to set a target temperature.


Looks very nice and clean!

Can you get this to work with any Google Home hub? (Google Nest Hub).
I can get it to work in the Google Home app, as well as using assistant through Google Home/Mini. But my Google Nest Hub says “mode is not supported”.

I’ve only tried it with my phone. What I haven’t done is set up a “heatingcoolingmode” item, which was listed as a requirement in GitHub - openhab/openhab-google-assistant: openHAB Google Assistant: Actions on Google for openHAB as it seemed to work for me without!

Same here… Except for the Google Next Hub… If you havnt got a Google Nest Hub, you wouldnt notice.

Excellent work, I love it…thanks for sharing.

I had something similar with my previous platform and I’ll use this as the basis of my fairly recent port to OH.

I used to have Nest but then switched to Ecobee. Using the Ecobee binding, I have the ability to read the status of all the remote sensors available. I have 9 of them scattered around the house. The Ecobee controls the forced air heating and cooling, using the remote sensors as to develope an “average” temp in the house but I use the remote sensors to control individual in floor radiant zones, just to tackle the cold spots in the house.

Thanks again for sharing.

I just noticed your rooms…Brewery??? Nice!

@Confused Great article.
I’m in process of replacing my Central heating control system at home. We have got at home Worcester combi boiler with Digistat thermostat without internet connectivity.
So looking to purchase some thermal actuators and thinking to control each of them with Sonoff Basic - I hope this is good idea as I know people got different opinions about Itead equipment these days.
I had a look on Ebay and Amazon and there are many manufacturers selling NC 230VC actuators from £5 per piece so there are cheap. But not sure if there are any good, perhaps you guys can recommend some good actuators for budget price.
We got three bedrooms with 6 actuators in total not including the one in bathroom as it’s always cold spot and there is 1kW heater to maintain the required temperature-usually 22C.

Someone has mentioned Drayton Wiser system earlier, I seen offer two weeks ago where thermostat, Gateway and two actuators cost £129 and each additional actuator was £25. So not bad at all if you compare to Evohome system price.
But decided not to buy as I would prefer to do it myself.

@vzorglub you have mentioned that you will be using new relay in the near future to fire the boiler, may I ask you which model it’s and what’s attached to this relay to connect to OpenHAB (sonoff ?)


Great question. I was going to do a small write up about this:

I used an electrodragon SDPT flashed with tasmota
I took the output of the Nest thermostat and I wired this to the GPIO4 of the board
Then I configured the GPIO4 as SWITCH1
And put SWITCH1 in switchmode 2 (Inverted follow)

I then wired the wires that used to go to the Nest to the NO (Normally Open) pins of RELAY1

This way, when the nest kicks is for downstairs, the boiler kicks in and openHAB knows through MQTT
I can also turn on the boiler via the temperatures sensors upstairs which turn on the radiator valve which in turn turn on the boiler.


Thanks @vzorglub I missed that you have Nest thermostat at home as well. There are quite expensive this days as I can see. I’m debating if I should rely on my own temperature sensors dotted around house (mostly DHT22/Sonoff) but i know that i could left house cold if my openHAB is down for any reason one day. I travel around country every few months so it could be disaster if that happens and I’m not around in the middle of winter (:cold_face: = :woman_facepalming:t2: & :boxing_glove:)

Then I would add a DHT22 to the Electrodragon and a TASMOTA rule that if the temp iss below say 5c then kick the boiler ON for 1 Hour and send a message to all the other sonoffs to open their valves.
It is important in this case to have the mosquitto broker on ANOTHER machine than the openHAB server. My broker runs on PIzero. Does only that. Plugged into a powerbank good enough for 4 hours of continuous operation.

I may need to consider splitting my broker from OpenHAB I think it’s good idea. I use OpenHABian assuming it can we done ?

With regards to thermal actuators not sure which brand to choose yet:

  • Two wire
  • Four wire
  • 230VAC or 24VDC
  • Any particular brand worth looking ? There is tons of them on the market at the moment.

Personally, my answers would be…

  • Two wire - only if you just need the valve opening
  • Four wire - Great if you want to use the “fully open” microswitch to confirm the valve opening, or “call for hear”
  • 230VAC or 24VDC - Totally up to you, no advantage either way. Unless… you want a sub 50v system, which may mean different / simpler building codes to comply with.
  • Any particular brand worth looking - In 8 years, I’ve only heard of 1 microswitch failing in an Emetti WTA.

Is there an actuator based on 5V? Something what can run on battery?
I have already read through Any TRV suggestions? but nothing mentioned of there as well.
So far I find only DIY tutorials:

The temperature can be measured using wireless sensors such as:

Not that I’m aware of. These types of actuators require constant power when “on”.

I very deliberately did not want anything battery powered.

There are products like the Shelly H&T, which are battery powered temp/humidity sensors, but they are hard-coded to only read & report once every 10 minutes. I wanted reporting more regularly than that - my bathroom sensors report every 30 seconds, and as well as being used for heating control, also are used to operate extractor fans based upon humidity changes - a sensor reporting every 10 minutes would not have been suitable for that, for me.

and I don’t want to pull cables to all my heatings :smile:

They do exist.
I think I saw some Z-Wave or Zigbee ones.
I’m sure Loxone has a battery powered model.
Do you already use one of these protocols ?