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

Ja, das mit dem return false; ist mir auch durchgerutscht. Das ist in der Tat Quatsch. Mach einfach das false weg, so dass nur return; übrig bleibt.

Ansonsten sind halt noch weitere Fehler in der Rule drin.
myGroup wird innerhalb einer Bedingung definiert, somit ist myGroup anschließend (außerhalb der Bedingung) nicht mehr definiert.
Außerdem wird versucht, der Konstanten einfach ein Item zuzuweisen. So geht das aber nicht.
Das korrekte Vorgehen ist, das passende Item aus einer Liste von Items herauszusuchen. Am einfachsten machst Du das, indem Du die vier Group Items
gRollladenX in einer Gruppe zusammenfasst:

Code: Alles auswählen

Group gGroups
Group gRollladenNorth (gGroups)
Group gRollladenEast (gGroups)
Group gRollladenSouth (gGroups)
Group gRollladenWest (gGroups)
Nun kannst Du über gGroups zugreifen. Nur der Teil des Codes, in dem die richtige Gruppe für die Beschattung bestimmt wird:

Code: Alles auswählen

    var String strGroup = ""
    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")
                strGroup = "gRollladenNorth"
                isActiveNorth = true
            }
        }
        case nAz > closingAzimuth_west : { // hinreichend, da 1. Bedingung nicht zutrifft
                if(!isActiveWest) {
                logInfo ("shading", "Verschattung für Rollläden WEST")
                strGroup = "gRollladenWest"
                isActiveWest = true
            }
        }
        case nAz > closingAzimuth_south : {// hinreichend, da 2. Bedingung nicht zutrifft
            if(!isActiveSouth) {
                logInfo ("shading", "Verschattung für Rollläden SÜD")
                strGroup = "gRollladenSouth"
                isActiveSouth = true
            }
        }
        case nAz > closingAzimuth_east : {// hinreichend, da 3. Bedingung nicht zutrifft
            if(!isActiveEast){
                logInfo ("shading", "Verschattung für Rollläden OST")
                strGroup = "gRollladenEast"
                isActiveEast = true
            }
        }
    }
    if(strGroup == "") { // myGroup ist leer bzw. nicht definiert
        logInfo ("shading", "Verschattung bereits aktiv oder außerhalb des Verschattungsbereichs")
        return;
    }
    val myGroup = gGroups.members.filter[i|i.name == strGroup].head
Der Trick besteht hier zum einen darin, den Namen des Gruppenitems in einer String Variablen zu speichern.
Anschließend wird die String Variable geprüft und gegebenenfalls wird das Objekt myGroup passend gefüllt.
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

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

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

Beitrag von cupra6 »

Cool, vielen herzlich Dank !!!

Bei der ZEILE Nr. 111 meckert der VSC noch:


val myGroup = gRollladenGroup.members.filter[i|i.name == strGroup].head


myGroup ist gelb unterstrichen mit dem Hinweis: "the value of the local variable myGroup is not used"
strGroup ist rot unterstrichen : Cannot refer to the non-final variable strGroup inside a lambda expression

Hier nochmal der komplette 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;   
        
    }
    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;
    }
    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;
    }
    
    val nAz = (Azimuth.state as Number).floatValue

    //Azimuth ist größer als 270° (NORD)

var String strGroup = ""
    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")
                strGroup = "gRollladenNorth"
                isActiveNorth = true
            }
        }
        case nAz > closingAzimuth_west : { // hinreichend, da 1. Bedingung nicht zutrifft
                if(!isActiveWest) {
                logInfo ("shading", "Verschattung für Rollläden WEST")
                strGroup = "gRollladenWest"
                isActiveWest = true
            }
        }
        case nAz > closingAzimuth_south : {// hinreichend, da 2. Bedingung nicht zutrifft
            if(!isActiveSouth) {
                logInfo ("shading", "Verschattung für Rollläden SÜD")
                strGroup = "gRollladenSouth"
                isActiveSouth = true
            }
        }
        case nAz > closingAzimuth_east : {// hinreichend, da 3. Bedingung nicht zutrifft
            if(!isActiveEast){
                logInfo ("shading", "Verschattung für Rollläden OST")
                strGroup = "gRollladenEast"
                isActiveEast = true
            }
        }
    }
    if(strGroup == "") { // myGroup ist leer bzw. nicht definiert
        logInfo ("shading", "Verschattung bereits aktiv oder außerhalb des Verschattungsbereichs")
        return;
    }
    val myGroup = gRollladenGroup.members.filter[i|i.name == strGroup].head

    }
    gRollladenGroup.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;
    gRollladenGroup.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


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 »

Warum steht denn in Zeile 112 plötzlich gRollladenGroup.members.forEach...?

Da stand in der vorgen Version noch myGroup.members.forEach...

