Bescheid!

Im Bad gibt es ein Fenster zum Lueften und das ist auch gut so, auf die Gruende moechte ich hier nicht weiter eingehen. Natuerlich soll die Heizung beim Lueften ausgestellt sein. Bei homematic kann man dazu entweder den Fensterkontakt direkt mit dem Heizungsthermostat koppeln, oder die Steuerung jemand anders ueberlassen, in meinem Fall dem openhab. Das kann dann so aussehen:

var Number targetTemp = 19
rule "heizung bad unten aus wenn fenster offen"
when
  Item Fenster_BadUnten changed from CLOSED to OPEN
then
  targetTemp = Soll_Temperatur_BadUnten.state
  sendCommand(Soll_Temperatur_BadUnten, 1.0)
end
rule "heizung bad unten an wenn fenster wieder zu"
when
  Item Fenster_BadUnten changed from OPEN to CLOSED
then
  sendCommand(Soll_Temperatur_BadUnten, targetTemp)
end

Das ist schonmal ganz gut, nur leider vergesse ich das Fenster ab und zu mal und so friert sich der naechste dann beim aktuellen Wetter (gestern Nacht -13 Grad) im wahrsten Sinne des Wortes den Allerwertesten ab. Openhab kann ja auch Mails schicken, dass passt ganz gut, fuege ich einfach ein

   sendMail("...", "Bad unten Fenster auf", "Bad unten Fenster auf")

hinter das Heizung-Ausschalten.

Leider kommt die Mail ja, wenn ich das Fenster aufmache; nach 5 Minuten, wenn ich es schliessen muesste, habe ich es laengst wieder vergessen. Das Senden der Mail muss also verzoegert werden. Dafuer gibt es Timer in openhab. Die sehen leider etwas komplizierter aus: generell funktioniert ein Timer ja praktisch immer so, dass ich eine Funktion aufrufe welche als Parameter ein Delay bekommt und einen Callback, welcher nach dem Delay aufgerufen wird. Die Rule-Syntax in openhab kennt leider keine Funktionen, aber lambdas. Fuer den Programmierer macht das keinen Unterschied, nur fuer die Lesbarkeit:

  timer = createTimer(now.plusMinutes(5), [|
      if (Fenster_BadUnten.state == OPEN) 
        sendMail("...", "Bad unten Fenster auf", "Bad unten Fenster seit 5min auf")
      timer = null
    ])
end

Zum Glueck komme ich ja aus der Welt von C++, da gibt es ja weitaus Schlimmeres.

Nun bekommen wir also unsere Mail 5 Minuten nachdem das Fenster geoeffnet wurde. Wenn es dann noch auf ist. Der Ordnung halber loeschen wir den Timer ordentlich (also genau genommen loeschen wir hier nichts, das ueberlassen wir dem GarbageCollector), wenn wir ihn nicht mehr brauchen, das Fenster also wieder zu ist:

    timer = null

Zuletzt brauchen wir noch etwas Feintuning: im schoensten Hamburger Sommer stoert ein offenes Fenster nicht wirklich. Dafuer habe ich einen Temperatursensor auf dem Balkon, mit dem verfeinern wir das lambda:

  timer = createTimer(now.plusMinutes(5), [|
      if (Fenster_BadUnten.state == OPEN && Temperature_Balkon.state < 15) 
        sendMail("...", "Bad unten Fenster auf", "Bad unten Fenster seit 5min auf")
      timer = null
    ])

Zuletzt nochmal alles am Stueck:

var Number targetTemp = 19
var Timer timer = null

rule "heizung bad unten aus wenn fenster offen"
when
  Item Fenster_BadUnten changed from CLOSED to OPEN
then
  targetTemp = Soll_Temperatur_BadUnten.state
  sendCommand(Soll_Temperatur_BadUnten, 1.0)

  // inform me if open too long
  timer = createTimer(now.plusMinutes(5), [|
      if (Fenster_BadUnten.state == OPEN && Temperature_Balkon.state < 15) 
        sendMail("...", "Bad unten Fenster auf", "Bad unten Fenster seit 5min auf")
      timer = null
    ])
end


rule "heizung bad unten an wenn fenster wieder zu"
when
  Item Fenster_BadUnten changed from OPEN to CLOSED
then
  sendCommand(Soll_Temperatur_BadUnten, targetTemp)
  timer = null
end