Jalousien nach Sonnenstand

Einrichtung der openHAB Umgebung und allgemeine Konfigurationsthemen.

Moderatoren: seppy, udo1toni

Antworten
Markus_JE
Beiträge: 138
Registriert: 6. Okt 2019 13:20
Answers: 0

Re: Jalousien nach Sonnenstand

Beitrag von Markus_JE »

Hi Udo,

Mega. Funktioniert.
Bei mir läuft alles auf OH3

Danke

Trommse
Beiträge: 7
Registriert: 9. Jun 2020 23:18
Answers: 0

Re: Jalousien nach Sonnenstand

Beitrag von Trommse »

Hallo zusammen, ich habe mir diese Rule mal "geklaut" und ein wenig angepasst. Aber es passiert nichts wenn die Werte erreicht werden.

Aktuell sind die Items bei folgenden Werten:

Höhenwinkel 15-65
47.97 °

Azimut SüdOst 77-180
166.81 °

Azimut SüdWest 160-270
166.81 °

Strahlung Min 150
500.80 W/m²

Wolken Max 80
46 %

Sonnenschutz_Aktiv:
ON


Als die Azimut auf 163 gesprungen sind, haben sich die Rollos im Süd/West Bereich aber nicht runterbewegt.

Die Rule:

Code: Alles auswählen


val nElevationMinSuedOst = 15 //15
val nElevationMaxSuedOst = 65 //65
val nElevationMinSuedWest = 15 //15
val nElevationMaxSuedWest = 65 //65
val nAzimutMin_SuedOst = 77 //140
val nAzimutMaxSuedOst = 180 //260
val nAzimutMin_SuedWest = 162 //140
val nAzimutMaxSuedWest = 270 //260
val nIntensityMin = 150 //150
val nCloudynessMax = 80 //80
var Timer tSchatten = null

rule "Beschattung SüdOst"
when
    Item Astro_Lokale_Sonnendaten_Hohenwinkel changed
then
    if(Sonnenschutz_Aktiv.state != ON)
        return;

//    if(!(LokaleSonnendaten_DiffuseStrahlung.state instanceof Number)) {
//       logWarn("shade","DiffuseStrahlung! Abbruch!")
//       return;

    if(!(Astro_Lokale_Sonnendaten_Hohenwinkel.state instanceof Number)) {
        logWarn("shade","Elevation ungültig! Abbruch!")
        return;
    }
    if(!(Astro_Lokale_Sonnendaten_Azimut.state instanceof Number)) {
        logWarn("shade","Azimut ungültig! Abbruch!")
        return;
    }
    val nElevation = (Astro_Lokale_Sonnendaten_Hohenwinkel.state as Number).floatValue
    val nAzimut = (Astro_Lokale_Sonnendaten_Azimut.state as Number).floatValue

    var nIntens = 100
    if(Astro_Lokale_Sonnendaten_Direkte_Strahlung.state instanceof Number)
        nIntens = (Astro_Lokale_Sonnendaten_Direkte_Strahlung.state as DecimalType).intValue

    var nCloud = 0
    if(LocalWeatherAndForecast_Bewolkung.state instanceof Number)
        nCloud = (LocalWeatherAndForecast_Bewolkung.state as Number).intValue

    if(nElevation < nElevationMinSuedOst || nElevation > nElevationMaxSuedOst || nAzimut < nAzimutMin_SuedOst || nAzimut > nAzimutMaxSuedOst || nIntens < nIntensityMin || nCloud > nCloudynessMax) {
        logInfo("shade","Jalousien Süd/Ost Beschattung aus!")
        gRollos_SuedOst.sendCommand(UP) // Rollläden hochfahren
    } else {
        logInfo("shade","Jalousien Süd/ Ost Beschattung an!")
        gRollos_SuedOst.sendCommand(DOWN) // Rollläden herunterfahren
    }
end




