Setup for home heating demand

So I have a setup that works - sort of - to control (demand) the as boiler to heat up this cold Brit homes, depending on TRV actual vs desired room temps:

items

Group:Number:MAX    g_TRV_Actual_Temperature            "Max Temp TRV"
Group:Number:MAX    g_TRV_Set_Temperature               "Max Set TRV"
...
...
String				i_TRV_Lounge_Get_Temperature		"Current temperature"		<temperature>	(g_TRV, g_TRV_Actual_Temperature)		{channel="mqtt:topic:b_MQTT_Broker:t_TRV_Lounge:c_Temperature" [profile="transform:JS", function="get_temp.js"] }
String				i_TRV_Lounge_Set_Temperature		"Set temperature"			<temperature>	(g_TRV, g_TRV_Set_Temperature)			{channel="mqtt:topic:b_MQTT_Broker:t_TRV_Lounge:c_Set_Temperature"}
String				i_TRV_Kitchen_Get_Temperature		"Current temperature"		<temperature>	(g_TRV, g_TRV_Actual_Temperature)		{channel="mqtt:topic:b_MQTT_Broker:t_TRV_Lounge:c_Temperature" [profile="transform:JS", function="get_temp.js"] }
String				i_TRV_Kitchen_Set_Temperature		"Set temperature"			<temperature>	(g_TRV, g_TRV_Set_Temperature)			{channel="mqtt:topic:b_MQTT_Broker:t_TRV_Lounge:c_Set_Temperature"}
String				i_TRV_Hall_Get_Temperature		"Current temperature"		<temperature>	(g_TRV, g_TRV_Actual_Temperature)		{channel="mqtt:topic:b_MQTT_Broker:t_TRV_Lounge:c_Temperature" [profile="transform:JS", function="get_temp.js"] }
String				i_TRV_Hall_Set_Temperature		"Set temperature"			<temperature>	(g_TRV, g_TRV_Set_Temperature)			{channel="mqtt:topic:b_MQTT_Broker:t_TRV_Lounge:c_Set_Temperature"}

and a rule that isnt quite right because it gets the highest actual temp and the highest desired temp , to determine whether to turn off or turn on, the heating demand:

rule 
    "HVAC_CH"
when
    Item g_TRV_Actual_Temperature changed 
    or
    Item g_TRV_Set_Temperature changed 
then 
	// Check if Desired/Actual temp needs to switch boiler ON or OFF
	
	val Number temperature = g_TRV_Actual_Temperature.state as Number
	val Number demand = g_TRV_Set_Temperature.state as Number
	val Number hysteresis = 0.5
	val Number ON_temp  = (demand - hysteresis) 
	val Number OFF_temp  = (demand + hysteresis) 
        
	if (temperature <= ON_temp) {

		// Turn on
		i_HVAC_CH_Switch.sendCommand(ON)
		logInfo("HVAC_CH.rules", "...CH turned ON")
	
	} else if (temperature > OFF_temp) {
			
		// Turn Off
		i_HVAC_CH_Switch.sendCommand(OFF) 
		logInfo("HVAC_CH.rules", "...CH turned OFF")
	}
end

Problem here, is the following scenario:-

  • For Kitchen, the actual [GET] temp is higher than its desired [SET] value from the sitemap setpoint, so no boiler demand needed.
  • For Hall, the actual temp is lower than its desired value from the sitemap setpoint, and so we need a boiler demand to keep the heating on.

However

  • The Hall desired temp is less than the Kitchen desired temp, so MAX:desired would be the Kitchen desired temp.
  • The Hall actual temp is less than the Kitchen actual temp, so MAX:actual would be the Kitchen actual temp.
  • So because the MAX:actual > MAX:desired, the boiler doesnt fire. This is incorrect because we need more heat in the Hall.
  • other combinations fail too !
  • What the system needs to do, is compare room-by-room whether heat is required. If it, and until the answer is “NO” for all rooms, then the heating should be demanded.
    I’ve got the grouping and logic wrong , but not sure in DST rules and openhab group/items, how to correct this?

take a look on my solution.
I solved it as average or lowest trigger switch, default is average which i can manually overide.

It’s perfectly fine together with “dumb” thermocouplers set to 24C so overheated room shuts itself down by that automatically.

You could take each temp item, add them together then divide by the amount you have to get the average and postUpdate that to a proxy item in a rule. Use the proxy item to control if heat is needed or not.

Example:

when
    Item Temp_T changed
or
    Item Temp_P changed
then
    if(!(Temp_T.state instanceof Number )) return; // check if a number item
    if(!(Temp_P.state instanceof Number )) return; // check if a number item
    // both items have a number value, so calculate...
    var t = ((Temp_T.state as Number) + (Temp_P.state as Number) /2)
    ProxyItem.postUpdate(t) // Use this value to turn on/off heating
