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

Antworten
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 »

Hier nun eine Frage zu einem bestimmten Item in der Rule.

Code: Alles auswählen

timeLast = Rolloautomatik_start_last.state.toString().substring(0,10)
In das Item "Rolloautomatik_start_last" wird der Zeitpunkt geschrieben wann die Rolladen runter gefahren wurden
so das die Rule nur einmal am Tag ausführt.

Kann ich diese Item auch persistieren ? Denn wenn OpenHab zwischenzeitlich neugestartet wurde, ist das Item ja erst mal
ohne "Zeitstempel"....
- OpenHab 2.4
#PWRUP

Benutzeravatar
Cyrelian
Beiträge: 601
Registriert: 24. Sep 2015 17:55
Answers: 4

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

Beitrag von Cyrelian »

Hi Peter,

den timeLast direkt nicht. Ich würde ein ITEM vom Typ DateTime anlegen und dann immer ein postUpdate drauf machen, bzw. einfach das Rollladenautomatik_Start_last persistieren mit everyChange, everyMinute, restoreOnStartup.

CU
Cyrelian

Benutzeravatar
Cyrelian
Beiträge: 601
Registriert: 24. Sep 2015 17:55
Answers: 4

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

Beitrag von Cyrelian »

Hi,

ich versuche gerade die Rule um eine lambda Funktion zu erweitern. Hänge aber gerade (ich vermute irgendwo falsch "geklammert") :roll:

bei dem VAL bekomme ich:
missing EOF at 'val'(org.eclipse.xtext.diagnostics.Diagnostic.Syntax)

Code: Alles auswählen

val Functions$Function1<GenericItem, String> Shading= [ shutter |
                if ((localCurrentTemperature.state as Number).floatValue > (AutoShading_Temp_min.state as Number)) {
                    if ((localCurrentCloudiness.state as Number).floatValue <= (AutoShading_Cloudiness_max.state as Number)) { 
                        if ((Elevation.state as Number) > (AutoShading_Elevation_ende.state as Number)) {
                            // Rollladen runterfahren
                            if (log) logInfo(filename, logPrefix + 'Rollladen werden runtergefahren')
                            shutter.forEach[blind|
                                if (blind.state as Number < (AutoShading_ShutterTargetPercent.state as Number)) {
                                    if (log) logInfo(filename, logPrefix + 'Fahre Rollladen auf ' + AutoShading_ShutterTargetPercent.state.toString() + '%: ' + blind.name)
                                    blind.sendCommand(AutoShading_ShutterTargetPercent.state as Number)
                                    //Pushnachricht versenden
                                    sendPushoverMessage(pushoverBuilder("Abschattung für " + blind.name.toString "aktiviert"))
                                } else {
                                    if (log) logInfo(filename, logPrefix + 'Rollladen ist bereits weiter geschlossen (' + blind.state.toString() + '%) als er geschlossen werden sollte und wird daher ignoriert')
                                }
                            ]
                            // Letzte Ausführung mit entsprechendem Zeitstempel belegen
                            AutoShading_Start_last.postUpdate(new DateTimeType())
                        } else {
                            if (log) logInfo(filename, logPrefix + 'Elevation für wieder abfahren (' + AutoShading_Elevation_ende.state.toString() + ') ist groesser als aktuelle (' + Elevation.state.toString() + ')')
                        }
                    } else {
                        if (log) logInfo(filename, logPrefix + 'Mindestbewoelkung (' + AutoShading_Cloudiness_max.state.toString() + ') wurde unterschritten (' + localCurrentCloudiness.state.toString() + ')')
                    }
                } else {
                    if (log) logInfo(filename, logPrefix + 'Mindest-Temperatur (' + AutoShading_Temp_min.state.toString() + ') wurde nicht erreicht durch aktuelle Temperatur (' + localCurrentTemperature.state.toString() + ')')
                }
end
Ideen? ;)