rule "Beschattung SüdWest"
when
    Item Astro_Lokale_Sonnendaten_Hohenwinkel changed
then
    if(Sonnenschutz_Aktiv.state != ON)
        return;

//    if(!(LokaleSonnendaten_DiffuseStrahlung.state instanceof Number)) {
//       logWarn("shade","DiffuseStrahlung! Abbruch!")
//       return;

    if(!(Astro_Lokale_Sonnendaten_Hohenwinkel.state instanceof Number)) {
        logWarn("shade","Elevation ungültig! Abbruch!")
        return;
    }
    if(!(Astro_Lokale_Sonnendaten_Azimut.state instanceof Number)) {
        logWarn("shade","Azimut ungültig! Abbruch!")
        return;
    }
    val nElevation = (Astro_Lokale_Sonnendaten_Hohenwinkel.state as Number).floatValue
    val nAzimut = (Astro_Lokale_Sonnendaten_Azimut.state as Number).floatValue

    var nIntens = 100
    if(Astro_Lokale_Sonnendaten_Direkte_Strahlung.state instanceof Number)
        nIntens = (Astro_Lokale_Sonnendaten_Direkte_Strahlung.state as DecimalType).intValue

    var nCloud = 0
    if(LocalWeatherAndForecast_Bewolkung.state instanceof Number)
        nCloud = (LocalWeatherAndForecast_Bewolkung.state as Number).intValue

    if(nElevation < nElevationMinSuedWest || nElevation > nElevationMaxSuedWest || nAzimut < nAzimutMin_SuedWest || nAzimut > nAzimutMaxSuedWest || nIntens < nIntensityMin || nCloud > nCloudynessMax) {
        logInfo("shade","Jalousien Süd/West Beschattung aus!")
        gRollos_SuedWest.sendCommand(UP) // Rollläden hochfahren
    } else {
        logInfo("shade","Jalousien Süd/West Beschattung an!")
        gRollos_SuedWest.sendCommand(DOWN) // Rollläden herunterfahren
    }
end









Vielen Dank schon mal für eure Hilfe

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

Re: Jalousien nach Sonnenstand

Beitrag von udo1toni »

Frage: Funktioniert die Steuerung über die Gruppen überhaupt? Wie sind die Gruppen exakt definiert?
Gegeben, dass die Gruppen korrekt definiert sind

Code: Alles auswählen

Group:Rollershutter gRollos_SuedOst
Group:Rollershutter gRollos_SuedWest 
einige Tipps:

Tipp 1: beide Rules nutzen den identischen Trigger. Es ist also sinnvoll, beide Rules zu einer Rule zusammenzufassen. Da ein Gutteil der ermittelten Daten auch noch identisch ist, ist das ohnehin eine gute Option.
Tipp 2: Du verwendest DecimalType als Datentyp. Number wäre hier besser (ohne dass das einen direkten Einfluss haben sollte...)
Tipp 3: Es ist notwendig, hier die Messwerte mitzuloggen, um möglichen Problemen bei der Typwandlung auf die Spur zu kommen.
Entsprechend eine erweiterte Fassung der Rule:

Code: Alles auswählen

val nElevationMinSuedOst  =  15 //  15
val nElevationMaxSuedOst  =  65 //  65
val nElevationMinSuedWest =  15 //  15
val nElevationMaxSuedWest =  65 //  65
val nAzimutMin_SuedOst    =  77 // 140
val nAzimutMaxSuedOst     = 180 // 260
val nAzimutMin_SuedWest   = 162 // 140
val nAzimutMaxSuedWest    = 270 // 260
val nIntensityMin         = 150 // 150
val nCloudynessMax        =  80 //  80
var Timer tSchatten       = null

rule "Beschattung SüdOst und SüdWest"
when
    Item Astro_Lokale_Sonnendaten_Hohenwinkel changed
then
    if(Sonnenschutz_Aktiv.state != ON)
        return;

