Rule reminder open Windows

I am a beginner with openhab and have a problem with my rule. Maybe there is somebody who can help me. I want to have a Reminder Rule that reminds me via Notification when my windows are still open for 10 minutes.

But i get the following Error Message in log:

ERROR] [.o.m.r.i.engine.ExecuteRuleJob] - Error during the execution of rule Reminder Window Livingroom
java.lang.IllegalStateException: Could not invoke method: org.openhab.core.persistence.extensions.PersistenceExtensions.changedSince(org.openhab.core.items.Item,org.joda.time.base.AbstractInstant,java.lang.String) on instance: null

my rules:

rule "Reminder Window Child"
when
Time cron "0 0/10 * * * ?"
then
Window_Child.state == OPEN && Window_Child.changedSince(now.minusMinutes(10))[|
sendBroadcastNotification(“The Window is still open”)
]
end

rule "Reminder Window Livingroom"
when
Time cron "0 0/10 * * * ?"
then
Window_Livingroom.state == OPEN && Window_Livingroom.changedSince(now.minusMinutes(10))[|
sendBroadcastNotification(“The Window is still open”)
]
end

my items:
Group:Contact:OR(OPEN, CLOSED) gContacts “Window_Contacts” (All)

Contact Window_Livingroom “Window [MAP(en.map):%s]” (Livingroom, gContacts) { maxcube=“MEQ0379020” }
Contact Window_Child “Window [MAP(en.map):%s]” (Child, gContacts) { maxcube=“MEQ0378172” }

Thanks for help.

Looks to me like two problems.

First, you should to put your THEN logic in an IF -block as below.

Second, “changedSince” requires that you have a persistence configuration setup (rrd4j or the like) with an rrd4j.persist configuration file which has a strategy encompassing the Window_Child item specifically, or by a group or *. (As have the matching add-on for that particular persistence.). Based on the error message, I suspect you have a missing or erroneous xxxx.persist configuration file.

