Seite 26 von 27

Re: Elektrischen Rolladen abhängig von Sonnenstand und Wetter steuern lassen

Verfasst: 21. Jul 2023 13:04
von udo1toni
Welche Items Du brauchst, hängt davon ab, was Du steuern willst und wie Du steuern willst. :)

Den Sonnenstand bekommst Du seit openHAB1 über das Astro Binding, das sind zwei Channel für Elevation und Azimut, also Höhenwinkel und Himmelsrichtung, das hat sich bis heute nicht geändert. Seit OH2 werden allerdings Einheiten mitgeliefert, Stichwort UoM, also °, das muss man in den Formeln berücksichtigen.
Beim Wetter sieht es ähnlich aus, erwartete Temperaturen, Bewölkungsgrad, was weiß ich, bildest Du in Items ab, die im Zweifel unabhängig von der openHAB Version sind - mal abgesehen von der Sache mit der eventuell mitgelieferten Einheit.
Und schließlich die Rollläden selbst. Auch da hat sich eigentlich nichts geändert, wichtig ist, die Läden passend zu organisieren, wenn Du mit einer Rule (oder meinetwegen einem Satz Rules) alle Läden automatisch steuern möchtest, das heißt, Du musst die Items dann passend gruppieren.
Wichtig: Im Semantic Model darf jedes Item nur exakt einer Gruppe angehören, es ist nicht zulässig, ein Item mehreren Ssemantic Group Items zuzuordnen (und über die Semantic Oberfläche ist das auch nicht möglich).
Aber selbstverständlich darf jedes Item beliebig vielen Nicht-Semantic-Gruppen gleichzeitig angehören, solange es nicht zu Zirkelbezügen kommt (ein Group Item ist gleichzeitig der eigene Vorfahre, gleich wie viele Ebenen dazwischen sind), Du darfst also z.B. eine Gruppe Rolllaeden_West anlegen und dort alle Rollläden der Westseite des Hauses zuordnen, dennoch befinden sich die Rollläden jeweils als Point in den verschiedenen Räumen. Die Rule nutzt dann die Gruppe Rolllaeden_West, um alle Rollläden der Westseite gemeinsam zu schließen oder zu öffnen, sobald die Sonne die Westseite des Hauses bescheint bzw. untergegangen ist.

Und welchen Code Du verwendest, ist selbstverständlich davon abhängig, wie Du steuern möchtest. Der Thread ist halt mal schon etwas älter und dennoch aktuell und augenscheinlich von höchstem Interesse :)

Im Zweifel wird es in den Rules tatsächlich zwingende Änderungen geben, weil z.B. zu Beginn UoM noch die Ausnahme war, weil irgendwo eine Zeitkomponente verwendet wird und von OH2 auf OH3 von Joda Time auf JavaTime umgestellt wurde. Und auch mit OH4 gibt es Neuerungen, allerdings wäre mir jetzt kein Breaking Change bekannt, eher kommen neue Möglichkeiten hinzu und damit evtl. auch Vereinfachungen...

Re: Elektrischen Rolladen abhängig von Sonnenstand und Wetter steuern lassen

Verfasst: 21. Jul 2023 14:09
von Cyrelian
udo1toni hat geschrieben: 21. Jul 2023 11:04
Cyrelian hat geschrieben: 21. Jul 2023 09:08 die funktioniert besser als die Wetterdienste
Kein Wunder, Du sammelst die Daten ja auch unmittelbar vor Ort ein. Solange nicht einer der Sensoren defekt ist, sind selbst erfasste Daten immer besser als solche über einen Webservice.

Anders sieht es bei der Vorhersage aus, da braucht es große Wettermodelle und Millionen Messpunkte, um eine vernünftige Vorhersage zu basteln.
ja absolut, deswegen hole ich seit längerem schon die "lokalen" Daten für den IST und die Daten der Wetterdienste für den Forecast ;) .

Re: Elektrischen Rolladen abhängig von Sonnenstand und Wetter steuern lassen

Verfasst: 9. Jul 2024 18:10
von cb13
Hoggle hat geschrieben: 21. Jul 2023 11:54 Hallo.
Wie in einem anderen Post geschrieben, will ich mein System von Grund auf neu installieren und dann auch dieses Projekt mit integrieren.
Ich werde das openhabian-Image installieren und auch wahrscheinlich sofort auf 4.0 gehen.
Ich frage mich jetzt allerdings, wo ich in diesem 25 Seiten langen Post anfangen soll, um die richtigen Items und Rules anzulegen.
Am Anfang begann ja alles mit OH 2.4 und zwischendrin wurden noch Ergänzungen am Code gemacht. Ich habe leider die Übersicht verloren.
Kann mich da jemand unterstützen?
Hallo Hoggle, ich habe ähnliches auf Basis von OH 4.2 vor. Hast du einen aktuellen Stand, den du posten könntest.
Oder hat jemand anderes einen aktuellen Stand?
Viele Grüße

Re: Elektrischen Rolladen abhängig von Sonnenstand und Wetter steuern lassen

Verfasst: 25. Jul 2025 21:28
von Backbe01
Sorry für´s ausgraben!!!



Ich hätte eine Frage, nein, zwei Fragen:



Die Stelle bei Verschattung beenden:

Code: Alles auswählen

 if (Jahreszeit.state !="SPRING" && Jahreszeit.state!= "SUMMER") {                              

        logInfo("rules", logPrefix + "Verschattung wird nicht ausgeführt, da weder, Frühling noch Sommer.")

        return;

    }



müsste nicht ein "oder" "||" rein? So wird doch gefragt ob Frühling und Sommer ist?



