Seite 1 von 3

regel nagative werte

Verfasst: 24. Jul 2023 21:01
von steinadler
hi, ich mal wieder

Code: Alles auswählen

rule "WRregel"



when
    //Item VerbrauchTest changed
    Time cron "0/1 * * * * ?"
then
    if (VerbrauchTest.state > 550) {
        VerbrauchTest.postUpdate(500)
   Thread::sleep(500)
    } else if (VerbrauchTest.state < 1) {
        VerbrauchTest.postUpdate(10)
    }
  //Thread::sleep(1000)
   val mqttActions = getActions("mqtt","mqtt:broker:neuer")
    mqttActions.publishMQTT("Leistung", VerbrauchTest.state.toString)

end  

Hmmm, mein problem ist, ich möchte wie ersichtlich die werte begrenzen. sollte der wert grösser als 550 sein,dann 500. sollte der wert kleiner 1 sein, dann 10. die werte sollen meinen wechselrichter eine 0 watt einspeisung dienen. die regel arbeitet soweit gut, bis ja, irgendwann kommen nagative werte durch ( z.b -110). nach ca 1-1,5 sec läuft die gegel wieder wie sie soll, auch mit nagativen werten, bis irgendwann wieder ein negativer wert erschein (durchkommt)t. mitgelesen habe ich die werte mit MQTT fx. mein WR hängt sich bei diesen "falschen" werten kurz auf, da die byte prüfung nicht hinhaut. ansonsten , wenn die regel keinen fehler macht, läuft das ding, der fehler tritt ca alle 2min in unregelmässigen abständen auf, also kein zyklus von irgendwass. Leistung lese ich mit MQTT fx mit, der WR erhält die daten auch nur von Leistung.

Re: regel nagative werte

Verfasst: 25. Jul 2023 11:02
von udo1toni
Die Regel ist ja auch k_cke... (sorry)

Punkt 1: Niemals einen Time cron Trigger einsetzen, wenn es keinen triftigen Grund dafür gibt! Nie! (Nein, es gibt hier keinen Grund dafür)
Punkt 2: Niemals Thread::sleep() verwenden (es sei denn siehe Punkt 1, triftiger Grund - ist hier nicht gegeben)
Punkt 3: Es ist nicht gut, Status einfach so als Zahl zu betrachten, obwohl gar nicht sichergestellt ist, dass es sich um eine Zahl handelt.
Punkt 4: Du kannst nicht einfach den Wert des Items überschreiben, das muss früher oder später zu Problemen führen. Entweder Du nutzt ein zweites Item, welches dann für die Nulleinspeisung genutzt wird, oder Du löst das Problem auf völlig andere Art, nämlich über eine JS-Transformation innerhalb des Channels (openHAB3 mal vorausgesetzt, bei openHAB2 abhängig vom Binding)

Frage am Rande: Welche Version von openHAB läuft? Davon hängt ab, wie sich die Rule Engine verhält. Tipp an dieser Stelle: Man kann im persönlichen Bereich im Profil eine Signatur setzen, das ist ein guter Platz für eine kurze Info über die verwendete Hard/Software, als Beispiel mag meine Signatur dienen :)

So, die "bessere" Version Deiner Rule:

Code: Alles auswählen

"WR Begrenzer"
when
    Item VerbrauchIn changed                                   // nicht! received update)
then
    if(!(newState instanceof Number))                          // keine Zahl?
        return;                                                // dann Abbruch!
    var nIst = (newState as Number).floatValue                 // Zahl in Variable üernehmen
    if(nIst > 550) nIst = 500                                  // mehr als 550? dann 500
    if(nIst < 1) nIst = 10                                     // weniger als 1? dann 10
    if(VerbrauchOut.state instanceof Number)                   // Hat Zielitem einen gültigen Wert?
        if((VerbrauchOut.state as Number).floatValue == nIst)  // falls ja, entspricht er dem neuen Wert?
            return;                                            // falls ja, Abbruch, nichts zu tun!
                                                               // Wert muss ins Item übernommen werden, also
    VerbrauchOut.postUpdate(nIst)
    val mqttActions = getActions("mqtt","mqtt:broker:neuer")
    mqttActions.publishMQTT("Leistung", nIst.toString)