//    if(!(LokaleSonnendaten_DiffuseStrahlung.state instanceof Number)) {
//       logWarn("shade","DiffuseStrahlung! Abbruch!")
//       return;

    if(!(Astro_Lokale_Sonnendaten_Hohenwinkel.state instanceof Number)) {
        logWarn("shade","Elevation ungültig! Abbruch!")
        return;
    }
    if(!(Astro_Lokale_Sonnendaten_Azimut.state instanceof Number)) {
        logWarn("shade","Azimut ungültig! Abbruch!")
        return;
    }
    val nElevation = (Astro_Lokale_Sonnendaten_Hohenwinkel.state as Number).floatValue
    val nAzimut    = (Astro_Lokale_Sonnendaten_Azimut.state as Number).floatValue

    var nIntens = 100
    if(Astro_Lokale_Sonnendaten_Direkte_Strahlung.state instanceof Number)
        nIntens = (Astro_Lokale_Sonnendaten_Direkte_Strahlung.state as Number).intValue

    var nCloud = 0
    if(LocalWeatherAndForecast_Bewolkung.state instanceof Number)
        nCloud = (LocalWeatherAndForecast_Bewolkung.state as Number).intValue

    logDebug("shade", "       Intensität : {} (Minimum {})", nIntens, nIntensityMin)
    logDebug("shade", "           Wolken : {} (Maximum {})", nCloud, nCloudynessMax)
    logDebug("shade", "Elevation Süd-Ost : {} (Minimum {}, Maximum {})", nElevation, nElevationMinSuedOst, nElevationMaxSuedOst)
    logDebug("shade", "Elevation Süd-West: {} (Minimum {}, Maximum {})", nElevation, nElevationMinSuedWest, nElevationMaxSuedWest)
    logDebug("shade", "   Azimut Süd-Ost : {} (Minimum {}, Maximum {})", nAzimut, nCloudynessMax, nAzimutMin_SuedOst, nAzimutMaxSuedOst)
    logDebug("shade", "   Azimut Süd-West: {} (Minimum {}, Maximum {})", nAzimut, nCloudynessMax, nAzimutMin_SuedWest, nAzimutMaxSuedWest)

    if(nElevation < nElevationMinSuedOst || nElevation > nElevationMaxSuedOst || nAzimut < nAzimutMin_SuedOst || nAzimut > nAzimutMaxSuedOst || nIntens < nIntensityMin || nCloud > nCloudynessMax) {
        logInfo("shade","Jalousien Süd/Ost Beschattung aus!")
        gRollos_SuedOst.sendCommand(UP) // Rollläden hochfahren
    } else {
        logInfo("shade","Jalousien Süd/ Ost Beschattung an!")
        gRollos_SuedOst.sendCommand(DOWN) // Rollläden herunterfahren
    }
    if(nElevation < nElevationMinSuedWest || nElevation > nElevationMaxSuedWest || nAzimut < nAzimutMin_SuedWest || nAzimut > nAzimutMaxSuedWest || nIntens < nIntensityMin || nCloud > nCloudynessMax) {
        logInfo("shade","Jalousien Süd/West Beschattung aus!")
        gRollos_SuedWest.sendCommand(UP) // Rollläden hochfahren
    } else {
        logInfo("shade","Jalousien Süd/West Beschattung an!")
        gRollos_SuedWest.sendCommand(DOWN) // Rollläden herunterfahren
    }
end
Damit Du logDebug() Meldungen überhaupt zu Gesicht bekommst, musst Du das Logging noch auf DEBUG schalten, das geht z.B. über die Karaf Konsole:

Code: Alles auswählen

log:set DEBUG org.openhab.core.model.script.shade
Eine andere Option wäre, die Bedingungen hintereinander abzuarbeiten:

Code: Alles auswählen

