Skip to content
  • Home
  • Aktuell
  • Tags
  • 0 Ungelesen 0
  • Kategorien
  • Unreplied
  • Beliebt
  • GitHub
  • Docu
  • Hilfe
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Standard: (Kein Skin)
  • Kein Skin
Einklappen
ioBroker Logo

Community Forum

donate donate
  1. ioBroker Community Home
  2. Deutsch
  3. Skripten / Logik
  4. JavaScript
  5. Anpassung eines Scripts / Hilfe benötigt

NEWS

  • UPDATE 31.10.: Amazon Alexa - ioBroker Skill läuft aus ?
    apollon77A
    apollon77
    48
    3
    8.8k

  • Monatsrückblick – September 2025
    BluefoxB
    Bluefox
    13
    1
    2.2k

  • Neues Video "KI im Smart Home" - ioBroker plus n8n
    BluefoxB
    Bluefox
    16
    1
    3.2k

Anpassung eines Scripts / Hilfe benötigt

Geplant Angeheftet Gesperrt Verschoben JavaScript
14 Beiträge 4 Kommentatoren 866 Aufrufe 3 Watching
  • Älteste zuerst
  • Neuste zuerst
  • Meiste Stimmen
Antworten
  • In einem neuen Thema antworten
Anmelden zum Antworten
Dieses Thema wurde gelöscht. Nur Nutzer mit entsprechenden Rechten können es sehen.
  • O 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ß

    paul53P Offline
    paul53P Offline
    paul53
    schrieb am zuletzt editiert von paul53
    #2

    @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
        });
    }
    

    Bitte verzichtet auf Chat-Nachrichten, denn die Handhabung ist grauenhaft !
    Produktiv: RPi 2 mit S.USV, HM-MOD-RPI und SLC-USB-Stick mit root fs

    O 1 Antwort Letzte Antwort
    0
    • paul53P 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 Offline
      O Offline
      opöl
      schrieb am zuletzt editiert von
      #3

      @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ß

      paul53P 1 Antwort Letzte Antwort
      0
      • O opöl

        @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ß

        paul53P Offline
        paul53P Offline
        paul53
        schrieb am zuletzt editiert von paul53
        #4

        @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.

        Bitte verzichtet auf Chat-Nachrichten, denn die Handhabung ist grauenhaft !
        Produktiv: RPi 2 mit S.USV, HM-MOD-RPI und SLC-USB-Stick mit root fs

        O 1 Antwort Letzte Antwort
        0
        • paul53P 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 Offline
          O Offline
          opöl
          schrieb am zuletzt editiert von
          #5

          @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ß

          paul53P 1 Antwort Letzte Antwort
          0
          • O opöl

            @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ß

            paul53P Offline
            paul53P Offline
            paul53
            schrieb am zuletzt editiert von paul53
            #6

            @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
                }
            }
            

            Bitte verzichtet auf Chat-Nachrichten, denn die Handhabung ist grauenhaft !
            Produktiv: RPi 2 mit S.USV, HM-MOD-RPI und SLC-USB-Stick mit root fs

            O 1 Antwort Letzte Antwort
            1
            • paul53P 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 Offline
              O Offline
              opöl
              schrieb am zuletzt editiert von
              #7

              @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 Antwort Letzte Antwort
              0
              • O 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ß

                OliverIOO Offline
                OliverIOO Offline
                OliverIO
                schrieb am zuletzt editiert von
                #8

                @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

                Meine Adapter und Widgets
                TVProgram, SqueezeboxRPC, OpenLiga, RSSFeed, MyTime,, pi-hole2, vis-json-template, skiinfo, vis-mapwidgets, vis-2-widgets-rssfeed
                Links im Profil

                1 Antwort Letzte Antwort
                1
                • CodierknechtC Online
                  CodierknechtC Online
                  Codierknecht
                  Developer Most Active
                  schrieb am zuletzt editiert von
                  #9

                  @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.

                  "Any fool can write code that a computer can understand. Good programmers write code that humans can understand." (Martin Fowler, "Refactoring")

                  Proxmox 9.1.1 LXC|8 GB|Core i7-6700
                  HmIP|ZigBee|Tasmota|Unifi
                  Zabbix Certified Specialist
                  Konnte ich Dir helfen? Dann benutze bitte das Voting unten rechts im Beitrag

                  O 1 Antwort Letzte Antwort
                  0
                  • CodierknechtC Codierknecht

                    @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 Offline
                    O Offline
                    opöl
                    schrieb am zuletzt editiert von
                    #10

                    @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 Antwort Letzte Antwort
                    0
                    • O opöl

                      @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 Offline
                      O Offline
                      opöl
                      schrieb am zuletzt editiert von
                      #11

                      @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ß

                      paul53P 1 Antwort Letzte Antwort
                      0
                      • O opöl

                        @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ß

                        paul53P Offline
                        paul53P Offline
                        paul53
                        schrieb am zuletzt editiert von paul53
                        #12

                        @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.

                        Bitte verzichtet auf Chat-Nachrichten, denn die Handhabung ist grauenhaft !
                        Produktiv: RPi 2 mit S.USV, HM-MOD-RPI und SLC-USB-Stick mit root fs

                        O 1 Antwort Letzte Antwort
                        0
                        • paul53P 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 Offline
                          O Offline
                          opöl
                          schrieb am zuletzt editiert von
                          #13

                          @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ß

                          paul53P 1 Antwort Letzte Antwort
                          0
                          • O opöl

                            @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ß

                            paul53P Offline
                            paul53P Offline
                            paul53
                            schrieb am zuletzt editiert von
                            #14

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

                            Ich habe mir nicht das komplette Skript angesehen.

                            Bitte verzichtet auf Chat-Nachrichten, denn die Handhabung ist grauenhaft !
                            Produktiv: RPi 2 mit S.USV, HM-MOD-RPI und SLC-USB-Stick mit root fs

                            1 Antwort Letzte Antwort
                            0
                            Antworten
                            • In einem neuen Thema antworten
                            Anmelden zum Antworten
                            • Älteste zuerst
                            • Neuste zuerst
                            • Meiste Stimmen


                            Support us

                            ioBroker
                            Community Adapters
                            Donate

                            904

                            Online

                            32.4k

                            Benutzer

                            81.5k

                            Themen

                            1.3m

                            Beiträge
                            Community
                            Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen | Einwilligungseinstellungen
                            ioBroker Community 2014-2025
                            logo
                            • Anmelden

                            • Du hast noch kein Konto? Registrieren

                            • Anmelden oder registrieren, um zu suchen
                            • Erster Beitrag
                              Letzter Beitrag
                            0
                            • Home
                            • Aktuell
                            • Tags
                            • Ungelesen 0
                            • Kategorien
                            • Unreplied
                            • Beliebt
                            • GitHub
                            • Docu
                            • Hilfe