NOTE: some of these suggestions are mutually exclusive.
-
You could benefit from the trinary operator.
-
Avoid the use of primitives unless absolutely necessary. Use of primitives is known to greatly extend the amount of time it takes .rules files to parse on an RPi. Just case Item states to Numbers and you can safely do all the necessary operations (comparisons, addition, etc) without problem.
val actualTemp = (if(Heating_Style.state == ON) HeatingHouseMin.state else HeatingHouseTemp.state) as Number
- This is more of a style thing, but I find the code easier to follow and shorter if you initialize your variables to a reasonable default to start and then your conditions are checking whether the default values need to be changed. Often you can eliminate 30% or more of if/else or switch cases by doing this. Using switch statements can also help with code clarity.
// Initialized to summer values
var targetTemp = 17
var lowerTemp = 15
...
// No longer require the summer else case
-
If you assign a value to a variable when you create it instead of null, you do not and should not supply the Type. as with the use of primitives, over specifying the Type is known to extend .rules file parsing by minutes.
-
Name your Heating_Temp Items the same as your modes and you can use Design Pattern: Associated Items to get the right Temp Item.
import org.eclipse.smarthome.model.script.ScriptServiceUtil
rule "Heating logic"
when
Item HeatingHouseTemp changed or
Item Heating_Temp_Manual changed or
Item Heating_Mode changed or
Item Heating_Plan changed
then
// 1. See if you need to run the Rule at all
// You should add some checks for UNDEF and NULL for all your Items used in this Rule here
// and return; if so. Exercise left to the student.
// 2. Calculate what needs to be done.
var actualTemp = (if(Heating_Style.state == ON) HeatingHouseMin.state else HeatingHouseTemp.state) as Number
var baseTemp = 0
var upper = 0
var lower = 0
if(Heating_Mode.state == ON){
baseTemp = Heating_Temp_Manual.state as Number
if(vTimeOfDay.state.toString == "BED") { upper = -1.5; lower = -3.5 }
else { upper = 0.3; lower = -0.5 }
}
// auto mode
else {
switch(Heating_Plan.state.toString){
case "WINTER": {
baseTemp = ScriptServiceUtil.getItemRegistry.getItem("Heating_Temp_"+Heating_AutoState.state.toString).state as Number
if(Heating_AutoState.state.toString == "Heating") { upper = 0.3; lower = -0.5 }
else { upper = 0.2; lower = -0.7 }
}
case "AWAY": { baseTemp = 15; upper = 0; lower = -1.5 }
default: { baseTemp = 17; upper = 0; lower = -2 }
}
}
val targetTemp = baseTemp + upper
val lowerTemp = baseTemp + lower
// 3. Do it
Heating_Visibility.sendCommand(Heating_Mode.state) // consider just using Heating_Mode to control visibility on your sitemap
// temp is higher, switch OFF
var newState = "STAY"
if(actualTemp > targetTemp) newState = "OFF"
else if(actualTemp <= lowerTemp) newState = "ON"
if(newState != "STAY && Heating.state.toString != newState)
Heating.sendCommand(newState)
logInfo("Heating", "Current temp is " + actualTemp + " and target temp is " + targetTemp + " so switching Heating to " + newState)
}
end