2. Frage:



Ich nutze auch die Hashmap. Bei mir kommt die Info, dass die Rollläden fahren via Telegram. Leider sind aber meine Namen für die Items sehr kryptisch. Gibt es eine Möglichkeit, die Namen etwas hübscher zu machen ohne den Namen der Items zu ändern? Schön wäre es, wenn das Label angezeigt wird.



Hier ein Beispiel:


Code: Alles auswählen

 val Map<String, Number> targetHights = newHashMap (

                "Shellyswitch25LesezimmerRollerControl" -> 40,

                    "Shellyswitch25BueroRollerControl" -> 100,

                    "Shellyswitch25SZRechtsRollerControl" -> 90,

                    "Shellyswitch25SZLinksRollerControl" -> 85,

                    "Shellyswitch25BadRollerControl" -> 80,

                    "Shellyswitch25RollladenRaphaelRollerControl" -> 80,

                    "Shellyswitch25KucheRollerControl" -> 0

                )

Code: Alles auswählen

val telegramAction = getActions("telegram","telegram:telegramBot:telegram")

                        telegramAction.sendTelegram(5128384828L, "Verschattung für " + blind.name.toString + " aktiviert, schließen auf " + targetHights.get(blind.name.toString()).toString() + " %%")

                    } 

Re: Elektrischen Rolladen abhängig von Sonnenstand und Wetter steuern lassen

Verfasst: 25. Jul 2025 21:31
von Backbe01
cb13 hat geschrieben: 9. Jul 2024 18:10
Hoggle hat geschrieben: 21. Jul 2023 11:54 Hallo.
Wie in einem anderen Post geschrieben, will ich mein System von Grund auf neu installieren und dann auch dieses Projekt mit integrieren.
Ich werde das openhabian-Image installieren und auch wahrscheinlich sofort auf 4.0 gehen.
Ich frage mich jetzt allerdings, wo ich in diesem 25 Seiten langen Post anfangen soll, um die richtigen Items und Rules anzulegen.
Am Anfang begann ja alles mit OH 2.4 und zwischendrin wurden noch Ergänzungen am Code gemacht. Ich habe leider die Übersicht verloren.
Kann mich da jemand unterstützen?
Hallo Hoggle, ich habe ähnliches auf Basis von OH 4.2 vor. Hast du einen aktuellen Stand, den du posten könntest.
Oder hat jemand anderes einen aktuellen Stand?
Viele Grüße
Wenn du noch Interesse hast, kann ich morgen meine rule hier einstellen. Heute leider nicht, da ich nur vom Handy schreiben kann. Meine IP vom Router ist heute auf einer Blacklist!?

Re: Elektrischen Rolladen abhängig von Sonnenstand und Wetter steuern lassen

Verfasst: 26. Jul 2025 11:41
von peter-pan
Backbe01 hat geschrieben: 25. Jul 2025 21:31 Meine IP vom Router ist heute auf einer Blacklist!?
Hast es schon mal mit einem Restart des Routers probiert ? Das hilft bei mir.
Backbe01 hat geschrieben: 25. Jul 2025 21:28 müsste nicht ein "oder" "||" rein? So wird doch gefragt ob Frühling und Sommer ist?
Ja das denke ich auch.
Backbe01 hat geschrieben: 25. Jul 2025 21:28 chön wäre es, wenn das Label angezeigt wird.
Ich kenne zwar nicht die ganze Rule, aber hast du schon mal "blind.label" probiert ?

Re: Elektrischen Rolladen abhängig von Sonnenstand und Wetter steuern lassen

Verfasst: 26. Jul 2025 11:50
von udo1toni
Backbe01 hat geschrieben: 25. Jul 2025 21:31 müsste nicht ein "oder" "||" rein? So wird doch gefragt ob Frühling und Sommer ist?
Nein, das != bedeutet "ungleich", es wird also abgefragt, ob nicht Frühling und nicht Sommer ist (oder anders ausgerückt weder Frühling noch Sommer). Beide Bedingungen müssen gleichzeitig zutreffen. Anders wäre es, wenn man fragte, ob Herbst oder Winter ist.
Backbe01 hat geschrieben: 25. Jul 2025 21:28 Schön wäre es, wenn das Label angezeigt wird.
Ja, kein Problem:

Code: Alles auswählen

val telegramAction = getActions("telegram","telegram:telegramBot:telegram")
blinds.members.forEach[blind|
    telegramAction.sendTelegram(5128384828L, "Verschattung für " + blind.label + " aktiviert, schließen auf " + targetHights.get(blind.name) + " %%")
    blind.sendCommand(targetHights.get(blind.name))
]
blinds ist hier ein Group Item, welches alle Jalousie Items enthält.
Die Methode .members liefert eine Liste aller enthaltenen Items (wobei die einzelnen Einträge der Liste wie "echte" Items funktionieren).
Die Methode .forEach durchläuft diese Liste, das Lambda (der Code zwischen [ und ]) wird also für jedes Item aufgerufen, welches zum Group Item gehört.
Das Lambda kennt ein bis zwei Variablen, welche als kommaseparierte Liste vor der Pipe | angegeben werden. Hier brauchen wir nur die erste dieser Variablen, in diesem Fall blind (man kann aber nehmen, was einem passt, solange die Namenskonvention eingehalten wird und es keine Verwechslung geben kann).
blind ist also ein Item Platzhalter, welcher für jeden Durchlauf des Codes für ein anderes Item steht.
Für jedes Item stehen mehrere Methoden und Eigenschaften zur Verfügung, hier sind die Eigenschaften .name (der "echte" Itemname als String) und .label (das Label des Items als String) interessant.

