Elektrischen Rolladen abhängig von Sonnenstand und Wetter steuern lassen mit openHAB2

Im Sommer nervt es besonders, wenn wir vergessen, die Rolläden der Kinderzimmer herunterzulassen. Dann heizen diese Zimmer sich sehr schnell auf und abends vor dem Schlafengehen ist es dann nur bedingt möglich, die wieder kühl zu lüften. Grund genug, darüber nachzudenken, was das Smarthome hier für uns leisten kann…

Und da ich mir kürzlich von Rademacher Rohrmotoren gegönnt und eingebaut habe und zur Steuerung den Homematic Unterputzaktor zur Jalosiensteuerung gekauft habe möchte ich das natürlich gleich ausprobierne und da wäre es doch schön, wenn das Haus die Zimmer automatisch beschattet, solange die Sonne auf bzw. in die Zimmer scheinen würde. Dies ist bei uns grundsätzlich grob ab Mittag der Fall, wenn die Sonne seitlich „um die Ecke kommt“ bis zum Abend, wenn die Sonne hinter den Nachbarhäusern verschwindet, der Fall. Also soll eine Schaltung abhängig von Sonnenwinkel und Sonnenhöhe erfolgen. Natürlich soll das aber erst ab einer bestimmten Außentemperatur greifen, denn im Winter sind wir dann doch eher froh über das Licht und wenn Regen oder auch nur Wolken am Himmel stehen, ist eine Beschattung auch nicht notwendig. Ist der Rolladen bereits weiter geschlossen, als er geschlossen werden soll, soll nichts passieren. Ebenso soll nichts passieren, der Rolladen beim Versuch ihn hochzufahren einen inzwischen veränderten Zustand hat.

Das Ganze soll natürlich auch für andere verwendbar und entsprechend konfigurierbar sein. Voraussetzung ist, dass das Szenario das gleiche ist, ansonsten muss man eben ein paar Bedingungen anpassen.

Für openHAB gibt es ja einerseits ein Wetter- und andrerseits ein Astro-Binding. Diese Daten können hier gut genutzt werden.

Wie es sich mit Sonnenrichtung und Sonnenhöhe so verhält, das kann man ganz gut auf folgender Website simulieren: https://www.sonnenverlauf.de

Was in openHAB2 zu tun ist

Ist das getan können die notwendigen Dateien angelegt werden.

.items-Datei

Group gruppeWetter "Wetter-Daten" <sun> (debug) 
Group gruppeAstro "Astronomische Daten" <sun_clouds>(debug)
Group gruppeRollo

// Wetter
Number wetter_temperatur "Temperatur [%.2f °C]" <temperature> (gruppeWetter) {weather="locationId=home, type=temperature, property=current"}
Number wetter_temperatur_gefuehlt "Temperatur gefühlt [%.2f °C]" <temperature> (gruppeWetter) {weather="locationId=home, type=temperature, property=feel"}
String wetter_temperatur_minmax "Temp. Min/Max [%s °C]" <temperature> (gruppeWetter) {weather="locationId=home, forecast=0, type=temperature, property=minMax"}
Number wetter_temperatur_min "Temperatur min [%.2f °C]" <temperature> (gruppeWetter) {weather="locationId=home, type=temperature, property=min"}
Number wetter_temperatur_max "Temperature max [%.2f °C]" <temperature> (gruppeWetter) {weather="locationId=home, type=temperature, property=max"}
Number wetter_windgeschwindigkeit "Windgeschwindigkeit [%.2f km/h]" <wind> (gruppeWetter) {weather="locationId=home, type=wind, property=speed"}
Number wetter_feuchtigkeit "Luftfeuchtigkeit [%d %%]" <humidity> (gruppeWetter) {weather="locationId=home, type=atmosphere, property=humidity"}
Number wetter_luftdruck "Luftdruck [%.2f mb]" <pressure> (gruppeWetter) {weather="locationId=home, type=atmosphere, property=pressure"}
Number wetter_bewoelkung "Bewölkung [%.0f %%]" <sun_clouds> (gruppeWetter) {weather="locationId=home, type=clouds, property=percent"}
Number wetter_regen "Regen [%.2f mm/h]" <rain> (gruppeWetter) {weather="locationId=home, type=precipitation, property=rain"}
Number wetter_schnee "Schnee [%.2f mm/h]" <snow> (gruppeWetter) {weather="locationId=home, type=precipitation, property=snow"}