Und das muss auch so bleiben. myGroup ist, je nachdem, wie der Sonnenstand ist, entweder die Gruppe für Osten, Süden, Westen oder Norden. Das ist ja der Punkt des gesamten vorigen Codes, dieses Gruppenitem zuzuweisen.

Im Übrigen ist das kein Fehler, sondern eine Warnung :) Der Code als solcher würde trotzdem laufen (natürlich nicht mit dem gewünschten Effekt...)
Die Warnung besagt lediglich, dass der Value im Code nicht verwendet wird, er wäre also überflüssig (aber eben nicht fehlerhaft).
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

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

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

Beitrag von cupra6 »

Ok, verstanden.
Ich füge jetzt 2 Screenshots ein, trotz der Korrektur auf myGroup hab ich immernoch 2 riesen Fehler (siehe Screenshoots).

Es werden gleichzeitig mehrere Zeilen rot markiert, vlt. ist das einfach ein TYPO, irgendwo fehlt 'ne Klammer o.ä.

Meine Items:

Code: Alles auswählen


Group   gRollladen     "alle Rollläden"    

Group   gRollladenEast      "Rollläden Ost"     (gRollladen)
Group   gRollladenSouth     "Rollläden Süd"     (gRollladen)
Group   gRollladenWest      "Rollläden West"    (gRollladen)
Group   gRollladenNorth     "Rollläden Nord"    (gRollladen)


Hier auch die Rule:

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;   
        
    }
    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;
    }
    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;
    }
    
    val nAz = (Azimuth.state as Number).floatValue

    //Azimuth ist größer als 270° (NORD)

var String strGroup = ""
    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")
                strGroup = "gRollladenNorth"
                isActiveNorth = true
            }
        }
        case nAz > closingAzimuth_west : { // hinreichend, da 1. Bedingung nicht zutrifft
                if(!isActiveWest) {
                logInfo ("shading", "Verschattung für Rollläden WEST")
                strGroup = "gRollladenWest"
                isActiveWest = true
            }
        }
        case nAz > closingAzimuth_south : {// hinreichend, da 2. Bedingung nicht zutrifft
            if(!isActiveSouth) {
                logInfo ("shading", "Verschattung für Rollläden SÜD")
                strGroup = "gRollladenSouth"
                isActiveSouth = true
            }
        }
        case nAz > closingAzimuth_east : {// hinreichend, da 3. Bedingung nicht zutrifft
            if(!isActiveEast){
                logInfo ("shading", "Verschattung für Rollläden OST")
                strGroup = "gRollladenEast"
                isActiveEast = true
            }
        }
    }
    if(strGroup == "") { // myGroup ist leer bzw. nicht definiert
        logInfo ("shading", "Verschattung bereits aktiv oder außerhalb des Verschattungsbereichs")
        return;
    }
    val myGroup = gRollladen.members.filter[i|i.name == strGroup].head

    
    myGroup.members.forEach [ blind |
        if ((blind.state as Number) < targetHights.get(blind.name.toString()).intValue) {
            logInfo ("shading", "Fahre Rollladen ({}) auf ({}) %",blind.name,targetHights.get(blind.name.toString()))
            blind.sendCommand(targetHights.get(blind.name.toString()).intValue)
            sendTelegram("bot1","Verschattung für " + blind.name.toString + " aktiviert, schließen auf " + targetHights.get(blind.name.toString()).toString() + " %")
        } else {
            logInfo ("shading", "Rollladen ist bereits weiter geschlossen ({} %) als er geschlossen werden sollte und wird daher ignoriert",blind.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;
    
    myGroup.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

Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.

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

welchen Vorteil bietet dieser Abschnitt im dem Du mit der var boolean bEnd arbeitest im Gengensatz zu einem direkten return in der IF- Abfrage?

Code: Alles auswählen

    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;
CU
Cyrelian

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

Elektrischen Rolladen abhängig von Sonnenstand und Wetter steuern lassen

Beitrag von udo1toni »

Also, ohne nun die Fehlermeldung lesen zu können, vermute ich für den ersten Fehler ein Problem mit dem Gültigkeitsbereich von strGroup.

Ausweg: Du definierst
var String strGroup = “” oberhalb er ersten Rule in der Datei. Dort, wo in der Rule die Zeile steht, löschst Du nur das var String weg, so dass die Variable an dieser Stelle gezielt mit einem leeren String gefüllt wird.

In der Rule, um die Verschattung zu beenden, hast Du nun myGroup stehen, an dieser Stelle existiert myGroup aber gar nicht. Du kannst an dieser Stelle aber die neue Gruppe nehmen, in der alle Himmelsrichtungen enthalten sind. Ich glaube, das war gRollladen.


Gesendet von iPad mit Tapatalk
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

asd
Beiträge: 4
Registriert: 17. Jul 2020 16:04

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

Beitrag von asd »

Hallo,

super Thread. Gratulation an alle.

Ich habe begonnen das Projekt von Cyrelian ins Laufen zu bringen, bin aber auf einige Fragen bzw. Probleme gestoßen. Es gibt einige Punkte / Aspekte, die man nicht aus dem Thread herauslesen kann, welche meine Probleme verursachen.

Gibt es neben den Beispielen im Thread auch ein Gesamtdokumentation (z.B. GitHub)?

@Cyrelian: Wäre es möglich das du das aktuelle Gesamtprojekt inklusive Items, Rules, InfluxDB, Sitemap schickst?

lg
asd

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: 17. Jul 2020 16:04 Also, ohne nun die Fehlermeldung lesen zu können, vermute ich für den ersten Fehler ein Problem mit dem Gültigkeitsbereich von strGroup.

Ausweg: Du definierst
var String strGroup = “” oberhalb er ersten Rule in der Datei. Dort, wo in der Rule die Zeile steht, löschst Du nur das var String weg, so dass die Variable an dieser Stelle gezielt mit einem leeren String gefüllt wird.

In der Rule, um die Verschattung zu beenden, hast Du nun myGroup stehen, an dieser Stelle existiert myGroup aber gar nicht. Du kannst an dieser Stelle aber die neue Gruppe nehmen, in der alle Himmelsrichtungen enthalten sind. Ich glaube, das war gRollladen.


Gesendet von iPad mit Tapatalk
Ok, ich füge den Code nochmal ein. Schau dir bitte die Zeilen 19 und 76 an. Da stehen:
19: var String strGroup = ""
76: strGroup = ""
Ich hoffe, ich habe es richtig verstanden.

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

var String strGroup = ""

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;   
        
    }
    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;
    }
    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;
    }
    
    val nAz = (Azimuth.state as Number).floatValue
    //Azimuth ist größer als 270° (NORD)
    strGroup = ""

    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")
                strGroup = "gRollladenNorth"
                isActiveNorth = true
            }
        }
        case nAz > closingAzimuth_west : { // hinreichend, da 1. Bedingung nicht zutrifft
                if(!isActiveWest) {
                logInfo ("shading", "Verschattung für Rollläden WEST")
                strGroup = "gRollladenWest"
                isActiveWest = true
            }
        }
        case nAz > closingAzimuth_south : {// hinreichend, da 2. Bedingung nicht zutrifft
            if(!isActiveSouth) {
                logInfo ("shading", "Verschattung für Rollläden SÜD")
                strGroup = "gRollladenSouth"
                isActiveSouth = true
            }
        }
        case nAz > closingAzimuth_east : {// hinreichend, da 3. Bedingung nicht zutrifft
            if(!isActiveEast){
                logInfo ("shading", "Verschattung für Rollläden OST")
                strGroup = "gRollladenEast"
                isActiveEast = true
            }
        }
    }
    if(strGroup == "") { // myGroup ist leer bzw. nicht definiert
        logInfo ("shading", "Verschattung bereits aktiv oder außerhalb des Verschattungsbereichs")
        return;
    }
    val myGroup = gRollladen.members.filter[i|i.name == strGroup].head
    
    gRollladen.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