Besser wäre es natürlich, den String zunächst zusammenzubauen und nur eine Telegram Nachricht zu schicken, so:

Code: Alles auswählen

val tBot = getActions("telegram","telegram:telegramBot:telegram")
var String strMessage = "Verschattung aktiviert für folgende Jalousien: "

blinds.members.forEach[blind, i|
    blind.sendCommand(targetHights.get(blind.name))
    strMessage = strMessage + blind.label + " (" + targetHights.get(blind.name) + " %)"
    strMessage = strMessage + if(i < blinds.members.size - 1) ", " else "."
]
    tBot.sendTelegram(5128384828L, strMessage)
Die String Variable strMessage wird mit dem Beginn des Textes initialisiert.
Anschließend wird die Liste der Jalousien durchlaufen und für jedes Element wird zum Einen die Targethöhe als Befehl gesendet, zum Anderen wird strMessage ein Eintrag hinzugefügt.
Die zweite Variable (i) ist der Durchlaufzähler, welcher bei jedem Durchlauf um 1 erhöht wird (beginnend mit 0).
blinds.members.size liefert die Anzahl der Elemente der Liste, solange i also kleiner ist als size - 1 (weil i ja 0-basiert ist), wird noch ein weiterer Eintrag bearbeitet, entsprechend muss strMessage um ein ", " ergänzt werden. Erst mit dem letzten Element wird die Nachricht mit einem "." abgeschlossen.
Nachdem die Schleife fertig abgearbeitet ist, enthält strMessage die gesamte Nachricht, welche nun gesendet werden kann.

Re: Elektrischen Rolladen abhängig von Sonnenstand und Wetter steuern lassen

Verfasst: 26. Jul 2025 16:19
von Backbe01
Ui, vielen Dank für Eure Antworten.

Das mit Frühling/Sommer klingt logisch - und die rule läuft ja auch, trotzdem steh ich gerade auf dem Schlauch! :lol:

Der erste Code von Dir, Udo, sieht relativ leicht zum einfügen aus. Quasi statt name wird label verwendet. Trotzdem muss ich mir das, und vor allem den zweiten Code, heute am Abend mal in Ruhe anschauen. Derzeit läuft ja die rule und es geht nur um Kosmetik.

Ich melde mich ggf. nochmal. Kämpfe auch gerade mit einer anderen rule... Ich befürchte, die muss ich auch bald posten... :oops:

P.S.: Hurra !!! Heute kann ich wieder schreiben...

Re: Elektrischen Rolladen abhängig von Sonnenstand und Wetter steuern lassen

Verfasst: 26. Jul 2025 19:36
von Backbe01
So... Habe die erste Codezeile von Dir, Udo, eingefügt. Leider kann ich es heute, aufgrund des Wetters, nicht testen.

Beim speichern der Rule kam allerdings folgende Meldung im log:

Code: Alles auswählen

2025-07-26 18:12:46.918 [INFO ] [el.core.internal.ModelRepositoryImpl] - Validation issues found in configuration model 'Verschattung copy.rules', using it anyway:
There is no context to infer the closure's argument types from. Consider typing the arguments or put the closures into a typed context.
There is no context to infer the closure's argument types from. Consider typing the arguments or put the closures into a typed context.
Keine Ahnung was das bedeutet, aber das "using it anyway" hat mich erstmal beruhigt! :lol:

Den zweiten Code von Dir, verstehe ich so, dass erst eine Nachricht versendet wird, wenn alle Rollladen angesteuert wurden. Wenn dem so sein sollte, bleibe ich lieber bei Variante 1. 1. möchte ich immer eine Nachricht, wann Nord, Ost und Süd fährt, 2. fahren nicht immer alle Seiten (z.B. wenn vormittags bewölkt, bleiben Nord und Ost offen),

Und zum Frühling/Sommer nochmal... "Ist nicht" leuchtet mir jetzt ein, hätte ich die Rule geschrieben, hätte ich mir aber gedacht, es müssen im Item "Jahreszeit" dann beide Argumente zutreffen, was ja nie der Fall ist. Daher hätte ich eher ein "oder" verbaut. Und mit einem "oder" sollte doch die Rule trotzdem das Gleiche machen? Oder stehe ich immer noch auf der Leitung??

Und falls cb13 noch die gesamte Rule benötigt, hier meine derzeitige:

Code: Alles auswählen

import java.util.Map

var Boolean message = true

val String filename = "shutter.rules"

var DWD1 = null
var DWD2 = null

// Values und Variablen für die Verschattung

//val Number blindClosed = 100
//val Number blindOpen = 0
//val Number blindTranslucent = 35

var Number closingAzimuth_north = 60
var Number closingAzimuth_east = 65
var Number closingAzimuth_south = 111


var Number closingCloudiness = 30   
val Number cloudHysteresis = 45         //die Mindestbewölkung in der letzten Stunde
var Number openingTemperature = 22
var Number closingTemperature = 24
val Number temperatureHysteresis = 4    //Temperaturabfall von min. 4 Grad in der letzten Stunde
val Number minPrecip = 5                //die Mindestmenge an Regen in der letzten Stunde

var Boolean isActiveNorth = false
var Boolean isActiveEast = false
var Boolean isActiveSouth = false
var Boolean isActiveTerasse = false
//var Boolean isActiveTerassebereitsausgefahren = false

val String logPrefix = "Rollläden - "

/* -------------  Verschattung FUNKTIONEN --------------------
*/
//-------------  Verschattung starten --------------------

