MAX! heating system, boiler controller and window contacts

Hello,
I installed eq-3 MAX! system components last winter. Now I would like to integrate it with rest of “smart” elements of my house. I have chosen Openhab as platform of integration. Posts published on this forum let me install openHAB on RPi with MAX! and alarm bindings. Everything is working and I can read states of items, WOW. I will appreciate if you give me some directions and examples for my future work. I suppose that I have to use rules, but till now this is a topic I’m not familiar with. So, in short:

  1. I would like to controll my gas boiler ON/OFF cycles. I’ve found many approaches to realize this funcionality. Because I’m max system user, I think I need observe valve opening percentage in reference rooms and on this basis turn on and off the boiler, then wait some time and if thermostat or group of thermostats call for heat again, turn on the boiler again. Example codes are kindly welcome :wink.

  2. My MAX! system has no window contacts. But I have window contacts of alarm system instead. I can see if contact items are violated (window is open). How to transfer state of the alarm window contacts to max system. I mean, how to write a rule which turn off heating in the room in case of airing - window opened more than 1 minute and return back to auto mode after window is closed. Which approach is correct - MAX! Cube know about airing and control the thermostats or openhab sends commands to thermostats in case of window is open more then 1 min.

I’ve seen many posts relating to my problems but they didn’t fit all my needs.
Thank you in advance,
Zbigniew Kordalski

1 Like

Well, first of all, you should NOT remote control power of your boiler. Switching the boiler ON/OFF electrically can damage it rather quickly. You can do this with the pump(s), though, or if you have an input signal to your boiler that if ON is signalling ‘heat requirement’.

Second, I’m realizing this using non-MAX! thermometers to determine need-for-heat per-room, then if any of the rooms attached to the same pump show a need, I turn on that pump.
You could trigger upon changes of the item(s) that’s mapped to the valve channel(s), i.e. if you have items like

Number target        "SOLL Bad Boden [%.1f °C]"                      <temperature> (OG_Bad,Heizung)          { channel="max:thermostat:KMD101XXXX:KMD302XXXX:set_temp" }
Number actual         "IST Bad Boden [%.1f °C]"                       <temperature> (OG_Bad,Heizung)          { channel="max:thermostat:KMD101XXXX:KMD302XXXX:actual_temp" }
Number valve    "Ventil Bad Boden [%.1f °C]"                                  (OG_Bad,Heizung)          { channel="max:thermostat:KMD101XXXX:KMD302XXXX:valve" }

then put a rule like this

rule "Waermecheck Bad"
when
        Item valve changed
then
         if (target.state > actual.state)
                pump.sendCommand(ON)
         else
                pump.sendCommand(OFF)
end

But ATTENTION, this is just the basic idea: You’re responsible to implement the proper algorithm yourself.
Remember there’s just one boiler/pump for a number of thermostats, you need to loop through these, and depending on your local setup, many more issues to watch for.
Be warned, it’s way more complex than you imagine in the first place. My heating.rules has grown to about a thousand lines of code.

AFAIK there’s no way to ‘inject’ this ‘window open’ data into the max cube (well you could try if the contact_state channel is writable, but I doubt it is). What you can do is to override the target temperature (modify the item that is mapped to the set_temp channel).
You can also change to MANUAL mode first but you don’t have to. Auto mode will only become active (i.e. turn the valve) when there’s a change of target temperature as defined inside the cube software for this thermostat/room.

Thank you Markus!

First of all, I’m not planning to turn on and off the power of my boiler. It has connectors designed for ON/OFF wallthermostats/controllers. Now these conectors are shorted and the boiler starts up on all demands. Heating cycles are short and not very economical and healthy for boiler. That’s why I decided for previously described solution.

I’ve noticed that your solution doesn’t assume any concept of hysteresis. Boiler it is not only pump. It is also burner which works with power modulation.

Thank you for directions and example codes. I will take it into account. Currently I try to become more familiar with rules syntax and in few days I would like to show you to check my concept.

Regarding window contacts - agreed.

Oh, it does, that’s some of the 1k lines I didn’t show.
Then again, you don’t need hysteresis with MAX! thermostats just to save on the number of boiler starts (well, unless you live in sort of a heated tent :slight_smile: )
And my boiler does not have that input signal, that’s why I do it on pump level.

Ha, ha, I’am trying to write my first 5 lines of openHAB rule.

So I have written my first 5+ lines of rule code. The idea is to switch boiler on when 2 or more thermostats call for heat (valve is opened 80% and more). This is done in 2 stages:

  1. Rule “Heat demands” examine if state of valves opening is above 80%. If yes, suitable switch is changing state to ON.
  2. Rule “Boiler switch” looks through group of these switches and if 2 or more are ON, changing to ON. This rule will fire up relay which turn on the boiler.
Group gMax
Group gDemands

Switch maxValve_Room1_Demand	"Room1 żąda ciepła"		(gDemands)
Switch maxValve_Room2_Demand	"Room2 żąda ciepła"       	(gDemands)
Switch maxValve_Room3_Demand	"Room3 żąda ciepła"      	(gDemands)

Switch heatDemand "Żądanie ciepła"

