Seite 4 von 5

Re: Prozentwert berechnen

Verfasst: 22. Feb 2019 16:21
von udo1toni
Peter Aschinger hat geschrieben: 22. Feb 2019 15:41 Und weshalb ist rrd4j nicht geeignet ?
rrd4j hat Probleme mit bestimmten Abfragen, z.B. changedSince ist so ein Fall.
Kann man da nicht ne art "Delay" einbauen, so das die Rule 120sec "hält" und dann weiter läuft ?
Nein, das geht gleich aus mehreren Gründen nicht. Zuerst mal arbeitet openHAB asynchron. Eine Rule kann beliebig oft getriggert werden und wird dann auch beliebig oft nebeneinander ausgeführt. Das "Anhalten" könnte im Extremfall dazu führen, dass gar kein Code mehr ausgeführt wird, weil alle zur Verfügung stehenden Threads von angehaltenen Rules belegt sind.
Die Rule wird ja nicht ausschließlich bei einem Wechsel der Betriebsart getriggert, sondern bei jeglicher Wertänderung. deshalb musst Du wissen, wann die Betriebsart gewechselt wurde.
Dann brauch ich keine Datenbank.
Na ja, die ist auch für andere Dinge sinnvoll. Man kann um das Problem herum programmieren, indem man die Funktion selbst implementiert:

Code: Alles auswählen

var Long lLStufe
rule "luefter geändert"
when
    Item Luefterstufe changed
then
    lLStufe = now.millis
end
In der eigentlichen Rule kannst Du dann mit

Code: Alles auswählen

if(lLStufe + 2*60*1000 < now.millis){
    //Lüfter läuft bereits mindestens 2 Minuten auf der aktuellen Stufe
}
als Abfrage arbeiten. Allerdings kannst Du dann den Trigger für Luefterstufe gleich ganz weg lassen, der bringt ja dann nichts mehr.
Bei dem ganzen geklammere wirds einem böse schwindelig. :-)
Aber nur zu Anfang, wenn man es mal verstanden hat, ist es einfach. Wenn man den Code immer schön einrückt, sieht man auf einen Blick, was wohin gehört.

Re: Prozentwert berechnen

Verfasst: 22. Feb 2019 18:10
von PeterA
[/quote]
Na ja, die ist auch für andere Dinge sinnvoll. Man kann um das Problem herum programmieren, indem man die Funktion selbst implementiert:

Code: Alles auswählen

var Long lLStufe
rule "luefter geändert"
when
    Item Luefterstufe changed
then
    lLStufe = now.millis
end
Ok, und wo muss der Code rein ? In eine extra rule ?

Re: Prozentwert berechnen

Verfasst: 22. Feb 2019 18:47
von PeterA
So habe ich jetzt mal die Rule eingetragen:

Code: Alles auswählen

rule "berechne Wirkungsgrad"
when
    Item Abluft changed or
    Item Zuluft changed or
    Item Aussenluft changed or
    Item Fort_Luft changed
then
    if(lLStufe + 2*60*1000 < now.millis){
    //Lüfter läuft bereits mindestens 2 Minuten auf der aktuellen Stufe
 }
{
    if(!(Abluft.state instanceof Number)) {
        logWarn("Wirkungsgrad","Abluft.state not a Number: {}",Abluft.state)
        return;
    }
    if(!(Zuluft.state instanceof Number)) {
        logWarn("Wirkungsgrad","Zuluft.state not a Number: {}",Zuluft.state)
        return;
    }
    if(!(Aussenluft.state instanceof Number)) {
        logWarn("Wirkungsgrad","Aussenluft.state not a Number: {}",Aussenluft.state)
        return;
    }
    if(!(Fort_Luft.state instanceof Number)) {
        logWarn("Wirkungsgrad","Fort_Luft.state not a Number: {}",Fort_Luft.state)
        return;
    }
    val Number Aussenluft = (Aussenluft.state as Number)
    val Number Fort_Luft = (Fort_Luft.state as Number)
    val Number nDivisor = (Abluft.state as Number) - Aussenluft //Wert fuer Berechung gem. Westaflex
    val Number nFaktor = (Zuluft.state as Number) - Aussenluft //Wert fuer Berechung gem. Westaflex
    val Number nDivisor2 = (Abluft.state as Number) - Fort_Luft
    if(nDivisor == 0) {
        logWarn("Wirkungsgrad","Aussentemperatur = Ablufttemperatur, Division durch 0!")
        Wirkungsgrad.postUpdate(NULL)
    } else
        Wirkungsgrad.postUpdate((100*nFaktor/nDivisor).intValue) //Berechung gem. Westaflex
    if(nDivisor2 == 0) {
        logWarn("Wirkungsgrad2","Ablufttemperatur = Aussentemperatur, Division durch 0!")
        Wirkungsgrad2.postUpdate(NULL)
    } else
        Wirkungsgrad2.postUpdate((100*nDivisor2/nDivisor).intValue)
 }
end
Aber dann kommt im Log das hier:

2019-02-22 18:46:31.709 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'berechne Wirkungsgrad': The name 'lLStufe' cannot be resolved to an item or type; line 8, column 8, length 7

Re: Prozentwert berechnen

Verfasst: 22. Feb 2019 22:26
von udo1toni
Ja, das ist eine extra Rule. Die Variablendefinition (var Long lLStufe) muss ganz zu Anfang der Rules-Datei stehen.

Und natürlich musst Du die Klammern um den auszuführenden Code setzen (das heißt, Du ersetzt den Kommentar mit dem Code, der nur ausgeführt werden soll, wenn der letzte Lüfterstufenwechsel mindestens zwei Minuten her ist)

Das gesamte Rules File sähe dann so aus (vorausgesetzt, es sind nicht noch weitere Rule vorhanden):

Code: Alles auswählen

// Beginn der Datei
// globale Variablen
var Long lLStufe

rule "luefter geändert"
when
    Item Luefterstufe changed
then
    lLStufe = now.millis
end

rule "berechne Wirkungsgrad"
when
    Item Abluft changed or
    Item Zuluft changed or
    Item Aussenluft changed or
    Item Fort_Luft changed
then
    if(lLStufe + 2*60*1000 < now.millis){
        if(!(Abluft.state instanceof Number)) {
            logWarn("Wirkungsgrad","Abluft.state not a Number: {}",Abluft.state)
            return;
        }
        if(!(Zuluft.state instanceof Number)) {
            logWarn("Wirkungsgrad","Zuluft.state not a Number: {}",Zuluft.state)
            return;
        }
        if(!(Aussenluft.state instanceof Number)) {
            logWarn("Wirkungsgrad","Aussenluft.state not a Number: {}",Aussenluft.state)
            return;
        }
        if(!(Fort_Luft.state instanceof Number)) {
            logWarn("Wirkungsgrad","Fort_Luft.state not a Number: {}",Fort_Luft.state)
            return;
        }

        val Number Aussenluft = (Aussenluft.state as Number)
        val Number Fort_Luft = (Fort_Luft.state as Number)
        val Number nDivisor = (Abluft.state as Number) - Aussenluft //Wert fuer Berechung gem. Westaflex
        val Number nFaktor = (Zuluft.state as Number) - Aussenluft //Wert fuer Berechung gem. Westaflex
        val Number nDivisor2 = (Abluft.state as Number) - Fort_Luft

        if(nDivisor == 0) {
            logWarn("Wirkungsgrad","Aussentemperatur = Ablufttemperatur, Division durch 0!")
            Wirkungsgrad.postUpdate(NULL)
        } else
            Wirkungsgrad.postUpdate((100*nFaktor/nDivisor).intValue) //Berechung gem. Westaflex
        if(nDivisor2 == 0) {
            logWarn("Wirkungsgrad2","Ablufttemperatur = Aussentemperatur, Division durch 0!")
            Wirkungsgrad2.postUpdate(NULL)
        } else
            Wirkungsgrad2.postUpdate((100*nDivisor2/nDivisor).intValue)
    }
end

Re: Prozentwert berechnen

Verfasst: 22. Feb 2019 23:31
von PeterA
Ok, habe ich jetzt mal alles so eingetragen.
Aber dann kommt das im Log:

2019-02-22 23:29:58.015 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'berechne Wirkungsgrad': An error occurred during the script execution: Could not invoke method: org.eclipse.xtext.xbase.lib.LongExtensions.operator_plus(long,int) on instance: null

EDIT:
Es scheint doch zu funktionieren:

Hier Starte ich den Lüfter:
2019-02-22 23:38:38.512 [ome.event.ItemCommandEvent] - Item 'LuefterStufe' received command 1

2019-02-22 23:38:38.519 [nt.ItemStatePredictedEvent] - LuefterStufe predicted to become 1

2019-02-22 23:38:38.527 [vent.ItemStateChangedEvent] - LuefterStufe changed from 0 to 1

und erst hier beginnt die Berechnung:
2019-02-22 23:40:28.531 [vent.ItemStateChangedEvent] - Abluft changed from 18.4 to 18.5

2019-02-22 23:40:44.431 [vent.ItemStateChangedEvent] - Aussenluft changed from 7.4 to 7.3

2019-02-22 23:40:44.514 [vent.ItemStateChangedEvent] - Wirkungsgrad changed from 58 to 56

2019-02-22 23:40:44.533 [vent.ItemStateChangedEvent] - Wirkungsgrad2 changed from 82 to 83

TOP TOP TOP!

Super Vielen Dank! :D :D

Edit2:

Funktioniert doch nicht..
2019-02-22 23:50:45.647 [vent.ItemStateChangedEvent] - Wirkungsgrad2 changed from 132 to 133

2019-02-22 23:50:48.191 [vent.ItemStateChangedEvent] - RasPi_Cpu_SystemUptime changed from 17386.8 to 17387.8

2019-02-22 23:50:56.050 [vent.ItemStateChangedEvent] - Abluft changed from 16.1 to 16.0

2019-02-22 23:50:56.076 [vent.ItemStateChangedEvent] - Wirkungsgrad changed from 58 to 59

2019-02-22 23:50:56.082 [vent.ItemStateChangedEvent] - Wirkungsgrad2 changed from 133 to 134

Berechnung läuft ob wohl die Lüftung Aus ist...

Re: Prozentwert berechnen

Verfasst: 23. Feb 2019 00:04
von PeterA
So, wenn ich mir das Log so ansehe kann ich folgendes beobachten:
Lüfter läuft, Berechnung läuft.
Lüfter wird gestoppt, Berechnung wird gestoppt aber nach 120sec startet die Berechnung wieder. Obwohl die Lüfter aus sind.
Lüfter werden wieder gestartet, Berechnung beginnt 120sec Später....

Re: Prozentwert berechnen

Verfasst: 23. Feb 2019 23:26
von udo1toni
Ups. Ich hab aus Versehen die BEdingung rausgenommen, die die Lüfterstufe abfragt. Die erste Zeile müsste also so aussehen:

Code: Alles auswählen