CYA
Cyrelian

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

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

Beitrag von udo1toni »

Eine Funktion endet mit der schließenden eckigen Klammer, nicht mit dem Schlüsselwort end (das hat überhaupt nichts in der Funktion zu suchen).

Allgemein ist der Ansatz der Funktionen in openHAB eher fragwürdig. rikoshak hat da im englischen Forum mal einen längeren Erklär-Artikel geschrieben; Normalerweise gibt es elegantere Ansätze, die ohne Funktionsaufrufe auskommen.
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

Benutzeravatar
Cyrelian
Beiträge: 601
Registriert: 24. Sep 2015 17:55
Answers: 4

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

Beitrag von Cyrelian »

Hi,

ups, das war noch ne alte Version. Die eckige Klammer hab ich bereits gefunden ;) . Du meinst den Artikel oder?
https://community.openhab.org/t/reusabl ... s/15888/11

Mein Ziel ist es eigentlich die Rollladen der verschiedenen Himmelsrichtungen in einer Rule abzufangen. Das würde mit eine Funktion relativ einfach laufen.

Code: Alles auswählen

rule "Abschattung starten"
when
    Item Azimuth changed
then
    val String logPrefix = 'Abschattung aktivieren - '
    if (log) logInfo(filename, logPrefix + 'Regel wurde gestartet')
    
    var String timeLast = 'xxxx-xx-xx'
    if (AutoShading_Start_last.state == NULL) {
        if (log) logInfo(filename, logPrefix + 'Erstmalige Ausführung, Belegung mit Initialwerten')
    } else {
        timeLast = AutoShading_Start_last.state.toString().substring(0,10)
    }
	var String timeNow = now.toString().substring(0,10)

    if (AutoShading.state == ON) {
        if (timeNow != timeLast) {
            //175 >
            if ((Azimuth.state as Number).floatValue > (AutoShading_Azimuth_west.state as Number)) {
                Shading.apply(gRollladenWest)
                return;
                }
            //110 >
            if ((Azimuth.state as Number).floatValue < (AutoShading_Azimuth_south.state as Number)) {
                Shading.apply(gRollladenSouth)
                return;
                }
            //70 >
            if ((Azimuth.state as Number).floatValue < (AutoShading_Azimuth_east.state as Number)) {
                Shading.apply(gRollladenEast)
                return;
                }
             } else {
                if (log) logInfo(filename, logPrefix + 'Automatik heute bereits einmal gelaufen, wird daher ignoriert')
                }
        } else {
          if (log) logInfo(filename, logPrefix + 'Beende, da Abschattung deaktiviert ist')
          }
end

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 »

Cyrelian hat geschrieben: 22. Jun 2019 10:03 Hi,

ups, das war noch ne alte Version. Die eckige Klammer hab ich bereits gefunden ;) . Du meinst den Artikel oder?
https://community.openhab.org/t/reusabl ... s/15888/11

Mein Ziel ist es eigentlich die Rollladen der verschiedenen Himmelsrichtungen in einer Rule abzufangen. Das würde mit eine Funktion relativ einfach laufen.

Code: Alles auswählen

rule "Abschattung starten"
when
    Item Azimuth changed