end

there is a group type to do it for you

Group:Number:AVG    House_Temperature

or

Group:Number:MIN    HeatingHouseMin 

etc.

I think I’d iterate through all actual-desired pairs, individually testing. If you begin with some flag for demand off, any pair can set it on. At the end, do whatever you need to do with your demand go/no-go status.

yep, that’s the way i think

i have smart TRVs and all radiators so AVG is not what i want.

I’ll setup discrete if/else blocks for each TRV . but my OP was hoping there would be a cleaner way, that’s self extensible - should i add TRVs, and avoid having to remember to edit rules , of which i have an increasing compendium of .

I think rossko57’s approach is the best for this particular situation where you have different desired temps for each room.

If you had only one desired temp setting, use MIN:actual to determine whether or not to turn on the boiler instead of MAX:actual. I use this approach to determine when to turn on my furnace’s fan in the summer to circulate the cold basement air to the rest of the house.

See Design Pattern: Working with Groups in Rules for all sorts of operations you can do on members of a Group. I think a map/reduce would be appropriate here coupled with Design Pattern: Associated Items.

    val heat = g_TRV_Actual_Temperature.members.map[(state as Number)].reduce[ res, itm | 
        val setItm = g_TRV_Set_Temperature.members.findFirst[ s | s.name == itm.name.replace("Actual", "Set") ]
        if(res) res else (itm.state as Number) < (setItm.state as Number)
    ]

You will probably want to add your hysteresis to the comparison in the reduce.

Im a dev albeit not in python/java. even i find the DP “groups and rules” extremely confusing due to

  • use of the noun item and group to refer to subtlety different but presumably important, differences. can we have more meaningful identifiers.
  • syntax tree would help immensely. DST im told, repeatedly, is not a language in its entirety so we cannot rely on syntax of established languages. DST is “similar” to … but that’s not helpful.
  • input/output would be a massive help, to visualise the code snippet’s transformational actions.

a seasoned openhab/DST guru might click straight away, but for devs and users coming from other domains of practice, it just turns me off and makes me post questions. A lot of time has been invested in documenting DPs, so lets avoid wasted effort and through improved narrative, open them up to more minds.:love_you_gesture::grin:

as it stands, its quicker and easier, focused and simpler, to disregard those DPs and just use repetitive code , which is a shame as you clearly spent a lot of time on this. but for me, and my view, key reference material is.missing
sorry.:pensive:
and i so so HATE it when people reply to this type of post of mine, with a bunch of links to tons of generic docs or references…i.mean whats the point of drafting DPs if people are them going to post a load of links for me to read. its a waste of time , both, but i bet someone now will do exactly as predicted.
time is precious.

I can’t fix the Rules DSL. It is what it is, and it may be going away. If you prefer some other language there are three available to you right now, which I’ve repeatedly told you and recommended to you.

I’ll note that almost all of the DPs now have Python versions of the code which includes both of the DPs posted above.

There is nothing subtle about it. From the docs:

Group Items collect other Items into Groups.

Perhaps other names for the concepts of Items and Groups and Things would be helpful, but we now have 10+ years of using these terms to refer to these concepts in OH. And what they mean in the OH context is well defined in the docs.

These two statements are completely contradictory. There’s no reference documentation and I HATE it when people give me links to the reference material.

You can’t have it both ways. And as I said in a getting started post once, would you rather some half-assed quickly typed answer someone wrote from their phone or a well thought out, thorough, and reviewed answer?

But to your main point:

  • thousands of users have been very successful with the docs as written including the DPs
  • since Rules DSL is no longer going to be the “main” language it makes no sense trying to document it any further

I’m sorry for wasting your time. But it’s a waste of my time to retype in the same damn thing over and over and over again. I’d have had to type in the Associated Items DP thousands of times by now if that were a case. The same for the Working with Groups in Rules. My time has value too, even if you seem to think your time is more important than the rest of ours.

So no, I’m not going to do it. If the answer to your question is in the docs or in another posting, I’m going to give you a link to it. I’m not going to retype it for your convenience.

Take it or leave it. As I’ve also said before, you don’t get to dictate to us in how we respond.

wholly illogical …,
very predictable !
i rest my case your honour :pensive:

talking of cases
when are you lot going to send that anne sacoolas over here to face some stiff UK Brit justice.

im going to HAS.io
been there for a few weeks now
faaaaaar more friendly
althogh tbh openhab is helpful but seems to me only a handful of gurus , yourself included. HAS has many, and they lack the pre madonna ‘attitude’ found here

sorry

well done, try harder, and good luck. you won’t miss me, I CERTAINLY will not miss this.