rule "Reminder Window Child"
when
Time cron "0 0/10 * * * ?"
then
    if ( (Window_Child.state == OPEN) && (Window_Child.changedSince(now.minusMinutes(10) ) ) 
       {
         sendBroadcastNotification("The Window is still open")
       }
end

I would suggest using a timer for this sort of thing. Create a rule which is triggered whenever the window contact changes state. If the window opens, start a timer which fires after 10 mins and sends your notification.

At the start of the rule, regardless of whether the window state has changed to open or closed, cancel the timer.

So the logic is, anything the window changes state cancel any running timer. Then if the window has been opened restart the timer.

Therefore when the window opens the first time there will be no running timer, so nothing to cancel. Then the 10 min timer is started.

If the window is untouched after 10 mind for timer will fire and you will hey your notification.

If the window is closed before the timer fires, the timer will be cancelled.

I use this pattern for a load of rules and it works very well.

You mean something like that?

var Timer Window_Timer = null

rule "Reminder Window"
when
Item Window_Child changed to OPEN or
Item Window_Livingroom changed to OPEN
then
if( Window_Child.state == OPEN || Window_Livingroom.state == OPEN)
{
Window_Timer = createTimer(now.plusMinutes(10)) [|

                    sendBroadcastNotification("The Window is still open")
                    ]
            }

end

Yes. I also agree with @ben_jones12 that using a timer is more straightforward than persistence in this situation – I myself use timers for similar use cases.

Here an example of what I am using for my bathroom windows as my family tends to forget closing them.
It sets the max! thermostat down to 5 degrees and starts a timer when opening the window (knx binary input).
Timer gets canceled when the windows gets closed, in addition it sets back the thermostat to automatic mode.
If the windows stays open for a longer period it pushes a message to an MQTT-Broker which in the end causes a message to be pushed to the iPhone via “nodeRed” using “boxcar”. In addition it closes the shutter to prevent cooling down the room to much (There is an iron window grate, but for security reasons this might make sense as well).

Still room for improvement, but working so far, maybe something you can use.

rule "EG_Badfenster_vergessen"
when
    Item EG_BAD_WINDOW changed
then
    if (EG_BAD_WINDOW.state==CLOSED) {
        sendCommand (MAX_Thermostat_EG_BAD_Mode, "AUTOMATIC" )
        if (EG_BAD_WINDOW_Timer!=null) {
            EG_BAD_WINDOW_Timer.cancel
            EG_BAD_WINDOW_Timer=null
        }
    }
    else if (EG_BAD_WINDOW.state==OPEN) {
        sendCommand (MAX_Thermostat_EG_BAD_Mode, "MANUAL" )
        sendCommand (MAX_Thermostat_EG_BAD, 5.0 )

        if (EG_BAD_WINDOW_Timer==null) {
            EG_BAD_WINDOW_Timer=createTimer(now.plusMinutes(15)) [|
                logDebug("BAD EG" , "Warning fired")
                postUpdate( MQTT_WARNING, "Badfenster EG steht seit ueber 15 Minuten offen, bitte schliessen.")
                sendCommand (KNX_Shutter_EG_BAD, DOWN )
                 ]
        }
    }
end

Put three (3) back quote (```) characters in a row at the start/end of the code snippet, on a line completely to themselves. If there’s enough code between these block markers, then it’ll be scrollable… In addition to colorized.

sendCommand (MAX_Thermostat_EG_BAD_Mode, "MANUAL" )
sendCommand (MAX_Thermostat_EG_BAD, 5.0 )
1 Like

Hey,
bit old thread but fits into the scenario I’d like to implement:
Send a notification with a list of open windows when leaving the house.

I’ve created an automated group which also containing the ammount of open windows. In case that value is greater 0 I’d like to send the item.names via messanger.
This is what I’ve done so far:

//We should also send the open windows
val openWindows = agFenster_open.members.filter(s|s.state==OPEN).size
//logInfo("AlarmSystem", "Offene Fenster: " + openWindows)
if(openWindows > 0){
    
    agFenster_offen.members.filter(s|s.state==OPEN).forEach(
        msg = msg + ", s"
    )
    sendTelegram("gruppe", "Es sind " + openWindows + " Fenster geöffnet\n" + msg)

Any help on creating the proper forEach loop would be appriciated?
And secondly how to add up a list of the open windows as string to send that via messanger?
Thanks much for your help

I am interested in this as well, want to do the same for pushover.

@waitz_sebastian have you managed to build the forEach loop?

Hey,
My setup looks like this:

items:

 /* activegroup: Open Windows */
 Group:Contact:OR(OPEN, CLOSED) agFenster_open
     "offene Fenster [(%s)]"
     <contact>
     (gFenster)

Then you have to add each window contact to that group and run the following rule:

 import org.openhab.core.library.items.SwitchItem
 import java.util.StringBuilder
 val StringBuilder sb = new StringBuilder

     val offeneFenster = agFenster_open.members.filter(s|s.state==OPEN).size
     if(offeneFenster > 0){
         agFenster_open.members.filter( x | x.state == OPEN).forEach[ item |
             sb.append("Fenster: " + item.label.toString + "\n")
         ]
         val String msg = sb.toString
         sendTelegram("gruppe", "Es sind " + offeneFenster + " offene Fenster:\n" + msg)
     }

In some rare cases the windows double up in the message. But since this happens once a month, I havent looked deeper into it yet.

@waitz_sebastian tried this but the get errors on execution.

Initially this was the error:
2017-11-07 07:42:59.475 [ERROR] [.script.engine.ScriptExecutionThread] - Rule ‘away’: The name ‘sb’ cannot be resolved to an item or type.

Afterwards I added a variable: var String sb = null

but get following error now:

2017-11-07 07:49:29.401 [ERROR] [.script.engine.ScriptExecutionThread] - Rule ‘away’: The name ‘.append()’ cannot be resolved to an item or type.

any idea?

Yeah, sorry. My bad. You have to import the Stringbuilder library and create the item on top of your rule file.
I updated the post above.

Will try it tonight, thanks

It worked, I changed it a little bit so the Stringbuilder library is not needed.

Thanks a lot

if (gRaam.state == OPEN)
{
var String sb = ""
gRaam.members.filter( x | x.state == OPEN).forEach[ item |
sb += item.label.toString
sb += “\n”
]
pushover(“Ramen of deuren open : \n” + sb, “iphone_rohnny”)
}