then
    val String logPrefix = 'Abschattung aktivieren - '
    if (log) logInfo(filename, logPrefix + 'Regel wurde gestartet')
    
    var String timeLast = 'xxxx-xx-xx'
    if (AutoShading_Start_last.state == NULL) {
        if (log) logInfo(filename, logPrefix + 'Erstmalige Ausführung, Belegung mit Initialwerten')
    } else {
        timeLast = AutoShading_Start_last.state.toString().substring(0,10)
    }
	var String timeNow = now.toString().substring(0,10)

    if (AutoShading.state == ON) {
        if (timeNow != timeLast) {
            //175 >
            if ((Azimuth.state as Number).floatValue > (AutoShading_Azimuth_west.state as Number)) {
                Shading.apply(gRollladenWest)
                return;
                }
            //110 >
            if ((Azimuth.state as Number).floatValue < (AutoShading_Azimuth_south.state as Number)) {
                Shading.apply(gRollladenSouth)
                return;
                }
            //70 >
            if ((Azimuth.state as Number).floatValue < (AutoShading_Azimuth_east.state as Number)) {
                Shading.apply(gRollladenEast)
                return;
                }
             } else {
                if (log) logInfo(filename, logPrefix + 'Automatik heute bereits einmal gelaufen, wird daher ignoriert')
                }
        } else {
          if (log) logInfo(filename, logPrefix + 'Beende, da Abschattung deaktiviert ist')
          }
end
Coole Sache.
Aber wenn die Rule einmal etwas ausgeführt hat dann wird doch ein Zeitstempel Gesetzt damit die Rule nicht noch mal ausführt...
Das würde ja bedeuten es müsste für jede Himmelsrichtung ein eigener Zeitstempel gesetzt werden ?

Gruß Peter
- OpenHab 2.4
#PWRUP

Benutzeravatar
Cyrelian
Beiträge: 601
Registriert: 24. Sep 2015 17:55
Answers: 4

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

Beitrag von Cyrelian »

Hi Peter,

gutes Auge ;) . Genau so ist es. Bis jetzt gibt es nur einen Zeitstempel. Ich baue es noch so um, dass jede Himmelsrichtung eine Zeitstempel bekommt.
Bin mir aber noch nicht sicher, ob ich das mit in die Funktion oder in die Rule packe. Eigentlich ist es mir in der Rule lieber, da ich mir dann den Aufruf der Funktion spare...mal schauen :? .
Erstmal will ich die Funktion ans laufen bekommen.

CU
Cyrelian

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 »

Cyrelian hat geschrieben: 22. Jun 2019 11:31 Hi Peter,

gutes Auge ;) . Genau so ist es. Bis jetzt gibt es nur einen Zeitstempel. Ich baue es noch so um, dass jede Himmelsrichtung eine Zeitstempel bekommt.
Bin mir aber noch nicht sicher, ob ich das mit in die Funktion oder in die Rule packe. Eigentlich ist es mir in der Rule lieber, da ich mir dann den Aufruf der Funktion spare...mal schauen :? .
Erstmal will ich die Funktion ans laufen bekommen.

CU
Cyrelian
Top!
Ich bin gespannt. Denn ich habe derzeit für zwei Himmelsrichtungen jeweils zwei individuelle Rules (Schliessen und Öffnen). Wenn man das im eine Rule packen könnte ist das bestimmt besser....

Gruß Peter
- OpenHab 2.4
#PWRUP

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 »

Und was natürlich auch besser ist die "Sollwerte" fest in die Rule zu schreiben. Das spart auch das persistieren usw.....
- OpenHab 2.4
#PWRUP

Benutzeravatar
Cyrelian
Beiträge: 601
Registriert: 24. Sep 2015 17:55
Answers: 4

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

Beitrag von Cyrelian »

Hi,

so, hat was länger gedauert und ich hatte noch ein kleines Problem mit der LAMBDA Funktion, bei der mir Rich aus der Community geholfen hat.
Danke auch an Seppy, bei dem hab ich die "val Map" abgeschaut :D

Der Ansatz ist etwas anders, da ich viel mit "early returns" gearbeitet habe, sobald ein Parameter nicht zutrifft. Damit wird die rule übersichtlicher (kaum einrücken und verschateln).

Code: Alles auswählen

import java.util.Map

// Das Logging und Messaging kann für diese Rules separat aktiviert werden (log=true)
var boolean log = true
var boolean message = true

val String filename = "shutter.rules"

var boolean returnvalueWest = false
var boolean returnvalueEast = false
var boolean returnvalueSouth = false

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

