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
pweissen
Beiträge: 4
Registriert: 24. Apr 2020 07:39

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

Beitrag von pweissen »

Vielen Dank für den Input zum Logging. Was das genau in der Rule bewirkt hat war mir bewusst. Mich hat es nur gewundert, dass es wohl nicht mehr mit neueren openhab Versionen funktioniert. @udo1toni Danke für den Tipp mit vscode und openhab. Das nutze ich auch schon, nur vll sollte ich auch die Instanz in den Settings hinterlegen an der ich gerade arbeite :D Aber ich debugge dann jetzt mal genauer.

pweissen
Beiträge: 4
Registriert: 24. Apr 2020 07:39

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

Beitrag von pweissen »

Das Debugging mit vscode war extrem hilfreich! Danke dafür.
Jetzt habe ich nur noch ein kleines Problem. Für die Items AutoShading_Temp_diff, AutoShading_Cloudiness_Hyst, AutoShading_Rain_min sind bei mir NULL. Mir fehlt also die Rule zur Berechnung dieser Werte. @Cyrelian kannst du mir deine Rule dafür posten?

Edit:
Hat sich erledigt ;-)

pweissen
Beiträge: 4
Registriert: 24. Apr 2020 07:39

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

Beitrag von pweissen »

So letztes Problem :D
Leider bewegen sich die Rollladen noch nicht. Ich habe meine Rollläden entsprechenden in Gruppen gesteckt. Beispiel gruppeRolloWest beinhaltet "Rollo_KiziWest_Percent".
Laut dem nachfolgende Code

Code: Alles auswählen

 //Azimuth ist größer als 181° (WEST)
            if (!isActiveWest) { 
                if ((astro_azimuth.state as Number).floatValue > (closingAzimuth_west)) {
                    logInfo( logPrefix, "Verschattung für Rollläden WEST")
                    isActiveWest = shadingStart.apply(gruppeRolloWest)
                    return;
                }      
             } else {
                     logInfo(logPrefix, "Verschattung für Rollläden WEST bereits aktiviert")
                 } 
sollte er in die Funktion

Code: Alles auswählen

