NEWS
Anpassung eines Scripts / Hilfe benötigt
-
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ß
-
@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 }); }
-
@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ß
-
@opöl sagte: Wenn ich sie verstehe, komme ich vielleicht weiter.
Ich habe Kommentar ergänzt.
Wo wird die Variabledatenpunkt
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.
-
@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ß
-
@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 } }
-
@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ß
-
@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 -
@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.
-
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ß
-
@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:
- 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",
- 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ß
- 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?
-
@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. -
@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ß
-
@opöl sagte: unabhängig davon, ob es einen „von“ und „nach“ Datenpunkt gibt.
Ich habe mir nicht das komplette Skript angesehen.