var Number closingAzimuth_west = 181
var Number closingAzimuth_south = 111
var Number closingAzimuth_east = 65

var Number closingCloudiness = 25
var Number openingTemperature = 22

val Map<String, Number> targetHights = newHashMap ( 
    "KuecheRollladenTuer" -> 58,
    "SchlafzimmerRollladenTuer" -> 100,
    "BadezimmerRollladen" -> 55,
    "WohnzimmerRollladenEsstisch" -> 65,
    "WohnzimmerRollladenTuer" -> 68,
    "WohnzimmerRollladenBalkon" -> 100
)

/* -------------  Automatische Abschattung ein/aus --------------------
*/

//-------------  Abschattung FUNKTION --------------------

val shadingStart = [GroupItem shutter |

        val String logPrefix = "Abschattung aktivieren - "
        var boolean log = true

        logInfo ("Lambda", logPrefix + shutter)

                val Map<String, Number> targetHights = newHashMap ( 
                "KuecheRollladenTuer" -> 58,
                "SchlafzimmerRollladenTuer" -> 100,
                "BadezimmerRollladen" -> 55,
                "WohnzimmerRollladenEsstisch" -> 65,
                "WohnzimmerRollladenTuer" -> 68,
                "WohnzimmerRollladenBalkon" -> 100
                )

                if ((localCurrentTemperature.state as Number).floatValue <= (AutoShading_Temp_min.state as Number)) {
                        if (log) logInfo ("Lambda", logPrefix + "Mindesttemperatur von (" + AutoShading_Temp_min.state.toString() + ") wurde nicht erreicht. Aktuelle Temperatur (" + localCurrentTemperature.state.toString() + ")")
                        return false;
                }

                if ((localCurrentCloudiness.state as Number).floatValue > (AutoShading_Cloudiness_max.state as Number)) { 
                        if (log) logInfo ("Lambda", logPrefix + "Aktuelle Bewoelkung (" + localCurrentCloudiness.state.toString() + ") ueberschreitet den eingestellten Grenzwert von (" + AutoShading_Cloudiness_max.state.toString() + ")")
                        return false;
                }

                if ((Elevation.state as Number) <= (AutoShading_Elevation_end.state as Number)) {
                        if (log) logInfo ("Lambda", logPrefix + "Elevation für das Beenden der Abschattung (" + AutoShading_Elevation_end.state.toString() + ") ist groesser als aktuelle (" + Elevation.state.toString() + ")")
                        return false;
                }

                // Rollladen werden geschlossen
                if (log) logInfo("Lambda", logPrefix + "Grenzwert wurden erreicht, Rollladen werden geschlossen")

                shutter.members.forEach[ blind |
                    if ((blind.state as Number) < targetHights.get(blind.name.toString()).intValue) {
                        logInfo ("Lambda", logPrefix + "Fahre Rollladen (" + blind.name.toString() + ") auf (" + targetHights.get(blind.name.toString()).intValue + ") %" )
                        //blind.sendCommand(targetHights.get(blind.name.toString()).intValue)
                        //Pushnachricht versenden
                        sendPushoverMessage(pushoverBuilder("Abschattung für " + blind.name.toString + " aktiviert, schließen auf " + targetHights.get(blind.name.toString()).toString() + " %"))
                    } else {
                        logInfo ("Lambda", logPrefix + "Rollladen ist bereits weiter geschlossen (" + blind.state.toString() + "%) als er geschlossen werden sollte und wird daher ignoriert")
                    }
                ]
                AutoShading_Start_last.postUpdate(now.toString())
    return true;
]

//-------------  Abschattung starten --------------------

rule "Abschattung starten"
when
    Time cron  "0/30 * * * * ?" or
    Item Azimuth changed
