Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Skripten / Logik
    4. Blockly
    5. Werteabhängiges loggen per Skript

    NEWS

    • ioBroker@Smart Living Forum Solingen, 14.06. - Agenda added

    • ioBroker goes Matter ... Matter Adapter in Stable

    • Monatsrückblick - April 2025

    Werteabhängiges loggen per Skript

    This topic has been deleted. Only users with topic management privileges can see it.
    • Homoran
      Homoran Global Moderator Administrators @apollon77 last edited by Homoran

      Ich versuche meine geloggte Datenflut etwas einzudämmen.
      Dazu habe ich in den letzten Tagen mit Blockzeit und minimale Änderung gespielt um nicht jede Sekunde einen Wert zu bekommen, was für den Chart nicht notwendig wäre.
      Allerdings erhalte ich jetzt Artefakte in der Kurve.
      Außerdem habe ich die Vermutunt, dass die Blockzeit nicht greift, wenn der minimale Unterschied überschritten wird.
      Auch den Algorithmus vom minimalen Unterschied kann ich nicht erkennen, zumindest nicht den, den ich erwarten würde.
      Beim letzten Wert von z.B. 18 und einer Einstellung von minimaler Differenz von 3 würde ich erwarten, dass der nächste Wert entweder über 21 oder unter 15 liegen muss. anscheinend wird aber immer der letzte Messwert, auch wenn er nicht geloggt wird, als Basis genommen, so dass im schlimmsten Fall bei gleichmäßig steigender Temperatur 18 - 20 - 22 - 24 - 26.... gar nicht geloggt würde, oder bei sehr unruhigem Sensor 18 - 20 - 17 - 19 - 21 - 18... viel zu oft.

      Ein weiteres Problem zeigt sich hier
      Screenshot_20230206-170115_Firefox.jpg

      Je nachdem wie ich die beiden Parameter einstelle, wird bei zu großer Differenz oder Blocktime die für den korrekten Chart notwendige 0 nicht geloggt, was zu den gezeigten Artefakten führt.
      Gehe ich nur über Blockzeit kann es mir ebenfalls oassieren, dass selbst hohe Verbräuche von kurzer Dauer (z.B. Durchlauferhitzer) nicht oder unvollständig angezeigt werden.


      nachdem in dem Originalthema
      https://forum.iobroker.net/topic/62761/wie-die-parameter-für-history-sinnvoll-nutzen
      die Lösung Richtung Wertebehandlung via Skript driftete, habe ich dies hier abgetrennt.

      1 Reply Last reply Reply Quote 0
      • paul53
        paul53 @klassisch last edited by paul53

        @klassisch sagte: hat @paul53 mal ein Skript geschrieben;

        Das bildet jede Minute den Mittelwert über die Messwerte.
        Wenn nur kleinere Schwankungen ausgeblendet werden sollen, dann besser so:

        Blockly_temp.JPG

        Homoran 2 Replies Last reply Reply Quote 2
        • Homoran
          Homoran Global Moderator Administrators @paul53 last edited by

          @paul53 Danke!
          Ich überdenke gerade mein gesamtes Konzept.
          Habe 50GB Historydaten. Und jetzt kommen noch einige hinzu.

          Ich muss Historisierung und hochfrequente Messungen trennen wo möglich.
          Nur ärgerlich wenn 4 Jahre Daten dann inkompatibel werden.

          apollon77 paul53 2 Replies Last reply Reply Quote 0
          • apollon77
            apollon77 @Homoran last edited by

            @homoran Konvertiere zu InfluxDB?

            1 Reply Last reply Reply Quote 0
            • Homoran
              Homoran Global Moderator Administrators last edited by

              @paul53 sagte:

              History hat einen Alias. Die neuen Daten werden nur seltener historisiert.

              den nutze ich bereits bei einigen DPs.
              Das wäre der schnelle Kompromiss.

              1 Reply Last reply Reply Quote 0
              • Homoran
                Homoran Global Moderator Administrators @paul53 last edited by Homoran

                @paul53 ich muss zugeben dass ich mir mit Absicht dein Blockly nicht angesehen hatte, weil ich es erst selbst versuchen wollte.

                Bei mir ist eben in einer ruhigen Minute das folgende herausgekommen
                Screenshot_20230207-174755_Firefox.jpg
                ist ja nicht ganz so verschieden.
                erst mal nur Entladung, da die Sonne jetzt weg ist.

                Scheint zu laufen.

                Edit: da stimmt noch was mit dem Timeout nicht
                EDIT2: kann auch ein Asynchron Effekt sein, dass der gerade geschriebene Wert noch nicht eingelesen wurde.
                Außerdem scheint der ganze Liste in Timeout möglicherweise gar nicht nötig zu sein.

                paul53 1 Reply Last reply Reply Quote 0
                • paul53
                  paul53 @Homoran last edited by

                  @homoran sagte: da stimmt noch was mit dem Timeout nicht

                  Richtig. Das habe ich auch gerade gesehen. Wozu sollte es dienen?

                  Homoran 1 Reply Last reply Reply Quote 0
                  • Homoran
                    Homoran Global Moderator Administrators @paul53 last edited by Homoran

                    @paul53

                    Wozu sollte es dienen?

                    siehe Edit2

                    ich hatte mir gedacht, dass bei relativ langen Serien mit Werten innerhalb des "Deviation-Bereichs" auch mal ein neuer Wert gesetzt werden soll.
                    Bei den momentanen +/- 20W aber auf jeden Fall unnötig.

                    Will aber diese Grenzen erhöhen und dann auch den Timeout

                    EDIT: Quatsch!
                    ich wollte nur Spitzen (und die 0) sofort und sonst einen Mittelwert in regelmäßigen Abständen haben.
                    Ist mir irgendwie durchgerutscht 😢

                    so in etwa
                    Screenshot_20230207-182531_Firefox.jpg

                    paul53 1 Reply Last reply Reply Quote 0
                    • paul53
                      paul53 @Homoran last edited by paul53

                      @homoran sagte: Mittelwert in regelmäßigen Abständen

                      Dann stoppe auch timeout bei Ablauf der Zeit und leere die Liste, da sonst der Mittelwert nur einmal geschrieben wird. Oder verwende ein Intervall.

                      1 Reply Last reply Reply Quote 0
                      • Homoran
                        Homoran Global Moderator Administrators last edited by

                        @paul53 sagte:

                        Dann stoppe auch timeout bei Ablauf der Zeit

                        jetzt bin ich irritiert. Nach Ablauf trotzdem stoppen?

                        @paul53 sagte in Wie die Parameter für History sinnvoll nutzen?:

                        und leere die Liste

                        der Baustein war beim umgestalten rausgefallen und ich wusste nicht mehr wohin 😊

                        sieht im Moment so aus
                        Screenshot_20230207-185011_Firefox.jpg

                        @paul53 sagte in Wie die Parameter für History sinnvoll nutzen?:

                        Oder verwende ein Intervall.

                        das feuert aber stumpf alle 5 Minuten, oder?
                        ist eigentlich egal. Ich hatte gedacht immer 5 Minuten nach dem letzten Wert, auch wenn es ein "high priority" Wert war.

                        paul53 1 Reply Last reply Reply Quote 0
                        • paul53
                          paul53 @Homoran last edited by paul53

                          @homoran sagt: das feuert aber stumpf alle 5 Minuten, oder?

                          Ja, bis es gestoppt wird.

                          @homoran sagte in Wie die Parameter für History sinnvoll nutzen?:

                          immer 5 Minuten nach dem letzten Wert

                          Der Timer kann erst wieder starten, wenn die Variable timeout auf null zurück gesetzt wurde. Sonst wirkt die erforderliche Sperre.

                          1 Reply Last reply Reply Quote 0
                          • Homoran
                            Homoran Global Moderator Administrators last edited by Homoran

                            @paul53 jetzt si d wir schon lange nicht mehr beim Originalthema.
                            Wenn ich's nicht vergesse spalte ich den "nicht History" Teil ab und schieb ihn nach Blockly.


                            Das ganze wird langsam zum Mammutwerk.
                            Nachdem der Entladen-Teil gestern erwartungsgemäß lief, warf er heute bei Sonnenschein Fehler, dass ich einen Mittelwert aus einem leeren Array bilden wollte.
                            Also flugs noch das Intervall gestoppt.
                            Screenshot_20230208-165259_Firefox.jpg

                            Dieser startete heute abend nachdem die Solarenergie nicht mehr zum Laden reichte, und die Batterie wieder entlud, jedoch nicht.
                            Also muss ich den Start Intervall irgendwie anders lösen.

                            Was mir auch nicht präsent war ist die Tatsache, dass das kopieren des Timeout Konstrukts jedesmal die Intervall-Variable hochzählt.

                            Geht es irgendwie mit dem selben Intervall mehrfach zu arbeiten?
                            ggf. als Funktion?
                            So in der Art Start oder Stop Intervall "Laden", resp. Start/Stop Intervall "Entladen".

                            Sonst habe ich in der Endgültigen Fassung mindestens 6 Intervalle, die alle an allen möglichen Programmstellen gestoppt werden müssten.

                            paul53 2 Replies Last reply Reply Quote 0
                            • paul53
                              paul53 @Homoran last edited by paul53

                              @homoran sagte: Geht es irgendwie mit dem selben Intervall mehrfach zu arbeiten ggf. als Funktion?

                              Ja, wenn innerhalb der Intervall-Callback-Funktion die gleichen Kommandos abgearbeitet werden, kann man das Intervall in eine Funktion auslagern.

                              Blockly_temp.JPG

                              Homoran 1 Reply Last reply Reply Quote 1
                              • Homoran
                                Homoran Global Moderator Administrators @paul53 last edited by

                                @paul53 DANKE!

                                werde ich später versuchen umzusetzen!

                                A 1 Reply Last reply Reply Quote 0
                                • A
                                  AndyGR42 @Homoran last edited by

                                  @homoran irgendwie finde ich ein Script übersichtlicher 🙂

                                  Im Prinzip bestimmst Du mit "historyArrayLength" und "updateFrequence", zusammen mit der Frequenz des eingehenden Signals, wie oft die History geschrieben wird und wie "glatt" das Ergebnis wird. Je länger das Array desto "glatter" die Kurve. History wird geschrieben, sobald das Array voll ist, um fehlerhafte Einträge zu vermeiden.

                                  const historyArrayLength = 5;
                                  const updateFrequence = 5;
                                  
                                  var updateFrequencecounter = updateFrequence;
                                  
                                  // create memory persistent arrays
                                  
                                  let historyArray = new Array(historyArrayLength); 
                                  
                                  var i;
                                  
                                  for (i = 0; i < historyArrayLength; i++){ //fill array with -1
                                      
                                      historyArray[i] = -1;
                                  }
                                  
                                  // process avarage
                                  
                                  on({id: "0_userdata.0.IoT.DaylightSensor.DayLight02", change: "any"}, function (obj) {
                                      var value = obj.state.val;
                                  
                                      update_historyArry(value);
                                  
                                      var index = historyArray.indexOf(-1);
                                  
                                      if (index == -1 && updateFrequencecounter <= 0)
                                      {
                                          
                                          var sum = historyArray.reduce((a, b) => a + b, 0);
                                          var avg = (sum / historyArray.length) || 0;
                                          
                                          setState('0_userdata.0.Test.Test01', Number(avg));
                                          updateFrequencecounter = updateFrequence;
                                      }
                                  
                                      updateFrequencecounter--;
                                  
                                  });
                                  
                                  
                                  // ################################### helper funcions
                                  
                                  // shift and update the array
                                  
                                  function update_historyArry(value)
                                  {
                                      var i;
                                  
                                      for (i = historyArrayLength - 1; i >= 0; i--)
                                      {
                                          if (i > 0)
                                          {
                                             historyArray[i] = historyArray[i - 1];
                                          }
                                          else
                                          {
                                              historyArray[i] = value;
                                          }
                                      }
                                  }
                                  
                                  Homoran 1 Reply Last reply Reply Quote 0
                                  • Homoran
                                    Homoran Global Moderator Administrators @AndyGR42 last edited by

                                    @andygr42 sagte in Werteabhängiges loggen per Skript:

                                    irgendwie finde ich ein Script übersichtlicher

                                    beim Lesen kann ich dir fast zustimmen.
                                    Schreiben kann ich es nicht

                                    A 2 Replies Last reply Reply Quote 0
                                    • paul53
                                      paul53 @Homoran last edited by paul53

                                      @homoran
                                      Meiner Meinung wird zu früh zwischen Laden und Entladen unterschieden. Ich würde erst auswerten, ob gegenüber dem zuletzt geschriebenen Wert eine große Leistungsänderung (in beiden Richtungen) stattgefunden hat und diese protokollieren. Bei der Mittelwertbildung über 2 Minuten würde ich den Mittelwert auswerten.

                                      Blockly_temp.JPG

                                      Homoran 1 Reply Last reply Reply Quote 0
                                      • A
                                        AndyGR42 @Homoran last edited by AndyGR42

                                        @homoran

                                        Ich habe es nochmal etwas aufgeräumt. Im Prinzip reicht Copy & Paste sowie das Ändern der ersten 4 Zeilen.

                                        Das Skript macht ganz simpel eine Mittelwertberechnung ohne Normalisierung. Mit den Werten kannst Du dann etwas rumspielen. Es macht natürlich keinen Sinn, dass die Array Länge kleiner als die Update Frequenz ist. Dann gehen Informationen verloren. Wenn aber (bei einem Signal mit 1Hz) bei einem Schreiben der History alle 60 Sekunden die Kurve immer noch zu unruhig ist, kann die Verlängerung des Arrays auf 120 oder 180 eine deutliche Verbesserung bringen.

                                        Ich habe auch noch ein Script mit einer Normalisierung, bei der vorher per Normalverteilung die höchsten und tiefsten Ausreißer abgeschnitten werden können. Das ist aber lange nicht so universell und selbsterklärend. Zudem könnte es in deinem Fall die Messwerte verfälschen, da Peaks keinen Einfluss auf den Durchschnitt mehr haben.

                                        Ach ja, für eine große Zahl an DP macht es natürlich keinen Sinn jeweils ein Script zu erstellen. Wenn gewünscht kann ich das noch umbauen um mehrere DP einfacher und übersichtlicher zu verwalten.

                                        const inputDP = '0_userdata.0.IoT.DaylightSensor.DayLight02';
                                        const historyDP = '0_userdata.0.Test.Test01';
                                        
                                        const historyArrayLength = 5;
                                        const updateFrequence = 5;
                                        
                                        /** nothing to chage below this line */
                                        /** -------------------------------- */
                                        
                                        var updateFrequenceCounter = updateFrequence; /** reset update counter */
                                        var i;
                                        
                                        let historyArray = new Array(historyArrayLength); /** create persistent arry */
                                        
                                        for (i = 0; i < historyArrayLength; i++){ /** fill array with "false" for data consistancy check */
                                            historyArray[i] = -1;
                                        }
                                        
                                        /** wait for changes and calculate avarage */
                                        
                                        on({id: inputDP, change: "any"}, function (obj) {
                                            var value = obj.state.val;
                                        
                                            update_historyArray(value); /** run shift & update array */
                                        
                                            var index = historyArray.indexOf(-1); /** search for remaining -1 in arry */
                                        
                                            if (index == -1 && updateFrequenceCounter <= 0) /** update history DP when data is consistent (array filled) and update cycle is reached */
                                            {
                                                
                                                var sum = historyArray.reduce((a, b) => a + b, 0); /** calculate average from the array */
                                                var avg = (sum / historyArray.length) || 0;
                                                
                                                setState(historyDP, Number(avg)); /** write history DP */
                                                updateFrequenceCounter = updateFrequence; /** reset update counter */
                                            }
                                            else
                                            {
                                                updateFrequenceCounter--; /** count down until next update */
                                            }
                                        });
                                        
                                        
                                        // ################################### helper funcions
                                        
                                        // shift and update the array
                                        
                                        function update_historyArray(value)
                                        {
                                            var i;
                                        
                                            for (i = historyArrayLength - 1; i >= 0; i--) 
                                            {
                                                if (i > 0)
                                                {
                                                   historyArray[i] = historyArray[i - 1];
                                                }
                                                else
                                                {
                                                    historyArray[i] = value;
                                                }
                                            }
                                        }
                                        
                                        1 Reply Last reply Reply Quote 0
                                        • Homoran
                                          Homoran Global Moderator Administrators @paul53 last edited by Homoran

                                          @paul53 sagte:

                                          Meiner Meinung wird zu früh zwischen Laden und Entladen unterschieden.

                                          ich habe einen Datenpunkt mit wechselndem Vorzeichen.
                                          natürlich kann ich da eine Hysterese einbauen, aber was soll die bringen (für das Skript)?
                                          je nach Verbraucher oder Wechsel in der Sonneneinstrahlung kann der Verbrauch/die Produktion immer schleichend an der Entscheidungsgrenze liegen oder auch noch nach einiger Zeit zwischen Be- und Entladung umschalten.

                                          Amüsantes Beispiel war heute Morgen die Moccamaster Kaffeemaschine, die Intervallbrühen betreibt, so dass mit 1500W oder 0W Last tatsächlich die Ladung dauernd umschaltete.

                                          bin gerade dabei dein Blockly häppchenweise zu verdauen 🙂

                                          A paul53 2 Replies Last reply Reply Quote 0
                                          • A
                                            AndyGR42 @Homoran last edited by

                                            @homoran Negative Vorzeichen und schnell wechselnde Lasten wären bei der einfachen Durchschnittsrechnung kein Problem. So lange Array Länge eine ganzzahliges, Vielfaches der Update Frequenz ist, stimmt auch der Durchschnitt.

                                            Homoran 1 Reply Last reply Reply Quote 0
                                            • First post
                                              Last post

                                            Support us

                                            ioBroker
                                            Community Adapters
                                            Donate

                                            536
                                            Online

                                            31.7k
                                            Users

                                            79.6k
                                            Topics

                                            1.3m
                                            Posts

                                            4
                                            53
                                            1853
                                            Loading More Posts
                                            • Oldest to Newest
                                            • Newest to Oldest
                                            • Most Votes
                                            Reply
                                            • Reply as topic
                                            Log in to reply
                                            Community
                                            Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
                                            The ioBroker Community 2014-2023
                                            logo