// Astro-Werte
DateTime astro_Sonnenaufgang "Sonnenaufgang" <sun> (gruppeAstro) {channel="astro:sun:local:rise#start"}
DateTime astro_Sonnenuntergang "Sonnenuntergang" <moon> (gruppeAstro) {channel="astro:sun:local:set#start"}
Number astro_elevation "Sonnenwinkel" <niveau> (gruppeAstro) {channel="astro:sun:local:position#elevation"}
Number astro_azimuth "Azimuth" <niveau> (gruppeAstro) {channel="astro:sun:local:position#azimuth"}

// Konfiguration Rollo-Automatik
Switch rolloautomatik "Rollo-Automatik an/aus"
Number rolloautomatik_zielwert "Schließen auf [%d Prozent]"
Number rolloautomatik_temp_min "Temperatur größer [%d °C]"
Number rolloautomatik_wolken_max "Bewölkung weniger als [%d Prozent]"
Number rolloautomatik_azimuth_start "Sonnenrichtung größer gleich [%d °]"
Number rolloautomatik_elevation_ende "Sonnenhöhe kleiner gleich [%d] °"
DateTime rolloautomatik_start_last "Letzte Ausführung (Rollo ab)"
DateTime rolloautomatik_ende_last "Letzte Ausführung (Rollo hoch)"

.sitemap-Datei

Das Folgende ist nur der relevante Auszug der Sitemap

Text label="Konfiguration Rollo-Automatik" icon="rollershutter" {
 Frame label="Aktivieren der Automatik" {
 Switch item=rolloautomatik
 Setpoint item=rolloautomatik_zielwert minValue=0 maxValue=100 step=1
 }
 Frame label="Rollo ab, wenn..." {
 Setpoint item=rolloautomatik_temp_min minValue=0 maxValue=35 step=1
 Setpoint item=rolloautomatik_wolken_max minValue=0 maxValue=100 step=1
 Setpoint item=rolloautomatik_azimuth_start minValue=0 maxValue=360 step=1
 }
 Frame label="Rollo hoch, wenn..." {
 Setpoint item=rolloautomatik_elevation_ende minValue=-20 maxValue=50 step=1
 } 
}

.rules-Datei

Die Regel fragt ab, ob die Automatik generell an, eventuell bereits gelaufen ist, ob Temperatur, Bewölkung und aktueller Status der Rolläden passen und wenn dies so ist werden sie hinuntergefahren.

Wichtig ist: Alle Rolläden müssen der Gruppe gruppeRollo zugeordnet werden.

Ist zum errechneten Zeitpunkt des wieder-hinauf-fahrens ein Rolladen in einem anderen Status, als er hätte sein müssen, als er heruntergefahren wurde, wird er nicht automatisch wieder hochgefahren.