then
    val String logPrefix = "Abschattung aktivieren - "
    
    //Prüfung ob Abschattungsautomatik an ist und ob es Tag ist
    if (AutoShading.state == ON && IsDay.state == ON) {
    
            //var String timeNow = now.toString().substring(0,10)
            //var String timeLastStart = AutoShading_Start_last.state.toString().substring(0,10)
            
            // Items für Sitemap füllen
            if (AutoShading_Azimuth_east == "NULL" ||  AutoShading_Azimuth_south == "NULL" || AutoShading_Azimuth_west == "NULL" ){
                    AutoShading_Azimuth_east.postUpdate(closingAzimuth_west)
                    AutoShading_Azimuth_south.postUpdate(closingAzimuth_south)
                    AutoShading_Azimuth_west.postUpdate(closingAzimuth_west)
            }
            
            //Azimuth ist größer als 181° (WEST)
            if (returnvalueWest == false) { 
                if ((Azimuth.state as Number).floatValue > (closingAzimuth_west)) {
                    if (log) logInfo (filename, logPrefix + "Abschatung für Rollläden WEST")
                    returnvalueWest = shadingStart.apply(gRollladenWest)
                    return;
                }      
            } 
           
            //Azimuth ist größer als 111° (SÜD)
           if (returnvalueSouth == false) { 
                if ((Azimuth.state as Number).floatValue > (closingAzimuth_south) && (Azimuth.state as Number).floatValue < (closingAzimuth_west)) {
                    if (log) logInfo (filename, logPrefix + "Abschatung für Rollläden SÜD")
                    returnvalueSouth = shadingStart.apply(gRollladenSouth)
                    return;
                }
           }

            //Azimuth ist größer als 65° (OST)
            if (returnvalueEast == false) { 
                if ((Azimuth.state as Number).floatValue > (closingAzimuth_east) && (Azimuth.state as Number).floatValue < (closingAzimuth_south)) {
                if (log) logInfo (filename, logPrefix + "Abschatung für Rollläden OST")
                returnvalueEast = shadingStart.apply(gRollladenEast)
                return;
                }
            }
    
    } else {
            if (log) logInfo(filename, logPrefix + "Abschattung ist deaktiviert, oder es ist Nacht.")
           }

end

//-------------  Abschattung beenden --------------------

rule "Abschattung beenden"
when 
    Time cron  "0/45 * * * * ?" or
    Item Elevation changed
then   
    if (AutoShading_end.state == ON && IsDay.state == ON) {
                    
            val String logPrefix = "Abschattung deaktivieren - "
            
            var String timeNow = now.toString().substring(0,10)
            var String timeLastEnde = AutoShading_End_last.state.toString().substring(0,10)


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

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

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

            if (returnvalueWest == false && returnvalueEast == false && returnvalueSouth == false) {
                if (log) logInfo(filename, logPrefix + "Beende, da heute noch keine automatische Abschattung stattfand")
                return;
            }

            if (returnvalueWest == true || returnvalueEast == true || returnvalueSouth == true) {
                            // Rollladen öffnen
                            if (log) logInfo(filename, logPrefix + "Rollladen werden geoeffnet")
                            gRollladen.allMembers.forEach[blind|
                                if((blind.state as Number).intValue == targetHights.get(blind.name.toString()).intValue) {
                                    if (log) logInfo(filename, logPrefix + "Oeffne Rollladen: " + blind.name.toString())
                                    blind.sendCommand(UP)
                                    //Pushnachricht versenden                        
                                    sendPushoverMessage(pushoverBuilder("Abschattung für (" + blind.name.toString() + ") beendet, Rollladen wird geöffnet."))
                                } else {
                                    if (log) logInfo(filename, 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(now.toString())
                            
                            //Variablen zurücksetzen
                            returnvalueWest = false
                            returnvalueEast = false
                            returnvalueSouth = false
            }
        }            
end
Hoffe das hilft dem einen oder anderen weiter oder dient als Gedankenanstoß. Bei Fragen...immer raus damit ;)

CYA
Cyrelian

Antworten