val shadingStart = [GroupItem shutter |

        val String logPrefix = "Verschattung aktivieren - "

                val Map<String, Number> targetHights = newHashMap ( 
                "Shellyswitch25LesezimmerRollerControl" -> 40,
                    "Shellyswitch25BueroRollerControl" -> 100,
                    "Shellyswitch25SZRechtsRollerControl" -> 90,
                    "Shellyswitch25SZLinksRollerControl" -> 85,
                    "Shellyswitch25BadRollerControl" -> 80,
                    "Shellyswitch25RollladenRaphaelRollerControl" -> 80,
                    "Shellyswitch25KucheRollerControl" -> 0
                )
                // Rollladen werden geschlossen
                logInfo("rules", logPrefix + "Grenzwerte wurden erreicht, Rollladen werden geschlossen")

                shutter.allMembers.forEach[ blind |
                    if ((blind.state as Number) < targetHights.get(blind.name.toString()).intValue) {
                        logInfo("rules", logPrefix + "Fahre Rollladen (" + blind.name.toString() + ") auf (" + targetHights.get(blind.name.toString()).intValue + ") %" )
                        blind.sendCommand(targetHights.get(blind.name.toString()).intValue)
                        //Telegram versenden
                        val telegramAction = getActions("telegram","telegram:telegramBot:telegram")
                        //telegramAction.sendTelegram(5128384828L, "Verschattung für " + blind.name.toString + " aktiviert, schließen auf " + targetHights.get(blind.name.toString()).toString() + " %%")
                        blinds.members.forEach[blind|
                        telegramAction.sendTelegram(5128384828L, "Verschattung für " + blind.label + " aktiviert, schließen auf " + targetHights.get(blind.name) + " %%")
                        blind.sendCommand(targetHights.get(blind.name))
                        ]

                    } 
                    else {
                        logInfo("rules", logPrefix + "Rollladen ist bereits weiter geschlossen (" + blind.state.toString() + "%) als er geschlossen werden sollte und wird daher ignoriert")
                    }
                ]
                AutoShading_Start_last.postUpdate(new DateTimeType())
    return true;
]

//-------------  Verschattung beenden -------------------

val shadingEnd = [GroupItem shutter |

        val String logPrefix = "Verschattung deaktivieren - "

                    val Map<String, Number> targetHights = newHashMap ( 
                    "Shellyswitch25LesezimmerRollerControl" -> 40,
                    "Shellyswitch25BueroRollerControl" -> 0,
                    "Shellyswitch25SZRechtsRollerControl" -> 20,
                    "Shellyswitch25SZLinksRollerControl" -> 25,
                    "Shellyswitch25BadRollerControl" -> 0,
                    "Shellyswitch25RollladenRaphaelRollerControl" -> 40,
                    "Shellyswitch25KucheRollerControl" -> 0
                                        
                     )
                    // Rollladen öffnen
                    logInfo("rules", logPrefix + "Rollladen werden geoeffnet")

                    shutter.allMembers.forEach[ blind |
                       if ((blind.state as Number) == targetHights.get(blind.name.toString()).intValue) {
                            logInfo("rules", logPrefix + "Öffne Rollladen: " + blind.name.toString())
                            blind.sendCommand(UP)
                            //Telegram versenden 
                            val telegramAction = getActions("telegram","telegram:telegramBot:telegram")
                            telegramAction.sendTelegram(5128384828L, "Verschattung für (" + blind.name.toString + ") beendet, Rollladen wird geöffnet.")
                            blinds.members.forEach[blind|
                            telegramAction.sendTelegram(5128384828L, "Verschattung für " + blind.label + " beendet, Rollladen wird geöffnet." + targetHights.get(blind.name) + " %%")
                            blind.sendCommand(targetHights.get(blind.name))
                            ]

                       
                        } else {
                            logInfo("rules", logPrefix + "Rollladen: (" + blind.name.toString() + ") wird nicht geoeffnet, da dieser zwischenzeitlich manuell verändert wurde.")
                        }    
                    ]                         
                    // Letzte Ausführung mit entsprechendem Zeitstempel belegen
                    AutoShading_End_last.postUpdate(new DateTimeType(now.minusDays(1)))
                    
                    //Variablen zurücksetzen
                    isActiveNorth = false
                    isActiveEast = false
                    isActiveSouth = false
                    Nordaktiv.sendCommand(OFF)
                    Ostaktiv.sendCommand(OFF)
                    Suedaktiv.sendCommand(OFF)
                    
    return true;
]

/* -------------  Verschattung RULES --------------------
*/
//-------------  Verschattung starten --------------------

rule "Verschattung starten"
when
    Item Azimuth changed
