A rule that tells me when the temperature has dropped below 0 degrees

  • Platform information:
    • Hardware: Laptop
    • OS: Ubuntu 19.10
    • Java Runtime Environment: idk
    • openHAB version: 2.4

Ive been reading up on this topic to get close to my goal.

The idea is that when the temperature drops below 0 degrees it will give me a push notification, telling me exactly that. And when it has told me once, i dont need a new notification that day.

The following is something i mashed together by reading up on the topic above. And it works, sort off. It tells me its cold, but it doesnt really care if its plus or minus degrees. And obviously the alerts get spammy as any change in temperature will give a push notification as it is now.

rule "Outside_Temp"
when 
Item Outside_Temp changed
then
if (Outside_Temp.state == NULL) return; // If no temp do nothing
// Calculate states
val temperature = Outside_Temp.state as Number
logInfo("Outside_Temp: ", temperature.toString)

if (temperature > 0) {
	sendNotification("email", "cold outside")
	logWarn("temp","cold?")
	}
end

Firstly, what you’re doing now is notifying if the temperature is above zero, not below.

What you could do is something like

if(Outside_Temp.state < 0 && previousState > 0)

This way you will only get a notification if the current reading is below zero and the previous one was above, this should make the spamming go down drastically. If you really just want to be notified once a day you should make a variable for remembering if you’ve been notified and then reset that variable every night.

3 Likes

You put that in to provide useful information - may we see that? (openhab.log)

Yes. What would you like to happen instead? Messages once per day? Every time it changes from above- to below-zero? etc.

For an example of Daniel’s suggestion, see Design Pattern: Rule Latching.

1 Like

I guess every time it changes from 0 to below zero would be ideal, and somehow prevent spamming if its just hovering around the mark. Tried this, but it does nothing. No log entry at all.

rule "Outside_Temp"
when 
Item Outside_Temp changed
then
if(Outside_Temp.state < 0 && previousState > 0) 
{
sendNotification("email", "Minusgrader ute!")
logInfo("Temperature: ", "Minusgrader ute!")
}
 end

It does nothing because you wanted it do something only when the temperature is below AND above zero, in can only be either OR!

i am manually posted via mqtt to say that the temperature is above 0. So when the real temp is read in, i thought it would catch that and give me the notification?

Ups, I’m sorry but I misread the if statement (missed the “previousState”) :slight_smile: It is too early for me I guess.

Try to put a logInfo before the if statement in order to see if the rule gets triggered at all.

In a real situation before going under zero it’s likely that the temperature IS zero, so you have to also catch the previous state to be equal or greater than zero.

There are a few challenges/potential pitfalls to deal with in this seemingly simple scenario… :sunglasses:

  1. Depending on the accuracy and frequency of reported temperature by the sensor, there can be a flip-flop scenrio where the temperature goes to just below and just above zero multiple times in a short period.
  2. If I’m not mistaken, previousState gives the last persisted state and not necessary the last changed state. So, if you persist every minute and a minute ago the temperature was the same, the .previousState will return the same value as the current state.

Without having tested it, this rule might work for you:

val alerted = 0     // Holds the alertes state (0=no, 1=yes)

val hysteresis = 0.2
val setPoint = 0

rule "Freezing alert"
when
    Item Temperature changed
then
    // Temperature below or above threshold?
    val tChanged = 0
    if (Temperature.state as Number < (setPoint - hystereris))
        tChanged = -1
    if (Temperature.state as Number > (setPoint + hysteresis))
        tChanged = 1

    // Temperature dropped below setpoint, should we alert?
    if (tChanged < 0 && alerted == 0) {
        // Send an alert....
        alerted = 1
    }
    else if (tChanged > 0)
        alerted = 0
    else
        logInfo("TempAlert", "Temperature {} is within hysteresis {} of setpoint {}.", Temperature.state, hysteresis, setPoint)
    // If temperature within hysteresis, do nothing.
end

When you use Item xxx changed as a trigger, previousState is an implicit variable holding the Item’s state before the change, even if no persistence is configured. So it should be perfectly fine to use in this scenario.

1 Like

Rather than show us the logInfo output from your original rule that would show your temperature Item’s actual state, you’ve now taken that logInfo line out of your rule.

It’s not casual nosiness - I think you might be struggling with UoM.

Testing yours, and it returns me this: Configuration model ‘notifications.rules’ has errors, therefore ignoring it: [57,50]: mismatched input ‘-’ expecting ‘)’
[57,63]: no viable alternative at input ‘)’

Edit; rossko, the previous rule didnt output anything in the log. Except for the temperature itself. Nothing else.

Rules interpreter can be bit funny about hyphen - depending on situation.
Sometimes you have to force a negative number like
fred = 0 - 1

Which is exactly the secret message I’m looking for. Does it say 22.5 or 22.5 °C ?

I am concerned that your Item may be either a Number type or a Number:Temperature type - which require different handling in rules - and we have seen no clues - not one state or Item definition - either way.

2019-11-05 19:49:52.533 [INFO ] [marthome.model.script.Outside_Temp: ] - 6.0 °C
2019-11-05 19:49:52.535 [WARN ] [.eclipse.smarthome.model.script.temp] - cold?

Thats the output, sorry i didnt realize it mattered.

Okay, I don’t know how you formatted the logInfo() to produce that now - but I will guess that it wasn’t you that added °C
The implication would be that your Item has units of measurement, UoM, and is not just a number.

You could also actually check the type of the Item involved that you defined, as already pointed out.

Wow, that did the trick indeed! It works! But ideally, i should be using @noppes123 solution with this fix. As now it is spamming me everytime the temperature is received from mqtt, wich is quite often.
Also, can i include the exact temperature in the push notification sendt?

Anyone that can help me with that?

Yes you can…
Why don’t you have a go and let us know if it’s not working
You will learn nothing by copying and pasting our code
You will learn tons by trying to write your own

2 Likes

I figured it out :smiley:

Ended up with the following, probably better solutions to this, but it works.

rule "Freezing alert"
when 
Item Outside_Temp changed
then
if(Outside_Temp.state < 0 | "°C" && previousState > 0 | "°C" ) 
{
sendNotification("email", "Det er nå minus: " + Outside_Temp.state.format("%.2f") + " °C")
logInfo("[INFO]: Temperature outside","Below zero")
}
end