Elektrischen Rolladen abhängig von Sonnenstand und Wetter steuern lassen

Für welche Projekte verwendet Ihr OpenHAB? Was habt Ihr automatisiert? Stellt eure Projekte hier vor.

Moderatoren: Cyrelian, seppy

Benutzeravatar
PeterA
Beiträge: 1052
Registriert: 8. Feb 2019 12:12
Answers: 13

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

Beitrag von PeterA »

Hallo zusammen,

zwischenzeitlich ist auch hier ein Balkonkraftwerk "eingezogen" :)

Leider sind die Wolkenmengen die übers Wetterbinding reinkommen nicht immer passend für meinen Standort.
Anstelle der Wolkenmenge verwende ich nun die Einstrahlung auf die Panels.
Das funktioniert viel besser als die Wolkenmenge vom Wetterbinding.

Gruß
Peter
- OpenHab 2.4
#PWRUP

Absinthe
Beiträge: 78
Registriert: 16. Jan 2022 13:30
Answers: 0

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

Beitrag von Absinthe »

Hallo,

zu erst: VIELEN DANK für die super Arbeit an der Rule zur automatischen Verschattung! Diese hat uns letzten Sommer echt ein kühles Zuhause ermöglicht.

Ich hatte noch einen kleinen Darstellungsfehler in der Sitemap, den ich ausbügeln wollte...

Ausgangslage: Der angezeigte Wert in der Sitemap stimmt nicht mit dem im Item hinterlegten Wert überein...

Im Item ist 65 eingestellt. Angezeigt wird allerdings 2.

Das Item ist als Nummer:Dimonsenless angelegt.
Bildschirm­foto 2023-05-21 um 14.39.49.png
Bildschirm­foto 2023-05-21 um 14.39.39.png
----------------------> Soweit so gut. In der Form funktioniert die Rule einwandfrei.

Sobald ich nun das Item auf den Typ Number umstelle, ist zwar die Anzeige in der Sitemap korrekt mit 65 % aber die Rule funktioniert dafür nicht mehr...

Im Log steht dann:
2023-05-21 14:34:59.541 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'auto_verschattung_sued_down-1' failed: For input string: "65.0" in auto_verschattung_sued_down
Ich vermute, dass in diesen Zeilen der Fehler versteckt ist:

Code: Alles auswählen