then
    val String logPrefix = "Verschattung aktivieren - "
    
    //Prüfung auf: Verschattungsautomatik an / ob es Tag ist / Jahreszeit
    if (AutoShading.state != ON) {                                                                  
        logInfo("rules", logPrefix + "Verschattung wird nicht ausgeführt, da deaktiviert.")
        return;
    }

    if (IsDay.state != ON) {                                                                       
        logInfo("rules", logPrefix + "Verschattung wird nicht ausgeführt, es ist Nacht.")
        return;
    }

    if (Jahreszeit.state !="SPRING" && Jahreszeit.state!= "SUMMER") {                               
        logInfo("rules", logPrefix + "Verschattung wird nicht ausgeführt, da weder, Frühling noch Sommer.")
        return;
    }

    if (AutoShading_Start_last.state == NULL) {
        logInfo("rules", logPrefix + "Letzte Ausführung unbekannt, Belegung mit Initialwert (-1 Tag)")
        AutoShading_Start_last.postUpdate(new DateTimeType(now.minusDays(1)))
    }

    //Markisenautomatik
        if (!isActiveTerasse) /*&& (!isActiveTerassebereitsausgefahren/*Markise_heute_bereits_ausgefahren.changedSince(now.minusMinutes(600),"influxdb") == false)))*/ {
        //Azimuth ist größer als 111° (WEST)
            if ((Azimuth.state as Number).floatValue > (closingAzimuth_south)) {
                logInfo("rules", logPrefix + "Markise Terasse - Azimuth erreicht")
                if (((MultisensorXiaomiTemperature.state as Number).floatValue > (AutoShading_Temp_min.state as Number) && (WetterUndWettervorhersageCurrentCloudiness.state as Number).floatValue < (AutoShading_Cloudiness_max.state as Number)) ||  
                    ((MultisensorXiaomiTemperature.state as Number).floatValue > (AutoShading_Temp_min.state as Number) && (Sonnensensor_Durchschnitt_20min.state as Number).floatValue > (Autoshading_Lux_max.state as Number))) {
                    logInfo("rules", logPrefix + "Markise Terasse könnte fahren")
                    val telegramAction = getActions("telegram","telegram:telegramBot:telegram")
                    telegramAction.sendTelegram("Verschattung Markise starten?, aktuelle Temperatur %s" + " Helligkeit %s" + " Bewölkung %s", MultisensorXiaomiTemperature.state.toString, Sonnensensor_Durchschnitt_20min.state.toString, WetterUndWettervorhersageCurrentCloudiness.state.toString)
                    telegramAction.sendTelegramQuery("Verschattung Markise starten?", "Markise_ausfahren", "Ausfahren", "25%", "Nein")
                    logInfo("rules", logPrefix + "Verschattung (Markise) wird ausgeführt, Aktuelle Temperatur Terasse ({}), aktuelle Helligkeit ({}); aktuelle Bewölkung ist ({}) ", MultisensorXiaomiTemperature.state, Sonnensensor_Durchschnitt_20min.state, WetterUndWettervorhersageCurrentCloudiness.state)
                    AutoShadingM_Start_last.postUpdate(new DateTimeType())                    
                    //isActiveTerassebereitsausgefahren = true
                    Markiseaktiv.sendCommand(ON)
                    isActiveTerasse = true;
                    }
                }
            }    
         else {
            logInfo("rules", logPrefix + "Verschattung für Terasse bereits aktiviert")
        }
/*
    //Rollladenautomatik
    if (gElternanwesend.state != CLOSED) {                                                                           
        logInfo("rules", logPrefix + "Verschattung (Rollläden) wird nicht ausgeführt, Anwesenheit erkannt.")
        return;
    }
 */   
    // Items für Sitemap füllen
    if(AutoShading_Azimuth_east.state == NULL)    AutoShading_Azimuth_east.postUpdate(closingAzimuth_east)
    if(AutoShading_Azimuth_south.state == NULL)   AutoShading_Azimuth_south.postUpdate(closingAzimuth_south)
    if(AutoShading_Azimuth_north.state == NULL)    AutoShading_Azimuth_north.postUpdate(closingAzimuth_north)
    if(AutoShading_Temp_diff.state == NULL)       AutoShading_Temp_diff.postUpdate(temperatureHysteresis)
    if(AutoShading_Cloudiness_Hyst.state == NULL) AutoShading_Cloudiness_Hyst.postUpdate(cloudHysteresis)
    if(AutoShading_Rain_min.state == NULL)        AutoShading_Rain_min.postUpdate(minPrecip)
    
    if ((Elevation.state as Number).floatValue <= (AutoShading_Elevation_end.state as Number)) {
            logInfo("rules", logPrefix + "Verschattung (Rollläden) wird nicht ausgeführt, Elevation für das Beenden der Verschattung ({}) ist groesser als aktuelle ({}) ", AutoShading_Elevation_end.state, Elevation.state)
            return;
    }

//
    //Azimuth ist größer als 65° (OST)
    if (!isActiveEast) { 
        if ((Azimuth.state as Number).floatValue > (closingAzimuth_east) /*&& (Azimuth.state as Number).floatValue < (closingAzimuth_south)*/ && ((Sonnensensor_Xiaomi_Durchschnitt_20min.state as Number).floatValue ) > (Autoshading_Lux_max_ost.state as Number)) {
            logInfo("rules", logPrefix + "Verschattung für Rollläden OST")
            isActiveEast = shadingStart.apply(grollladeneast)
            Ostaktiv.sendCommand(ON)
        return;
        }
    } else {
            logInfo("rules", logPrefix + "Verschattung für Rollläden OST bereits aktiviert")
        }

    

    //Azimuth ist größer als 60° (NORD)
    if (!isActiveNorth) {
        if ((MultisensorXiaomiTemperature.state as Number).floatValue <= (AutoShading_Temp_min.state as Number)) {
            logInfo("rules", logPrefix + "Verschattung (Rollläden) wird nicht ausgeführt, Mindesttemperatur von ({}) wurde nicht erreicht. Aktuelle Temperatur ({}) ", AutoShading_Temp_min.state, MultisensorXiaomiTemperature.state)
            return;
            } 
        if (((Azimuth.state as Number).floatValue > (closingAzimuth_north)) && ((Sonnensensor_Xiaomi_Durchschnitt_20min.state as Number).floatValue ) > (Autoshading_Lux_max_ost.state as Number)) {
            logInfo("rules", logPrefix + "Verschattung für Rollläden NORD")
            isActiveNorth = shadingStart.apply(grollladennord)
            Nordaktiv.sendCommand(ON)
            return;
        }      
    } else {
            logInfo("rules", logPrefix + "Verschattung für Rollläden NORD bereits aktiviert")
        }

    if ((Sonnensensor_Durchschnitt_20min.state as Number).floatValue < (Autoshading_Lux_max.state as Number)) { 
            logInfo("rules", logPrefix + "Verschattung (Rollladen Süd) wird nicht ausgeführt, aktuelle Lichtstärke ({}) unterrschreitet den eingestellten Grenzwert von ({})", Sonnensensor_Durchschnitt_20min.state, Autoshading_Lux_max.state)
            return;
    }

    //Azimuth ist größer als 111° (SÜD)
    if (!isActiveSouth) { 
        if (((Azimuth.state as Number).floatValue > (closingAzimuth_south)) && ((Sonnensensor_Durchschnitt_20min.state as Number).floatValue > (Autoshading_Lux_max.state as Number)) /*&& (Azimuth.state as Number).floatValue < (closingAzimuth_north)*/) {
            logInfo("rules", logPrefix + "Verschattung für Rollläden SÜD")
            isActiveSouth = shadingStart.apply(grollladensued)
            Suedaktiv.sendCommand(ON)
            return;
        }
    } else {
            logInfo("rules", logPrefix + "Verschattung für Rollläden SÜD bereits aktiviert")
        }