var boolean log = true
rule "Rollos abfahren"
when Item astro_azimuth changed
then
    val String logPrefix = 'Rolloautomatik (Rollo ab) - '
    if (log) logInfo('rules', logPrefix + 'Regel wurde gestartet')
    
    var String timeLast = 'xxxx-xx-xx'
    if (rolloautomatik_start_last.state == NULL) {
        if (log) logInfo('rules', logPrefix + 'Erstmalige Ausführung am System, Belegung mit Initialwert')
    } else {
        timeLast = rolloautomatik_start_last.state.toString().substring(0,10)
    }
	var String timeNow = now.toString().substring(0,10)

    if (rolloautomatik.state == ON) {
        if (timeNow != timeLast) {
            if (astro_azimuth.state > Integer::parseInt(rolloautomatik_azimuth_start.state.toString())) {
                if (wetter_temperatur.state > Integer::parseInt(rolloautomatik_temp_min.state.toString())) {
                    if (wetter_bewoelkung.state  <= Integer::parseInt(rolloautomatik_wolken_max.state.toString())) { if (astro_elevation.state > Integer::parseInt(rolloautomatik_elevation_ende.state.toString())) {
                            // Rollos runterfahren
                            if (log) logInfo('rules', logPrefix + 'Rollos werden abgefahren')
                            gruppeRollo.members.forEach[i|
                                if (i.state <= Integer::parseInt(rolloautomatik_zielwert.state.toString())) {
                                    if (log) logInfo('rules', logPrefix + 'Fahre Rolladen auf ' + rolloautomatik_zielwert.state.toString() + '%: ' + i.name)
                                    i.sendCommand(Integer::parseInt(rolloautomatik_zielwert.state.toString()))
                                } else {
                                    if (log) logInfo('rules', logPrefix + 'Rolladen ist bereits weiter geschlossen (' + i.state.toString() + '%) als er geschlossen werden sollte und wird daher ignoriert')
                                }
                            ]
                            // Letzte Ausführung mit entsprechendem Zeitstempel belegen
                            rolloautomatik_start_last.postUpdate(now.toString())
                        } else {
                            if (log) logInfo('rules', logPrefix + 'Elevation für wieder abfahren (' + rolloautomatik_elevation_ende.state.toString() + ') ist groesser als aktuelle (' + astro_elevation.state.toString() + ')')
                        }
                    } else {
                        if (log) logInfo('rules', logPrefix + 'Mindestbewoelkung (' + rolloautomatik_wolken_max.state.toString() + ') wurde unterschritten (' + wetter_bewoelkung.state.toString() + ')')
                    }
                } else {
                    if (log) logInfo('rules', logPrefix + 'Mindest-Temperatur (' + rolloautomatik_temp_min.state.toString() + ') wurde nicht erreicht durch aktuelle Temperatur (' + wetter_temperatur.state.toString() + ')')
                }
            } else {
                if (log) logInfo('rules', logPrefix + 'Azimuth (' + astro_azimuth.state.toString() + ') hat noch nicht Schwellwert (rolloautomatik_azimuth_start.state.toString()) erreicht')
            }
        } else {
            if (log) logInfo('rules', logPrefix + 'Automatik heute bereits einmal gelaufen, wird daher ignoriert')
        }
    } else {
         if (log) logInfo('rules', logPrefix + 'Beende, da Automatik generell nicht aktiv')
    }
end