val nElevationMinSuedOst  =  15 //  15
val nElevationMaxSuedOst  =  65 //  65
val nElevationMinSuedWest =  15 //  15
val nElevationMaxSuedWest =  65 //  65
val nAzimutMin_SuedOst    =  77 // 140
val nAzimutMaxSuedOst     = 180 // 260
val nAzimutMin_SuedWest   = 162 // 140
val nAzimutMaxSuedWest    = 270 // 260
val nIntensityMin         = 150 // 150
val nCloudynessMax        =  80 //  80
var Timer tSchatten       = null

rule "Beschattung SüdOst und SüdWest"
when
    Item Astro_Lokale_Sonnendaten_Hohenwinkel changed
then
    if(Sonnenschutz_Aktiv.state != ON)
        return;

//    if(!(LokaleSonnendaten_DiffuseStrahlung.state instanceof Number)) {
//       logWarn("shade","DiffuseStrahlung! Abbruch!")
//       return;

    if(!(Astro_Lokale_Sonnendaten_Hohenwinkel.state instanceof Number)) {
        logWarn("shade","Elevation ungültig! Abbruch!")
        return;
    }
    if(!(Astro_Lokale_Sonnendaten_Azimut.state instanceof Number)) {
        logWarn("shade","Azimut ungültig! Abbruch!")
        return;
    }
    val nElevation = (Astro_Lokale_Sonnendaten_Hohenwinkel.state as Number).floatValue
    val nAzimut    = (Astro_Lokale_Sonnendaten_Azimut.state as Number).floatValue

    var nIntens = 100
    if(Astro_Lokale_Sonnendaten_Direkte_Strahlung.state instanceof Number)
        nIntens = (Astro_Lokale_Sonnendaten_Direkte_Strahlung.state as Number).intValue

    var nCloud = 0
    if(LocalWeatherAndForecast_Bewolkung.state instanceof Number)
        nCloud = (LocalWeatherAndForecast_Bewolkung.state as Number).intValue

    var Boolean bSuedWest = true
    var Boolean bSuedOst  = true

    if(nCloud > nCloudynessMax) {
		logInfo("shade","Bewölkung {} überschreitet Maximum {}, Beschattung aus!", nCloud,  nCloudynessMax)
		bSuedWest = false
		bSuedOst  = false
	}
    if(nIntens < nIntensityMin) {
		logInfo("shade","Intensität {} unterschreitet Minimum {}, Beschattung aus!", nIntens, nIntensityMin)
		bSuedWest = false
		bSuedOst  = false
	}
    if(nElevation < nElevationMinSuedOst) {
		logInfo("shade","Elevation {} unterhalb Minimum Süd-Ost {}, Beschattung Süd-Ost aus!", nElevation, nElevationMinSuedOst)
		bSuedOst  = false
	}
    if(nElevation < nElevationMinSuedWest) {
		logInfo("shade","Elevation {} unterhalb Minimum Süd-West {}, Beschattung Süd-West aus!", nElevation, nElevationMinSuedWest)
		bSuedWest = false
	}
    if(nElevation > nElevationMaxSuedOst) {
		logInfo("shade","Elevation {} oberhalb Maximum Süd-Ost {}, Beschattung Süd-Ost aus!", nElevation, nElevationMaxSuedOst)
		bSuedOst = false
	}
    if(nElevation > nElevationMaxSuedWest) {
		logInfo("shade","Elevation {} oberhalb Maximum Süd-West {}, Beschattung Süd-West aus!", nElevation, nElevationMaxSuedWest)
		bSuedWest = false
	}
    if(nAzimut > nAzimutMaxSuedOst) {
		logInfo("shade","Azimut {} oberhalb Maximum Süd-Ost {}, Beschattung Süd-Ost aus!", nAzimut > nAzimutMaxSuedOst)
		bSuedOst = false
	}
    if(nAzimut > nAzimutMaxSuedWest) {
		logInfo("shade","Azimut {} oberhalb Maximum Süd-West {}, Beschattung Süd-West aus!", nAzimut > nAzimutMaxSuedWest)
		bSuedWest = false
	}
    if(nAzimut < nAzimutMin_SuedOst) {
		logInfo("shade","Azimut {} unterhalb Minimum Süd-Ost {}, Beschattung Süd-Ost aus!", nAzimut > nAzimutMin_SuedOst)
		bSuedWest = false
	}
    if(nAzimut < nAzimutMin_SuedWest) {
		logInfo("shade","Azimut {} unterhalb Minimum Süd-West {}, Beschattung Süd-West aus!", nAzimut > nAzimutMin_SuedWest)
		bSuedWest = false
	}

    if(!bSuedOst) {
        // logInfo("shade","Jalousien Süd/Ost Beschattung aus!")
        gRollos_SuedOst.sendCommand(UP) // Rollläden hochfahren
    } else {
        // logInfo("shade","Jalousien Süd/ Ost Beschattung an!")
        gRollos_SuedOst.sendCommand(DOWN) // Rollläden herunterfahren
    }
    if(!bSuedWest) {
        // logInfo("shade","Jalousien Süd/West Beschattung aus!")
        gRollos_SuedWest.sendCommand(UP) // Rollläden hochfahren
    } else {
        // logInfo("shade","Jalousien Süd/West Beschattung an!")
        gRollos_SuedWest.sendCommand(DOWN) // Rollläden herunterfahren
    }