end

//-------------  Verschattung beenden --------------------

rule "Verschattung beenden"
when 
    Item Elevation changed
then   
    
    val String logPrefix = "Verschattung deaktivieren - "

    //Prüfung auf: Verschattungsautomatik an / ob es Tag ist / Jahreszeit
    if (AutoShading_end.state != ON) {                                                                  
        logInfo("rules", logPrefix + "Verschattung wird nicht ausgeführt, da deaktiviert.")
        return;
    }

    if (IsDay.state != ON) {                                                                        
        logInfo("rules", logPrefix + "Verschattung wird nicht ausgeführt, es ist Nacht.")
        return;
    }

    if (Jahreszeit.state !="SPRING" && Jahreszeit.state!= "SUMMER") {                               
        logInfo("rules", logPrefix + "Verschattung wird nicht ausgeführt, da weder, Frühling noch Sommer.")
        return;
    }
            
    val Boolean isRainLastHour = (WetterUndWettervorhersageCurrentRain.maximumSince(now.minusHours(1), "influxdb").state >= (minPrecip))
    logInfo("rules", logPrefix + "Rain " + isRainLastHour)
    
    val Boolean isCloudLastHour = (WetterUndWettervorhersageCurrentCloudiness.averageSince(now.minusHours(1), "influxdb")as Number >= (cloudHysteresis))
    logInfo("rules", logPrefix + "Clouds " + isCloudLastHour )
    
    val Boolean isTemperature = ((MultisensorXiaomiTemperature.state as Number).floatValue < ((MultisensorXiaomiTemperature.minimumSince(now.minusHours(1), "influxdb").state as Number).floatValue -(temperatureHysteresis)))
    logInfo("rules", logPrefix + "Temperatur " + isTemperature)
    
    
    if (AutoShading_End_last.state === NULL || AutoShadingM_End_last.state === NULL) {
        logInfo("rules", logPrefix + "Letzte Ausführung unbekannt, Belegung mit Initialwert (-1 Tag)")
            AutoShading_End_last.postUpdate(new DateTimeType(now.minusDays(1)))
            AutoShadingM_End_last.postUpdate(new DateTimeType(now.minusDays(1)))
        }

    var String timeNow = now.toString().substring(0,10)
    var String timeLastEnde = AutoShading_End_last.state.toString().substring(0,10)
    var String timeLastEndeM = AutoShadingM_End_last.state.toString().substring(0,10)

    if (timeLastEnde == timeNow && timeLastEndeM == timeNow) {
        logInfo("rules", logPrefix + "Beende, da heute bereits ein automatisches Hochfahren stattfand")
        return;
    }

    if (!isActiveNorth && !isActiveEast && !isActiveSouth && !isActiveTerasse) {
        logInfo("rules", logPrefix + "Beende, da heute noch keine automatische Verschattung stattfand")
        return;
    }

    if (isTemperature) {
        logInfo("rules", logPrefix + "Verschattung beenden, Temperaturabfall von min. ({})° erkannt", temperatureHysteresis)
        Markise.sendCommand(0)
        AutoShadingM_End_last.postUpdate(now.toLocalDateTime().toString())
        shadingEnd.apply(gRollladen)
        return;
    }

    if ((MultisensorXiaomiTemperature.state as Number).floatValue > (AutoShading_Temp_raise.state as Number)) {
        logInfo("rules", logPrefix + "Beende, aktuelle Temperatur ({})° ueberschreitet den eingestellten Grenzwert zum hochfahren von ({})°",MultisensorXiaomiTemperature.state, AutoShading_Temp_raise.state )
        return;
    }

    if (isRainLastHour || isCloudLastHour) {
        logInfo("rules", logPrefix + "Verschattung beenden, Mindestregenmenge von ({}) mm oder druchschnittliche Bewölkung von ({}) % erreicht",minPrecip, cloudHysteresis)
        Markise.sendCommand(0)
        AutoShadingM_End_last.postUpdate(new DateTimeType())
        shadingEnd.apply(gRollladen)
        return;
    }

    if ((Elevation_shutter.state as Number) > (AutoShading_Elevation_end.state as Number)) {
        logInfo("rules", logPrefix + "Beende, aktuelle Elevation ({}) ueberschreitet den eingestellten Grenzwert von ({}) ", Elevation.state, AutoShading_Elevation_end.state)
        return;
    }

    if (isActiveTerasse) {
        logInfo("rules", logPrefix + "Verschattung Terasse beenden")
        Markise.sendCommand(0)
        AutoShadingM_End_last.postUpdate(new DateTimeType())
    }

    if (isActiveNorth || isActiveEast || isActiveSouth ) {
        logInfo("rules", logPrefix + "Verschattung Rollläden beenden")
        shadingEnd.apply(gRollladen)
        return;
    }        