end
Die Rule triggert bei Wertänderung, nicht einmal pro Sekunde.
Die Rule prüft, ob der aktuelle Wert (aus der impliziten Variablen newState entnommen, das geht schneller als aus dem Item auszulesen) eine Zahl ist. Ist das nicht der Fall, bricht die Rule ab, da sie nur Unsinn anstellen könnte.
Ist der Wert eine gültige Zahl, so wird dieser Wert als Fließkommazahl in eine lokale Variable übernommen.
Anschließend werden Werte über 550 auf 500 und Werte unter 1 auf 10 korrigiert. (gewöhnlich wird man allerdings exakt den Grenzwert setzen und nicht akzeptieren, dass es überhaupt Werte außerhalb der Grenzwerte gibt)
Jetzt folgt noch die Prüfung, ob das Ausgangsitem (welches nicht identisch mit dem Wertgeber ist!) einen gültigen Wert als Status hat. Ist das der Fall, wird geprüft, ob es sich um den aktuellen Wert handelt. Ist das der Fall, muss die Rule nichts weiter tun und bricht ab. Die Prüfung muss hier in zwei Schritten erfolgen, da der Vergleich ansonsten eine Fehlermeldung nach sich ziehen kann - die wird durch die Typprüfung verhindert.

Ansonsten (Kein Wert, oder Wert unterscheidet sich) wird nun der neue Wert ins Ausgangsitem übernommen und es erfolgt eine Meldung.

Soll es ein Item sein (und die Voraussetzungen sind gegeben), so kannst Du im Link zwischen Channel und Item als Profile eine JS Transformation setzen. Der Code dafür ist dann JavaScript. Im JavaScript Script wird eine Funktion definiert, die einzelnen Schritte sind dann, aus dem übergebenen String eine Zahl zu machen, die Zahl auf die Grenzwerte hin zu untersuchen und abschließend den begrenzten Wert zurückzugeben. sieht etwa so aus:

Code: Alles auswählen

(function(inValue) {
    if(isNaN(inValue))
        return null;
    var out = parseFloat(inValue);
    if(out > 550)
        out = 500;
    if(out < 1)
        out = 10;
    return out;
})(input)
Der Code ist aber nicht getestet :)
Du musst den Code im Verzeichnis $OPENHAB_CONF/transform/ in einer einzelnen Datei abspeichern, z.B. borders.js (die Endung ist verpflichtend, der Name aber frei wählbar. Kurz, möglichst keine führenden Ziffern, keine Sonderzeichen usw... sollte klar sein)
Und dann setzt Du im Link als Profile JS und gibst als Parameter den Scriptnamen an, also z.B. borders.js
Sollte JS nicht zur Auswahl stehen, musst Du zuerst noch die JS Transformation installieren :)

Unter openHAB4 musst Du stattdessen nur JS Scripting einrichten, da ist die Transformation integraler Bestandteil. :)

Re: regel nagative werte

Verfasst: 25. Jul 2023 15:46
von steinadler
retter in der not...
danke ersteinmal
habe die variante mit dem zweitem item genommen, muss jetzt ersteinmal auf sonne warten, um in den negativen bereich zu kommen(mehr einspeisen als verbrauch)...
dann kann ich ja auch aus meinem "schlecht" geschriebenen c++ code

Code: Alles auswählen

  client.loop();
       //item = Leistung;
   
   Serial.println(item);
  
  
   if (item >= 550) {
      item = 500;
     } else if (item <= 0) {
      item = 10;
  
  
     }
    Serial.println(item);
    int c = 0x24;
    int d = 0x56;
    int h = 0x00;  
    int e = 0x21;
    int i = (item >> 8);               
die überprüfung wieder raus nehmen

edit
zu früh gefreut, wenn ich die überprüfung aus meinem sketch rausnehme, läuft der wr nicht mehr, mit geht wieder alles...
muss aber an meinem sketch liegen(auf esp8266)
dein teil läuft
danke deiner mühe...
wie gesagt danke ersteinmal , mein WR(soyosource) spielt bis jetzt mit, warte auf sonne...

Re: regel nagative werte

Verfasst: 25. Jul 2023 19:35
von steinadler
rückmeldung
die sonne scheint, habe negative werte(speise also ca 300 watt ein), deine regel geht leider nicht
dennoch danke für deine aufmerksamkeit...

Re: regel nagative werte

Verfasst: 25. Jul 2023 22:11
von udo1toni
Das kann aber nicht sein, dann hast Du einen Fehler drin. Im Item VerbrauchOut können keine Zahlen über +550 oder unter +1 landen, bei Werten außerhalb dieses Bereichs landet dort +500 oder +10. Es ist schlicht nicht möglich, dass hier negative Zahlen übernommen werden.

Re: regel nagative werte

Verfasst: 26. Jul 2023 16:22
von steinadler
hi
ist aber leider so, das geht dann solange, bis das topic(Leistung) nicht mehr gesendet wird.
ich denke, dass ich deine regel einigermassen verstanden habe, sehe auch keinen fehler drin(bin ja auch nur anfänger, du profi)
werde weiter basteln, vielleicht ersteinmal das in c++ auf meinem wemos brutzeln(deine tips werde ich berücksichtigen)
danke