end
Die Beschattung wird zunächst als aktiv angesehen (in den Boolean Variablen bSuedOst und bSuedWest). Trifft eine der Bedingungnen zu, so wird die betreffende Variable auf false gesetzt.
Nachdem alle Vergleiche stattgefunden haben, wird abhängig von den Variablen der Befehl zum Schließen bzw. Öffnen erteilt.

Es wäre hier allerdings gut, die Rollläden nur bei Bedarf anzusteuern. Dazu muss aber die Rückmeldung korrekt funktionieren. Ein weiterer Punkt wäre dann noch, ob Du tatsächlich die Rollläden komplett schließen willst.

Da meine Rollläden absolute Positionierung beherrschen und ihre Position auch aktiv zurückmelden, läuft das bei mir etwas anders, so im Groben:

Code: Alles auswählen

import java.util.HashMap
val HashMap<String,Number> hmShade    = newHashMap( "Rollladen_1" -> 25, "Rollladen_2" -> 43, "RollKueche" -> 17)
val HashMap<String,Number> hmOpen     = newHashMap( "Rollladen_1" -> 0, "Rollladen_2" -> 0, "RollKueche" -> 0)

rule "Schatten"
when
    Item Elevation changed
then
   // Auswertung der Grenzwerte und Entscheidung, ob Beschattung für die jeweilige Seite aktiv sein soll
  ... // Code wie oben
  // ab hier Steuerung der einzelnen Rollläden auf ihre Sollposition
    gRollos_SuedWest.members.forEach[r|
        var soll = if(bSuedWest) hmShade.get(r.name) else hmOpen.get(r.name)
        if((r.state as Number) != soll)
            r.sendCommand(soll)
    ]
    gRollos_SuedOst.members.forEach[r|
        var soll = if(bSuedOst) hmShade.get(r.name) else hmOpen.get(r.name)
        if((r.state as Number) != soll)
            r.sendCommand(soll)
    ]
end
Die Rule sucht also anhand des Itemnamens den Sollwert aus einer der beiden HashMaps hmShade bzw. hmOpen und prüft, ob der Rollladen diese Position hat. Ist das nicht der Fall, wird der Rollladen auf die Sollposition gefahren.
Meine Rule macht das anhand anderer Abhängigkeiten, aber im Groben sollte das bei Dir auch so funktionieren, vorausgesetzt, Deine Rollläden unterstützen direkte Positionsfahrten.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Antworten