- Platform information:
- Hardware: x64 VM
- OS: Debian 10
- Java Runtime Environment: JDK11
- openHAB version: 3.0
- Issue of the topic:
I have noticed that When I am working in rules it can cause existing running rules to stop triggering.
You can try and manually run the rule or even restart OH but it will stay dead.
Until you alter the rule and save it again. Even just adding a empty line and saving it will make the rule work again with no issues.
The log doesn’t show any output and OH otherwise appears to work just fine, it only forgets about rules it seems.
Now this is an issue you can work around by going around your rules altering them all slightly and then saving again. But that is still inconvenient, and obviously if you forget a rule that rule will no longer be triggered.
Below a couple of examples of the kind of rules that get affected by this.
// Imports
import java.util.concurrent.locks.ReentrantLock
// Global Variables
var ReentrantLock genericThermostatLock = new ReentrantLock()
rule "Central Heater"
when
Item Radiators changed
then
if (Gas_Heater.state.toString != Radiators.state.toString) {
if ( Gas_Heater.changedSince(now.minusMinutes(1))) {
createTimer(now.plusSeconds(30), [| Gas_Heater.sendCommand(Radiators.state.toString) ] )
} else {
Gas_Heater.sendCommand(Radiators.state.toString)
}
Heating.sendCommand(Radiators.state.toString)
}
end
rule "Generic Thermostat"
when
Item Thermostats changed or
Item Thermometers changed
then
if (genericThermostatLock.tryLock()) {
Thermostats.members.forEach[thermostat|
// in order for this generic rule to work the naming of thermometer, Radiator, fan, and thermostat items needs to follow the convention
// <RoomName>_<temp, valve, fan, target>
val thermostatNameStart = thermostat.name.split("_").get(0)
val temperatureName = thermostatNameStart + "_temp"
val targetName = thermostatNameStart + "_target"
val valveName = thermostatNameStart + "_valve"
val stateName = thermostatNameStart + "_state"
val current_temperature = Thermometers.members.filter[ tt| tt.name == temperatureName ].head as NumberItem
val target_temperature = Thermostats.members.filter[ th|th.name == targetName ].head as NumberItem
val hvac_state = Thermostats.members.filter[ th|th.name == stateName ].head as StringItem
val radiatorvalve = Radiators.members.filter[ h|h.name == valveName ].head as SwitchItem
if ((current_temperature.state as Number) < (target_temperature.state as Number) - 0.35 ) {
if (radiatorvalve.state.toString == "OFF") {
radiatorvalve.sendCommand("ON")
hvac_state.sendCommand("Heating")
return;
}
}
if ((current_temperature.state as Number) > (target_temperature.state as Number) + 0.35 ) {
if ( radiatorvalve.state.toString == "ON" ) {
radiatorvalve.sendCommand("OFF")
hvac_state.sendCommand("Idle")
return;
}
}
val fanName = thermostatNameStart + "_fan"
val roomventilation = RoomVentilators.members.filter[ h|h.name == fanName ].head as SwitchItem
val fan_target_temperature = if ( (target_temperature.state as Number) < (FanThermostat.state as Number)) {
FanThermostat
} else {
target_temperature
}
if ( (current_temperature.state as Number) > (fan_target_temperature.state as Number) + 3.35 ) {
if (roomventilation.state.toString == "OFF") {
roomventilation.sendCommand("ON")
hvac_state.sendCommand("Cooling")
return;
}
}
if ( (current_temperature.state as Number) < (fan_target_temperature.state as Number) + 2.65 ) {
if ( roomventilation.state.toString == "ON" ) {
roomventilation.sendCommand("OFF")
hvac_state.sendCommand("Idle")
return;
}
}
]
}
end
rule "Thermostat Checker and Setter"
when
Time cron "0 */2 * ? * *"
then
Thermostats.members.forEach[thermostat|
if (thermostat.state == NULL || (thermostat.state as Number) < 10) {
thermostat.sendCommand(10)
} else {
if ((thermostat.state as Number) > 21) {
thermostat.sendCommand(21)
}
}
]
if (FanThermostat.state == NULL || (FanThermostat.state as Number) < 18) {
FanThermostat.sendCommand(18)
} else {
if ((FanThermostat.state as Number) > 32) {
FanThermostat.sendCommand(32)
}
}
end
// Imports
import java.util.concurrent.locks.ReentrantLock
// Global Variables
var ReentrantLock genericZoneLock = new ReentrantLock()
var motionsensorstate = "IDLE"
rule "Generic Zone"
when
Item MotionSensor_1_TestZone received update
then
if (genericZoneLock.tryLock()) {
SecurityZones.members.forEach[zone|
motionsensorstate = "IDLE"
(zone as GroupItem).members.filter[ m| m.name.startsWith("MotionSensor")].forEach[motionsensor|
if (motionsensor.state.toString != "OPEN" ) {
motionsensorstate = "ACTIVE"
}
]
val zonestate = (zone as GroupItem).members.filter[ m| m.name.startsWith("State")].head as StringItem
val armed = (zone as GroupItem).members.filter[ m| m.name.startsWith("Armed")].head as SwitchItem
val maintennance = (zone as GroupItem).members.filter[ m| m.name.startsWith("Maintennance")].head as SwitchItem
if (motionsensorstate == "ACTIVE" && armed.state.toString != "OFF" && maintennance.state.toString != "ON") {
zonestate.sendCommand("ALARM")
}
if (motionsensorstate == "ACTIVE" && (armed.state.toString == "OFF" || maintennance.state.toString == "ON")) {
zonestate.sendCommand("OCUPIED")
}
if (motionsensorstate == "IDLE") {
zonestate.sendCommand("IDLE")
}
]
}
end