//Room1
Switch	maxBattery_Room1	"Poziom baterii"					(gMAX)	{channel="max:thermostat:KEQ0644794:MEQ1445534:battery_low"}
Number	maxValve_Room1		"Otwarcie zaworu głowicy [%.0f %%]"	(gMAX)	{channel="max:thermostat:KEQ0644794:MEQ1445534:valve"}
Switch	maxBattery_RoomT1	"Poziom baterii"					(gMAX)	{channel="max:wallthermostat:KEQ0644794:NEQ0086069:battery_low"}
String	maxMode_RoomT1		"Tryb"								(gMAX)	{channel="max:wallthermostat:KEQ0644794:NEQ0086069:mode"}
Number	maxActual_RoomT1	"Temperatura aktualna  [%.1f °C]"	(gMAX)	{channel="max:wallthermostat:KEQ0644794:NEQ0086069:actual_temp"}
Number	maxSetTemp_RoomT1	"Temperatura żądana [%.1f °C]"		(gMAX)	{channel="max:wallthermostat:KEQ0644794:NEQ0086069:set_temp"}
//Room2
Switch	maxBattery_Room2	"Poziom baterii"					(gMAX)	{channel="max:thermostat:KEQ0644794:NEQ0661111:battery_low"}
Number	maxValve_Room2		"Otwarcie zaworu głowicy [%.0f %%]"	(gMAX)	{channel="max:thermostat:KEQ0644794:NEQ0661111:valve"}
Switch	maxBattery_RoomT2	"Poziom baterii"					(gMAX)	{channel="max:wallthermostat:KEQ0644794:NEQ1334138:battery_low"}
String	maxMode_RoomT2		"Tryb"								(gMAX)	{channel="max:wallthermostat:KEQ0644794:NEQ1334138:mode"}
Number	maxActual_RoomT2	"Temperatura aktualna  [%.1f °C]"	(gMAX)	{channel="max:wallthermostat:KEQ0644794:NEQ1334138:actual_temp"}
Number	maxSetTemp_RoomT2	"Temperatura żądana [%.1f °C]"		(gMAX)	{channel="max:wallthermostat:KEQ0644794:NEQ1334138:set_temp"}
//Room3
Switch	maxBattery_Room3	"Poziom baterii"					(gMAX)	{channel="max:thermostat:KEQ0644794:NEQ0661639:battery_low"}
Number	maxValve_Room3		"Otwarcie zaworu głowicy [%.0f %%]"	(gMAX)	{channel="max:thermostat:KEQ0644794:NEQ0661639:valve"}
Switch	maxBattery_RoomT3	"Poziom baterii"					(gMAX)	{channel="max:wallthermostat:KEQ0644794:NEQ1334111:battery_low"}
String	maxMode_RoomT3		"Tryb"								(gMAX)	{channel="max:wallthermostat:KEQ0644794:NEQ1334111:mode"}
Number	maxActual_RoomT3	"Temperatura aktualna  [%.1f °C]"	(gMAX)	{channel="max:wallthermostat:KEQ0644794:NEQ1334111:actual_temp"}
Number	maxSetTemp_RoomT3	"Temperatura żądana [%.1f °C]"		(gMAX)	{channel="max:wallthermostat:KEQ0644794:NEQ1334111:set_temp"}

Number	maxDutyCycle	"Duty cycle [%.0f %%]"				(gMAX)	{channel="max:bridge:KEQ0644794:duty_cycle"}
rule "Heat demands"
when
	Item maxValve_Room1 changed or 
	Item maxValve_Room2 changed or 
	Item maxValve_Room3 changed 
then
	if(maxValve_Room1.state > 79)
		{maxValve_Room1_Demand.postUpdate(ON)} else {maxValve_Room1_Demand.postUpdate(OFF)}
	if(maxValve_Room2.state > 79)
		{maxValve_Room2_Demand.postUpdate(ON)} else {maxValve_Room2_Demand.postUpdate(OFF)}
	if(maxValve_Room3.state > 79)
		{maxValve_Room3_Demand.postUpdate(ON)} else {maxValve_Room3_Demand.postUpdate(OFF)}
end


rule "Boiler switch"
when
	Item maxValve_Room1_Demand received update or
	Item maxValve_Room2_Demand received update or
	Item maxValve_Room3_Demand received update
then
	if(gDemands.members.filter[d|d.state == ON].size > 1)
		{heatDemand.sendCommand(ON)} else {heatDemand.sendCommand(OFF)}
end

I am still working in test environment with thermostats but without heating. Everythitg seems to work but sometimes in log I get error within Boiler switch rule ann changing state of 1 from 3 items:

2017-09-16 21:29:39.548 [ItemStateChangedEvent     ] - maxValve_Room2_Demand changed from OFF to ON
2017-09-16 21:29:39.559 [ERROR] [.script.engine.ScriptExecutionThread] - Rule 'Boiler switch': null
2017-09-16 21:29:39.613 [ItemCommandEvent          ] - Item 'heatDemand' received command ON
2017-09-16 21:29:39.614 [ItemCommandEvent          ] - Item 'heatDemand' received command ON

How it looks like? I’am not sure about syntax. I have tried write Heat demands rule in more elegant way but I failed.

Hej,
Przyglądam się temu wątkowi bo mam takie samo wyzwanie. Mogę się jakoś do Ciebie odezwać poza forum aby podpytac się ciebie o kilka rzeczy ? - nie chcę tu śmiecić, ani tym bardzie produkowac się do opisywania pytań nie po polsku. :wink: