Beeinflussung einer Rule durch eine andere Rule ?

Einrichtung der openHAB Umgebung und allgemeine Konfigurationsthemen.

Moderatoren: seppy, udo1toni

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

Re: Beeinflussung einer Rule durch eine andere Rule ?

Beitrag von udo1toni »

Ach ja, zu viel weg gekürzt. Warum er sich über die non finals innerhalb des Lambda aufregt, verstehe ich jetzt grade nicht, da das Lambda ja zur Rule gehört, aber sei's drum...

Es gibt ein paar Meldungen darüber, dass die nicht finale Variable innerhalb des Lambdas nicht definiert sei. Ich hätte eigentlich erwartet, dass das Lambda in diesem Fall die Variable erbt, aber das ist anscheinend nicht der Fall. Also müssen die Variablen global definiert werden. Das ändert aber nichts an der Funktion als solcher, nur dass die Variablen eben schon im Kopf der Datei aufgeführt werden.
An einer Stelle habe ich eine Definition zu arg gekürzt, im Eifer des Gefechts... aber das führt nun zu einer weiteren Verkürzung :) denn man kann lfAvg den Wert 0 auch schon bei der Definition zuweisen und spart sich damit noch ein paar Klammern im else-Teil. Die restlichen Fehler sind Folgefehler der fehlerhaften Definition von lfAvg.

Nun also so:

Code: Alles auswählen

// globale Variablen zu Beginn der Datei definieren!
var Integer lfSumme=0
var lfMax=0
var Integer lfCnt=0

rule "PluggitLuftfeuchtigkeit"                              // bestimme die durchschnittliche und maximale Luftfeuchte
when
    Member of gPluggit_Items_Luftfeuchtigkeit changed
then
    lfSumme=0
    lfMax=0
    lfCnt=0
    gPluggit_Items_Luftfeuchtigkeit.members.filter[i |
    i.state instanceof Number].forEach[ item |
        lfCnt+=1
        val lf=(item.state as Number).intValue
        lfSumme+=lf
        if (lf>lfMax) lfMax=lf
    ]
    var lfAvg=0
    if (lfCnt>=2)  lfAvg=lfSumme/lfCnt                       // nur bei mindestens 2 Werten ist es sinnvoll, die Werte zu betrachten
    else lfMax=0
    var newState=Pluggit_Status_Luftfeuchte.state
    if (lfMax>=65 || lfAvg>=60) newState=ON                 // Bei mehr als max 65% oder avg 60% Luftfeuchtigkeit lüfte.
    else if (lfMax<60) newState=OFF                         // fällt die Luftfeuchte aller Stationen unter 60%, wurde genug gelüftet
    if(Pluggit_Status_Luftfeuchte.state != newState)
        Pluggit_Status_Luftfeuchte.postUpdate(newState)
end
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

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

Re: Beeinflussung einer Rule durch eine andere Rule ?

Beitrag von PeterA »

Mault immer noch :)

Code: Alles auswählen

{
	"resource": "/Volumes/openHAB-conf/rules/WAC_feuchte3.rules",
	"owner": "_generated_diagnostic_collection_name_#0",
	"code": "org.eclipse.xtext.xbase.validation.IssueCodes.incompatible_types",
	"severity": 8,
	"message": "Type mismatch: cannot convert from int to Integer",
	"startLineNumber": 15,
	"startColumn": 14,
	"endLineNumber": 15,
	"endColumn": 16
}

Code: Alles auswählen

{
	"resource": "/Volumes/openHAB-conf/rules/WAC_feuchte3.rules",
	"owner": "_generated_diagnostic_collection_name_#0",
	"code": "org.eclipse.xtext.xbase.validation.IssueCodes.incompatible_types",
	"severity": 8,
	"message": "Type mismatch: cannot convert from int to Integer",
	"startLineNumber": 17,
	"startColumn": 16,
	"endLineNumber": 17,
	"endColumn": 18
}

Code: Alles auswählen

{
	"resource": "/Volumes/openHAB-conf/rules/WAC_feuchte3.rules",
	"owner": "_generated_diagnostic_collection_name_#0",
	"code": "org.eclipse.xtext.xbase.validation.IssueCodes.incompatible_types",
	"severity": 8,
	"message": "Type mismatch: cannot convert from BigDecimal to int",
	"startLineNumber": 21,
	"startColumn": 26,
	"endLineNumber": 21,
	"endColumn": 39
}
- OpenHab 2.4
#PWRUP

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

Re: Beeinflussung einer Rule durch eine andere Rule ?

Beitrag von PeterA »

So, erst mal Danke an Violine, Tokamak und Udo für den Input!

So hab ich jetzt mal zusammen gebaut:

Code: Alles auswählen

rule "WACLuftfeuchtigkeit"
when
    Member of Durchschnitt_Feuchte_Haus changed // Durchschnitt Feuchte durch Lacrosse Sensoren
then
    if (WAC350_Durchschnitt_Feuchte_Haus.state != ON) { // wenn Schalter aus(nicht an) , keine Aktionen
        logInfo("Feuchtesteuerung:","Steuerung deaktiviert!")
    return;
    }
    //if ((Durchschnitt_Feuchte_Haus.state as Number > 48) && (49.9 > Durchschnitt_Feuchte_Haus.state as Number)){ // wenn Bereich Optimal breche ab
    //    logInfo("Feuchtesteuerung:","Bereich optimal!")
    //return;
    //}
    // bestimme die durchschnittliche und maximale Luftfeuchte
    var int lfSumme=0
    var int lfMax=0
    var int lfCnt=0
    for (item: Durchschnitt_Feuchte_Haus.members) {
        if (item.state instanceof Number) {
            lfCnt+=1
            val int lf=(item.state as Number).intValue()
            lfSumme+=lf
            if (lf>lfMax) lfMax=lf
        }
    }
    // nur bei mindestens 2 Werten ist es sinnvoll, die Werte zu betrachten
    var int lfAvg
    if (lfCnt>=2) {
        lfAvg=lfSumme/lfCnt
    }
    else {
        lfAvg=0
        lfMax=0
    }
    // Bei mehr als max 60% pro Sensor oder avg 55% Luftfeuchtigkeit lüfte.
    if (lfMax>=60 || lfAvg>=55) {
        FanStandby_Switch.sendCommand(OFF) // Schalte Lüftung EIN
        logInfo("Feuchtesteuerung:","Lüftung EIN") 
        //sendBroadcastNotification("Feuchtesteuerung: Lüftung EIN") //Pushnachricht
    }
    else {
    // fällt die Luftfeuchte aller Sensoren unter 55%, wurde genug gelüftet. Lüftung Stop
    if (lfMax<55) {
        FanStandby_Switch.sendCommand(ON) // Schalte Lüftung Standby
        logInfo("Feuchtesteuerung:","Lüftung Standby")
        //sendBroadcastNotification("Feuchtesteuerung: Lüftung Standby") //Pushnachricht
        }
    }
end
- OpenHab 2.4
#PWRUP

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

Re: Beeinflussung einer Rule durch eine andere Rule ?

Beitrag von PeterA »

Tokamak hat geschrieben: 24. Mär 2020 08:36 Klar:

Code: Alles auswählen

rule "PluggitLuftfeuchtigkeit"
when
    Member of gPluggit_Items_Luftfeuchtigkeit changed
then
    // bestimme die durchschnittliche und maximale Luftfeuchte
    var int lfSumme=0
    var int lfMax=0
    var int lfCnt=0
    for (item: gPluggit_Items_Luftfeuchtigkeit.members) {
        if (item.state instanceof Number) {
            lfCnt+=1
            val int lf=(item.state as Number).intValue()
            lfSumme+=lf
            if (lf>lfMax) lfMax=lf
        }
    }
    // nur bei mindestens 2 Werten ist es sinnvoll, die Werte zu betrachten
    var int lfAvg
    if (lfCnt>=2) {
        lfAvg=lfSumme/lfCnt
    }
    else {
        lfAvg=0
        lfMax=0
    }

    // Bei mehr als max 65% oder avg 60% Luftfeuchtigkeit lüfte.
    if (lfMax>=65 || lfAvg>=60) {
        Pluggit_Status_Luftfeuchte.postUpdate(ON)
    }
    else {
        // fällt die Luftfeuchte aller Stationen unter 60%, wurde genug gelüftet
        if (lfMax<60) {
            Pluggit_Status_Luftfeuchte.postUpdate(OFF)
        }
    }
end
Das Item Pluggit_Status_Luftfeuchte geht in eine andere Rule, wo neben dem CO2-Status auch bewertet wird, ob die Lüftung manuell angeschaltet wurde.
Im letzteren Fall läuft sie dann 30 Minuten. Meine Frau nutzt das, um Essensgerüche aus dem Haus zu bekommen.
Jetzt ist mir noch etwas aufgefallen:

im letzen "else if" Teil steht ..."aller Stationen".... aber du nutzt "lfMax" als Bedingung.
Das bedeutet doch wenn nur eine der Stationen unter dem Wert liegt wird getriggert ?
Müsste hier nicht der "lfAvg" Wert genommen werden ?
- OpenHab 2.4
#PWRUP

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

Re: Beeinflussung einer Rule durch eine andere Rule ?

Beitrag von udo1toni »

PeterA hat geschrieben: 24. Mär 2020 22:00 im letzen "else if" Teil steht ..."aller Stationen".... aber du nutzt "lfMax" als Bedingung.
Das bedeutet doch wenn nur eine der Stationen unter dem Wert liegt wird getriggert ?
Müsste hier nicht der "lfAvg" Wert genommen werden ?
Die Bedingung ist, dass keiner der Fühler mehr als 60% meldet. lfMax liefert den Maximalwert der Fühler. lfAvg liefert den Durchschnitt der Fühler (wobei nur Fühler mit gültigem Status berücksichtigt werden)
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

Tokamak
Beiträge: 168
Registriert: 20. Aug 2019 08:37
Answers: 4
Wohnort: Aachen

Re: Beeinflussung einer Rule durch eine andere Rule ?

Beitrag von Tokamak »

udo1toni hat geschrieben: 24. Mär 2020 11:24
  1. Es gibt eine Methode forEach, welche sich hier anbietet, um über die Gruppe zu iterieren.
  2. Wann immer möglich, sollte man keine Primitives verwenden. Hier also lieber Integer statt int
  3. Die Definition als Integer ist nur für lfCnt zwingend, da sonst die Abkürzung lfCnt+=1 fehlschlägt. lfAvg könnte dann natürlich auch einen Dezimalbruch enthalten, das sollte aber für die Funktion keine Rolle spielen.
    Allgemein wird davon abgeraten, alle Variablen auf einen Typ festzulegen, da sich dadurch die Startzeit erhöht. Ob das stimmt, weiß ich nicht. ;)
  4. ...
Du kannst es nicht lassen...

Meine Schleife

Code: Alles auswählen

    // bestimme die durchschnittliche und maximale Luftfeuchte
    var int lfSumme=0
    var int lfMax=0
    var int lfCnt=0
    for (item: gPluggit_Items_Luftfeuchtigkeit.members) {
        if (item.state instanceof Number) {
            lfCnt+=1
            val int lf=(item.state as Number).intValue()
            lfSumme+=lf
            if (lf>lfMax) lfMax=lf
        }
    }
anstelle

Code: Alles auswählen

    var lfSumme=0
    var lfMax=0
    var Integer lfCnt=0
    gPluggit_Items_Luftfeuchtigkeit.members.filter[i |
    i.state instanceof Number].forEach[ item |
        lfCnt+=1
        val Integer lf=(item.state as Number).intValue
        lfSumme+=lf
        if (lf>lfMax) lfMax=lf
    ]
war bewusst so geschrieben, aus verschiedenen Gründen. Das möchte ich den weniger erfahrenen Entwicklern erläutern:
  • Das Statement "gPluggit_Items_Luftfeuchtigkeit.members.filter[i | i.state instanceof Number].forEach[ item | " erzeugt mit filter[] ein weiteres, temporäres Objekt. Das vermeidet meine Variante.
  • Meine Variante vermeidet die Warnings "Cannot refer to the non-final variable lfSumme/lfMax/lfCnt inside a lambda expression", die mich unglaublich nerven.
  • Zur Vermeidung von Coding-Fehlern nutze ich immer strenge Typisierung und kann es jedem nur raten. Daher "var int lfSumme".
  • Bei der Nutzung von Integer anstelle int sehe ich keinen Vorteil, da ich kein Objekt benötige, sondern nur rechnen will. Wahrscheinlich ist ein primitiver Datentyp, da ohne Konstruktor und alles andere in diesem Fall nicht benötigte Rahmenwerk, schneller, ohne die Lesbarkeit einzuschränken.
Welche der beiden Varianten besser lesbar ist, ist vermutlich Geschmacksache.

Generell möchte ich unterfahreneren Entwicklern nahelegen, nicht alles mit Lamdas lösen zu wollen, wo einfaches Werkzeug genauso, vielleicht sogar besser funktioniert.

Derzeit arbeite ich in einem agilen Projekt und sehe, wohin die exzessive, weil "schicke" und "coole" Nutzung von Lamdas führt: Zu schlechter wartbarem Code.

Das alles nur am Rande und für mich damit auch abgeschlossen.
Produktiv: Proxmox mit OH 3.4 und HABApp im LXC-Container
Entwicklung: Proxmox mit OH 4.1 und HABApp im LXC-Container

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

Re: Beeinflussung einer Rule durch eine andere Rule ?

Beitrag von Markus_JE »

Hallo zusammen,
ich bekomme auch solch einen Fehler. Was bedeutet dieser denn genau?
2020-03-25 08:35:24.681 [ERROR] [xbase.resource.BatchLinkableResource] - resolution of uriFragment '|::0.2.0.2.0.0.0.0.2.6.6.0.0.0::1::/0' failed.

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

Re: Beeinflussung einer Rule durch eine andere Rule ?

Beitrag von PeterA »

Hi Markus,

ich hab das Thema ja begonnen :) Leider liegen meine Kenntnisse bei solchen Meldungen bei 0% :/
Aktuell habe ich auf Basis der Rule von Tokamak das implementiert und bekomme keine Fehlermeldungen.
viewtopic.php?p=17366#p17366

Gruß Peter
- OpenHab 2.4
#PWRUP

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

Re: Beeinflussung einer Rule durch eine andere Rule ?

Beitrag von Markus_JE »

Hi Peter,
leider weiss ich nicht mal genau wo die Meldung her kommt.

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

Re: Beeinflussung einer Rule durch eine andere Rule ?

Beitrag von PeterA »

So, der guten Ordnung halber noch ein mal die Rule welche hier ohne Fehlermeldungen läuft:

Code: Alles auswählen

rule "WACLuftfeuchtigkeit"
when
    Member of Durchschnitt_Feuchte_Haus changed // Durchschnitt Feuchte durch Lacrosse Sensoren
then
    if (WAC350_Durchschnitt_Feuchte_Haus.state != ON) { // wenn Schalter aus(nicht an) , keine Aktionen
        logInfo("Feuchtesteuerung:","Steuerung deaktiviert!")
    return;
    }
    // bestimme die durchschnittliche und maximale Luftfeuchte
    var int lfSumme=0
    var int lfMax=0
    var int lfCnt=0
    for (item: Durchschnitt_Feuchte_Haus.members) {
        if (item.state instanceof Number) {
            lfCnt+=1
            val int lf=(item.state as Number).intValue()
            lfSumme+=lf
            if (lf>lfMax) lfMax=lf
        }
    }
    // nur bei mindestens 2 Werten ist es sinnvoll, die Werte zu betrachten
    var int lfAvg
    if (lfCnt>=2) {
        lfAvg=lfSumme/lfCnt
    }
    else {
        lfAvg=0
        lfMax=0
    }
    // Bei mehr als max 60% pro Sensor oder avg 55% Luftfeuchtigkeit lüfte.
    if ((lfMax>=60 || lfAvg>=55) && FanStandby_Switch.state != OFF) {  // Standby ist ON und nicht OFF = Lüftung läuft nicht
        FanStandby_Switch.sendCommand(OFF)                             // Schalte Lüftung EIN
        logInfo("Feuchtesteuerung:","Lüftung EIN") 
        sendBroadcastNotification("Feuchtesteuerung: Lüftung EIN")     //Pushnachricht
    }
    else {
    // fällt die Luftfeuchte aller Sensoren unter 55%, wurde genug gelüftet. Lüftung Stop
    if ((lfMax<55) && FanStandby_Switch.state != ON) {                 // Standby ist OFF und nicht ON = Lüftung läuft
        FanStandby_Switch.sendCommand(ON)                              // Schalte Lüftung Standby
        logInfo("Feuchtesteuerung:","Lüftung Standby")
        sendBroadcastNotification("Feuchtesteuerung: Lüftung Standby") //Pushnachricht
        }
    }
end
- OpenHab 2.4
#PWRUP

Antworten