end


/* -------------  Verschattung Variablen zurücksetzen wenn kein automtisches hochfahren erfolgt --------------------
*/

rule "Verschattung Variablen zurücksetzen"
when
        Time cron "0 0 23 * * ?" or 
        Channel 'astro:sun:home:nauticDusk#event' triggered END 
then
        logInfo("rules", logPrefix + "Verschattung Variablen zurücksetzen")
        isActiveNorth = false
        isActiveEast = false
        isActiveSouth = false
        isActiveTerasse = false
        Nordaktiv.sendCommand(OFF)
        Ostaktiv.sendCommand(OFF)
        Suedaktiv.sendCommand(OFF)
        Markiseaktiv.sendCommand(OFF)
end

rule "Verschattung Variablen update"
when
        Item Shading_Var received command
then
        logInfo("rules", "Verschattung Variablen: " + receivedCommand)
        switch (receivedCommand) {
            case "queryState" : {
                        logInfo("rules", logPrefix + "Verschattung Variablen update")
                        if (isActiveNorth) {
                            logInfo("rules", logPrefix + "Verschattung für Rollläden NORD aktiv")
                        } else { 
                            logInfo("rules", logPrefix + "Verschattung für Rollläden NORD inaktiv")
                        }
                        if (isActiveEast) {
                            logInfo("rules", logPrefix + "Verschattung für Rollläden OST aktiv")
                        } else { 
                            logInfo("rules", logPrefix + "Verschattung für Rollläden OST inaktiv")
                        }
                        if (isActiveSouth) {
                            logInfo("rules", logPrefix + "Verschattung für Rollläden SÜD aktiv")
                        } else { 
                            logInfo("rules", logPrefix + "Verschattung für Rollläden SÜD inaktiv")
                        }
                        if (isActiveTerasse) {
                            logInfo("rules", logPrefix + "Verschattung für Markise (Terasse) aktiv")
                        } else { 
                            logInfo("rules", logPrefix + "Verschattung für Markise (Terasse) inaktiv")
                        }
                        /* if (isActiveTerassebereitsausgefahren) {
                            logInfo("rules", logPrefix + "Verschattung für Markise (Terasse) heute bereits einmal automatisch ausgefahren")
                        } else { 
                            logInfo("rules", logPrefix + "Verschattung für Markise (Terasse) heute noch nicht automatisch ausgefahren")
                        }*/
                        
            }
            case "reset" : {
                    logInfo("rules", logPrefix + "Verschattung Variablen reset")
                    isActiveNorth = false
                    isActiveEast = false
                    isActiveSouth = false
                    isActiveTerasse = false
                    Nordaktiv.sendCommand(OFF)
                    Ostaktiv.sendCommand(OFF)
                    Suedaktiv.sendCommand(OFF)
                    Markiseaktiv.sendCommand(OFF)
                    //isActiveTerassebereitsausgefahren = false
                }
        }
        Shading_Var.postUpdate(NULL) 
end


rule "Test Telegram Markise ausfahren"
when
    
    Item telegramReplyId received update Markise_ausfahren
then
    val telegramAction = getActions("telegram","telegram:telegramBot:telegram")
   
    if (telegramMessage.state.toString == "Ausfahren")
    {
        telegramAction.sendTelegramAnswer(telegramReplyId.state.toString, "Ok, Markise wird ausgefahren! Info: ")
        var DWD1 = DWDUnwetterWarnungenOnset1.state.toString
        var DWD2 = DWDUnwetterWarnungenDescription1.state.toString
        telegramMessage.postUpdate(DWD1)
        telegramAction.sendTelegram(DWD1)
        telegramMessage.postUpdate(DWD2)
        telegramAction.sendTelegram(DWD2)
        Markise.sendCommand(100)
    }
    if (telegramMessage.state.toString == "25%")
    {
        telegramAction.sendTelegramAnswer(telegramReplyId.state.toString, "Ok, Markise wird auf 25% ausgefahren! Info: ")
        var DWD1 = DWDUnwetterWarnungenOnset1.state.toString
        var DWD2 = DWDUnwetterWarnungenDescription1.state.toString
        telegramMessage.postUpdate(DWD1)
        telegramAction.sendTelegram(DWD1)
        telegramMessage.postUpdate(DWD2)
        telegramAction.sendTelegram(DWD2)
        Markise.sendCommand(75)
    }

    if (telegramMessage.state.toString == "Nein")
    {
     
        telegramAction.sendTelegramAnswer(telegramReplyId.state.toString, "Ok, Markise wird NICHT ausgefahren!")
    }
end

rule "Tag und Nacht"
when
    Item Elevation changed or System started