Das einzige was noch im LOG kommt, ist der folgender Hinweis, aber das hast du ja schon erwähnt. Mal schauen ob es jetzt klappen wird:
Validation issues found in configuration model 'astro_rollershutter.rules', using it anyway:

The value of the local variable myGroup is not used

Refreshing model 'astro_rollershutter.rules'

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

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

Beitrag von cupra6 »

Cool, jetzt scheint es schonmal zum Teil zu funktionieren.

Trotzdem fahren die Rollos noch nicht.
Hier die Fehlermeldung aus dem LOG:

ERROR, [ntime.internal.engine.RuleEngieImpl] - Rule "Verschattung starten": Could not cast NULL to java.lang.Number; line 115, column 14, length 21

Hier die Line 115:

if ((blind.state as Number) < targetHights.get(blind.name.toString()).intValue) {

Ich vermute, dass "blind" nicht gefüllt wird, und deswegen passiert erstmal nichts.

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 »

asd hat geschrieben: 20. Jul 2020 16:37 Hallo,

super Thread. Gratulation an alle.

Ich habe begonnen das Projekt von Cyrelian ins Laufen zu bringen, bin aber auf einige Fragen bzw. Probleme gestoßen. Es gibt einige Punkte / Aspekte, die man nicht aus dem Thread herauslesen kann, welche meine Probleme verursachen.

Gibt es neben den Beispielen im Thread auch ein Gesamtdokumentation (z.B. GitHub)?

@Cyrelian: Wäre es möglich das du das aktuelle Gesamtprojekt inklusive Items, Rules, InfluxDB, Sitemap schickst?

lg
asd
Hi asd,

eine Gesamtdoku im Git gibt es nicht. Ich kann aber meine letzten Stand hier gerne nochmal posten.

CU
Cyrelian

Antworten