if(lLStufe + 2*60*1000 < now.millis && Luefterstufe.state.toString != "0"){

Re: Prozentwert berechnen

Verfasst: 27. Feb 2019 11:31
von PeterA
udo1toni hat geschrieben: 22. Feb 2019 22:26 Ja, das ist eine extra Rule. Die Variablendefinition (var Long lLStufe) muss ganz zu Anfang der Rules-Datei stehen.

Und natürlich musst Du die Klammern um den auszuführenden Code setzen (das heißt, Du ersetzt den Kommentar mit dem Code, der nur ausgeführt werden soll, wenn der letzte Lüfterstufenwechsel mindestens zwei Minuten her ist)

Das gesamte Rules File sähe dann so aus (vorausgesetzt, es sind nicht noch weitere Rule vorhanden):
Hallo Udo, was meinst Du mit "weitere Rule vorhhanden" ?
Ja es gibt noch eine Rule. Die hat aber nix mit der Berechnungsrule zu tun.

Re: Prozentwert berechnen

Verfasst: 27. Feb 2019 11:47
von PeterA
So , hier nun noch mal die Aktuelle Rule:
Leider haut das hier immer noch nicht so hin...
Wenn die Lüfter aus sind = LuefterStufe 0, Läuft die Berechnung weiter.

Code: Alles auswählen

// Beginn der Datei
// globale Variablen
var Long lLStufe

rule "luefter geändert"
when
    Item LuefterStufe changed
then
    lLStufe = now.millis
end

rule "berechne Wirkungsgrad"
when
    Item Abluft changed or
    Item Zuluft changed or
    Item Aussenluft changed
then
    if(lLStufe + 2*60*1000 < now.millis && LuefterStufe.state.toString != "0"){
    //Lüfter läuft bereits mindestens 2 Minuten auf der aktuellen Stufe
 }
{
    if(!(Abluft.state instanceof Number)) {
        logWarn("Wirkungsgrad","Abluft.state not a Number: {}",Abluft.state)
        return;
    }
    if(!(Zuluft.state instanceof Number)) {
        logWarn("Wirkungsgrad","Zuluft.state not a Number: {}",Zuluft.state)
        return;
    }
    if(!(Aussenluft.state instanceof Number)) {
        logWarn("Wirkungsgrad","Aussenluft.state not a Number: {}",Aussenluft.state)
        return;
    }
    val Number Aussenluft = (Aussenluft.state as Number)
    val Number nDivisor = (Abluft.state as Number) - Aussenluft //Wert fuer Berechung gem. Westaflex
    val Number nFaktor = (Zuluft.state as Number) - Aussenluft //Wert fuer Berechung gem. Westaflex
    if(nDivisor == 0) {
        logWarn("Wirkungsgrad","Aussentemperatur = Ablufttemperatur, Division durch 0!")
        Wirkungsgrad.postUpdate(NULL)
    } else
        Wirkungsgrad.postUpdate((100*nFaktor/nDivisor).intValue) //Berechung gem. Westaflex
       
 }
end

Re: Prozentwert berechnen

Verfasst: 27. Feb 2019 13:13
von peter-pan
Hallo Peter,
vielleicht sind da ein paar geschweifte Klammern nach dem ersten if zuviel. Deshalb werden diese Anweisungen immer ausgeführt, da sie durch die Klammerung keine Unteranweisungen der ersten Bedingung sind. Udo hatte das extra schön eingerückt, damit es visuell erkannt werden kann.
So sollte es gehen:

Code: Alles auswählen

// Beginn der Datei
// globale Variablen
var Long lLStufe

rule "luefter geändert"
when
    Item LuefterStufe changed
then
    lLStufe = now.millis
end

rule "berechne Wirkungsgrad"
when
    Item Abluft changed or
    Item Zuluft changed or
    Item Aussenluft changed
then
    if(lLStufe + 2*60*1000 < now.millis && LuefterStufe.state.toString != "0"){
    //Lüfter läuft bereits mindestens 2 Minuten auf der aktuellen Stufe

       if(!(Abluft.state instanceof Number)) {
           logWarn("Wirkungsgrad","Abluft.state not a Number: {}",Abluft.state)
           return;
       }
       if(!(Zuluft.state instanceof Number)) {
           logWarn("Wirkungsgrad","Zuluft.state not a Number: {}",Zuluft.state)
           return;
       }
       if(!(Aussenluft.state instanceof Number)) {
           logWarn("Wirkungsgrad","Aussenluft.state not a Number: {}",Aussenluft.state)
           return;
       }
       val Number Aussenluft = (Aussenluft.state as Number)
       val Number nDivisor = (Abluft.state as Number) - Aussenluft //Wert fuer Berechung gem. Westaflex
       val Number nFaktor = (Zuluft.state as Number) - Aussenluft //Wert fuer Berechung gem. Westaflex
       if(nDivisor == 0) {
           logWarn("Wirkungsgrad","Aussentemperatur = Ablufttemperatur, Division durch 0!")
           Wirkungsgrad.postUpdate(NULL)
       } else
           Wirkungsgrad.postUpdate((100*nFaktor/nDivisor).intValue) //Berechung gem. Westaflex
          
 }
end
Ich hoffe, ich hab's jetzt nicht "verschlimmbösert" :roll: ;)

Gruss - Peter