Hello,
I have a working rule that controls my heating, which was developed with the help of the community here for v2. I’ll include my items and the rule below, however, with OH3 the rule does not always work as expected, because it leaves the basement heating on even if there is no need for it and I’d like to ask for your opinion why that happens. The basement heating controls the boiler, so if any of the floors need heating, basement needs to be turned on - it seems when the heat need goes away, for some reason the relay isn’t turned off and I can’t figure out why; it was working flawlessly under v2. The items, the old rule and the new rules from the OH3 interface are below:
Items:
Switch GF_Heating_Pump "Groundfloor heating pump" <faucet> (GF, gFaucet) ["Switch","Switchable"] {autoupdate="false", channel="souliss:t11:77:0-15:onoff"}
Switch FF_Heating_Pump "First floor heating pump" <faucet> (FF, gFaucet) ["Switch","Switchable"] {autoupdate="false", channel="souliss:t11:77:0-16:onoff"}
Switch BF_Heating_Pump "Basement heating pump" <faucet> (BF, gFaucet) ["Switch","Switchable"] {autoupdate="false", channel="souliss:t11:77:0-17:onoff"}
Switch BF_Heat_Need "Basement heat need" <heating> (gHneed)
Switch GF_Heat_Need "Ground floor heat need" <heating> (gHneed)
Switch FF_Heat_Need "First floor heat need" <heating> (gHneed)
Switch Heating_Mode_Auto "Automata fűtésmód"
Group:Number:AVG gHeatingTargetTemp (gHeating)
Number BF_Target_Temp "Pince célhőm. [%.1f °C]" (gHeatingTargetTemp)
Number GF_Target_Temp "Földszint célhőm. [%.1f °C]" (gHeatingTargetTemp)
Number FF_Target_Temp "Emelet célhőm. [%.1f °C]" (gHeatingTargetTemp)
Group Heating_PresetNormal_Group (gHeating)
Number BF_Heating_PresetTempNormal "Pince alap [%.1f °C]" <heating> (Heating_PresetNormal_Group)
Number GF_Heating_PresetTempNormal "Fszt. alap [%.1f °C]" <heating> (Heating_PresetNormal_Group)
Number FF_Heating_PresetTempNormal "Emelet alap [%.1f °C]" <heating> (Heating_PresetNormal_Group)
Number hysteresis "Hiszterézis"
Group:Switch:OR(ON, OFF) gHneed "Heat need" <heating> (Home)
Old rule:
val String filename = "heating_mode.rules"
val Number hysteresis = 0.2
rule "Initialize uninitialized virtual Items"
when
System started
then
createTimer(now.plusSeconds(60)) [ |
logInfo(filename, "Executing 'System started' rule for Heating")
Heating_PresetNormal_Group.members.filter[item | item.state == NULL].forEach[item | item.postUpdate(22.0)]
BF_Heating_PresetTempNormal.postUpdate(20.0)
gHneed.members.forEach[item | item.postUpdate("OFF")]
if (Heating_Mode_Auto.state == NULL) Heating_Mode_Auto.postUpdate("ON")
]
end
rule "React on heating mode switch, send target temperatures"
when
Item Heating_Mode_Auto received update
then
BF_Target_Temp.sendCommand(BF_Heating_PresetTempNormal.state as Number)
GF_Target_Temp.sendCommand(GF_Heating_PresetTempNormal.state as Number)
FF_Target_Temp.sendCommand(FF_Heating_PresetTempNormal.state as Number)
end
rule "Check heating actuators every 15 minutes"
when
Time cron "* 0/15 * * * ? *" or
Member of gHeatingTargetTemp received update
then
//logInfo("heatcheck.tdebug", "Heatcheck started ")
if (Heating_Mode_Auto.state == ON) { // automatic heating enabled
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 = temp.name.substring(0, 3) // set groupname based on first 3 bytes
val avgtemp = org.openhab.core.model.script.ScriptServiceUtil.getItemRegistry.getItem(GroupName + "AvgTemp")
val needheat = org.openhab.core.model.script.ScriptServiceUtil.getItemRegistry.getItem(GroupName + "Heat_Need")
if ((avgtemp.state as Number) <= hylow && needheat.state == OFF) { //if average temp lower than preset-hysteresis and heating is not working
needheat.sendCommand(ON) //turn heating on
logInfo("ghneedrule.debug", "Heating turned on for: {}", needheat)
}
if ((avgtemp.state as Number) >= hyhigh && needheat.state == ON) { //if average temp higher than preset+hysteresis and heating is working
needheat.sendCommand(OFF) // turn heating off
logInfo("ghneedrule.debug", "Heating turned off for: {}", needheat)
}
}
]
}
end
rule "Process heating need"
when
Member of gHneed received update
then
logInfo("ghneed.debug", "gHneed state is: {}", gHneed.state)
logInfo("ghneed.debug", "BF_Heat_need state is: {}", BF_Heat_Need.state)
logInfo("ghneed.debug", "BF_Heating_Pump state is: {}", BF_Heating_Pump.state)
logInfo("ghneed.debug", "GF_Heat_need state is: {}", GF_Heat_Need.state)
logInfo("ghneed.debug", "GF_Heating_Pump state is: {}", GF_Heating_Pump.state)
logInfo("ghneed.debug", "FF_Heat_need state is: {}", FF_Heat_Need.state)
logInfo("ghneed.debug", "FF_Heating_Pump state is: {}", FF_Heating_Pump.state)
BF_Heating_Pump.sendCommand(gHneed.state.toString)
GF_Heating_Pump.sendCommand(GF_Heat_Need.state.toString)
FF_Heating_Pump.sendCommand(FF_Heat_Need.state.toString)
end
New rules from OH3:
// Triggers:
// - When the system has reached start level 20
// context: heating_mode-1
createTimer(now.plusSeconds(60)) [ |
logInfo(filename, "Executing 'System started' rule for Heating")
Heating_PresetNormal_Group.members.filter[item | item.state == NULL].forEach[item | item.postUpdate(22.0)]
BF_Heating_PresetTempNormal.postUpdate(20.0)
gHneed.members.forEach[item | item.postUpdate("OFF")]
if (Heating_Mode_Auto.state == NULL) Heating_Mode_Auto.postUpdate("ON")
]
// Triggers:
// - When Heating_Mode_Auto was updated
// context: heating_mode-2
BF_Target_Temp.sendCommand(BF_Heating_PresetTempNormal.state as Number)
GF_Target_Temp.sendCommand(GF_Heating_PresetTempNormal.state as Number)
FF_Target_Temp.sendCommand(FF_Heating_PresetTempNormal.state as Number)
// Triggers:
// - Every second, every 15 minutes
// - When a member of gHeatingTargetTemp was updated
// context: heating_mode-3
//logInfo("heatcheck.tdebug", "Heatcheck started ")
if (Heating_Mode_Auto.state == ON) { // automatic heating enabled
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 = temp.name.substring(0, 3) // set groupname based on first 3 bytes
val avgtemp = org.openhab.core.model.script.ScriptServiceUtil.getItemRegistry.getItem(GroupName + "AvgTemp")
val needheat = org.openhab.core.model.script.ScriptServiceUtil.getItemRegistry.getItem(GroupName + "Heat_Need")
if ((avgtemp.state as Number) <= hylow && needheat.state == OFF) { //if average temp lower than preset-hysteresis and heating is not working
needheat.sendCommand(ON) //turn heating on
logInfo("ghneedrule.debug", "Heating turned on for: {}", needheat)
}
if ((avgtemp.state as Number) >= hyhigh && needheat.state == ON) { //if average temp higher than preset+hysteresis and heating is working
needheat.sendCommand(OFF) // turn heating off
logInfo("ghneedrule.debug", "Heating turned off for: {}", needheat)
}
}
]
}
// Triggers:
// - When a member of gHneed was updated
// context: heating_mode-4
logInfo("ghneed.debug", "gHneed state is: {}", gHneed.state)
logInfo("ghneed.debug", "BF_Heat_need state is: {}", BF_Heat_Need.state)
logInfo("ghneed.debug", "BF_Heating_Pump state is: {}", BF_Heating_Pump.state)
logInfo("ghneed.debug", "GF_Heat_need state is: {}", GF_Heat_Need.state)
logInfo("ghneed.debug", "GF_Heating_Pump state is: {}", GF_Heating_Pump.state)
logInfo("ghneed.debug", "FF_Heat_need state is: {}", FF_Heat_Need.state)
logInfo("ghneed.debug", "FF_Heating_Pump state is: {}", FF_Heating_Pump.state)
BF_Heating_Pump.sendCommand(gHneed.state.toString)
GF_Heating_Pump.sendCommand(GF_Heat_Need.state.toString)
FF_Heating_Pump.sendCommand(FF_Heat_Need.state.toString)