then
      if (Elevation.state > 0|°) {
        if (IsDay.state==OFF || IsDay.state==NULL || IsDay.state==UNDEF) {
            logInfo("AstroRules:Tag und Nacht", "Sonnenstand > 0 Grad - Es ist Tag")
              sendCommand(IsTwilight, OFF)
              sendCommand(IsDay, ON)
              sendCommand(IsNight, OFF)          
        }
      }
	  if (Elevation.state <= 0|° && Elevation.state >= -6|°) {
          if (IsDay.state==ON || IsDay.state==NULL || IsDay.state==UNDEF) {
              logInfo("AstroRules:Tag und Nacht", "Sonnenstand ist zwischen 0 und -6 Grad - Es ist Abenddämmerung")
              sendCommand(IsTwilight, ON)
              sendCommand(IsDay, OFF)
              sendCommand(IsNight, ON)
         }            
      }
      if (Elevation.state < -6|°) {     
        if (IsTwilight.state==ON || IsTwilight.state==NULL || IsTwilight.state==UNDEF) {
            logInfo("AstroRules:Tag und Nacht", "Sonnenstand < -6 Grad - Es ist Nacht")
              sendCommand(IsTwilight, OFF) 
              sendCommand(IsDay, OFF)
              sendCommand(IsNight, ON)        
          }
      }
end
Und hier die Rollladensteuerung Items (es fehlen die astro-, Temperatur-, Helligkeits- und Rollladen-Items, da individuell):

Code: Alles auswählen

/* -------------  Rollladensteuerung --------------------
 */

// -------------  Manuell --------------------
Switch		ManualShading				"Manuelle Verschattung"																(gInitializeOff) {alexa="Switch", autoupdate="false"}
String		Shading_Var				"Verschattungsvariablen"												<time>				(gShading)

// -------------  Automatic --------------------
Switch		AutoShading			"Automatische Verschattung"																	(gShading,gInitializeOn)
Switch		AutoShading_end			"Rollladen automatisch öffnen"																(gShading,gInitializeOn)
Number		AutoShading_Temp_min		"Temperatur größer [%d °C]"												<temperature>		(gShading)
Number		AutoShading_Temp_raise		"Temperatur zum hochfahren der Rollladen [%d °C]"						<temperature>		(gShading)
Number		AutoShading_Temp_diff		"Temperaturunterschied der letzten Stunde [- %d °C]"					<temperature>		(gShading)
Number      Autoshading_Lux_max         "Helligkeit mehr als [%.1f Lux]"                                        <sun>               (gShading)
Number      Autoshading_Lux_max_ost     "Helligkeit Osten mehr als [%.1f Lux]"                                  <sun>               (gShading)
Number		AutoShading_Cloudiness_max	"Bewölkung weniger als [%d Prozent]"									<sun_clouds>		(gShading)
Number		AutoShading_Cloudiness_Hyst	"Durchschn. Bewölkung der letzten Stunde größer gleich [%d Prozent]"	<sun_clouds>		(gShading)
Number		AutoShading_Rain_min		"Mindestregenmenge der letzten Stunde größer gleich [%.2f mm/h]"		<sun_clouds>		(gShading)
Number		AutoShading_Azimuth_east	"Sonnenrichtung / Azimuth (Ost) größer gleich [%d °]"					<compass>			(gShading)
Number		AutoShading_Azimuth_south	"Sonnenrichtung / Azimuth (Süd) größer gleich [%d °]"					<compass>			(gShading)
Number		AutoShading_Azimuth_north	"Sonnenrichtung / Azimuth (Nord) größer gleich [%d °]"					<compass>			(gShading)
Number		AutoShading_Elevation_end	"Sonnenhöhe / Elevation kleiner gleich [%d °]"							<niveau>			(gShading)
DateTime	AutoShading_Start_last		"Letzte Ausführung (Rollladen ab) [%1$td.%1$tm %1$tH:%1$tM Uhr]"		<time>				(gShading)
DateTime	AutoShading_End_last		"Letzte Ausführung (Rollladen hoch) [%1$td.%1$tm %1$tH:%1$tM Uhr]"		<time>				(gShading)
DateTime	AutoShadingM_Start_last		"Letzte Ausführung (Markisen ausfahren) [%1$td.%1$tm %1$tH:%1$tM Uhr]"	<time>				(gShading)
DateTime	AutoShadingM_End_last		"Letzte Ausführung (Markiesen einfahren) [%1$td.%1$tm %1$tH:%1$tM Uhr]"	<time>				(gShading)

Switch ShutterControll "Rollladen Automatik Abends"
Group gShading 
Group gInitializeOff
Group gInitializeOn

Number  Shuttercontroll_Elvation_State "Schließzeitpunkt Elevatin [%d °]" <moon>
DateTime Shuttercontroll_Elvation_Zeitpunkt "letzte Schließzeit Abends [%1$td.%1$tm %1$tH:%1$tM Uhr]" <time>

Switch Nordaktiv "Nord aktiv" <sun>
Switch Ostaktiv "Ost aktiv" <sun>
Switch Suedaktiv "Süd Aktiv"<sun>
Switch Markiseaktiv "Markise aktiv" <sun>

Switch Rollladen_Urlaub

Re: Elektrischen Rolladen abhängig von Sonnenstand und Wetter steuern lassen

Verfasst: 29. Jul 2025 15:23
von Backbe01
Kurze Rückmeldung:

Überraschenderweise haben Deine Codes, Udo, nicht den gewünschten Erfolg gebracht.

Der Hinweis von Peter-Pan hat allerdings voll ins Schwarze getroffen! Vielen Dank Euch zweien!

Einfach "name" durch "label" ersetzt...

Code: Alles auswählen

telegramAction.sendTelegram(5128384828L, "Verschattung für " + blind.label.toString + " aktiviert, schließen auf " + targetHights.get(blind.name.toString()).toString() + " %%")