val shadingStart = [GroupItem shutter |

        val String logPrefix = "Verschattung aktivieren - "

                val Map<String, Number> targetHights = newHashMap ( 
                // "KuecheRollladenTuer" -> 58,
                // "SchlafzimmerRollladenTuer" -> 100,
                // "BadezimmerRollladen" -> 55,
                // "WohnzimmerRollladenEsstisch" -> 65,
                 "Rollo_KiziWest_Percent" -> 50,
                 "Rollo_KiziSued_Percent" -> 50
                )
gehen. Laut openhab.log passiert das auch aber es bewegt sich nichts. Ich vermutet das hat etwas mit dieser Map zu tun. Daher die Frage zu den Strings in dieser Map. Ich habe dort meine Rollläden Items eingetragen. Sollte ja richtig sein, oder? Und was ich nicht verstehe ich das "GroupItem shutter". Ist das eine neue Gruppe die dynamisch erstellt wird? Ich habe nämlich keine Gruppe "shutter" bei mir in Openhab. Ich habe eine andere Gruppe die alle Rollläden beinhaltet (gruppeRollo).
Hier der ganze Code, falls das einfacher zu verstehen ist:

Code: Alles auswählen

// Values und Variablen für die Verschattung

//val Number blindClosed = 100
//val Number blindOpen = 0
//val Number blindTranslucent = 35
import java.util.Map
var Number closingAzimuth_west = 181
var Number closingAzimuth_south = 111
var Number closingAzimuth_east = 65

var Number closingCloudiness = 20   
val Number cloudHysteresis = 45         //die Mindestbewölkung in der letzten Stunde
var Number openingTemperature = 22
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 isActiveWest = false
var boolean isActiveEast = false
var boolean isActiveSouth = false


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

val shadingStart = [GroupItem shutter |

        val String logPrefix = "Verschattung aktivieren - "

                val Map<String, Number> targetHights = newHashMap ( 
                // "KuecheRollladenTuer" -> 58,
                // "SchlafzimmerRollladenTuer" -> 100,
                // "BadezimmerRollladen" -> 55,
                // "WohnzimmerRollladenEsstisch" -> 65,
                 "Rollo_KiziWest_Percent" -> 50,
                 "Rollo_KiziSued_Percent" -> 50
                )

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

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

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

                // Rollladen werden geschlossen
                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("Verschattung 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;
]

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

val shadingEnd = [GroupItem shutter |

        val String logPrefix = "Verschattung deaktivieren - "

                    val Map<String, Number> targetHights = newHashMap ( 
                    // "KuecheRollladenTuer" -> 58,
                    // "SchlafzimmerRollladenTuer" -> 100,
                    // "BadezimmerRollladen" -> 55,
                    // "WohnzimmerRollladenEsstisch" -> 65,
                    "Rollo KiziWest" -> 50,
                    "Rollo KiziSued" -> 100
                     )
                    
                    // Rollladen öffnen
                    logInfo ("Lambda", logPrefix, "Rollladen werden geoeffnet")
                    shutter.allMembers.forEach[blind|
                        if((blind.state as Number).intValue == targetHights.get(blind.name).intValue) {
                            logInfo ("Lambda", logPrefix, "Oeffne Rollladen: " + blind.name.toString())
                            blind.sendCommand(100)
                            //Pushnachricht versenden                        
                            //sendPushoverMessage(pushoverBuilder("Verschattung für (" + blind.name.toString() + ") beendet, Rollladen wird geöffnet."))
                        } else {
                            logInfo ("Lambda", 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
                    isActiveWest = false
                    isActiveEast = false
                    isActiveSouth = false
    return true;
]

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

rule "Verschattung starten"
when
    Item astro_azimuth changed
then
    val String logPrefix = "Verschattung aktivieren - "

    //Prüfung auf: Verschattungsautomatik an / ob es Tag ist / Präsenz / Jahreszeit
    if ((AutoShading.state == ON && Daylight.state == ON) && (Jahreszeit.state== "SPRING" || Jahreszeit.state== "SUMMER")) {
  
            if (AutoShading_Start_last.state === NULL) {
                logInfo(logPrefix, "Letzte Ausführung unbekannt, Belegung mit Initialwert (-1 Tag)")
                    AutoShading_Start_last.postUpdate(now.minusDays(1).toString())
                }
            
            //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)
                    AutoShading_Temp_diff.postUpdate(temperatureHysteresis)
                    AutoShading_Cloudiness_Hyst.postUpdate(cloudHysteresis)
                    AutoShading_Rain_min.postUpdate(minPrecip)
            }
            
            //Azimuth ist größer als 181° (WEST)
            if (!isActiveWest) { 
                if ((astro_azimuth.state as Number).floatValue > (closingAzimuth_west)) {
                    logInfo( logPrefix, "Verschattung für Rollläden WEST")
                    isActiveWest = shadingStart.apply(gruppeRolloWest)
                    return;
                }      
             } else {
                     logInfo(logPrefix, "Verschattung für Rollläden WEST bereits aktiviert")
                 } 
        
            //Azimuth ist größer als 111° (SÜD)
           if (!isActiveSouth) { 
                if ((astro_azimuth.state as Number).floatValue > (closingAzimuth_south) && (astro_azimuth.state as Number).floatValue < (closingAzimuth_west)) {
                    logInfo(logPrefix, "Verschattung für Rollläden SÜD")
                    isActiveSouth = shadingStart.apply(gruppeRolloSouth)
                    return;
                }
           } else {
                     logInfo(logPrefix, "Verschattung für Rollläden SÜD bereits aktiviert")
                }

            //Azimuth ist größer als 65° (OST)
            if (!isActiveEast) { 
                if ((astro_azimuth.state as Number).floatValue > (closingAzimuth_east) && (astro_azimuth.state as Number).floatValue < (closingAzimuth_south)) {
                    logInfo(logPrefix, "Verschattung für Rollläden OST")
                    isActiveEast = shadingStart.apply(gruppeRolloEast)
                return;
                }
            } else {
                     logInfo(logPrefix, "Verschattung für Rollläden OST bereits aktiviert")
                }
    
    } else {
            logInfo(logPrefix, "Verschattung wird nicht ausgeführt, da einer der folgenden Parameter matched: Verschattung deakiviert, es ist Nacht, Herbst oder Winter erkannt.")
           }
end

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

rule "Verschattung beenden"
when 
    Item Elevation changed
then   
    if ((AutoShading_end.state == ON && Daylight.state == ON) && (Jahreszeit.state=="SPRING" || Jahreszeit.state=="SUMMER")) {
                    
            val String logPrefix = "Verschattung deaktivieren - "
            
            val boolean isRainLastHour = (Rain.maximumSince(now.minusHours(1), "influxdb").state >= (minPrecip))
            logInfo(logPrefix, "Rain " + isRainLastHour)
            
            val boolean isCloudLastHour = (Clouds.averageSince(now.minusHours(1), "influxdb")as Number >= (cloudHysteresis))
            logInfo(logPrefix, "Clouds " + isCloudLastHour )
            
            val boolean isTemperature = ((Temperature.state as Number).intValue < (Temperature.minimumSince(now.minusHours(1), "influxdb").state as DecimalType -(temperatureHysteresis)))
            logInfo(logPrefix, "Temperatur " + isTemperature)
            
            
            if (AutoShading_End_last.state === NULL) {
                logInfo(logPrefix, "Letzte Ausführung unbekannt, Belegung mit Initialwert (-1 Tag)")
                    AutoShading_End_last.postUpdate(now.minusDays(1).toString())
                }

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

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

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

            if (isTemperature) {
                logInfo(logPrefix, "Verschattung beenden, Temperaturabfall von min. ({})° erkannt", temperatureHysteresis)
                shadingEnd.apply(gruppeRollo)
                return;
            }

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

            if (isRainLastHour || isCloudLastHour) {
                logInfo(logPrefix, "Verschattung beenden, Mindestregenmenge von ({}) mm oder druchschnittliche Bewölkung von ({}) % erreicht",minPrecip, cloudHysteresis)
                shadingEnd.apply(gruppeRollo)
                return;
            }
            if ((Elevation.state as Number) > (AutoShading_Elevation_end.state as Number)) {
               logInfo(logPrefix, "Beende, aktuelle Elevation ({}) ueberschreitet den eingestellten Grenzwert von ({}) ", Elevation.state, AutoShading_Elevation_end.state)
               return;
            }
            if (isActiveWest || isActiveEast || isActiveSouth ) {
                logInfo (logPrefix, "Verschattung beenden")
                shadingEnd.apply(gruppeRollo)
                return;
            }
        }            
end


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

rule "Verschattung Variablen zurücksetzen"
when
        Time cron "15 59 23 * * ?"
then
        if (isActiveWest == true || isActiveEast == true || isActiveSouth == true) {
            isActiveWest = false
            isActiveEast = false
            isActiveSouth = false
        }
end

EDIT: Klappt nun. :D :D :D :D

cupra6
Beiträge: 35
Registriert: 4. Jan 2019 22:09

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

Beitrag von cupra6 »

Erstmal vielen herzlichen Dank an ALLE die hier mitgewirkt haben, eine MEGA Projekt !!!
Habe sehr lange auf sowas gewartet und ich glaube ich bin kurz davor, dass es auch funktioniert :-)

Leider will bei mir die Regel nicht:

hier die RULES Datei

Code: Alles auswählen

// Values und Variablen für die Verschattung

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

import java.util.Map

var Number closingAzimuth_east = 85
var Number closingAzimuth_south = 111
var Number closingAzimuth_west = 171
var Number closingAzimuth_north = 260

var Number closingCloudiness = 20   
val Number cloudHysteresis = 45         //die Mindestbewölkung in der letzten Stunde
var Number openingTemperature = 22
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 isActiveWest = false
var boolean isActiveEast = false
var boolean isActiveSouth = false
var boolean isActiveNorth = false


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

val shadingStart = [GroupItem shutter |

        val String logPrefix = "Verschattung aktivieren - "
        //var boolean log = true

                val Map<String, Number> targetHights = newHashMap ( 
                "Shutter_EG_Office" -> 74,
                
                "Shutter_EG_Wohnen3" -> 64,
                
                "Shutter_EG_Kueche2" -> 40,
                "Shutter_EG_Wohnen1" -> 78,
                "Shutter_EG_Wohnen2" -> 78,
                
                "Shutter_EG_Technik" -> 73,
                "Shutter_OG_HWR" -> 74

                //"KuecheRollladenTuer" -> 58,
                //"SchlafzimmerRollladenTuer" -> 100,
                //"BadezimmerRollladen" -> 55,
                //"WohnzimmerRollladenEsstisch" -> 65,
                //"WohnzimmerRollladenTuer" -> 68,
                //"WohnzimmerRollladenBalkon" -> 100
                )

                // Temperature.state wird durch weatherN_Temperature ausgetauscht !!! insgesamt 4x
                //if ((Temperature.state as Number).floatValue <= (AutoShading_Temp_min.state as Number)) {
                if ((weatherN_Temperature.state as Number).floatValue <= (AutoShading_Temp_min.state as Number)) {
                        //logInfo ("Lambda", logPrefix + "Mindesttemperatur von (" + AutoShading_Temp_min.state.toString() + ") wurde nicht erreicht. Aktuelle Temperatur (" + Temperature.state.toString() + ")")
                        logInfo ("Lambda", logPrefix + "Mindesttemperatur von ({}) wurde nicht erreicht. Aktuelle Temperatur ({}) ", AutoShading_Temp_min.state, weatherN_Temperature.state)
                        return false;
                }

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

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

                // Rollladen werden geschlossen
                logInfo("Lambda", logPrefix + "Grenzwerte 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("Verschattung für " + blind.name.toString + " aktiviert, schließen auf " + targetHights.get(blind.name.toString()).toString() + " %"))
                        sendTelegram("bot1","Verschattung 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;
]

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

val shadingEnd = [GroupItem shutter |

        val String logPrefix = "Verschattung deaktivieren - "
        //var boolean log = true

                val Map<String, Number> targetHights = newHashMap ( 
                "Shutter_EG_Office" -> 74,
                
                "Shutter_EG_Wohnen3" -> 64,
                
                "Shutter_EG_Kueche2" -> 40,
                "Shutter_EG_Wohnen1" -> 78,
                "Shutter_EG_Wohnen2" -> 78,
                
                "Shutter_EG_Technik" -> 73,
                "Shutter_OG_HWR" -> 74

                //"KuecheRollladenTuer" -> 58,
                //"SchlafzimmerRollladenTuer" -> 100,
                //"BadezimmerRollladen" -> 55,
                //"WohnzimmerRollladenEsstisch" -> 65,
                //"WohnzimmerRollladenTuer" -> 68,
                //"WohnzimmerRollladenBalkon" -> 100
                    //"KuecheRollladenTuer" -> 58,
                    //"SchlafzimmerRollladenTuer" -> 100,
                    //"BadezimmerRollladen" -> 55,
                    //"WohnzimmerRollladenEsstisch" -> 65,
                    //"WohnzimmerRollladenTuer" -> 68,
                    //"WohnzimmerRollladenBalkon" -> 100
                     )
                    
                    // Rollladen öffnen
                    logInfo ("Lambda", logPrefix + "Rollladen werden geoeffnet")
                    shutter.allMembers.forEach[blind|
                        if((blind.state as Number).intValue == targetHights.get(blind.name).intValue) {
                            logInfo ("Lambda", logPrefix + "Oeffne Rollladen: " + blind.name.toString())
                            blind.sendCommand(UP)
                            //Pushnachricht versenden                        
                            //sendPushoverMessage(pushoverBuilder("Verschattung für (" + blind.name.toString() + ") beendet, Rollladen wird geöffnet."))
                            sendTelegram("bot1", "Verschattung für (" + blind.name.toString() + ") beendet, Rollladen wird geöffnet.")
                        } else {
                            logInfo ("Lambda", 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
                    isActiveWest = false
                    isActiveEast = false
                    isActiveSouth = false
                    isActiveNorth = false
    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 / Präsenz / Jahreszeit
    //if ((AutoShading.state == ON && IsDay.state == ON) && (DinesiPhone_Presence.state == OFF && OllisiPhone_Presence.state == OFF) && (Jahreszeit.state=="SPRING" || Jahreszeit.state=="SUMMER")) {
    if ((AutoShading.state == ON && IsDay.state == ON) && (Jahreszeit.state=="SPRING" || Jahreszeit.state=="SUMMER")) {
               
            if (AutoShading_Start_last.state === NULL) {
                logInfo(logPrefix, 'Letzte Ausführung unbekannt, Belegung mit Initialwert (-1 Tag)')
                    AutoShading_Start_last.postUpdate(now.minusDays(1).toString())
                }
            
            //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_north == "NULL" ){
                    //AutoShading_Azimuth_east.postUpdate(closingAzimuth_west)
                    AutoShading_Azimuth_east.postUpdate(closingAzimuth_east)
                    AutoShading_Azimuth_south.postUpdate(closingAzimuth_south)
                    AutoShading_Azimuth_west.postUpdate(closingAzimuth_west)
                    AutoShading_Azimuth_north.postUpdate(closingAzimuth_north)
                    AutoShading_Temp_diff.postUpdate(temperatureHysteresis)
                    AutoShading_Cloudiness_Hyst.postUpdate(cloudHysteresis)
                    AutoShading_Rain_min.postUpdate(minPrecip)
            }
            
            
            //Azimuth ist größer als 270° (NORD)
            if (!isActiveNorth) { 
                if ((Azimuth.state as Number).floatValue > (closingAzimuth_north)) {
                    logInfo ("rules", logPrefix + "Verschattung für Rollläden NORD")
                    isActiveNorth = shadingStart.apply(gRollladenNorth)
                    return;
                }      
            } else {
                     logInfo ("rules", logPrefix + "Verschattung für Rollläden NORD bereits aktiviert")
                }
            
            //Azimuth ist größer als 181° (WEST)
            if (!isActiveWest) { 
                //if ((Azimuth.state as Number).floatValue > (closingAzimuth_west)) {
                if ((Azimuth.state as Number).floatValue > (closingAzimuth_west) && (Azimuth.state as Number).floatValue < (closingAzimuth_north)) {
                    logInfo ("rules", logPrefix + "Verschattung für Rollläden WEST")
                    isActiveWest = shadingStart.apply(gRollladenWest)
                    return;
                }      
            } else {
                     logInfo ("rules", logPrefix + "Verschattung für Rollläden WEST bereits aktiviert")
                } 
        
            //Azimuth ist größer als 111° (SÜD)
           if (!isActiveSouth) { 
                if ((Azimuth.state as Number).floatValue > (closingAzimuth_south) && (Azimuth.state as Number).floatValue < (closingAzimuth_west)) {
                    logInfo ("rules", logPrefix + "Verschattung für Rollläden SÜD")
                    isActiveSouth = shadingStart.apply(gRollladenSouth)
                    return;
                }
           } else {
                     logInfo ("rules", logPrefix + "Verschattung für Rollläden SÜD bereits aktiviert")
                }

            //Azimuth ist größer als 65° (OST)
            if (!isActiveEast) { 
                if ((Azimuth.state as Number).floatValue > (closingAzimuth_east) && (Azimuth.state as Number).floatValue < (closingAzimuth_south)) {
                    logInfo ("rules", logPrefix + "Verschattung für Rollläden OST")
                    isActiveEast = shadingStart.apply(gRollladenEast)
                return;
                }
            } else {
                     logInfo ("rules", logPrefix + "Verschattung für Rollläden OST bereits aktiviert")
                }
    
    } else {
            //logInfo("rules", logPrefix + "Verschattung wird nicht ausgeführt, da einer der folgenden Parameter matched: Verschattung deakiviert, es ist Nacht, Herbst oder Winter oder Anwesenheit erkannt.")
            logInfo("rules", logPrefix + "Verschattung wird nicht ausgeführt, da einer der folgenden Parameter matched: Verschattung deakiviert, es ist Nacht, Herbst oder Winter erkannt.")
           }

end

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

rule "Verschattung beenden"
when 
    Item Elevation changed
then   
    if ((AutoShading_end.state == ON && IsDay.state == ON) && (Jahreszeit.state=="SPRING" || Jahreszeit.state=="SUMMER")) {
                    
            val String logPrefix = "Verschattung deaktivieren - "
            
            val boolean isRainLastHour = (Rain.maximumSince(now.minusHours(1), "influxdb").state >= (minPrecip))
            logInfo("rules", logPrefix + "Rain " + isRainLastHour)
            
            val boolean isCloudLastHour = (Clouds.averageSince(now.minusHours(1), "influxdb")as Number >= (cloudHysteresis))
            logInfo("rules", logPrefix + "Clouds " + isCloudLastHour )
            
            val boolean isTemperature = ((weatherN_Temperature.state as Number).intValue < (weatherN_Temperature.minimumSince(now.minusHours(1), "influxdb").state as DecimalType -(temperatureHysteresis)))
            logInfo("rules", logPrefix + "Temperatur " + isTemperature)
            
            
            if (AutoShading_End_last.state === NULL) {
                logInfo(logPrefix, "Letzte Ausführung unbekannt, Belegung mit Initialwert (-1 Tag)")
                    AutoShading_End_last.postUpdate(now.minusDays(1).toString())
                }

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

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

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

            if (isTemperature) {
                logInfo ("rules", logPrefix + "Verschattung beenden, Temperaturabfall von min. ({})° erkannt", temperatureHysteresis)
                shadingEnd.apply(gRollladen)
                return;
            }

            if ((weatherN_Temperature.state as Number).floatValue > (AutoShading_Temp_raise.state as Number)) {
                logInfo("rules", logPrefix + "Beende, aktuelle Temperatur ({})° ueberschreitet den eingestellten Grenzwert zum hochfahren von ({})°",weatherN_Temperature.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)
                shadingEnd.apply(gRollladen)
                return;
            }
            if ((Elevation.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 (isActiveWest || isActiveEast || isActiveSouth ) {
                logInfo ("rules", logPrefix + "Verschattung beenden")
                shadingEnd.apply(gRollladen)
                return;
            }
        }            
end


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

rule "Verschattung Variablen zurücksetzen"
when
        Time cron "15 59 23 * * ?"
then
        if (isActiveNorth == true || isActiveWest == true || isActiveEast == true || isActiveSouth == true) {
            isActiveNorth = false
            isActiveWest = false
            isActiveEast = false
            isActiveSouth = false
        }
end
Folgende Fehlermeldung bekomme ich:

Code: Alles auswählen

2020-06-07 20:49:40.206 [INFO ] [clipse.smarthome.model.script.Lambda] - Verschattung aktivieren - Grenzwerte wurden erreicht, Rollladen werden geschlossen

2020-06-07 20:49:40.215 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Verschattung starten': cannot invoke method public abstract int java.lang.Number.intValue() on null

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

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

Beitrag von udo1toni »

Also, <Nörgelmodus> ;)

Die Formatierung Deiner Rules ist unübersichtlich. Einrückungen sind dazu da, zusammengehörende Codeteile deutlicher erkennbar zu machen. Massig auskommentierte Befehle helfen auch nicht. Die Hashmap wird unnötigerweise mehrfach definiert.
Du verwendest das Logging falsch. Der Befehl logInfo() erwartet zwei Strings als Parameter, wobei der erste String der Logger Name ist. Weder "Rules" noch "Lambda" sind im openHAB-Umfeld sinnvolle Loggernamen. Der Loggername in Rules wird ohnehin immer in den Loggerbaum integriert, und zwar im Zweig org.openhab.model.script.
Die Auslagerung eines Teils des Codes in ein Lambda erhöht die Komplexität, ohne dass es (hier) Vorteile bringt.
</Nörgelmodus>

Die (ungetesteten) Rules, (einigermaßen) vom Balast befreit:

Code: Alles auswählen

import java.util.Map

var Number closingAzimuth_east = 85
var Number closingAzimuth_south = 111
var Number closingAzimuth_west = 171
var Number closingAzimuth_north = 260

var Number closingCloudiness = 20
val Number cloudHysteresis = 45         //die Mindestbewölkung in der letzten Stunde
var Number openingTemperature = 22
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 isActiveWest = false
var boolean isActiveEast = false
var boolean isActiveSouth = false
var boolean isActiveNorth = false

val Map<String, Number> targetHights = newHashMap ( 
    "Shutter_EG_Office" -> 74,
    "Shutter_EG_Wohnen3" -> 64,
    "Shutter_EG_Kueche2" -> 40,
    "Shutter_EG_Wohnen1" -> 78,
    "Shutter_EG_Wohnen2" -> 78,
    "Shutter_EG_Technik" -> 73,
    "Shutter_OG_HWR" -> 74
)

rule "Verschattung starten"
when
    Item Azimuth changed
then
    if (AutoShading.state != ON) {                                                                  // Verschattung deaktiviert?
        logInfo("shading", "Verschattung wird nicht ausgeführt, da deaktiviert."
        return;
    }
    if (IsDay.state != ON) {                                                                        // Nacht?
        logInfo("shading", "Verschattung wird nicht ausgeführt, da Nacht."
        return;
    }
    if (Jahreszeit.state.toString !="SPRING" && Jahreszeit.state.toString != "SUMMER") {            // Winter oder Herbst?
        logInfo("shading", "Verschattung wird nicht ausgeführt, da weder, Frühling noch Sommer.")
        return;
    }
    if (AutoShading_Start_last.state == NULL) {
        logInfo("shading", "Letzte Ausführung unbekannt, Belegung mit Initialwert (gestern)")
        AutoShading_Start_last.postUpdate(now.minusDays(1).toString())
    }
    // 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_west.state == NULL)    AutoShading_Azimuth_west.postUpdate(closingAzimuth_west)
    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 ((weatherN_Temperature.state as Number).floatValue <= (AutoShading_Temp_min.state as Number)) {
        logInfo ("shading", "Mindesttemperatur von {} °C wurde nicht erreicht. Aktuelle Temperatur {} °C", AutoShading_Temp_min.state, weatherN_Temperature.state)
        return false;
    }
    if ((Clouds.state as Number).floatValue > (AutoShading_Cloudiness_max.state as Number)) { 
        logInfo ("shading", "Aktuelle Bewoelkung {} % ueberschreitet den eingestellten Grenzwert von {} %", Clouds.state, AutoShading_Cloudiness_max.state)
        return false;
    }
    if ((Elevation.state as Number) <= (AutoShading_Elevation_end.state as Number)) {
        logInfo ("shading", "Elevation für das Beenden der Verschattung {} ° ist groesser als aktuelle {}°", AutoShading_Elevation_end.state, Elevation.state)
        return false;
    }
    val nAz = Azimuth.state as Number).floatValue

    //Azimuth ist größer als 270° (NORD)
    switch(true) { // erste zutreffende Bedingung wird exclusiv ausgeführt (alle nachfolgenden nicht, auch wenn sie zutreffen)
        case nAz > closingAzimuth_north : {
            if(!isActiveNorth) {
                logInfo ("shading", "Verschattung für Rollläden NORD")
                val myGroup = gRollladenNorth
                isActiveNorth = true
            }
        }
        case nAz > closingAzimuth_west : { // hinreichend, da 1. Bedingung nicht zutrifft
                if(!isActiveWest) {
                logInfo ("shading", "Verschattung für Rollläden WEST")
                val myGroup = gRollladenWest
                isActiveWest = true
            }
        }
        case nAz > closingAzimuth_south : {// hinreichend, da 2. Bedingung nicht zutrifft
            if(!isActiveSouth) {
                logInfo ("shading", "Verschattung für Rollläden SÜD")
                val myGroup = gRollladenSouth
                isActiveSouth = true
            }
        }
        case nAz > closingAzimuth_east : {// hinreichend, da 3. Bedingung nicht zutrifft
            if(!isActiveEast){
                logInfo ("shading", "Verschattung für Rollläden OST")
                val myGroup = gRollladenEast
                isActiveEast = true
            }
        }
    }
    if(myGroup === null) { // myGroup ist leer bzw. nicht definiert
        logInfo ("shading", "Verschattung bereits aktiv oder außerhalb des Verschattungsbereichs")
        return;
    }
    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.state)
        }
    ]
    AutoShading_Start_last.postUpdate(now.toString())
end

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

rule "Verschattung beenden"
when 
    Item Elevation changed
then
    if (AutoShading.state != ON) {                                                                  // Verschattung deaktiviert?
        logInfo("shading", "Verschattungsende wird nicht ausgeführt, da deaktiviert."
        return;
    }
    if (IsDay.state != ON) {                                                                        // Nacht?
        logInfo("shading", "Verschattungsende wird nicht ausgeführt, da Nacht."
        return;
    }
    if (Jahreszeit.state.toString !="SPRING" && Jahreszeit.state.toString != "SUMMER") {            // Winter oder Herbst?
        logInfo("shading", "Verschattungsende wird nicht ausgeführt, da weder, Frühling noch Sommer.")
        return;
    }
    val boolean isRainLastHour = (Rain.maximumSince(now.minusHours(1), "influxdb").state >= (minPrecip))
    logInfo("shading", "Rain " + isRainLastHour)
    val boolean isCloudLastHour = (Clouds.averageSince(now.minusHours(1), "influxdb")as Number >= (cloudHysteresis))
    logInfo("shading", "Clouds " + isCloudLastHour )
    val boolean isTemperature = ((weatherN_Temperature.state as Number).intValue < (weatherN_Temperature.minimumSince(now.minusHours(1), "influxdb").state as DecimalType -(temperatureHysteresis)))
    logInfo("shading", "Temperatur " + isTemperature)
    if (AutoShading_End_last.state === NULL) {
        logInfo("shading", "Letzte Ausführung unbekannt, Belegung mit Initialwert (-1 Tag)")
        AutoShading_End_last.postUpdate(now.minusDays(1).toString())
        }
    var String timeNow = now.toString().substring(0,10)
    var String timeLastEnde = AutoShading_End_last.state.toString().substring(0,10)
    if (timeLastEnde == timeNow) {
        logInfo("shading", "Beende, da heute bereits ein automatisches Hochfahren stattfand")
        return;
    }
    if (!isActiveWest && !isActiveEast && !isActiveSouth && !isActiveNorth) {
        logInfo("shading", "Beende, da heute noch keine automatische Verschattung stattfand")
        return;
    }
    if ((weatherN_Temperature.state as Number).floatValue > (AutoShading_Temp_raise.state as Number)) {
        logInfo("shading", "Beende, aktuelle Temperatur ({})° ueberschreitet den eingestellten Grenzwert zum hochfahren von ({})°",weatherN_Temperature.state, AutoShading_Temp_raise.state )
        return;
    }
    if ((Elevation.state as Number) > (AutoShading_Elevation_end.state as Number)) {
       logInfo("shading", "Beende, aktuelle Elevation ({}) ueberschreitet den eingestellten Grenzwert von ({}) ", Elevation.state, AutoShading_Elevation_end.state)
       return;
    }
    var boolean bEnd = false
    if (isTemperature) {
        logInfo ("shading", "Verschattung beenden, Temperaturabfall von min. ({})°C erkannt", temperatureHysteresis)
        bEnd = true
    }
    if (isRainLastHour || isCloudLastHour) {
        logInfo ("shading", "Verschattung beenden, Mindestregenmenge von ({}) mm oder druchschnittliche Bewölkung von ({}) % erreicht",minPrecip, cloudHysteresis)
        bEnd = true
    }
    if (isActiveWest || isActiveEast || isActiveSouth ) {
        logInfo ("shading", "Verschattung beenden")
        bEnd = true
    }
    if (!bEnd) return;
    gRolladen.allMembers.forEach[blind|
        if((blind.state as Number) == targetHights.get(blind.name)) {
            logInfo ("shading", "Öffne Rollladen ", blind.name)
            blind.sendCommand(UP)
            sendTelegram("bot1", "Verschattung für (" + blind.name + ") beendet, Rollladen wird geöffnet.")
        } else {
            logInfo ("shading", "Rollladen {} wird nicht geoeffnet, da dieser zwischenzeitlich manuell verändert wurde.",blind.name)
        }
    ]
    // Letzte Ausführung mit entsprechendem Zeitstempel belegen
    AutoShading_End_last.postUpdate(now.toString())
    //Variablen zurücksetzen
    isActiveWest = false
    isActiveEast = false
    isActiveSouth = false
    isActiveNorth = false
end

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

rule "Verschattung Variablen zurücksetzen"
when
    Time cron "15 59 23 * * ?"
then
    isActiveNorth = false
    isActiveWest = false
    isActiveEast = false
    isActiveSouth = false
end
Das Problem, warum die Rule nicht funktioniert, ist eine Variable, die nicht mit einem gültigen Wert gefüllt ist (null kann nicht nach Integer gecastet werden). Dieses Problem ist noch nicht in den Rules berücksichtigt.
Beide Rules (Beschattung Ein/Aus) werden immer gleichzeitig getriggert, da beide Rules von Astro Items abhängen, welche sich bei jedem Update ändern. So gesehen wäre es sinnvoller, beide Rules als eine Rule zu definieren und die Funktionsweise der Rules entsprechend anzupassen. Auch wäre es sinnvoll, das Logging zu minimieren, soweit die Rule nichts zu tun hat.
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,

bin heute zufälligerweise über etwas gestolpert was die "boolean" angeht.

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

Diese werde zur Laufzeit auf TRUE gesetzt. Gibt es die Möglichkeit, von "aussen" zu prüfen, ob diese auf TRUE oder FALSE stehen, oder sie gar zu ändern? Via REST API gehts nicht.

THX
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 habs jetzt mal so gebaut ;).

Code: Alles auswählen

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 (isActiveWest) {
                            logInfo("rules", logPrefix + "Verschattung für Rollläden WEST aktiv")
                        } else { 
                            logInfo("rules", logPrefix + "Verschattung für Rollläden WEST 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 (isActiveBalkon) {
                            logInfo("rules", logPrefix + "Verschattung für Markise (Balkon) aktiv")
                        } else { 
                            logInfo("rules", logPrefix + "Verschattung für Markise (Balkon) inaktiv")
                        }
            }
            case "reset" : {
                    logInfo("rules", logPrefix + "Verschattung Variablen reset")
                    isActiveWest = false
                    isActiveEast = false
                    isActiveSouth = false
                    isActiveBalkon = false
                }
        }
        Shading_Var.postUpdate(NULL) 
end
Vielleicht habt ihr ja noch andere Ideen.

CYA
Cyrelian

msantoni
Beiträge: 1
Registriert: 12. Jun 2020 22:55

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

Beitrag von msantoni »

hallo Bin ganz neu

bei mir kommt in log immer diese Meldung. Habe es versucht zu verstehen aber ohne Erfolg. Galube se hängt vom grad Zeichen?

Code: Alles auswählen

2020-07-01 12:10:20.219 [INFO ] [eclipse.smarthome.model.script.rules] - Rolloautomatik (Rollo West ab) - Azimuth (143.45207931536362 °) hat noch nicht Schwellwert (119) erreicht

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 msantoni,

ohne deine Items/Code zu kennen ist das etwas schwierig zu analysieren. Ich Tippe aber mal drauf, dass dein Item für Azimuth so aussieht:

Code: Alles auswählen

Number:Angle Azimuth "Azimuth"
Deine Rule kann die beiden Werte nicht vergleichen.

Deswegen versuch es mal so:

Code: Alles auswählen

Number Azimuth "Azimuth"   
Cu
Cyrelian

cupra6
Beiträge: 35
Registriert: 4. Jan 2019 22:09

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

Beitrag von cupra6 »

udo1toni hat geschrieben: 8. Jun 2020 01:20 Also, <Nörgelmodus> ;)

Die Formatierung Deiner Rules ist unübersichtlich. Einrückungen sind dazu da, zusammengehörende Codeteile deutlicher erkennbar zu machen. Massig auskommentierte Befehle helfen auch nicht. Die Hashmap wird unnötigerweise mehrfach definiert.
Du verwendest das Logging falsch. Der Befehl logInfo() erwartet zwei Strings als Parameter, wobei der erste String der Logger Name ist. Weder "Rules" noch "Lambda" sind im openHAB-Umfeld sinnvolle Loggernamen. Der Loggername in Rules wird ohnehin immer in den Loggerbaum integriert, und zwar im Zweig org.openhab.model.script.
Die Auslagerung eines Teils des Codes in ein Lambda erhöht die Komplexität, ohne dass es (hier) Vorteile bringt.
</Nörgelmodus>

Die (ungetesteten) Rules, (einigermaßen) vom Balast befreit:

Code: Alles auswählen

import java.util.Map

var Number closingAzimuth_east = 85
var Number closingAzimuth_south = 111
var Number closingAzimuth_west = 171
var Number closingAzimuth_north = 260

var Number closingCloudiness = 20
val Number cloudHysteresis = 45         //die Mindestbewölkung in der letzten Stunde
var Number openingTemperature = 22
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 isActiveWest = false
var boolean isActiveEast = false
var boolean isActiveSouth = false
var boolean isActiveNorth = false

val Map<String, Number> targetHights = newHashMap ( 
    "Shutter_EG_Office" -> 74,
    "Shutter_EG_Wohnen3" -> 64,
    "Shutter_EG_Kueche2" -> 40,
    "Shutter_EG_Wohnen1" -> 78,
    "Shutter_EG_Wohnen2" -> 78,
    "Shutter_EG_Technik" -> 73,
    "Shutter_OG_HWR" -> 74
)

rule "Verschattung starten"
when
    Item Azimuth changed
then
    if (AutoShading.state != ON) {                                                                  // Verschattung deaktiviert?
        logInfo("shading", "Verschattung wird nicht ausgeführt, da deaktiviert."
        return;
    }
    if (IsDay.state != ON) {                                                                        // Nacht?
        logInfo("shading", "Verschattung wird nicht ausgeführt, da Nacht."
        return;
    }
    if (Jahreszeit.state.toString !="SPRING" && Jahreszeit.state.toString != "SUMMER") {            // Winter oder Herbst?
        logInfo("shading", "Verschattung wird nicht ausgeführt, da weder, Frühling noch Sommer.")
        return;
    }
    if (AutoShading_Start_last.state == NULL) {
        logInfo("shading", "Letzte Ausführung unbekannt, Belegung mit Initialwert (gestern)")
        AutoShading_Start_last.postUpdate(now.minusDays(1).toString())
    }
    // 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_west.state == NULL)    AutoShading_Azimuth_west.postUpdate(closingAzimuth_west)
    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 ((weatherN_Temperature.state as Number).floatValue <= (AutoShading_Temp_min.state as Number)) {
        logInfo ("shading", "Mindesttemperatur von {} °C wurde nicht erreicht. Aktuelle Temperatur {} °C", AutoShading_Temp_min.state, weatherN_Temperature.state)
        return false;
    }
    if ((Clouds.state as Number).floatValue > (AutoShading_Cloudiness_max.state as Number)) { 
        logInfo ("shading", "Aktuelle Bewoelkung {} % ueberschreitet den eingestellten Grenzwert von {} %", Clouds.state, AutoShading_Cloudiness_max.state)
        return false;
    }
    if ((Elevation.state as Number) <= (AutoShading_Elevation_end.state as Number)) {
        logInfo ("shading", "Elevation für das Beenden der Verschattung {} ° ist groesser als aktuelle {}°", AutoShading_Elevation_end.state, Elevation.state)
        return false;
    }
    val nAz = Azimuth.state as Number).floatValue

    //Azimuth ist größer als 270° (NORD)
    switch(true) { // erste zutreffende Bedingung wird exclusiv ausgeführt (alle nachfolgenden nicht, auch wenn sie zutreffen)
        case nAz > closingAzimuth_north : {
            if(!isActiveNorth) {
                logInfo ("shading", "Verschattung für Rollläden NORD")
                val myGroup = gRollladenNorth
                isActiveNorth = true
            }
        }
        case nAz > closingAzimuth_west : { // hinreichend, da 1. Bedingung nicht zutrifft
                if(!isActiveWest) {
                logInfo ("shading", "Verschattung für Rollläden WEST")
                val myGroup = gRollladenWest
                isActiveWest = true
            }
        }
        case nAz > closingAzimuth_south : {// hinreichend, da 2. Bedingung nicht zutrifft
            if(!isActiveSouth) {
                logInfo ("shading", "Verschattung für Rollläden SÜD")
                val myGroup = gRollladenSouth
                isActiveSouth = true
            }
        }
        case nAz > closingAzimuth_east : {// hinreichend, da 3. Bedingung nicht zutrifft
            if(!isActiveEast){
                logInfo ("shading", "Verschattung für Rollläden OST")
                val myGroup = gRollladenEast
                isActiveEast = true
            }
        }
    }
    if(myGroup === null) { // myGroup ist leer bzw. nicht definiert
        logInfo ("shading", "Verschattung bereits aktiv oder außerhalb des Verschattungsbereichs")
        return;
    }
    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.state)
        }
    ]
    AutoShading_Start_last.postUpdate(now.toString())
end

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

rule "Verschattung beenden"
when 
    Item Elevation changed
then
    if (AutoShading.state != ON) {                                                                  // Verschattung deaktiviert?
        logInfo("shading", "Verschattungsende wird nicht ausgeführt, da deaktiviert."
        return;
    }
    if (IsDay.state != ON) {                                                                        // Nacht?
        logInfo("shading", "Verschattungsende wird nicht ausgeführt, da Nacht."
        return;
    }
    if (Jahreszeit.state.toString !="SPRING" && Jahreszeit.state.toString != "SUMMER") {            // Winter oder Herbst?
        logInfo("shading", "Verschattungsende wird nicht ausgeführt, da weder, Frühling noch Sommer.")
        return;
    }
    val boolean isRainLastHour = (Rain.maximumSince(now.minusHours(1), "influxdb").state >= (minPrecip))
    logInfo("shading", "Rain " + isRainLastHour)
    val boolean isCloudLastHour = (Clouds.averageSince(now.minusHours(1), "influxdb")as Number >= (cloudHysteresis))
    logInfo("shading", "Clouds " + isCloudLastHour )
    val boolean isTemperature = ((weatherN_Temperature.state as Number).intValue < (weatherN_Temperature.minimumSince(now.minusHours(1), "influxdb").state as DecimalType -(temperatureHysteresis)))
    logInfo("shading", "Temperatur " + isTemperature)
    if (AutoShading_End_last.state === NULL) {
        logInfo("shading", "Letzte Ausführung unbekannt, Belegung mit Initialwert (-1 Tag)")
        AutoShading_End_last.postUpdate(now.minusDays(1).toString())
        }
    var String timeNow = now.toString().substring(0,10)
    var String timeLastEnde = AutoShading_End_last.state.toString().substring(0,10)
    if (timeLastEnde == timeNow) {
        logInfo("shading", "Beende, da heute bereits ein automatisches Hochfahren stattfand")
        return;
    }
    if (!isActiveWest && !isActiveEast && !isActiveSouth && !isActiveNorth) {
        logInfo("shading", "Beende, da heute noch keine automatische Verschattung stattfand")
        return;
    }
    if ((weatherN_Temperature.state as Number).floatValue > (AutoShading_Temp_raise.state as Number)) {
        logInfo("shading", "Beende, aktuelle Temperatur ({})° ueberschreitet den eingestellten Grenzwert zum hochfahren von ({})°",weatherN_Temperature.state, AutoShading_Temp_raise.state )
        return;
    }
    if ((Elevation.state as Number) > (AutoShading_Elevation_end.state as Number)) {
       logInfo("shading", "Beende, aktuelle Elevation ({}) ueberschreitet den eingestellten Grenzwert von ({}) ", Elevation.state, AutoShading_Elevation_end.state)
       return;
    }
    var boolean bEnd = false
    if (isTemperature) {
        logInfo ("shading", "Verschattung beenden, Temperaturabfall von min. ({})°C erkannt", temperatureHysteresis)
        bEnd = true
    }
    if (isRainLastHour || isCloudLastHour) {
        logInfo ("shading", "Verschattung beenden, Mindestregenmenge von ({}) mm oder druchschnittliche Bewölkung von ({}) % erreicht",minPrecip, cloudHysteresis)
        bEnd = true
    }
    if (isActiveWest || isActiveEast || isActiveSouth ) {
        logInfo ("shading", "Verschattung beenden")
        bEnd = true
    }
    if (!bEnd) return;
    gRolladen.allMembers.forEach[blind|
        if((blind.state as Number) == targetHights.get(blind.name)) {
            logInfo ("shading", "Öffne Rollladen ", blind.name)
            blind.sendCommand(UP)
            sendTelegram("bot1", "Verschattung für (" + blind.name + ") beendet, Rollladen wird geöffnet.")
        } else {
            logInfo ("shading", "Rollladen {} wird nicht geoeffnet, da dieser zwischenzeitlich manuell verändert wurde.",blind.name)
        }
    ]
    // Letzte Ausführung mit entsprechendem Zeitstempel belegen
    AutoShading_End_last.postUpdate(now.toString())
    //Variablen zurücksetzen
    isActiveWest = false
    isActiveEast = false
    isActiveSouth = false
    isActiveNorth = false
end

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

rule "Verschattung Variablen zurücksetzen"
when
    Time cron "15 59 23 * * ?"
then
    isActiveNorth = false
    isActiveWest = false
    isActiveEast = false
    isActiveSouth = false
end
Das Problem, warum die Rule nicht funktioniert, ist eine Variable, die nicht mit einem gültigen Wert gefüllt ist (null kann nicht nach Integer gecastet werden). Dieses Problem ist noch nicht in den Rules berücksichtigt.
Beide Rules (Beschattung Ein/Aus) werden immer gleichzeitig getriggert, da beide Rules von Astro Items abhängen, welche sich bei jedem Update ändern. So gesehen wäre es sinnvoller, beide Rules als eine Rule zu definieren und die Funktionsweise der Rules entsprechend anzupassen. Auch wäre es sinnvoll, das Logging zu minimieren, soweit die Rule nichts zu tun hat.
Wow, vielen herzlichen Dank für die Überarbeitung und Korrektur meines Codes. Und das ganze auch noch nachts, MEGA !

Wir kommen der Sache schon näher.
Ich habe deinen Code übernommen und nach "meinen Möglichkeiten" korrigiert, wann auch immer "VSC" gemeckert hat.
Allerdings gibt es noch ein paar Stellen, die ich alleine leider nicht lösen kann. Hier der Code:

Code: Alles auswählen

import java.util.Map

var Number closingAzimuth_east = 85
var Number closingAzimuth_south = 111
var Number closingAzimuth_west = 171
var Number closingAzimuth_north = 260

var Number closingCloudiness = 20
val Number cloudHysteresis = 45         //die Mindestbewölkung in der letzten Stunde
var Number openingTemperature = 22
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 isActiveWest = false
var boolean isActiveEast = false
var boolean isActiveSouth = false
var boolean isActiveNorth = false

val Map<String, Number> targetHights = newHashMap ( 
    "Shutter_EG_Office" -> 74,
    "Shutter_EG_Wohnen3" -> 73,
    "Shutter_EG_Kueche2" -> 40,
    "Shutter_EG_Wohnen1" -> 78,
    "Shutter_EG_Wohnen2" -> 78,
    "Shutter_EG_Technik" -> 73,
    "Shutter_OG_HWR" -> 74
)

rule "Verschattung starten"
when
    Item Azimuth changed
then
    if (AutoShading.state != ON) {                                                                  // Verschattung deaktiviert?
        logInfo("shading", "Verschattung wird nicht ausgeführt, da deaktiviert.")
        return;
    }
    if (IsDay.state != ON) {                                                                        // Nacht?
        logInfo("shading", "Verschattung wird nicht ausgeführt, da Nacht.")
        return;
    }
    if (Jahreszeit.state.toString !="SPRING" && Jahreszeit.state.toString != "SUMMER") {            // Winter oder Herbst?
        logInfo("shading", "Verschattung wird nicht ausgeführt, da weder, Frühling noch Sommer.")
        return;
    }
    if (AutoShading_Start_last.state == NULL) {
        logInfo("shading", "Letzte Ausführung unbekannt, Belegung mit Initialwert (gestern)")
        AutoShading_Start_last.postUpdate(now.minusDays(1).toString())
    }
    // 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_west.state == NULL)    AutoShading_Azimuth_west.postUpdate(closingAzimuth_west)
    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 ((weatherN_Temperature.state as Number).floatValue <= (AutoShading_Temp_min.state as Number)) {
        logInfo ("shading", "Mindesttemperatur von {} °C wurde nicht erreicht. Aktuelle Temperatur {} °C", AutoShading_Temp_min.state, weatherN_Temperature.state)
        return false;   
        
    }
    if ((Clouds.state as Number).floatValue > (AutoShading_Cloudiness_max.state as Number)) { 
        logInfo ("shading", "Aktuelle Bewoelkung {} % ueberschreitet den eingestellten Grenzwert von {} %", Clouds.state, AutoShading_Cloudiness_max.state)
        return false;
    }
    if ((Elevation.state as Number) <= (AutoShading_Elevation_end.state as Number)) {
        logInfo ("shading", "Elevation für das Beenden der Verschattung {} ° ist groesser als aktuelle {}°", AutoShading_Elevation_end.state, Elevation.state)
        return false;
    }
    val nAz = (Azimuth.state as Number).floatValue

    //Azimuth ist größer als 270° (NORD)
    switch(true) { // erste zutreffende Bedingung wird exclusiv ausgeführt (alle nachfolgenden nicht, auch wenn sie zutreffen)
        case nAz > closingAzimuth_north : {
            if(!isActiveNorth) {
                logInfo ("shading", "Verschattung für Rollläden NORD")
                val myGroup = gRollladenNorth
                isActiveNorth = true
            }
        }
        case nAz > closingAzimuth_west : { // hinreichend, da 1. Bedingung nicht zutrifft
                if(!isActiveWest) {
                logInfo ("shading", "Verschattung für Rollläden WEST")
                val myGroup = gRollladenWest
                isActiveWest = true
            }
        }
        case nAz > closingAzimuth_south : {// hinreichend, da 2. Bedingung nicht zutrifft
            if(!isActiveSouth) {
                logInfo ("shading", "Verschattung für Rollläden SÜD")
                val myGroup = gRollladenSouth
                isActiveSouth = true
            }
        }
        case nAz > closingAzimuth_east : {// hinreichend, da 3. Bedingung nicht zutrifft
            if(!isActiveEast){
                logInfo ("shading", "Verschattung für Rollläden OST")
                val myGroup = gRollladenEast
                isActiveEast = true
            }
        }
    }
    if(myGroup === null) { // myGroup ist leer bzw. nicht definiert
        logInfo ("shading", "Verschattung bereits aktiv oder außerhalb des Verschattungsbereichs")
        return;
    }
    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.state)
        }
    ]
    AutoShading_Start_last.postUpdate(now.toString())
end

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

rule "Verschattung beenden"
when 
    Item Elevation changed
then
    if (AutoShading.state != ON) {                                                                  // Verschattung deaktiviert?
        logInfo("shading", "Verschattungsende wird nicht ausgeführt, da deaktiviert.")
        return;
    }
    if (IsDay.state != ON) {                                                                        // Nacht?
        logInfo("shading", "Verschattungsende wird nicht ausgeführt, da Nacht.")
        return;
    }
    if (Jahreszeit.state.toString !="SPRING" && Jahreszeit.state.toString != "SUMMER") {            // Winter oder Herbst?
        logInfo("shading", "Verschattungsende wird nicht ausgeführt, da weder, Frühling noch Sommer.")
        return;
    }
    val boolean isRainLastHour = (Rain.maximumSince(now.minusHours(1), "influxdb").state >= (minPrecip))
    logInfo("shading", "Rain " + isRainLastHour)
    val boolean isCloudLastHour = (Clouds.averageSince(now.minusHours(1), "influxdb")as Number >= (cloudHysteresis))
    logInfo("shading", "Clouds " + isCloudLastHour )
    val boolean isTemperature = ((weatherN_Temperature.state as Number).intValue < (weatherN_Temperature.minimumSince(now.minusHours(1), "influxdb").state as DecimalType -(temperatureHysteresis)))
    logInfo("shading", "Temperatur " + isTemperature)
    if (AutoShading_End_last.state === NULL) {
        logInfo("shading", "Letzte Ausführung unbekannt, Belegung mit Initialwert (-1 Tag)")
        AutoShading_End_last.postUpdate(now.minusDays(1).toString())
        }
    var String timeNow = now.toString().substring(0,10)
    var String timeLastEnde = AutoShading_End_last.state.toString().substring(0,10)
    if (timeLastEnde == timeNow) {
        logInfo("shading", "Beende, da heute bereits ein automatisches Hochfahren stattfand")
        return;
    }
    if (!isActiveWest && !isActiveEast && !isActiveSouth && !isActiveNorth) {
        logInfo("shading", "Beende, da heute noch keine automatische Verschattung stattfand")
        return;
    }
    if ((weatherN_Temperature.state as Number).floatValue > (AutoShading_Temp_raise.state as Number)) {
        logInfo("shading", "Beende, aktuelle Temperatur ({})° ueberschreitet den eingestellten Grenzwert zum hochfahren von ({})°",weatherN_Temperature.state, AutoShading_Temp_raise.state )
        return;
    }
    if ((Elevation.state as Number) > (AutoShading_Elevation_end.state as Number)) {
       logInfo("shading", "Beende, aktuelle Elevation ({}) ueberschreitet den eingestellten Grenzwert von ({}) ", Elevation.state, AutoShading_Elevation_end.state)
       return;
    }
    var boolean bEnd = false
    if (isTemperature) {
        logInfo ("shading", "Verschattung beenden, Temperaturabfall von min. ({})°C erkannt", temperatureHysteresis)
        bEnd = true
    }
    if (isRainLastHour || isCloudLastHour) {
        logInfo ("shading", "Verschattung beenden, Mindestregenmenge von ({}) mm oder druchschnittliche Bewölkung von ({}) % erreicht",minPrecip, cloudHysteresis)
        bEnd = true
    }
    if (isActiveWest || isActiveEast || isActiveSouth ) {
        logInfo ("shading", "Verschattung beenden")
        bEnd = true
    }
    if (!bEnd) return;
    gRollladen.allMembers.forEach[blind|
        if((blind.state as Number) == targetHights.get(blind.name)) {
            logInfo ("shading", "Öffne Rollladen ", blind.name)
            blind.sendCommand(UP)
            sendTelegram("bot1", "Verschattung für (" + blind.name + ") beendet, Rollladen wird geöffnet.")
        } else {
            logInfo ("shading", "Rollladen {} wird nicht geoeffnet, da dieser zwischenzeitlich manuell verändert wurde.",blind.name)
        }
    ]
    // Letzte Ausführung mit entsprechendem Zeitstempel belegen
    AutoShading_End_last.postUpdate(now.toString())
    //Variablen zurücksetzen
    isActiveWest = false
    isActiveEast = false
    isActiveSouth = false
    isActiveNorth = false
end

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

rule "Verschattung Variablen zurücksetzen"
when
    Time cron "15 59 23 * * ?"
then
    isActiveNorth = false
    isActiveWest = false
    isActiveEast = false
    isActiveSouth = false
end
Jetzt zu den Problemen:

Nr. 1.

Bei den Zeilen 60,65 und 69 wird "return false;" unterstrichen mit der Fehlermeldung: "Void functions cannot return a value".



Nr. 2.

siehe mein Screenshot. Da wird über "myGroup" gemeckert mit dem Hinweis: "The value of the local variable myGroup is not used"

Zusätzlich Zeile Nr. 104: The method or field myGroup is undefined.
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.

Antworten