Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Skripten / Logik
    4. JavaScript
    5. Anpassung eines Scripts / Hilfe benötigt

    NEWS

    • Neuer Blog: Fotos und Eindrücke aus Solingen

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

    • ioBroker goes Matter ... Matter Adapter in Stable

    Anpassung eines Scripts / Hilfe benötigt

    This topic has been deleted. Only users with topic management privileges can see it.
    • O
      opöl last edited by opöl

      Hallo zusammen,
      erst einmal ein verspätetes „Frohes neues Jahr“.

      Sorry, viel Text.

      Ich habe ein Problem mit einem Script, dass ich mit meinen Kenntnissen leider noch nicht in den Griff bekomme. Vielleicht kann mir da jemand auf die Sprünge helfen.

      Das hier bekannte Script des Users @skb mit den Ergänzungen von @SpacerX : „Shelly Verbrauchs-Historie für Tag, Woche, Monat, Jahr“ von hier:
      https://forum.iobroker.net/topic/37262/shelly-verbrauchs-historie-für-tag-woche-monat-jahr/82?_=1736424008402&lang=de
      habe ich seit langem erfolgreich im Einsatz und seit einem Jahr auch für Sonoff Geräte (z.B. für Nous A1T Steckdosen mit Tasmota) adaptiert. Läuft soweit prima. Hier für interessierte das Script für die Nous Steckdosen (leider noch nicht ganz aufgeräumt):

       /*
       *
       * Dieses Skript dient zur Verbrauchserfassung von Tasmota Geräten
       * Z.B. Nous Steckdosen oder auf Tasmota geflashte Shelly Geräte.
       * 
       * Das Script ermittelt aus dem Zählerstand der Geräte die Tages- Wochen- Monats- 
       * und Jahresverbräuche und legt diese in neuen Objekten unter "0_userdata.0.NousVerbrauch"
       * im iobroker ab. Damit ist eine einfachere grafische Darstellung und Auswertung möglich.
       * 
       * Die Verbreitung, Anpassung und Optimierung zu privaten Zwecken ist ausdrücklich gestattet.
       * 
       * Jegliche Verantwortung liegt beim Benutzer. 
       * 
       * 
       * Skript Name:      Nous-Verbrauch
       * Skript Version:   1.70  | 25. April 2024
       * Erstell-Datum:    08. Oktober 2023
       *
       * Das Script basiert auf dem Shelly-Verbrauch Script des Autors 
       * Stephan Kreyenborg sowie den Anpassungen von SpacerX.
       * 
       */
      
      // Datenpunkte neu erstellen
      var ueberschreiben = false;
      // Hauptdatenpunkt unterhalb javascript
      var datenpunkt = "NousVerbrauch."; // Abschließender Punkt !!! WICHTIG !!!
      // Verbrauchs Objekte der einzelnen Nous
      var objekt = ["gesamt", "dieses_jahr", "letztes_jahr", "letzter_monat", "dieser_monat", "letzte_woche",
          "diese_woche", "gestern", "heute", "alter_wert", "aktueller_wert"
      ];
      // Beschreibung der Objekte
      var beschreibung = ["Gesamter Vebrauch des Nous", "Verbrauch aktuelles Jahr", "Verbrauch letztes Jahr",
          "Verbrauch letzten Monat", "Verbrauch aktueller Monat", "Verbrauch letzte Woche", "Verbrauch diese Woche",
          "Verbrauch gestern", "Verbrauch heute", "Messwert alt", "Messwert neu"
      ];
      // Datenpunkt der Nous (Standard: sonoff.0)
      var Nous_dp = "sonoff.0";
      // Datenpunkte der Nous (!!! Bitte nicht ändern !!!)
      var NousDps = $('state[id=' + Nous_dp + '.*.*.Total]');  
      // Datenpunkte der Nous Namen (!!! Bitte nicht ändern !!!)
      var NousDpsName = $('state[id=' + Nous_dp + '.*.name]');
      // Nous Verbrauch aktualisieren - nachts um 00:00 Uhr
      function Nous_vebrauch_tag() {
          // Nochmals das Tagesupdate durchlaufen, damit die restlichen Werte gelesen werden
          Nous_verbrauch_update();
          // Datumsvariable
          var heute = new Date();
          // Heute zu Gestern verschieben. Täglich um 00:00 Uhr
          verschiebe_verbrauch_objekt("heute", "gestern");
          log("Nous Verbrauch: Werte für gestern und heute aktualisiert!");
          // aktuelle Woche in letzte Woche verschieben. Am Montag um 00:00 Uhr
          if (heute.getDay() === 1) {
              verschiebe_verbrauch_objekt("diese_woche", "letzte_woche");
              log("Nous Verbrauch: Werte für diese und letzte Woche aktualisiert!");
          }
          // aktueller Monat in letzten Monat verschieben. Am 1. des Monats um 00:00 Uhr
          if (heute.getDate() === 1) {
              verschiebe_verbrauch_objekt("dieser_monat", "letzter_monat");
              log("Nous Verbrauch: Werte für diesen und letzten Monat aktualisiert!");
          }
          // aktuelles Jahr in letztes Jahr verschieben. Am 1. des Monats am 1. Monat um 00:00 Uhr
          if (heute.getDate() === 1 && heute.getMonth() === 0) {
              verschiebe_verbrauch_objekt("dieses_jahr", "letztes_jahr");
              log("Nous Verbrauch: Werte für dieses und letztes Jahr aktualisiert!");
          }
      }
      // Tagesverbrauch alle 15 Min von der Original Variable des Nous in eigene Variable kopieren
      function Nous_verbrauch_update() {
          var anzahl_updates = 0;
          var anzahl_reboots = 0;
          var anzahl_gleich = 0;
          NousDps.each(function (id, i) {
              //var Nous_verbrauch = getState(id).val; 
              var Nous_verbrauch = 1000 * getState(id).val; // Nous Steckdoesen geben die Leistungswerte in kWH an, Shellys in Wh
              if (Nous_verbrauch != null) {
                  // Hole aktuellen Wert, um zu kontrollieren, ob ein Reboot stattgefunden hat
                  var aktueller_wert = getState(Nous_DP(id) + "aktueller_wert").val;
                  var alter_wert = 0;
                  // Prüfe alten und neuen Wert
                  if (Nous_verbrauch > aktueller_wert) {
                      // Verbrauchswert ist größer als alter Wert -> es wurde kein Reboot durchgeführt
                      setState(Nous_DP(id) + "alter_wert", aktueller_wert, true);
                      alter_wert = aktueller_wert;
                      anzahl_updates++;
                  }
                  
      
                  if (aktueller_wert > Nous_verbrauch) {
                      // Verbrauchswert ist kleiner als alter Wert -> es wurde ein Reboot durchgeführt
                      // setState(Nous_DP(id) + "alter_wert", 0, true);
                      // alter_wert = 0;
                      alter_wert = aktueller_wert; // Um Rechenfegler durch fehlende Messwerte zu verhindern
                      anzahl_reboots++;
                  }
      
                  if (Nous_verbrauch == aktueller_wert) {
                      // Verbrauchswert ist gleich altem Wert -> kein Update notwendig
                      alter_wert = aktueller_wert;
                      anzahl_gleich++;
                  }
                  setState(Nous_DP(id) + "aktueller_wert", Nous_verbrauch, true);
                  // Alter und neuer Wert -> aktuelle Differenz
                  var verbrauch = parseFloat(Nous_verbrauch) - alter_wert;
                  // Tagesverbrauch aktualisieren
                  aktualisiere_vebrauch_objekt(Nous_DP(id), "heute", verbrauch);
                  // Wochenverbrauch aktualisieren
                  aktualisiere_vebrauch_objekt(Nous_DP(id), "diese_woche", verbrauch);
                  // Monatsverbrauch aktualisieren
                  aktualisiere_vebrauch_objekt(Nous_DP(id), "dieser_monat", verbrauch);
                  // Jahresverbrauch aktualisieren
                  aktualisiere_vebrauch_objekt(Nous_DP(id), "dieses_jahr", verbrauch);
                  // Gesamten Vebrauch aktualisieren
                  aktualisiere_vebrauch_objekt(Nous_DP(id), "gesamt", verbrauch);
              }
          });
          
          aktualisiere_namen();
          log("Nous Verbrauch: Verbrauchswerte aktualisiert: " + anzahl_updates + " | Reboots korrigiert: " + anzahl_reboots + " | Unveränderte Werte: " + anzahl_gleich);
      }
      // aktualisiert das jeweilige Verbrauchs-Objekt und addiert den Verbrauch dazu
      function aktualisiere_vebrauch_objekt(dp, objekt, wert) {
          // Hole alten Verbrauch
          let alter_verbrauch = getState(dp + objekt).val;
          let verbrauch = 0;
          // Kein Wert vorhanden - nutze den übermittelten Wert
          if (alter_verbrauch < 1 || alter_verbrauch == null) {
              verbrauch = parseFloat(wert)
          } else {
              verbrauch = parseFloat(alter_verbrauch) + parseFloat(wert);
          }
          setState(dp + objekt, parseFloat(verbrauch.toFixed(2)), true);
      }
      // Verschiebt das jeweilige Verbrauchs-Objekt und nullt den Ursprung (Tag, Woche, Monat, Jahr)
      function verschiebe_verbrauch_objekt(von, nach) {
          $('state[id=*.' + datenpunkt + '*.*.' + von + ']').each(function (id, i) {
              // Temporärer Gruppen-Datenpunkt
              var tmp_dp = id.slice(0, -(von.length));
              var verbrauch = getState(id).val;
              if (verbrauch != null) {
                  setState(tmp_dp + nach, verbrauch, true);
              }
              // Setze "von" zurück
              setState(id, 0, true);
          });
      }
      // Funktion um die aktuellen Namen des Nous abzuholen
      function aktualisiere_namen() {
          if (typeof extendObject === "function") {
              NousDpsName.each(function (id, i) {
                  if (existsState(id)) {
                      setState(Nous_DP_Name(id), String(getState(id).val), true);
                      extendObject("javascript.0." + Nous_DP_Name_Main(id), {
                          common: {
                              name: String(getState(id).val),
                              desc: String(getState(id).val)
                          },
                          type: "channel"
                      });
                  }
              });
          }
      }
      // Erstelle die benötigten Datenpunkte
      function datenpunkte_erstellen() {
          // Anzahl der gefundenen Nous
          var anzahl = NousDps.length;
      log("Nous Datenpukte erstellt: " + anzahl);	    
          NousDps.each(function (id, j) {
              var initial_wert = 0.0;
              for (var i = 0; i < objekt.length; i++) {
                  // Startwerte werden nur bei alter_wert und aktueller_wert eingetragen
                  if (i > 8) {
                      initial_wert = getState(id).val;
                  }
                  createState(Nous_DP(id) + objekt[i], initial_wert, ueberschreiben, {
                      name: beschreibung[i],
                      desc: beschreibung[i],
                      type: "number",
                      role: "value.power",
                      unit: "Wh"
                  });
              }
          });
          
          
          
          // Alle Datenpunkte erstellt. Frage ersten Verbrauch ab!
          log("Nous Verbrauch: Datenpunkte erstellt! Erster Verbrauch steht nach 30 Sekunden zur Verfügung! Anzahl gefundener Nous Datenpunkte: " + anzahl );
          setTimeout(Nous_verbrauch_update, 30000);
          // Datenpunkte für die Namen der Nous erstellen
          NousDpsName.each(function (id, j) {
              createState(Nous_DP_Name(id), "", ueberschreiben, {
                  name: "Name des Nous",
                  desc: "Name des Nous",
                  type: "string",
                  role: "value",
                  unit: ""
              });
          });
      }
      /**
       * Wenn 3EM DP, dann anderen Wert zurückgeben
       * @param {any} dp
       * @param {boolean} extended
       */
      function Nous_DP(dp, extended = false) {
          dp = dp.split(".");
          dp = datenpunkt + dp[2] + "." + dp[3];
          if (extended) {
              dp = dp + "_Returned.";
          } else {
              dp = dp + ".";
          }
          return dp;
      }
      function Nous_DP_Name(dp) {
          dp = dp.split(".");
          dp = datenpunkt + dp[2] + "." + dp[3];
          return dp;
      }
      function Nous_DP_Name_Main(dp) {
          dp = dp.split(".");
          dp = datenpunkt + dp[2];
          return dp;
      }
      function Nous_verbrauch_erster_start() {
          log("Nous Verbrauch: Erster Start des Skriptes! Datenpunkte werden erstellt!");
          // Datenpunkte werden erstellt
          datenpunkte_erstellen();
      }
      /*
       * Override Functions
       * @autor 2022 SpacerX <spacerx@rbe-base.de>
       * Überschreibt Funktionen um Datenpunkte unter 0_userdata.0 zu erstellen
       *
       *** START SpacerX ***/
      // Userdatenpunkt
      var userdir = "0_userdata.0."; // Abschließender Punkt !!! WICHTIG !!!
      /**
       * Letzten des Monats berechnen.
       * @param {Date} oHeute
       */
      function letzterDesMonats(oHeute) {
          return new Date(oHeute.getFullYear(), oHeute.getMonth() + 1, 0).getDate();
      }
      //Override at row 48
      // Nous Verbrauch aktualisieren - nachts um 23:59 Uhr
      function Nous_vebrauch_tag() {
          // Nochmals das Tagesupdate durchlaufen, damit die restlichen Werte gelesen werden
          Nous_verbrauch_update();
          // Datumsvariable
          var heute = new Date();
          // Heute zu Gestern verschieben. Täglich um 23:59 Uhr
          verschiebe_verbrauch_objekt("heute", "gestern");
          log("Nous Verbrauch: Werte für gestern und heute aktualisiert!");
          // aktuelle Woche in letzte Woche verschieben. Am Sonntag um 23:59 Uhr
          if (heute.getDay() === 0) {   /*line changed by spacerx (Sonntag=0, Montag=1)*/
              verschiebe_verbrauch_objekt("diese_woche", "letzte_woche");
              log("Nous Verbrauch: Werte für diese und letzte Woche aktualisiert!");
          }
          // aktueller Monat in letzten Monat verschieben. Am letzten des Monats um 23:59 Uhr
          if (heute.getDate() === letzterDesMonats(heute)) {   /*line changed by spacerx*/
              verschiebe_verbrauch_objekt("dieser_monat", "letzter_monat");
              log("Nous Verbrauch: Werte für diesen und letzten Monat aktualisiert!");
          }
          // aktuelles Jahr in letztes Jahr verschieben. Am letzten Tag des Jahres um 23:59 Uhr
          if (heute.getDate() === letzterDesMonats(heute) && heute.getMonth() === 11) { /*line changed by spacerx (Jan=0, Dez=11)*/
              verschiebe_verbrauch_objekt("dieses_jahr", "letztes_jahr");
              log("Nous Verbrauch: Werte für dieses und letztes Jahr aktualisiert!");
          }
      }
      //Override at row 254
      //Verschiebt das jeweilige Verbrauchs-Objekt und nullt den Ursprung (Tag, Woche, Monat, Jahr)
      function verschiebe_verbrauch_objekt(von, nach) {
          $('state[id=' + userdir + datenpunkt + '*.*.' + von + ']').each(function (id, i) {   /*line changed by spacerx*/
              // Temporärer Gruppen-Datenpunkt
              var tmp_dp = id.slice(0, -(von.length));
              var verbrauch = getState(id).val;
              if (verbrauch != null) {
                  setState(tmp_dp + nach, verbrauch, true);
              }
              // Setze "von" zurück
              setState(id, 0, true);
          });
      }
      //Override at row 267
      // Funktion um die aktuellen Namen des Nous abzuholen
      function aktualisiere_namen() {
          if (typeof extendObject === "function") {
              NousDpsName.each(function (id, i) {
                  if (existsState(id)) {
                      setState(Nous_DP_Name(id), String(getState(id).val), true);
                      extendObject(Nous_DP_Name_Main(id), {   /*line changed by spacerx*/
                          common: {
                              name: String(getState(id).val),
                              desc: String(getState(id).val)
                          },
                          type: "channel"
                      });
                  }
              });
          }
      }
      //Override at row 377
      function Nous_DP(dp, extended = false) {
          dp = dp.split(".");
          dp = userdir + datenpunkt + dp[2] + "." + dp[3];   /*line changed by spacerx*/
          if (extended) {
              dp = dp + "_Returned.";
          } else {
              dp = dp + ".";
          }
          return dp;
      }
      //Override at row 387
      function Nous_DP_Name(dp) {
          dp = dp.split(".");
          dp = userdir + datenpunkt + dp[2] + "." + dp[3];   /*line changed by spacerx*/
          return dp;
      }
      //Override at row 392
      function Nous_DP_Name_Main(dp) {
          dp = dp.split(".");
          dp = userdir + datenpunkt + dp[2];   /*line changed by spacerx*/
          return dp;
      }
      /*** END SpacerX ***/
      // Erster Start und Initialisierung
      Nous_verbrauch_erster_start();
      // Alle 15 Minuten das Skript für den Tagesverbrauch ausführen
      schedule('*/15 * * * *', Nous_verbrauch_update);
      /*** START Edit SpacerX ***/
      // Nachts um 24 Uhr werden die Werte in andere Variablen gespeichert, um den Verlauf zu erstellen
      //schedule('0 0 * * *', Nous_vebrauch_tag);
      // Nachts um 23:59 Uhr werden die Werte in andere Variablen gespeichert, um den Verlauf zu erstellen
      schedule('59 23 * * *', Nous_vebrauch_tag);
      /*** END Edit SpacerX ***/
      

      Nun möchte ich dieses Script so adaptieren, dass für von mir in einem Array vorgegebene (virtuelle) Zählerwerte* die Tages-, Wochen-, Monats- und Jahreswerte ermittelt und in die entsprechenden Datenpunkte geschrieben werden. Das klappt auch soweit bis auf das Verschieben der Werte „heute -> gestern“, „diese Woche -> letzte Woche“ etc. Die zuständige Routine verstehe ich leider nicht. Es sollte die Funktion ab Zeile 175 in diesem Script sein:
      function verschiebe_verbrauch_objekt(von, nach) {

      /*
       * Dieses Script dient dazu, aus definierten Datenpunkten (zumeist Zählerständen) 
       * den jeweils letzten Tages- Wochen- Monats- und Jahreswert auszulesen und in
       * separate Datenpunkte zu schreiben. 
       * Damit erhält man besser auswertbare Daten eines Zeitraums und umgeht die nicht 
       * ausreichenden bzw. nicht vorhandenen Gruppierungsmöglichkeiten in Grafana.
       * 
       * In der Regel wird man diese Methode anwenden, wenn es keinen geräteseitigen Zählerstand gibt, 
       * etwa bei errechneten Werten und der "Source Analytics" Adapter nicht zur Anwendung kommen soll."
       * 
       * Die Funktionsweise:
       * Zuerst werden viertelstündlich die Zählerwerte (in Wm) aus den Quelldatenpunkten ausgelesen, in Wh umgerechnet und in die Datenpunkte 
       * "gesamt", "dieses Jahr", "dieser Monat", "diese Woche" und "heute" für die weitere Verarbeitung geschrieben.
       * Diese Werte werden alle 15 Minuten um die angefallene Different erhöht.
       * Jeweils um 23:59 eines jeden Tages wird der letzte Tageswert aus dem "heute" Datenpunkt gelesen und in den Datenpunkt "gestern" kopiert.
       * Jeweils um 23:59 jeden Sonntag wird der letzte Wert aus "diese_woche" in den Datenpunkt "letzte_woche" kopiert.
       * Jeweils am Monatsletzten um 23:59 wird der letzte Wert aus "dieser_monat" in den Datenpunkt "letzter_monat" kopiert.
       * Am 31.12. jedes Jahres um 23:59 wird der letzte Wert aus "dieses_jahr" in den Datenpunkt "letztes_jahr" kopiert.
       * Damit sind die Tages-, Wochen-, Monats- und Jahreswerte in sepataten Datenpunkten verfügbar.
       * 
       * Skript Name:      Tag-Woche-Monat-Jahr
       * Skript Version:   0.4
       * Erstell-Datum:    11. September 2024 | Last Update: 7.01.2025
       * 
       */
      
      // Datenpunkte, aus denen Tages- Wochen- Monats- und Jahreswerte erstellt werden sollen:
      var quelldatenpunkt = ["0_userdata.0.Einspeisung.PV-Erzeugung-Counter", "0_userdata.0.Einspeisung.PV-Eigenverbrauch-Counter", "0_userdata.0.Einspeisung.PV-Einspeisung-Counter"];
      var zieldatenpunkt = ["0_userdata.0.Einspeisung.PV-Erzeugung", "0_userdata.0.Einspeisung.PV-Eigenverbrauch", "0_userdata.0.Einspeisung.PV-Einspeisung"];
      var anz1;                   //Zähler für Quell- und Zieldatenpunkt Verzeichnisse
      var anz2;                   //Innerer Zähler für die Objekte (Zieldatenpunkte)
      var verbrauch_wm;           // Werte in Wm!!!
      var verbrauch;              // Umgewandelt in Wh!!!
      var ueberschreiben = false;
      var anzahl_updates = 0;
      var anzahl_reboots = 0;
      var anzahl_gleich = 0;
      
      // Datenpunkte neu erstellen unterhalb 0.userdata.0
      // Verbrauchs Objekte 
      var objekt = ["gesamt", "dieses_jahr", "letztes_jahr", "letzter_monat", "dieser_monat", "letzte_woche", "diese_woche", "gestern", "heute", "alter_wert", "aktueller_wert"];
      // Beschreibung der Objekte
      var beschreibung = ["Gesamt", "Aktuelles Jahr", "Letztes Jahr", "Letzter Monat", "Aktueller Monat", "Letzte Woche", "Aktuelle Woche", "Gestern", "Heute", "Messwert alt", "Messwert neu"];
      
      datenpunkte_erstellen()
      
      // Erstelle die benötigten Datenpunkte
      function datenpunkte_erstellen() {
          // Anzahl der Quelldatenpunkt Ordner
          for (anz1 = 0; anz1 < quelldatenpunkt.length ; anz1++) {
              var initial_wert = 0.0;
              // Anzahl der neuen Datenpunkte
              for (anz2 = 0; anz2 < objekt.length; anz2++) {
                  createState(zieldatenpunkt[anz1] + "." + objekt[anz2], initial_wert, ueberschreiben, {
                      name: beschreibung[anz2],
                      desc: beschreibung[anz2],
                      type: "number",
                      role: "value.power",
                      unit: "Wh"
                  });
              }
          }
      }
      
      // Verbrauch alle 15 Min ermitteln
      function verbrauch_update() {
          anzahl_updates = 0;
          anzahl_reboots = 0;
          anzahl_gleich = 0;
          for (anz1 = 0; anz1 < quelldatenpunkt.length; anz1++) {
      		// Zählerwerte liegen in Wm vor und müssen erst in Wh umgewandelt werden
              verbrauch_wm  = getState(quelldatenpunkt[anz1]).val; 
      		// Runden auf 2 Stellen	
              verbrauch = Math.round(verbrauch_wm / 60*100) /100; 					
              if (verbrauch != null) {
                  // Hole aktuellen Wert, um zu kontrollieren, ob ein Reboot stattgefunden hat
      			// In den Zieldatenpunkten liegen die Werte in der Einheit Wh vor
                  var aktueller_wert = getState(zieldatenpunkt[anz1] + ".aktueller_wert").val;  
                  var alter_wert = 0;
                  // Prüfe alten und neuen Wert
                  if (verbrauch > aktueller_wert) {
                      // Verbrauchswert ist größer als alter Wert -> es wurde kein Reboot durchgeführt
                      setState(zieldatenpunkt[anz1] + ".alter_wert", aktueller_wert, true);   		// "Aktueller Wert" wird aktualisiert
                      alter_wert = aktueller_wert;												// "Alter Wert" wird aktualisiert
                      anzahl_updates++;
                  }
      			// Kommt nicht vor, da die Werte errechnet werden. Kein Gerät, das resettet werden könnte
                  // if (aktueller_wert > shelly_verbrauch) {
                  // Verbrauchswert ist kleiner als alter Wert -> es wurde ein Reboot durchgeführt
                  //    setState(shelly_DP(id) + "alter_wert", 0, true);
                  //    alter_wert = 0;
                  //    anzahl_reboots++;
                  //}
                  if (verbrauch == aktueller_wert) {
                      // Verbrauchswert ist gleich dem alten Wert -> kein Update notwendig
                      alter_wert = aktueller_wert;
                      anzahl_gleich++;
                  }
                   setState(zieldatenpunkt[anz1] + ".aktueller_wert", verbrauch, true);
                  // Neuer Wert - alter Wert = aktuelle Differenz
                  var differenz = parseFloat(verbrauch) - alter_wert;
                  //console.log("Alter Wert = " + alter_wert);
                  //console.log("Neuer Wert = " + verbrauch);
                  //console.log("Differenz = " + differenz);
                  
                  // Tagesverbrauch aktualisieren
                  aktualisiere_vebrauch_objekt(zieldatenpunkt[anz1], ".heute", differenz);
                  // Wochenverbrauch aktualisieren
                  aktualisiere_vebrauch_objekt(zieldatenpunkt[anz1], ".diese_woche", differenz);
                  // Monatsverbrauch aktualisieren
                  aktualisiere_vebrauch_objekt(zieldatenpunkt[anz1], ".dieser_monat", differenz);
                  // Jahresverbrauch aktualisieren
                  aktualisiere_vebrauch_objekt(zieldatenpunkt[anz1], ".dieses_jahr", differenz);
                  // Gesamten Vebrauch aktualisieren
                  aktualisiere_vebrauch_objekt(zieldatenpunkt[anz1], ".gesamt", differenz);
              }
          };
      }
      
      // Aktualisiert das jeweilige Verbrauchs-Objekt und addiert den Verbrauch dazu
      function aktualisiere_vebrauch_objekt(dp, objekt, wert) {
          // Hole alten Verbrauch
          let alter_verbrauch = getState(dp + objekt).val;
          let verbrauch = 0;
          // Kein Wert vorhanden - nutze den übermittelten Wert
          if (alter_verbrauch < 1 || alter_verbrauch == null) {
              verbrauch = parseFloat(wert)
          } else {
              verbrauch = parseFloat(alter_verbrauch) + parseFloat(wert);
          }
          setState(dp + objekt, parseFloat(verbrauch.toFixed(2)), true);
      }
      
      function shelly_verbrauch_erster_start() {
          log("Shelly Verbrauch: Erster Start des Skriptes! Datenpunkte werden erstellt!");
          // Datenpunkte werden erstellt
          datenpunkte_erstellen();
      }
      
      // Userdatenpunkt
      var userdir = "0_userdata.0."; // Abschließender Punkt !!! WICHTIG !!!
      
      // Letzten des Monats berechnen.
      function letzterDesMonats(oHeute) {
          return new Date(oHeute.getFullYear(), oHeute.getMonth() + 1, 0).getDate();
      }
      
      // Shelly Verbrauch aktualisieren - nachts um 23:59 Uhr
      function verbrauch_tag() {
          // Nochmals das Tagesupdate durchlaufen, damit die restlichen Werte gelesen werden
          verbrauch_update();
          // Datumsvariable
          var heute = new Date();
          // Heute zu Gestern verschieben. Täglich um 23:59 Uhr
          verschiebe_verbrauch_objekt("heute", "gestern");
          log("Shelly Verbrauch: Werte für gestern und heute aktualisiert!");
          // aktuelle Woche in letzte Woche verschieben. Am Sonntag um 23:59 Uhr
          if (heute.getDay() === 0) {   // (Sonntag=0, Montag=1)
              verschiebe_verbrauch_objekt("diese_woche", "letzte_woche");
              log("Shelly Verbrauch: Werte für diese und letzte Woche aktualisiert!");
          }
          // aktueller Monat in letzten Monat verschieben. Am letzten des Monats um 23:59 Uhr
          if (heute.getDate() === letzterDesMonats(heute)) {   /*line changed by spacerx*/
              verschiebe_verbrauch_objekt("dieser_monat", "letzter_monat");
              log("Shelly Verbrauch: Werte für diesen und letzten Monat aktualisiert!");
          }
          // aktuelles Jahr in letztes Jahr verschieben. Am letzten Tag des Jahres um 23:59 Uhr
          if (heute.getDate() === letzterDesMonats(heute) && heute.getMonth() === 11) { /*line changed by spacerx (Jan=0, Dez=11)*/
              verschiebe_verbrauch_objekt("dieses_jahr", "letztes_jahr");
              log("Shelly Verbrauch: Werte für dieses und letztes Jahr aktualisiert!");
          }
      }
      
      // Verschiebt das jeweilige Verbrauchs-Objekt und nullt den Ursprung (Tag, Woche, Monat, Jahr)
      function verschiebe_verbrauch_objekt(von, nach) {
          //$('state[id=*.' + datenpunkt + '*.*.' + von + ']').each(function (id, i) {
      	$('state[id=' + zieldatenpunkt(anz1)+ '*.*.' + von + ']').each(function (id, anz2) {	
              // Temporärer Gruppen-Datenpunkt
              var tmp_dp = id.slice(0, -(von.length));
              var verbrauch = getState(id).val;
              if (verbrauch != null) {
                  setState(tmp_dp + nach, verbrauch, true);
              }
              // Setze "von" zurück
              setState(id, 0, true);
          });
      }
      
      //Verschiebt das jeweilige Verbrauchs-Objekt und nullt den Ursprung (Tag, Woche, Monat, Jahr)
      function verschiebe_verbrauch_objekt(von, nach) {
          //$('state[id=' + userdir + datenpunkt + '*.*.' + von + ']').each(function (id, anz2) {   
      	$('state[id=' + zieldatenpunkt[anz1]+ '*.*.' + von + ']').each(function (id, anz2) {	
              // Temporärer Gruppen-Datenpunkt
              var tmp_dp = id.slice(0, -(von.length));
              var verbrauch = getState(id).val;
              if (verbrauch != null) {
                  setState(tmp_dp + nach, verbrauch, true);
              }
              // Setze "von" zurück
              setState(id, 0, true);
          });
      }
      
      // Erster Start und Initialisierung
      shelly_verbrauch_erster_start();
      
      // Alle 15 Minuten das Skript für den Tagesverbrauch ausführen
      schedule('*/15 * * * *', verbrauch_update);
      
      // Nachts um 23:59 Uhr werden die Werte in andere Variablen gespeichert, um den Verlauf zu erstellen
      schedule('59 23 * * *', verbrauch_tag);
      
      

      *Die virtuellen Zählerwerte errechne ich aus den Ertrags- und Einspeiseleistungen meiner PV, die jede Minute ermittelt werden. Mein Zähler zeigt leider nur die eingespeiste Leistung, aber nicht den zugehörigen Zählerstand an.

      Und da die Fragen sicher kommen werden:

      • Ich habe keine Möglichkeit, einen Shelly 3EM etc. unterzubringen und der Source Analytics Adapter soll auch nicht zum Einsatz kommen.
      • Und ja, ich könnte die „heute“ Werte auch manuell nach „gestern“ schreiben und anschließend nullen, dann hätte ich das Konstrukt aber immer noch nicht verstanden.

      Ich hoffe, ich konnte mein Anliegen verständlich beschreiben und hoffe auf Eure Hilfestellung.

      Gruß

      paul53 OliverIO 2 Replies Last reply Reply Quote 0
      • paul53
        paul53 @opöl last edited by paul53

        @opöl sagte: Funktion ab Zeile 175 in diesem Script

        Die Funktion ist doppelt enthalten (auch ab Zeile 190).
        So ist die Funktion etwas übersichtlicher:

        function verschiebe_verbrauch_objekt(von, nach) {
            $(userdir + datenpunkt + '*.*.' + von).each(function (id) {   /*line changed by spacerx*/
                const verbrauch = getState(id).val;
                if (verbrauch != null) {
                    setState(id.replace(von, nach), verbrauch, true); // Schreibe Verbrauch in "nach"
                }
                setState(id, 0, true); // Setze "von" zurück
            });
        }
        
        O 1 Reply Last reply Reply Quote 0
        • O
          opöl @paul53 last edited by

          @paul53 ,

          Oops, ist mir entgangen. Habe ich korrigiert. Typischer Fall von Betriebsblindheit. Sorry.

          Das alleine kann es aber nicht gewesen sein, der DP heute ist ja letzte Nacht nicht genullt worden. Das Script läuft ohne Fehler.

          Kannst Du mir die fragliche Funktion entschlüsseln?
          Wenn ich sie verstehe, komme ich vielleicht weiter.
          Wie ich schrieb, geht es mir hauptsächlich um den Lerneffekt.

          Gruß

          paul53 1 Reply Last reply Reply Quote 0
          • paul53
            paul53 @opöl last edited by paul53

            @opöl sagte: Wenn ich sie verstehe, komme ich vielleicht weiter.

            Ich habe Kommentar ergänzt.
            Wo wird die Variable datenpunkt deklariert und gesetzt? Habe ich nicht gefunden.
            Funktioniert es so?

            function verschiebe_verbrauch_objekt(von, nach) {
                $(userdir + 'Einspeisung.*.' + von).each(function (id) { 
                    const verbrauch = getState(id).val;
                    if (verbrauch != null) {
                        setState(id.replace(von, nach), verbrauch, true); // Schreibe Verbrauch in "nach"
                    }
                    setState(id, 0, true); // Setze "von" zurück
                });
            }
            

            Überprüfe den Selektor mit

            log($(userdir + 'Einspeisung.*.heute'));
            

            am Skriptende.

            O 1 Reply Last reply Reply Quote 0
            • O
              opöl @paul53 last edited by

              @paul53 ,

              "userdir" + "datenpunkt" sind Benamsungen aus dem originalen Script. Die habe ich auskommentiert (vielleicht nicht komplett), weil sich sie in meinem Script nicht verwende.
              Meine Quell- und Zieldatenpunktordner sind:

              var quelldatenpunkt = ["0_userdata.0.Einspeisung.PV-Erzeugung-Counter", "0_userdata.0.Einspeisung.PV-Eigenverbrauch-Counter", "0_userdata.0.Einspeisung.PV-Einspeisung-Counter"];
              var zieldatenpunkt = ["0_userdata.0.Einspeisung.PV-Erzeugung", "0_userdata.0.Einspeisung.PV-Eigenverbrauch", "0_userdata.0.Einspeisung.PV-Einspeisung"];
              

              indiziert mit dem index (anz1) sowie den daran hängenden Datenpunkten

              var objekt = ["gesamt", "dieses_jahr", "letztes_jahr", "letzter_monat", "dieser_monat", "letzte_woche", "diese_woche", "gestern", "heute", "alter_wert", "aktueller_wert"];
              

              indiziert mit dem Index (anz2).

              Daher hatte ich es in Zeile 177 mit

              $('state[id=' + zieldatenpunkt[anz1]+ '*.*.' + von + ']').each(function (id, anz2) {
              

              versucht, was aber nicht klappt.

              Ich möchte also einen Wert von z.B.

              zieldatenpunkt[anz1].heute 
              

              nach

              zieldatenpunkt[anz1].gestern 
              

              verschieben und dann

              zieldatenpunkt[anz1].heute 
              

              auf "0" setzen.

              Und das ganze dann in einer Schleife für die Zieldatenpunkte 1-3 aus dem 1. Array und für die Objekte heute, diese_woche- dieser_monat und dieses_jahr.

              Und genau da komme ich mit der Funktion ins schleudern, weil ich die Syntax nicht blicke.

              Vielleicht habe ich mich da missverständlich ausgedrückt.

              Gruß

              paul53 1 Reply Last reply Reply Quote 0
              • paul53
                paul53 @opöl last edited by paul53

                @opöl sagte: was aber nicht klappt.

                Woher kommt anz1?
                So funktioniert der Selektor nicht. Prüfe den von mir geposteten Selektor. Er sollte 3 Datenpunkt-IDs mit "heute" liefern.

                $(userdir + 'Einspeisung.*.heute').each(function(id) {
                    log(id);
                });
                

                Wenn du das Array zieldatenpunkt verwenden willst, musst du es direkt mit dem Array machen:

                function verschiebe_verbrauch_objekt(von, nach) {
                    zieldatenpunkt.forEach(function(id) { 
                        const verbrauch = getState(id + '.' + von).val;
                        if (verbrauch != null) {
                            setState(id + '.' + nach), verbrauch, true); // Schreibe Verbrauch in "nach"
                        }
                        setState(id + '.' + von, 0, true); // Setze "von" zurück
                    });
                }
                

                oder mit Schleife "for of"

                function verschiebe_verbrauch_objekt(von, nach) {
                    for(let id of zieldatenpunkt) { 
                        const verbrauch = getState(id + '.' + von).val;
                        if (verbrauch != null) {
                            setState(id + '.' + nach), verbrauch, true); // Schreibe Verbrauch in "nach"
                        }
                        setState(id + '.' + von, 0, true); // Setze "von" zurück
                    }
                }
                
                O 1 Reply Last reply Reply Quote 1
                • O
                  opöl @paul53 last edited by

                  @paul53 ,

                  die Variablen anz1 und anz2 sind in Zeile 30/31 definiert und indizieren die Objekte in den Arrays. Siehe ab Zeile 48 „Anlegen der Datenpunkte“.
                  Wenn ich so drüber nachdenke, muss eigentlich zieldatenpunkt(anz1).objekt(8) nach
                  zieldatenpunkt(anz1).objekt(7) in einer Schleife von anz1 =0 bis anz1= 2 verschoben werden, also von heute nach gestern. Der 1. Wert im Array hat ja den Index 0.

                  Ich kann Deinen Vorschlag erst morgen testen. Ich melde mich dann. Vielen Dank erst einmal.

                  Gruß

                  1 Reply Last reply Reply Quote 0
                  • OliverIO
                    OliverIO @opöl last edited by

                    @opöl
                    Du mal so als Anregung.
                    Für sowas sind Datenbanken prädestiniert.
                    Man schreibt regelmäßig nur die rohdaten in die Datenbank.
                    Zu einem späteren Zeitpunkt kann man die dann schön aggregieren nach verschiedenen Zeitscheiben, vergleichen, etc.
                    Alles dynamisch

                    1 Reply Last reply Reply Quote 1
                    • Codierknecht
                      Codierknecht Developer Most Active last edited by

                      @opöl
                      Das was @OliverIO schreibt.
                      Und wenn es darum geht, dass diese "Datenbank" (Influx, MySQL, MariaDB etc.) bestimmte Werte (Tagesverbrauch) nur 1x am Tag protokollieren soll, kann man den Wert (z.B. ENERGY_Today) per Script um 23:59 in einen eigenen DP schreiben und diesen historisieren. So hat man dann pro Tag genau 1 Wert mit passendem Timestamp in der DB.

                      Der Vorteil von Datenbanken: Damit hat man dann echte Langzeitwerte, die man zu einem beliebigen Zeitpunkt über beliebige Zeiträume aggregieren kann.

                      O 1 Reply Last reply Reply Quote 0
                      • O
                        opöl @Codierknecht last edited by

                        @codierknecht , @OliverIO ,

                        das ist doch genau das, was ich erreichen möchte. Die Rohdaten stehen bereits in der influx DB und sollen für die grafische Auswertung zu bestimmten Zeitpunkten in separate Datenpunkte (Woche, Monat...) geschrieben werden.

                        Mir hat das Wissen über die Funktionsweise der "for each" Methode gefehlt. Habe ich mir inzwischen angelesen und mit @paul53 's Anregung:

                        function verschiebe_verbrauch_objekt(von, nach) {
                           zieldatenpunkt.forEach(function(id) { 
                               const verbrauch = getState(id + '.' + von).val; // Hole Verbrauch "von" 
                               console.error("id= " + id);
                               console.error("Verbrauch= " + verbrauch);
                               if (verbrauch != null) {
                                   setState(id + '.' + nach, verbrauch, true); // Schreibe Verbrauch in "nach"
                               }
                               setState(id + '.' + von, 0, true);              // Setze "von" zurück
                           });
                        }
                        

                        sowie eines zeitgesteuerten Aufrufs dieser Funktion in meinem Script wurden die Datenpunkte "heute" nach "gestern" kopiert und im Anschluss auf "0" gesetzt, also genau das, was ich erreichen wollte.

                        Ich lasse das jetzt mal bis Sonntag laufen, bis dahin sollte ich dann die täglichen und die ersten wöchentlichen Aktualisierungen haben.

                        Wenn alles klappt, setze ich diesen Thread dann auf "gelöst", andernfalls melde ich mich nochmal. Vielen Dank an Euch alle.

                        Gruß

                        O 1 Reply Last reply Reply Quote 0
                        • O
                          opöl @opöl last edited by

                          @paul53 ,

                          die Tageswerte wurden seit dem 10.1. alle wie geplant aktualisiert bzw. zurückgesetzt und am Sonntag um 23:59 wurden ebenfalls die Datenpunkte "letzte_woche" aktualisiert und die DPs "diese_woche" genullt. Deine Funktion tut also, was ich möchte. Vielen Dank für Deine Hilfe.

                          Ich hätte da aber noch abschließend zwei Verständnis Fragen:

                          1. Beim Anlegen der DPs per Script habe ich bereits früher einen Flüchtigkeitsfehler eingebaut, den ich erst jetzt bemerkt habe. Statt der DP Namen habe ich beim Anlegen der DPs die Beschreibung in die Definition geschrieben. Kann ich das nachträglich im Script korrigieren oder werden dann die DPs noch einmal neu angelegt und die bisher gespeicherten Werte sind weg?
                            Siehe Zeile 2 -> Objekt Array (Namen der DPs) und Zeile 14 -> DP Name.
                          // Verbrauchs Objekte 
                          var objekt = ["gesamt", "dieses_jahr", "letztes_jahr", "letzter_monat", "dieser_monat", "letzte_woche", "diese_woche", "gestern", "heute", "alter_wert", "aktueller_wert"];
                          // Beschreibung der Objekte
                          var beschreibung = ["Gesamt", "Aktuelles Jahr", "Letztes Jahr", "Letzter Monat", "Aktueller Monat", "Letzte Woche", "Aktuelle Woche", "Gestern", "Heute", "Messwert alt", "Messwert neu"];
                          
                          // Erstelle die benötigten Datenpunkte
                          function datenpunkte_erstellen() {
                              // Anzahl der Quelldatenpunkt Ordner
                              for (anz1 = 0; anz1 < quelldatenpunkt.length ; anz1++) {
                                  var initial_wert = 0.0;
                                  // Anzahl der neuen Datenpunkte
                                  for (anz2 = 0; anz2 < objekt.length; anz2++) {
                                      createState(zieldatenpunkt[anz1] + "." + objekt[anz2], initial_wert, ueberschreiben, {
                                          name: beschreibung[anz2], <-- Hier sollte "objekt[anz2]" stehen, also die Objekt Namen aus dem Array
                                          desc: beschreibung[anz2],
                                          type: "number",
                                          role: "value.power",
                                          unit: "Wh"
                                      });
                                  }
                              }
                          }
                          
                          

                          So sieht z.B. der DP 0_userdata.0.Einspeisung.PV-Erzeugung.letzte_woche aus:

                          {
                            "common": {
                              "name": "Letzte Woche",
                              "desc": "Letzte Woche",
                              "type": "number",
                              "role": "value.power",
                              "unit": "Wh",
                          
                          1. Warum steht in Deiner Funktion
                          function verschiebe_verbrauch_objekt(von, nach) {
                              zieldatenpunkt.forEach(function(id) { 
                                  const verbrauch = getState(id + '.' + von).val;
                                  if (verbrauch != null) {
                                      setState(id + '.' + nach), verbrauch, true); // Schreibe Verbrauch in "nach"
                                  }
                                  setState(id + '.' + von, 0, true); // Setze "von" zurück
                              });
                          }
                          

                          die Zeile 7 nicht innerhalb der "If" Anweisung, also vor der geschlossenen Klammer in Zeile 6?
                          In meinem Fall (Quelldatenpunkte sind vorhanden) kann der Verbrauch doch nicht "null" zurück liefern. Verbrauch = null kann doch nur vorkommen, wenn es zu einem Array Wert keinen "von" Wert gibt, dann muss dieser aber auch nicht zurückgesetzt werden. Oder andersrum: Nur wenn "von" existiert und einen Wert hat, muss "nach" aktualisiert und "von" resettet werden.
                          Ich würde mich freuen, wenn Du mich da noch kurz abholen könntest.

                          Nochmals Danke und Gruß

                          paul53 1 Reply Last reply Reply Quote 0
                          • paul53
                            paul53 @opöl last edited by paul53

                            @opöl sagte: Kann ich das nachträglich im Script korrigieren

                            Korrigiere es besser im Tab "Objekte" (Bleistift rechts).

                            @opöl sagte in Anpassung eines Scripts / Hilfe benötigt:

                            Zeile 7 nicht innerhalb der "If" Anweisung

                            ... weil ich es so aus dem Original-Skript übernommen habe.

                            EDIT: Verbrauchswerte sind Zahlen, weshalb ich den Vergleich verbrauch != null ohnehin nicht verstanden habe. Er dürfte immer erfüllt sein.

                            O 1 Reply Last reply Reply Quote 0
                            • O
                              opöl @paul53 last edited by

                              @paul53 ,
                              ich denke, das wurde eingefügt, weil ja die Schleife für alle Werte des Arrays durchlaufen wird, unabhängig davon, ob es einen „von“ und „nach“ Datenpunkt gibt. Z.B. für den DP „gesamt“ gibt es keine Notwendigkeit, Werte zu verschieben. Ergo gibt es „von“ nicht und daher wird von einem nicht existierenden DP ein „null“ zurückgegeben. Da entfällt aber auch die Notwendigkeit, etwas nicht existentes zu nullen.
                              Die If Anweisung wirkt quasi als Filter, damit nur da verschoben und genullt wird, wo das benötigt wird.

                              So zumindest mein Verständnis…

                              Ich probiere es mal aus.

                              Gruß

                              paul53 1 Reply Last reply Reply Quote 0
                              • paul53
                                paul53 @opöl last edited by

                                @opöl sagte: unabhängig davon, ob es einen „von“ und „nach“ Datenpunkt gibt.

                                Ich habe mir nicht das komplette Skript angesehen.

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

                                Support us

                                ioBroker
                                Community Adapters
                                Donate

                                563
                                Online

                                31.8k
                                Users

                                80.0k
                                Topics

                                1.3m
                                Posts

                                4
                                14
                                460
                                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