I would like to share my rule to detect the status of my chimney
It is more a kind of experimental rule, that you have to customize to your envirement
Why? (Ideas)
refuel firewood
heating control
music/light/etc.
Issues
delay of a few minutes
Inaccurate ( < 5% incorrect detections - depends on the config and envirement)
Code (ChimneyDetection.rules)
rule "ChimneyDetection"
when
Time cron "11 */3 * ? * *" // At second :11, every 3 minutes starting at minute :00, of every hour
then
var int nTimeShort = 4
var int nTimeLong = 30
var int nThreshold = 6
var int nComfortTemperature = 23
var Number nAvgTempShort = GroundFloor_Living_Temperature.averageSince(now.minusMinutes(nTimeShort))
var Number nAvgTempLong = GroundFloor_Living_Temperature.averageSince(now.minusMinutes(nTimeLong))
if (nAvgTempShort != NULL && nAvgTempLong != NULL)
{
var Double dAvgTempShort = nAvgTempShort.doubleValue
var Double dAvgTempLong = nAvgTempLong.doubleValue
logInfo("Rule", "Da heizt wohl einer, ist der Kamin an? " + ((dAvgTempShort) / dAvgTempLong * 100).toString + "----" + (100 + nThreshold).toString)
if ((dAvgTempShort) / dAvgTempLong * 100 >= (100 + nThreshold))
{
logInfo("Rule", "Kamin wurde neu angemacht? " + ((dAvgTempShort) / dAvgTempLong * 100).toString + "----" + (100 + nThreshold).toString)
Chimney.sendCommand(ON)
}
else if ((dAvgTempShort) / dAvgTempLong * 100 >= (100 + (nThreshold/2)))
{
logInfo("Rule", "Frisches Holz ist im Kamin" + ((dAvgTempShort) / dAvgTempLong * 100).toString + "----" + (100 + nThreshold/2).toString)
Chimney.sendCommand(ON)
ChimneyHeating.sendCommand(ON)
}
else if ((dAvgTempShort) / dAvgTempLong * 100 <= (99))
{
logInfo("Rule", "Wohnzimmer kühlt weiter ab. " + ((dAvgTempShort) / dAvgTempLong * 100).toString + "---- 99")
if (dAvgTempLong <= nComfortTemperature)
{
// Wenn die Komfort Temperartur erreicht wurde, ist der Kamin vermutlich ganz aus. Eine bessere Idee habe ich gerade nicht
logInfo("Rule", "Die Raumtemperatur rutscht unter die Komforttemperatur")
Chimney.sendCommand(OFF)
}
ChimneyHeating.sendCommand(OFF)
}
else if ((dAvgTempShort) / dAvgTempLong * 100 <= (100 - nThreshold/2))
{
logInfo("Rule", "Da ist wohl ein Fenster offen" + ((dAvgTempShort) / dAvgTempLong * 100).toString + "----" + (100 - nThreshold/2).toString)
ChimneyHeating.sendCommand(OFF)
}
else
{
logInfo("Rule", "Kamin heizt dem Raum nicht mehr" + ((dAvgTempShort) / dAvgTempLong * 100).toString)
ChimneyHeating.sendCommand(OFF)
}
}
end
Also, on RPis and other single board computers they see significantly increased Rules loading and parsing times when primitives are used.This problem does not appear when using .intValue though.
Since the first four lines are defining constants, they should definitely be defined using val instead of var and they should probably be defined as globals instead of in the Rule.
nAvgTempShort and nAvgTempLong are Numbers, not Items. They will never be NULL so the if statement isn’t meaningful. What you want to test against is null, which indicates there was a problem with the call to averageSince.
There is no reason to convert the nAvg variables to Doubles. They are already stored as BigDecimals which is the default type for the result of calculations.
val nTimeShort = 4
val nTimeLong = 30
val nThreshold = 6
val nComfortTemperature = 23
rule "ChimneyDetection"
when
Time cron "11 */3 * ? * *" // At second :11, every 3 minutes starting at minute :00, of every hour
then
val nAvgTempShort = GroundFloor_Living_Temperature.averageSince(now.minusMinutes(nTimeShort.intValue))
val nAvgTempLong = GroundFloor_Living_Temperature.averageSince(now.minusMinutes(nTimeLong))
// 1. See if the rule need to run at all
if(nAvgTempShort === null || nAvgTempLong === null) {
logError("chimney", "One or both of the averages is null!")
return;
}
// 2. Calculate what to do.
logInfo("Rule", "Da heizt wohl einer, ist der Kamin an? " + ((nAvgTempShort) / nAvgTempLong * 100).toString + "----" + (100 + nThreshold).toString)
val ratio = nAvgTempShort / nAvgTempLong * 100
var chimneyNewState = Chimney.state
var chimneyHeatingState = ChimneyHeating.state
var sendNotification = false
switch(nAvgTempShort) {
case ratio >= 100 + nThreshold: {
chimneyNewState = ON
}
case ratio >= 100 + (nThreshold / 2): {
chimneyNewState = ON
chimneyHeatingNewState = ON
}
case ratio <= 99: {
chimneyNewState = if(nAvgTempLong <= nComfortTemperature) ON else Chimney.state
chimneyHeatingState = OFF
}
case ratio <= 100 - (nThreshold / 2): {
sendNotification = true
chimneyHeatingNewState = OFF
}
default: chimneyHeatingNewState = OFF
}
// 3. Do it
if(sendNotification) sendNotification("email@server.com","Da ist wohl ein Fenster im Wohnzimmer offen")
if(Chimney.state != chimneyNewState) Chimney.sendCommand(chimneyNewState)
if(ChimneyHeating.state != chimneyHeatingNewState) ChimneyHeating.sendCommand(chimneyHeatingNewState)
end
I don’t read German so I don’t know if the logging statements can be consolidated in section 3. If not, add them to the case statements.