Re: regel nagative werte

Verfasst: 26. Jul 2023 17:23
von udo1toni
Eventuell wird das Item zusätzlich über einen anderen Weg mit Daten versorgt. Wir reden zwingend von zwei Items, das eine, in meinem Code VerbrauchIn, ist mit dem Channel verknüpft, der die Messung liefert.
Das andere, VerbrauchOut in meiner Rule, ist mit keinem Channel verknüpft, oder der verknüpfte Channel wird ausschließlich zum Senden verwendet (Du willst ja evtl. mit der Zahl etwas steuern). Empfangen darf dieses Item aber keinesfalls, von nirgendwo, nur die Rule darf in dieses Item schreiben!

Re: regel nagative werte

Verfasst: 26. Jul 2023 19:47
von steinadler
danke für deine geduld
habe die regel etwas abgeändert, so läuft sie derzeit bei positiven und negativen werten stabil. der wechselrichter spielt auch mit(rauf und runter regeln).
ist nicht so schick wie deine, wenn du noch verbesserungsvorschläge hast, ich lerne gern dazu
hab sie auch noch nicht entrümpelt...

Code: Alles auswählen

rule "WechselrichterSoyosorce"
when
  Item VerbrauchTest changed
then
  //double zahl = (VerbrauchTest.state as DecimalType).doubleValue()
  var zahl = (newState as Number).floatValue  
  if (zahl < 1) {
    zahl = 10;
  } else if (zahl > 550) {
    zahl = 500;
  }
  
  // zahl = Math.floor(zahl);
  //var geZahl = Float.parseFloat(Float.toString(zahl));
 
 
 val mqttActions = getActions("mqtt","mqtt:broker:neuer")
    mqttActions.publishMQTT("Leistung", zahl.toString)  
  


end



Re: regel nagative werte

Verfasst: 27. Jul 2023 12:27
von udo1toni
Dir ist aber schon klar, dass Du lediglich einige Zeilen von meiner Rule entfernt, sowie unnötige Zeichen eingefügt hast? Die Funktion der Rule ist auch gegenüber dem von Dir gewünschten (zu Beginn) reduziert, Du schreibst gar keine Werte mehr in ein Item.

Nun:
Es ist wirklich keine gute Idee, innerhalb einer Rule einen Status eines Number Items zu verwenden und einfach davon auszugehen, dass dieser Status sicher eine gültige Zahl enthält. Konkret geht es um diese beiden Zeilen meiner Rule:

Code: Alles auswählen

    if(!(newState instanceof Number))
        return;
Diese beiden Zeilen stellen sicher, dass der aktuelle Wert des Items vom Typ Number ist. Diese Prüfung ist nicht "kann man machen", sondern sie verhindert NullPointer Exceptions. Number Items können jederzeit die Status NULL oder UNDEF einnehmen, beide Status werden Deine Rule crashen lassen.

Das Semikolon...
Es gibt in der DSL exakt eine Stelle, wo ein Semikolon gebraucht wird, das ist nach dem Schlüsselwort return. Ansonsten solltest Du keine Semikola setzen. Nie.
Was die geschwungenen Klammern betrifft, so kann man die auch um einzelne Befehle setzen, es ist aber nicht unbedingt notwendig und nimmt in dem Fall letztlich nur Platz weg.

else...
kann man machen, ändert aber hier das Verhalten nicht.
Eine Variable hat einen Wert. Der Wert wird auf Überschreiten eines Werts geprüft und gegebenenfalls unter die Obergrenze gesetzt (allerdings nicht unter die Untergrenze). Anschließend wird auf die Untergrenze geprüft. Diese Bedingung kann nicht wahr sein, wenn die erste Bedingung erfüllt war, sie wird also ohnehin übersprungen. Wozu also das else? Die Reihenfolge des Test (zuerst Ober- dann Untergrenze oder zuerst Unter-, dann Obergrenze) spielt ebenfalls keine Rolle.

Re: regel nagative werte

Verfasst: 30. Jul 2023 17:51
von steinadler
sorry, aber eine doofe frage hätte ich noch... wenn ich darf...
du sagtest, --Niemals einen Time cron Trigger einsetzen --, wollte aber dasss die regel nur zu bestimmter uhrzeit läuft, in der form

Code: Alles auswählen

when
    Time cron "0 0 19-23,0-8 * * ? *"
then
    .......
end

wie dann?
eine regel, die die regel an und ausschaltet?
danke