I noticed I was copying rules to perform the same logic but on different items.
So I went looking for methods/functions to use rather then having duplicate code.
This wiki article gave me a good start. https://github.com/openhab/openhab1-addons/wiki/Reusable-Rules-via-Functions
However I can’t quite seem to get the details right. The lambda appears to have trouble referring back to a Boolean causing and error at run-time.
2018-05-14 01:24:39.375 [INFO ] [el.core.internal.ModelRepositoryImpl] - Validation issues found in configuration model 'thermostats.rules', using it anyway:
Function4 is a raw type. References to generic type Function4<P1, P2, P3, P4, Result> should be parameterized
Assignment to final parameter
Assignment to final parameter
Assignment to final parameter
Assignment to final parameter
2018-05-14 01:24:40.560 [INFO ] [el.core.internal.ModelRepositoryImpl] - Refreshing model 'thermostats.rules'
2018-05-14 01:25:48.830 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'test thermostat2': Couldn't invoke 'assignValueTo' for feature param frozen
2018-05-14 01:25:49.835 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'test thermostat2': Couldn't invoke 'assignValueTo' for feature param frozen
2018-05-14 01:25:50.836 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'test thermostat2': Couldn't invoke 'assignValueTo' for feature param frozen
2018-05-14 01:25:51.850 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'test thermostat2': Couldn't invoke 'assignValueTo' for feature param frozen
2018-05-14 01:25:52.843 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'test thermostat2': Couldn't invoke 'assignValueTo' for feature param frozen
In addition to this I updated my Visual Studio Code to 1.23.1 since it said there was a new version.
But now it is giving me loads of errors on files where it previously saw no errors and which have been working just fine.
Any one ran into that as well?
Here is the .rules in question.
The Boolean’s are to prevent rapid switching on and off which would be detrimental to the heating system. This rule consists of two main parts one is the room thermostat which measures the temperature and opens the radiator valve. The second part is the switch that turns on the central heating.
The “function” is executed, but when it comes to setting the Boolean it fails as it is interpreted as a final parameter.
The same code (which is there but commented out. works just fine as it is referencing the objects directly.
// Imports
// Global Variables
var Boolean HVAC_CM_Target_Temp_frozen = false
var Boolean HVAC_MB_Target_Temp_frozen = false
var Boolean central_heater_frozen = false
val org.eclipse.xtext.xbase.lib.Functions$Function4 themostatlogic = [
Boolean frozen,
NumberItem current_temperature,
NumberItem target_temperature,
SwitchItem heater |
if (!frozen) {
if ((current_temperature.state as DecimalType) < (target_temperature.state as DecimalType)) {
if (heater.state.toString == "OFF") {
frozen = true
heater.sendCommand("ON")
CENTRAL_GAS_HEATING.sendCommand("ON")
createTimer(now.plusMinutes(1), [| frozen = false ] )
}
} else {
if (heater.state.toString == "ON") {
frozen = true
heater.sendCommand("OFF")
CENTRAL_GAS_HEATING.sendCommand("OFF")
createTimer(now.plusMinutes(1), [| frozen = false ] )
}
}
} else {
createTimer(now.plusSeconds(30), [| target_temperature.postUpdate((target_temperature.state as DecimalType)) ] )
}
]
rule "central heater"
when
Item CENTRAL_GAS_HEATING received update
then
if (!central_heater_frozen) {
if (CENTRAL_GAS_HEATING.state.toString == "ON") {
if (DO4.state.toString == "OFF") {
central_heater_frozen = true
createTimer(now.plusSeconds(30), [| DO4.sendCommand("ON") ] )
createTimer(now.plusMinutes(2), [| central_heater_frozen = false ] )
}
} else {
if ((DO4.state.toString == "ON") && (Heaters.state.toString == "OFF")) {
central_heater_frozen = true
DO4.sendCommand("OFF")
createTimer(now.plusMinutes(2), [| central_heater_frozen = false ] )
}
}
} else {
if (CENTRAL_GAS_HEATING.state.toString == "ON") {
createTimer(now.plusSeconds(30), [| CENTRAL_GAS_HEATING.sendCommand("OFF") ] )
} else {
createTimer(now.plusSeconds(30), [| CENTRAL_GAS_HEATING.sendCommand("ON") ] )
}
}
end
rule "test thermostat"
when
Item HVAC_CM_Temp received update or
Item HVAC_CM_Target_Temp received update
then
if (!HVAC_CM_Target_Temp_frozen) {
if ((HVAC_CM_Temp.state as DecimalType) < (HVAC_CM_Target_Temp.state as DecimalType)) {
if (DO2.state.toString == "OFF") {
HVAC_CM_Target_Temp_frozen = true
DO2.sendCommand("ON")
CENTRAL_GAS_HEATING.sendCommand("ON")
createTimer(now.plusMinutes(1), [| HVAC_CM_Target_Temp_frozen = false ] )
}
} else {
if (DO2.state.toString == "ON") {
HVAC_CM_Target_Temp_frozen = true
DO2.sendCommand("OFF")
CENTRAL_GAS_HEATING.sendCommand("OFF")
createTimer(now.plusMinutes(1), [| HVAC_CM_Target_Temp_frozen = false ] )
}
}
} else {
createTimer(now.plusSeconds(30), [| HVAC_CM_Target_Temp.postUpdate((HVAC_CM_Target_Temp.state as DecimalType)) ] )
}
end
rule "test thermostat2"
when
Item HVAC_MB_Temp received update or
Item HVAC_MB_Target_Temp received update
then
themostatlogic.apply(HVAC_MB_Target_Temp_frozen, HVAC_MB_Temp, HVAC_MB_Target_Temp, DO5)
// The bit I would like to not repeat for every single room
// if (!HVAC_MB_Target_Temp_frozen) {
// if ((HVAC_MB_Temp .state as DecimalType) < (HVAC_MB_Target_Temp.state as DecimalType)) {
// if (DO5.state.toString == "OFF") {
// HVAC_MB_Target_Temp_frozen = true
// DO5.sendCommand("ON")
// CENTRAL_GAS_HEATING.sendCommand("ON")
// createTimer(now.plusMinutes(1), [| HVAC_MB_Target_Temp_frozen = false ] )
// }
// } else {
// if (DO5.state.toString == "ON") {
// HVAC_MB_Target_Temp_frozen = true
// DO5.sendCommand("OFF")
// CENTRAL_GAS_HEATING.sendCommand("OFF")
// createTimer(now.plusMinutes(1), [| HVAC_MB_Target_Temp_frozen = false ] )
// }
// }
// } else {
// createTimer(now.plusSeconds(30), [| HVAC_MB_Target_Temp.postUpdate((HVAC_MB_Target_Temp.state as DecimalType)) ] )
// }
end