group_Rollladen_Sued_hight.members.forEach[i|
                                if ((i.state as Number).floatValue <= (Rollladenautomatik_zielwert_sued.state as Number)) {
                                    if (log) logInfo('rules', logPrefix + 'Fahre Rolladen auf ' + Rollladenautomatik_zielwert_sued.state.toString() + '%: ' + i.name)
                                    i.sendCommand(Integer::parseInt(Rollladenautomatik_zielwert_sued.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')
                                }
                            ]
Jemand eine Idee, woran dieses Verhalten liegen könnte?

Grüße und vielen Dank für eure Ideen :)
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.
OpenHAB 4.1.1
in einem Docker-Container
auf einer Synology DS1515+

Benutzeravatar
udo1toni
Beiträge: 13989
Registriert: 11. Apr 2018 18:05
Answers: 222
Wohnort: Darmstadt

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

Beitrag von udo1toni »

Der Codeschnipsel ist unnötig kompliziert. Probiere es mal so:

Code: Alles auswählen

val Integer iZiel = (Rollladenautomatik_zielwert_sued.state as Number).intValue
group_Rollladen_Sued_hight.members.forEach[i|
    if((i.state as Number).intValue < iZiel) {
        logInfo("autoRoll", "Fahre {} auf {} %",i.name,iZiel)
        i.sendCommand(iZiel)
    } else {
        logInfo("autoRoll'" "{} ist weiter geschlossen ({} %) als er geschlossen werden sollte und wird daher ignoriert",i.name,i.state)
    }
]
Der springende Punkt ist die Umwandlung nach Integer, aber es waren da noch einige andere Dinge, die ich angepasst habe.

BITTE nicht dieses schreckliche (und echt schlechte) if(log) logInfo() verwenden. Ich habe das (sehr viel) weiter oben erläutert. logInfo() ist mehr als ein Print-Befehl. Der erste Parameter ist der Loggername und sollte keinesfalls "rules" lauten. Auch ein dateiabhängiger String ist Quatsch. Stattdessen setzt man für logisch zusammenhängende Rule den identischen Loggernamen und kann so gezielt während openHAB läuft! das Logging auf verschiedenen Leveln ein- oder ausschalten. log:set WARN org.openhab.core.module.script.autoRoll schaltet z.B. die Info-Logs aus, lässt aber logWarn() und logError() durch. Mit log:set DEBUG org.openhab.core.module.script.autoRoll werden zusätzlich noch logDebug() Meldungen eingeschaltet. Das ist wesentlich besser als ein ungenaues if(log)

Die log Befehle beherrschen außerdem Substitution, das heißt, innerhalb einer Strings, der als zweiter Parameter angegeben wird (das ist die Meldung, die geloggt wird), werden diese Klammerpaare {} durch die zusätzlich übergebenen Parameter ersetzt, dabei werden die Parameter automatisch nach String gewandelt.
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

Absinthe
Beiträge: 78
Registriert: 16. Jan 2022 13:30
Answers: 0

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

Beitrag von Absinthe »

Hallo @udo1toni,

wieder einmal DANKE für deine ausführliche Antwort.

Bei deiner verbesserten Variante bekomme ich ab dem Bereich des else mit der "logINFO" leider im OH Log mehrere Fehlermeldungen beim Laden der Rule...

Code: Alles auswählen

2023-05-29 11:01:18.373 [WARN ] [el.core.internal.ModelRepositoryImpl] - Configuration model 'auto_verschattung_sued_down.rules' has errors, therefore ignoring it: [30,57]: missing ')' at '"null ist weiter geschlossen (null %) als er geschlossen werden sollte und wird daher ignoriert"'
[30,149]: mismatched input ',' expecting '}'
[30,156]: mismatched input ',' expecting ']'
[30,164]: extraneous input ')' expecting '}'
[32,33]: mismatched input ']' expecting '}'
[48,9]: mismatched input '}' expecting 'end'

2023-05-29 11:03:03.529 [INFO ] [el.core.internal.ModelRepositoryImpl] - Load
Eine Idee, was hier los sein könnte?

Kann es sein, dass in der logINFO anstelle von " immer ' verwendet werden müsste?

Grüße
OpenHAB 4.1.1
in einem Docker-Container
auf einer Synology DS1515+

Benutzeravatar
udo1toni
Beiträge: 13989
Registriert: 11. Apr 2018 18:05
Answers: 222
Wohnort: Darmstadt

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

Beitrag von udo1toni »

Ja, da hat sich ein ' eingeschlichen.

Code: Alles auswählen

logInfo("autoRoll'" "{} ist weiter geschlossen ({} %) als er geschlossen werden sollte und wird daher ignoriert",i.name,i.state)
                 ^ ^
das muss weg. Außerdem fehlt da noch ein Komma...

Code: Alles auswählen

logInfo("autoRoll", "{} ist weiter geschlossen ({} %) als er geschlossen werden sollte und wird daher ignoriert",i.name,i.state)
                ^ ^
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

Absinthe
Beiträge: 78
Registriert: 16. Jan 2022 13:30
Answers: 0

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

Beitrag von Absinthe »

Tadaaa :)

Vielen Dank - jetzt funktioniert die automatische Verschattung einwandfrei :)

Schöne Grüße
OpenHAB 4.1.1
in einem Docker-Container
auf einer Synology DS1515+

jensilein
Beiträge: 34
Registriert: 24. Feb 2018 09:11
Answers: 0

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

Beitrag von jensilein »

Cyrelian hat geschrieben: 14. Jul 2021 17:55 Hi,

zwei Xiaomi Lichtsensoren, angebunden via Deconz.

CU
Cyrelian
Hallo Cyrelian,

könntest Du evtl. kurz einmal posten, wie Du das genau umgesetzt hast von der Programmierung her? Ich bin mit der Verwendung der Bewölkung von OWM auch nicht mehr zufrieden und würde gern auf den von Dir beschriebenen Ansatz schwenken.
Vielen Dank für die Unterstützung.