rule "Rollo wieder öffnen"
when Item astro_elevation changed
then
    val String logPrefix = 'Rolloautomatik (Rollo hoch) - '
    if (log) logInfo('rules', logPrefix + 'Regel wurde gestartet')

    var String timeLastEnde = 'xxxx-xx-xx'
    if (rolloautomatik_ende_last.state == NULL) {
        if (log) logInfo('rules', logPrefix + 'Erstmalige Ausführung am System, Belegung mit Initialwert')
    } else {
        timeLastEnde = rolloautomatik_ende_last.state.toString().substring(0,10)
    }

    var String timeLastStart = 'yyyy-yy-yy'
    if (rolloautomatik_start_last.state == NULL) {
        if (log) logInfo('rules', logPrefix + 'Erstmalige Ausführung am System, Belegung mit Initialwert')
    } else {
        timeLastStart = rolloautomatik_start_last.state.toString().substring(0,10)
    }

	var String timeNow = now.toString().substring(0,10)


    if (rolloautomatik.state == ON) {
        if (astro_elevation.state <= Integer::parseInt(rolloautomatik_elevation_ende.state.toString())) {
            if (timeLastStart == timeNow) {
                if (timeLastEnde != timeNow) {
                    // Rollos wieder hoch
                    if (log) logInfo('rules', logPrefix + 'Rollos werden hinaufgefahren')
                    gruppeRollo.members.forEach[i|
                        if (rolloautomatik_zielwert.state == Integer::parseInt(i.state.toString())) {
                            if (log) logInfo('rules', logPrefix + 'Fahre Rolladen auf 0%: ' + i.name)
                            i.sendCommand(0)
                        } else {
                            if (log) logInfo('rules', logPrefix + 'Fahre Rolladen nicht auf 0%, da dieser zwischenzeitlich manuell verändert wurde: ' + i.name)
                        }
                    ]
                    // Letzte Ausführung mit entsprechendem Zeitstempel belegen
                    rolloautomatik_ende_last.postUpdate(now.toString())
                } else {
                    if (log) logInfo('rules', logPrefix + 'Beende, da heute bereits ein automatisches Wiederhochfahren stattfand')
                }
            } else {
                if (log) logInfo('rules', logPrefix + 'Beende, da heute noch keine Ausführung stattfand. Demzufolge kann auch kein automatisches Öffnen gewollt sein')
            }
        } else {
            if (log) logInfo('rules', logPrefix + 'Beende, da Elevation (' + astro_elevation.state.toString() + ') nicht  kleiner der eingestellten Elevation (' + rolloautomatik_elevation_ende.state.toString()+ ') war')
        }
    } else {
        if (log) logInfo('rules', logPrefix + 'Beende, da Automatik generell nicht aktiv')
    }
end

Ergebnis an der Oberfläche:

24 Antworten auf „Elektrischen Rolladen abhängig von Sonnenstand und Wetter steuern lassen mit openHAB2“

  1. Hallo Florian
    danke für diese klasse Umsetzung. Wäre es möglich die Rolladen abhängig vom Sonnenwinkel auch wieder hoochzufahren? Hintergrund ist dass beim Haus der Rollladen an der Ostseite ja nur morgens unten sein soll, der im Westen müsste aber erst Nachmittag zufahren. Der im Süden erst etwas nach dem Rollladen im Osten.
    Gruss Manuel

    1. Hallo Manuel,

      Im Prinzip ist das einfach möglich, es müssen nur die Regeln im Rule entsprechend angepasst bzw. erweitert werden. So kann man alle Rollläden auch separat je einzeln per Winkel und Richtung zur Sonne konfigurieren. Mir selbst fehlt leider der Anwendungsfall, daher bitte ich um Verständnis, dass ich nicht individuelle Programmierung einfach so anbieten kann, das geht nur, wenn ich es selbst für mich auch nutzen will. Wenn du Hilfe als Dienstleistung haben willst kannst du dich gerne bei mir melden, dann können wir das Weitere besprechen.
      Es freut mich aber, dass du zumindest mit dem veröffentlichen Code etwas anfangen und ihn nutzen konntest!

      Viele Grüße
      Florian

  2. Hallo Florian.
    Danke für die schnelle Antwort. Ich werde mal schauen ob ich die Regel entsprechend erweitern kann. Eine Frage noch zu der gruppeRollo. Was muss ich denn in die Gruppe Rollo packen und wo ist die Gruppe gruppeRollo definiert?

    Grus Manuel

    1. Hallo Manuel,
      die Gruppe muss einfach nur als Gruppe existieren (habe das im Artikel eben noch ergänzt im .items-file) und die Rollädenaktoren, die durch die Rule geschalten werden sollen, müssen natürlich der Gruppe zugewiesen sein.
      Gruß
      Florian

  3. Danke Florian.
    welche Items vom Rolladen Aktor ordnest du denn alles der Gruppe gruppeRollo zu? irgendwie will es bei mir nicht funktionieren

    1. Hallo Manuel alle Rollladenaktoren, die durch das Script geschaltet werden sollen müssen in der Gruppe sein.
      Bitte ggf das logfile im Auge behalten, falls irgendwo ein Fehler reingekommen ist hilft das meist schnell..

  4. Danke dir hat geklappt. Ich musste noch die Items LEVEL in die Gruppe gruppeRollo packen und das Astro Binding hat bei mir keine Werte gesendet.
    Hast du eine Quick n Dirty Idee wie ich in deinen Code die Bedingung hochfahren einbauen kann wenn die Bewölkung zunimmt? wenn also nachmittags der Himmel zuzieht würde ich die Rollos gerne wieder hochfahren

    1. Hallo Manuel, man müsste in die Regel für’s Hochfahren weitere Kriterien wie die Bewölkung einbringen, dann geht das schon. Aber mal schnell gemacht ist es nicht. Und es bleibt die Frage, was machst Du, wenn dann die Sonne wieder kommt? Dann hätte man am Ende eventuell ständig hoch- und runterfahrende Rollos…

  5. Klasse. Tolle Anregungen und Vorlagen für jemanden wie mich, der so etwas zwar adaptieren aber niemals selbst entwickeln könnte. Bin gespannt auf weitere Projekte.
    VG

  6. Hallo,

    Vielen Dank, dass Du hier Deinen Konfig zur Verfügung stellst. Eine kurze Frage hierzu: Wie kann man das ganze testen? Ich habe in der App alles eingestellt, mit den Werten, die in Deiner Oberfläche stehen. Leider tut sich nichts. Hast Du einen Tipp?

    Danke Dir!

      1. Hi Florian super Seite hast du und grade der Betrag ist sehr sehr hilfreich sich einzufinden und Learning by doing erfolg zu haben.
        FAST: ich habe alle probiert und ausgetauscht, umgeschrieben…. aber die Rollos bewegen sich nicht! Im Logfile wird des öfteren gesagt das was passieren sollte.
        Ich schätze es liegt an der Gruppe Rollos! Kannst du für die ganz dummen einmal erklären wie man eine Gruppe erstellt und einbindet?

        Vielen vielen dank vorab…

        1. Hallo Dominik,

          meine items sehen so aus:

          Group gruppeRollo „Rollos insgesamt“
          Rollershutter OG_ROLLO_1 „Rolladen 1“ (gruppeOG, gruppeRollo) {channel=“homematic:HG-HM-LC-Bl1PBU-FM:xxx:1#LEVEL“}
          Rollershutter OG_ROLLO_2 „Rolladen 2“
          (gruppeOG, gruppeRollo) {channel=“homematic:HG-HM-LC-Bl1PBU-FM:xxx:1#LEVEL“}

          Gruß
          Florian

  7. Hallo,

    erst mal vielen Dank für diesen Beitrag. Soetwas hatte ich auch vor und Du hast sogar noch mehr eingebaut (Wetter) als ich erst geplnt hatte.

    *DaumenHoch*

    Allerdings habe ich ein (vielleicht auch nur Verständnis-)Problem.
    Du holst die aktuelle Zeit mit
    var String timeNow = now.toString().substring(0,10)
    Wenn ich mir die ins Log schreiben lasse [hiermit: if (log) logInfo(‚rules‘, logPrefix + ‚timeNow=‘ + timeNow)], bekomme ich soetwas:
    [eclipse.smarthome.model.script.rules] – Rolloautomatik (Rollo ab) – timeNow=2019-02-15

    Soll das wirklich das Datum sein? Von Namen und von der Logik her würde ich eher die Uhrzeit erwarten.
    Kann es sein, das ich das lokale Zeit/Datumsformat einstellen Muss?
    Falls ja, weißt Du zufällig wie ich das mache?
    Ich verwende Openhabian2 auf einem Raspberry.

    Tschööö Thorsten

    1. Hallo Thorsten,

      zuerst Danke für dein Feedback!

      now.toString() liefert Datum und Uhrzeit – das hast Du richtig erkannt.
      Im Code sieht Du aber, dass ich den String dann mit substring abschneide. Dies mache ich, weil ich möchte, dass nur Jahr-Monat-Tag als Zeitstempel über bleibt.

      Im Nachfolgenden der Rule prüfe ich das dann immer ab und verhindere, dass die Rule an einem Tag ggf mehrfach getriggert wird. Dies wäre z.B. der Fall, wenn openhab die Rollos runterfährt, ich aber das Tageslicht von außen dennoch will, das runterfahren stoppe oder das Rollo wieder ganz hoch fahre. Beim nächsten Verändern des Sonnenwinkels (z.B.) wird die Rule wieder getriggert und er würde wieder runterfahren. Daher die Reduktion auf den Tag.

      Die Variablenbenennung ist vermutlich unglückllich. timeNow sollte eher datumHeute lauten o.ä. – dann wäre das vielleicht klar gewesen…

      Viele Grüße
      Florian

  8. Hallo Florian,

    vielen Dank für die schnelle Anwort und deutliche Erklärung.
    Nun verstehe ich, dass es kein Problem mit der Konfiguration der locals bei meinem raspberry ist.

    Tschööö Thorsten

  9. Hallo Florian,
    vielen Dank für diese tolle Lösung zur Verschattung.
    Nun habe ich eine frage zu Meldungen im Log:
    Bei der Meldung zum Azimuth wird der eingestellte Wert (170)
    im Log nicht ausgegeben.
    Bei der Elevation aber schon…. ?

    2019-04-06 10:39:53.395 [INFO ] [eclipse.smarthome.model.script.rules] – Rolloautomatik (Rollo ab) – Regel wurde gestartet

    2019-04-06 10:39:53.417 [INFO ] [eclipse.smarthome.model.script.rules] – Rolloautomatik (Rollo hoch) – Regel wurde gestartet

    2019-04-06 10:39:53.452 [INFO ] [eclipse.smarthome.model.script.rules] – Rolloautomatik (Rollo ab) – Azimuth (126.7569316374283) hat noch nicht Schwellwert (rolloautomatik_azimuth_start.state.toString()) erreicht

    2019-04-06 10:39:53.474 [INFO ] [eclipse.smarthome.model.script.rules] – Rolloautomatik (Rollo hoch) – Beende, da Elevation (34.15977963883472) nicht kleiner der eingestellten Elevation (10) war

    1. Welcher Aktor verwendet wird dürfte ziemlich egal sein, das kapselt openhab ja entsprechend. Da ich sonst auch fast nur Homematic nutze habe ich deren Aktoren auch bei den Rollläden im Einsatz.

  10. Viele Dank für die Info.
    Soweit habe ich deine Rule jetzt bei mir in OpenHab eingebaut.
    Ich möchte mir, wenn die Verschattung möglich ist, auch eine Push Nachricht schicken lassen.
    Das geht in OH so:
    sendBroadcastNotification(„Verschattung möglich“)
    Könntest Du mir einen Hinweis geben wo ich das noch einfügen muss ?
    Vielen Dank.

    1. Hallo Peter,
      für’s Melden der Beschattung kannst Du den Code nach „// Letzte Ausführung mit entsprechendem Zeitstempel belegen“ einfügen. Hier gibt es zwei Fundstellen im Code von diesem Kommentar.
      Für’s Melden des Aufhebens der Beschattung nimmst Du die Fundstelle, wo zuvor das sendCommand(0) zu finden ist, für’s Melden der Beschattung die andere sendCommand-Fundstelle.
      Grüße
      Florian

  11. Hallo Florian,
    nun habe ich noch eine Frage zu einem Logeintrag den die Rule erzeugt:
    „Rolloautomatik (Rollo ab) – Mindest-Temperatur (10) wurde nicht erreicht durch aktuelle Temperatur (18.1 °C)“
    Kannst Du mir einen Tip geben weshalb das nicht funktioniert ?
    Vielen Dank.
    Grüße
    Peter

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.