DJFlaxi
Beiträge: 27
Registriert: 16. Apr 2020 19:40
Answers: 0

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

Beitrag von DJFlaxi »

Hallo zusammen,

ich habe die Rule 1:1 (mit kleinen Anpassungen der Items) aus Post 1 kopiert und bekomme folgende Fehlermeldung:

Code: Alles auswählen

2023-06-11 14:32:07.571 [INFO ] [org.openhab.core.model.script.rules ] - Rolloautomatik (Rollo West ab) - Regel wurde gestartet
2023-06-11 14:32:07.572 [INFO ] [org.openhab.core.model.script.rules ] - Rolloautomatik (Rollo West hoch) - Regel wurde gestartet
2023-06-11 14:32:07.576 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'Rollo-Sonnenstand-1' failed: For input string: "204.0" in Rollo-Sonnenstand
2023-06-11 14:32:07.579 [INFO ] [org.openhab.core.model.script.rules ] - Rolloautomatik (Rollo West hoch) - Beende, da Automatik generell nicht aktiv
Hier meine Rule:

Code: Alles auswählen

var boolean log = true
rule "Rollos West abfahren"
when Item Azimuth changed
then
    val String logPrefix = 'Rolloautomatik (Rollo West 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 (Azimuth.state > Integer::parseInt(Rolloautomatik_azimuth_start.state.toString())) {
                if (LocalWeatherAndForecastCurrentTemperature.state > Integer::parseInt(Rolloautomatik_temp_min.state.toString())) {
                    if (LocalWeatherAndForecastCurrentCloudiness.state  <= Integer::parseInt(Rolloautomatik_wolken_max.state.toString())) { if (Sonnenstand.state > Integer::parseInt(Rolloautomatik_elevation_ende.state.toString())) {
                            // Rollos runterfahren
                            if (log) logInfo('rules', logPrefix + 'Rollos werden abgefahren')
                            gruppeRolladen_West.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
                            sendBroadcastNotification("Verschattung Westseite aktiv") //Pushnachricht
                            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 (' + Sonnenstand.state.toString() + ')')
                        }
                    } else {
                        if (log) logInfo('rules', logPrefix + 'Mindestbewoelkung (' + Rolloautomatik_wolken_max.state.toString() + ') wurde unterschritten (' + LocalWeatherAndForecastCurrentCloudiness.state.toString() + ')')
                    }
                } else {
                    if (log) logInfo('rules', logPrefix + 'Mindest-Temperatur (' + Rolloautomatik_temp_min.state.toString() + ') wurde nicht erreicht durch aktuelle Temperatur (' + LocalWeatherAndForecastCurrentTemperature.state.toString() + ')')
                }
            } else {
                if (log) logInfo('rules', logPrefix + 'Azimuth (' + 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 West wieder öffnen"
when Item Sonnenstand changed
then
    val String logPrefix = 'Rolloautomatik (Rollo West 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_oeffnen.state == ON) {
        if (Sonnenstand.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')
                    gruppeRolladen_West.members.forEach[i|
                        if((Rolloautomatik_zielwert.state as Number).intValue <= (i.state as Number).intValue +5 && (Rolloautomatik_zielwert.state as Number).intValue >= (i.state as Number).intValue -5) {
                            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
                    sendBroadcastNotification("Verschattung Westseite beendet") //Pushnachricht
                    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 (' + Sonnenstand.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
Ich verwende Openhab 3.4.4 und komme einfach nicht drauf, woran es liegt.
Danke vorab für Eure Hilfe.

Viele Grüße
DJFlaxi

Benutzeravatar
udo1toni
Beiträge: 13989
Registriert: 11. Apr 2018 18:05
Answers: 222
Wohnort: Darmstadt

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

Beitrag von udo1toni »

Die Rules sind in dieser Form aus verschiedenen Gründen ned so dolle :)

Formal: logInfo() erzeugt Zeilen im zugehörigen log File (default ist das openhab.log). ABER: Man kann dieses Logging abschalten, und zwar über die Karaf Konsole im laufenden Betrieb. Das geht getrennt für jeden definierten Logger. Der Logger wird mit durch den ersten String definiert, in den Rules also "rules", was halt etwas sehr allgemein ist. Besser wäre z.B. "autoshutter", der entsprechende Logger hieße dann org.openhab.core.model.script.autoshutter (der Teil vor dem letzten Punkt ist für alle Logs aus Rules heraus identisch).
Mittels

Code: Alles auswählen

log:set WARN org.openhab.core.model.script.autoshutter
werden also alle logInfo()-Zeilen spezifisch für diese beiden Rules unterdrückt. Deshalb scheint ein Konstrukt if(log) logInfo() nicht sehr elegant - zumal es mit einem Neustart der Rule Engine verbunden ist - die rules-Datei muss neu eingelesen werden...
Dann die Schachtelung der verschiedenen Bedingungen... es wäre sinnvoller, die Bedingungen in der Form abzuarbeiten, dass, wenn eine Bedingung für das Fahren nicht erfüllt ist, die Meldung geloggt wird und anschließend die Rule direkt beendet wird (dafür gibt es den Befehl return;)
Das Konstrukt, sich über einen Datumsstempel zu merken, ob die Rule am aktuellen Tag bereits ausgeführt wurde, ist auch... mäßig elegant. Einfacher, und genauso wirkungsvoll ist es, sich in einer globalen Variablen zu merken, wenn die Fahrt stattgefunden hat (wahlweise könnte man das auch über Items lösen, die können persistiert werden). Man benötigt lediglich eine Mini Rule, welche um 0 Uhr die Merker zurücksetzt - und falls man schon so eine Mitternachtsrule hat, kann man den Reset auch mit dort rein packen.

Beide Rules werden durch unterschiedliche Ereignisse des selben Bindings getriggert, beide Ereignisse treten immer (!) zeitgleich auf. Es werden also immer (!) beide Rules gestartet, unmittelbar. Es gibt keinen Grund, warum man immer zwei Rules gleichzeitig laufen lässt - eine reicht (allerdings hat das Konsequenzen für die Abbruchbedingungen...).

Es ist recht wichtig, die Status von Items immer auf einen sinnvollen Inhalt zu prüfen. Die beiden Items Azimuth und Sonnenstand enthalten zwei Winkel. in allen aktuellen openHAB Versionen wird also nach der Zahl ein ° stehen (und das ist für openHAB ein wichtiger Unterschied). Man muss das erst los werden, damit Vergleiche mit anderen Zahlen funktionieren. Ähnliches gilt auch für Temperatur (°C) und Bewölkung (%).
Ausnahme: z.B. ein Rollershutter Item liefert immer eine Zahl (genauso ein Dimmer Item) - eigentlich sollten die auch eine Prozentwert liefern, sind aber keine UoM Items :) (UoM -> Units of Measurement, die Einheit wird mit übergeben und auch berücksichtigt, z.B. 0°C == 32°F - das geht tatsächlich!)

Ich gehe anhand der Fehlermeldung davon aus, dass hier der eigentliche Fehler liegt (Wert wird nicht korrekt gewandelt) Könnte auch damit zusammenhängen, dass hier fälschlich ein intValue genutzt wird, die Winkel Azimuth und Sonnenstand (eigentlich Elevation) sind aber vom Typ Float.

Hier mal eine aktuell überarbeitete Variante unter Berücksichtigung aller obigen Punkte.
Zu beachten wäre noch, dass es diverse Grenzwerte gibt, die korrekt gesetzt wein müssen. Man könnte default Werte direkt in der Rule einpflegen (bei der Konstantendefinition hinter dem else des ternären Operators)

Code: Alles auswählen

// Globale Variablen müssen vor der ersten Rule definiert werden!
var Boolean bAutoZu  = false
var Boolean bAutoAuf = false

rule "Rollos West abfahren"
    when Item Azimuth changed
then
    logInfo('autoshutter', 'Rolloautomatik (West) - Regel wurde gestartet')
    if(bAutoAuf && bAutoZu) {
        logInfo('autoshutter', 'Rolloautomatik (West) - Stoppe die Rule frühzeitig, da bereits beide Bewegungen stattfanden.')
        return;
    }
    // lokale Variablen definieren
    var Boolean bNoAutoZu  = false
    var Boolean bNoAutoAuf = false

    // lokale Konstanten definieren
    val fAzimuthIs    = if(Rolloautomatik_azimuth_start.state instanceof Number) (Rolloautomatik_azimuth_start.state as Number).floatValue else 0.0
    val fElevationIs  = if(Sonnenstand.state instanceof Number) (Sonnenstand.state as Number).floatValue else 0.0
    val fTempIs       = if(LocalWeatherAndForecastCurrentTemperature.state instanceof Number) (LocalWeatherAndForecastCurrentTemperature.state as Number).floatValue else 0.0
    val iCloudIs      = if(LocalWeatherAndForecastCurrentCloudiness.state instanceof Number) (LocalWeatherAndForecastCurrentCloudiness.state as Number).intValue else 100

    val fAzimuthMin   = if(Azimuth.state instanceof Number) (Azimuth.state as Number).floatValue else 270.0
    val fElevationMin = if(Rolloautomatik_elevation_ende.state instanceof Number) (Rolloautomatik_elevation_ende.state as Number).floatValue else 90.0
    val fTempMin      = if(Rolloautomatik_temp_min.state instanceof Number) (Rolloautomatik_temp_min.state as Number) else 23.0
    val iCloudMax     = if(Rolloautomatik_wolken_max.state instanceof Number) (Rolloautomatik_wolken_max.state as Number).intValue else 0

    val iZiel = if(Rolloautomatik_zielwert.state instanceof Number) (Rolloautomatik_zielwert.state as Number).intValue else 0

    // Prüfen der Bedingungen für ab

    if(Rolloautomatik.state != ON) {
        logInfo('autoshutter', 'Rolloautomatik (West) - kein Abwärts, da Automatik generell nicht aktiv')
        bNoAutoZu = true
    }
    if(bAutoZu && !bNoAutoZu) {
        logInfo('autoshutter', 'Rolloautomatik (West) - kein Abwärts, da bereits ausgeführt')
        bNoAutoZu = true
    }
    if(fAzimuthMin > fAzimuthIs && !bNoAutoZu) {
        logInfo('autoshutter', 'Rolloautomatik (West) - kein Abwärts, Azimuth ({}) hat noch nicht Schwellwert ({}) erreicht', fAzimuthIs, fAzimuthMin)
        bNoAutoZu = true
    }
    if(fTempIs <= fTempMin && !bNoAutoZu) {
        logInfo('autoshutter', 'Rolloautomatik (West) - kein Abwärts, Mindest-Temperatur ({}°C) wurde nicht erreicht; aktuelle Temperatur: {}°C',fTempMin, fTempIs)
        bNoAutoZu = true
    }
    if(iCloudIs > iCloudMax && !bNoAutoZu) {
        logInfo('autoshutter', 'Rolloautomatik (West) - kein Abwärts, Maximalbewölkung ({}%) wurde überschritten ({}%)', iCloudMax, iCloudIs)
        bNoAutoZu = true
    }
    if(fElevationIs >= fElevationMin && !bNoAutoZu) {
        logInfo('autoshutter', 'Rolloautomatik (West) - kein Abwärts, Elevation für abfahren ({}°) ist kleiner als aktuelle ({}°)', fElevationMin, fElevationIs)
        bNoAutoZu = true
    }
    if(!bNoAutoZu) {    // Rollos runterfahren
        logInfo('autoshutter', 'Rolloautomatik (West ab) - Rollos werden abgefahren')
        gruppeRolladen_West.members.forEach[i|
            if((i.state as Number) <= iZiel) {
                logInfo('autoshutter', 'Rolloautomatik (West ab) - Fahre Rollladen auf {}%: {}', Rolloautomatik_zielwert.state, i.name)
                i.sendCommand(iZiel)
            } else 
                logInfo('autoshutter', 'Rolloautomatik (West ab) - Rollladen ist bereits weiter geschlossen ({}%) als er geschlossen werden sollte und wird daher ignoriert', i.state)
        ]
        sendBroadcastNotification("Verschattung Westseite aktiv") //Pushnachricht
        bAutoZu = true
        return;
    }

    // prüfen der Bedingungen für hoch

    if(Rolloautomatik_oeffnen.state != ON) {
        logInfo('autoshutter', 'Rolloautomatik (West) - kein Aufwärts, da Automatik generell nicht aktiv')
        bNoAutoAuf = true
    }
    if(fElevationIs > fElevationMin && !bNoAutoAuf) {
        logInfo('autoshutter', 'Rolloautomatik (West) - kein Aufwärts, da Elevation ({}°) nicht kleiner als eingestellte Elevation ({}°) war',fElevationIs,fElevationMin)
        bNoAutoAuf = true
    }
    if(!bAutoZu && !bNoAutoAuf) {
        logInfo('autoshutter', 'Rolloautomatik (West) - kein Aufwärts, da heute noch kein Abwärts stattfand. Demzufolge kann auch kein automatisches Öffnen gewollt sein')
        bNoAutoAuf = true
    }
    if(bAutoAuf && !bNoAutoAuf) {
        logInfo('autoshutter', 'Rolloautomatik (West) - kein Aufwärts, da heute bereits ein automatisches Wiederhochfahren stattfand')
        bNoAutoAuf = true
    }
    if(!bNoAutoAuf) {     // Rollos wieder hoch
        logInfo('autoshutter', 'Rolloautomatik (West hoch) - Rollos werden hochgefahren')
        gruppeRolladen_West.members.forEach[i|
            val iPosRel = Math.abs((i.state as Number).intValue - iZiel) // Abweichung des aktuellen Ladens von Zielwert
            if(iPosRel <= 5) {
                logInfo('autoshutter', 'Rolloautomatik (West hoch) - Fahre Rollladen {} auf 0%', i.name)
                i.sendCommand(0)
            } else
                logInfo('autoshutter', 'Rolloautomatik (West hoch) - Fahre Rollladen {} nicht auf 0%, da dieser zwischenzeitlich manuell verändert wurde', i.name)
        ]
        sendBroadcastNotification("Verschattung Westseite beendet") //Pushnachricht
        bAutoAuf = true
    }
end

rule "Reset globale Variablen"
when
    Time cron "1 0 0 * * ?"
then
    bAutoAuf = false
    bAutoZu  = false
end
Ich habe in diesem Thread genau die angesprochenen Probleme schon mehrfach erläutert :)
Bei so langen Threads ist es oft keine gute Idee, den Inhalt des ersten Post zu nutzen (ja, das wird in anderen Foren gerne anders gehandhabt, da werden solche Posts immer mal wieder auf den neuesten Stand gebracht - hier aber eher nicht)
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

thoffacker
Beiträge: 7
Registriert: 9. Mär 2021 01:25
Answers: 0

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

Beitrag von thoffacker »

Hallo zusammen,

ich habe mit großem Interesse das Projekt verfolgt und finde es echt klasse, was ihr hier auf die Beine gestellt habt!

Ich bin nun auch endlich dazu gekommen, die Rule bei mir zu implementieren und habe versucht aus den ganzen Beiträgen hier eine eigene Regel zu erstellen. Leider habe ich nur rudimentäre Kenntnisse im Programmieren und bin deshalb auf eure Hilfe angewiesen.

Im großen und ganzen funktioniert die Rule nun. Ich habe nun allerdings ein Problem bei Zeile 106 bis 114. Hier möchte ich die Gruppe variabel zuordnen, wie Udo das am 15.7.2020 vorgeschlagen hat.

Ich bekomme nun wie cupra6 3 Beiträge weiter, ebenfalls Fehler angezeigt:
Screenshot 2023-06-21 224439.png
Auch im Log bekomme ich einen Fehler:
Screenshot 2023-06-21 224529.png
Auch "allMembers" anstatt "members" funktionier leider nicht.

Wenn ich jedoch, wie von Udo vorgeschlagen die Gruppe der einzelnen Gruppen nehme, fahren immer alle Rollos.

Habt ihr vielleicht noch eine Idee, an was das liegt und wie ich das lösen könnte?

RULES-Datei:

Code: Alles auswählen

// Globale Variablen müssen vor der ersten Rule definiert werden!
import java.util.Map
var Number closingAzimuth_east = 300
var Number closingAzimuth_south = 120
var Number closingAzimuth_west = 210

var boolean isActiveWest = false
var boolean isActiveEast = false
var boolean isActiveSouth = false

val Map<String, Number> targetHights = newHashMap ( 
    "R_OL3_01" -> 75,
    "R_OL4_01" -> 75,
    "R_OR3_01" -> 75,
    "R_OL5_01" -> 75,
    "R_OR2_01" -> 75,
    "R_OR3_02" -> 75,
    "R_OR4_01" -> 75,
    "R_OR5_01" -> 75
)

var String strGroup = ""

rule "Rollos abfahren"
    when Item LokaleSonnendaten_Azimut changed
then
    logInfo('shading', 'Rolloautomatik ab - Regel wurde gestartet')
    
    // lokale Variablen definieren


    // lokale Konstanten definieren
    val fAzimuthIs    = if(LokaleSonnendaten_Azimut.state instanceof Number) (LokaleSonnendaten_Azimut.state as Number).floatValue else 0.0
    val fElevationIs  = if(LokaleSonnendaten_Hohenwinkel.state instanceof Number) (LokaleSonnendaten_Hohenwinkel.state as Number).floatValue else 0.0
    val fTempIs       = if(Wetterinformationen_Aussentemperatur.state instanceof Number) (Wetterinformationen_Aussentemperatur.state as Number).floatValue else 0.0
    val iCloudIs      = if(Wetterinformationen_Bewolkung.state instanceof Number) (Wetterinformationen_Bewolkung.state as Number).intValue else 100

    val fAzimuthMin   = if(v_rollo_azimuth_start.state instanceof Number) (v_rollo_azimuth_start.state as Number).floatValue else 270.0
    val fElevationMin = 20//if(Rolloautomatik_elevation_ende.state instanceof Number) (Rolloautomatik_elevation_ende.state as Number).floatValue else 90.0
    val fTempMin      = if(v_rollo_temp_min.state instanceof Number) (v_rollo_temp_min.state as Number) else 23.0
    val iCloudMax     = if(v_rollo_wolken_max.state instanceof Number) (v_rollo_wolken_max.state as Number).intValue else 0

    // Prüfen der Bedingungen für ab

    if(v_rollo.state != ON) {
        logInfo('shading', 'Rolloautomatik - kein Abwärts, da Automatik generell nicht aktiv')
        return;
    }
    if(sw_DayNight.state != ON) {
        logInfo('shading', 'Rolloautomatik - kein Abwärts, da Nacht')
        return;
    }
    if(fAzimuthMin > fAzimuthIs) {
        logInfo('shading', 'Rolloautomatik - kein Abwärts, Azimuth ({}) hat noch nicht Schwellwert ({}) erreicht', fAzimuthIs, fAzimuthMin)
        return;
    }
    if (v_rollo_start_letzter.state == NULL) {
        logInfo("shading", "Letzte Ausführung unbekannt, Belegung mit Initialwert (gestern)")
        v_rollo_start_letzter.postUpdate(new DateTimeType(now.minusDays(1)))
    }
    if(fTempIs <= fTempMin) {
        logInfo('shading', 'Rolloautomatik - kein Abwärts, Mindest-Temperatur ({}°C) wurde nicht erreicht; aktuelle Temperatur: {}°C',fTempMin, fTempIs)
        return;
    }
    if(iCloudIs > iCloudMax) {
        logInfo('shading', 'Rolloautomatik - kein Abwärts, Maximalbewölkung ({}%) wurde überschritten ({}%)', iCloudMax, iCloudIs)
        return;
    }
    if(fElevationIs >= fElevationMin) {
        logInfo('shading', 'Rolloautomatik - kein Abwärts, Elevation für abfahren ({}°) ist kleiner als aktuelle ({}°)', fElevationMin, fElevationIs)
        return;
    }
    val nAz = (LokaleSonnendaten_Azimut.state as Number).floatValue
    strGroup = ""

    //Azimuth ist größer als 210° (West)
    switch(true) { // erste zutreffende Bedingung wird exclusiv ausgeführt (alle nachfolgenden nicht, auch wenn sie zutreffen)
        case nAz > closingAzimuth_west : {
            if(!isActiveWest) {
                logInfo ("shading", "Verschattung für Rollläden WEST")
                strGroup = "g_R_OG_West"
                isActiveWest = true
            }
        }
        case nAz > closingAzimuth_south : {// hinreichend, da 1. Bedingung nicht zutrifft
            if(!isActiveSouth) {
                logInfo ("shading", "Verschattung für Rollläden SÜD")
                strGroup = "g_R_OG_Sued"
                isActiveSouth = true
            }
        }
        case nAz > closingAzimuth_east : {// hinreichend, da 2. Bedingung nicht zutrifft
            if(!isActiveEast){
                logInfo ("shading", "Verschattung für Rollläden OST")
                strGroup = "g_R_OG_Ost"
                isActiveEast = true
            }
        }
    }
    if(strGroup == "") { // strGroup ist leer bzw. nicht definiert
        logInfo ("shading", "Verschattung bereits aktiv oder außerhalb des Verschattungsbereichs")
        return;
    }
    val myGroup = g_R_OG_Group.members.filter[i|i.name == strGroup].head

    myGroup.members.forEach[ blind |
        if ((blind.state as Number) < targetHights.get(blind.name.toString()).intValue) {
            logInfo ("shading", "Fahre Rollladen ({}) auf ({}) %",blind.name,targetHights.get(blind.name.toString()))
            blind.sendCommand(targetHights.get(blind.name.toString()).intValue)
            //sendTelegram("bot1","Verschattung für " + blind.name.toString + " aktiviert, schließen auf " + targetHights.get(blind.name.toString()).toString() + " %")
        } else {
            logInfo ("shading", "Rollladen ({}) ist bereits weiter geschlossen ({} %) als er geschlossen werden sollte und wird daher ignoriert",blind.name,blind.state)
        }
    ]
    v_rollo_start_letzter.postUpdate(new DateTimeType(now.toString()))
end

rule "Rollos auffahren"
when 
    Item LokaleSonnendaten_Azimut changed
then
    logInfo('shading', 'Rolloautomatik hoch - Regel wurde gestartet')

    // prüfen der Bedingungen für hoch

    if (v_rollo_ende_letzter.state === NULL) {
        logInfo("shading", "Letzte Ausführung unbekannt, Belegung mit Initialwert (-1 Tag)")
        v_rollo_ende_letzter.postUpdate(new DateTimeType(now.minusDays(1)))
        }
    if(v_rollo.state != ON) {
        logInfo('shading', 'Rolloautomatik - kein Aufwärts, da Automatik generell nicht aktiv')
        return;
    }
    if(sw_DayNight.state != ON) {
        logInfo('shading', 'Rolloautomatik - kein Aufwärts, da Nacht')
        return;
    }
    if (!isActiveWest && !isActiveEast && !isActiveSouth) {
        logInfo("shading", "Beende, da heute noch keine automatische Verschattung stattfand")
        return;
    }    
    if ((LokaleSonnendaten_Azimut.state as Number).floatValue > (v_rollo_azimuth_ende_ost.state as Number).floatValue && (LokaleSonnendaten_Azimut.state as Number).floatValue < (v_rollo_azimuth_ende_ost.state as Number).floatValue +5) {
            logInfo("shading", "Verschattung für Rollläden OST beenden")
            g_R_OG_Ost.members.forEach[ blind |
                if ((blind.state as Number) -5 < targetHights.get(blind.name.toString()).intValue && (blind.state as Number) +5 > targetHights.get(blind.name.toString()).intValue) {
                    logInfo ("shading", "Fahre Rollladen ({}) auf 0%",blind.name)
                    blind.sendCommand(0)
                    //sendTelegram("bot1","Verschattung für " + blind.name.toString + " aktiviert, schließen auf " + targetHights.get(blind.name.toString()).toString() + " %")
                } else {
                    logInfo ("shading", "Fahre Rolladen {} nicht auf 0%, da dieser zwischenzeitlich manuell verändert wurde.",blind.name)
                }
            ]
            //shadingEnd.apply(g_R_OG_Ost)
            
            return;
    }
end
Hinweis: das wieder auffahren geht aktuell nur für Osten, die anderen Himmelsrichtungen muss ich noch machen
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.

Antworten