Wie schon in meinem Artikel https://www.md-technologie.de/baublog/shelly-plug-s-stromverbrauch-ermittlen-mit-iobroker/ beschrieben kann man via Skript den Verbrauch berechnen lassen. Allerdings ist dieses Skript bereits etwas älter und kann nicht die Werte des aktuellen Shelly EM Mini Gen4 auslesen, da die Energiewerte dort auf einer anderen Objektpunkt liegen.
In den älteren Shelly Generationen ließt man den aktuellen Verbrauch über den Punkt shelly.0.SHSW-25#1111111111#1.Relay1.Energy aus.
Die neuen Shellys können aber nicht nur den Strom messen sondern zeigen auch an ob es sich um Verbrauch oder Einspeisung z.B. von einer Balkon PV wie bei mir handelt. Dazu nutzen die Shellys die Werte
shelly.0.shellyemminig4#1111111111#1.EM1Data0.TotalActiveEnergy
und
shelly.0.shellyemminig4#1111111111#1.EM1Data0.TotalActiveReturnEnergy
Um das Skript fit für die neue Generation zu machen habe ich die KI mit ChatGPT und Claude Opus darüber grübeln lassen und das Skript von Stephan Keyenborg überarbeitet (https://www.kreyenborg.koeln/shelly-verbrauchs-historie-fuer-tag-woche-monat-jahr/). Den neuen Code habe ich grob validiert und erfolgreich getestet:
/*
* @copyright 2021 Stephan Kreyenborg <stephan@kreyenborg.koeln>
*
* @author 2021 Stephan Kreyenborg <stephan@kreyenborg.koeln>
*
* Dieses Skript dient zur freien Verwendung in ioBroker zur Verbrauchserfassung der Shelly Geräte.
* Jegliche Verantwortung liegt beim Benutzer. Das Skript wurde unter Berücksichtigung der bestmöglichen Nutzung
* und Performance entwickelt.
* Der Entwickler versichert, das keine böswilligen Systemeingriffe im originalen Skript vorhanden sind.
*
* Sollte das Skript wider Erwarten nicht korrekt funktionieren, so hast Du jederzeit die Möglichkeit, Dich auf
* https://www.kreyenborg.koeln
* für Unterstützung zu melden. Jedes Skript besitzt seine eigene Kommentarseite, auf der,
* nach zeitlicher Möglichkeit des Autors, Hilfe angeboten wird. Ein Anrecht hierauf besteht nicht!
*
* Ansprüche gegenüber Dritten bestehen nicht.
*
* Skript Name: Shelly-Verbrauch
* Skript Version: 1.60
* Erstell-Datum: 08. Oktober 2021 | Update: 21. April 2022
*
* Überarbeitet von Michael Schumann (https://www.md-technologie.de/baublog/)
* Skript Version: 1.70
* Letzte Änderung: 31. März 2026
*
* Shelly Verbrauch - robust für Gen2 / Gen3 / Gen4
* verarbeitet auflaufende Energiezaehler in Wh
*/
// Datenpunkte neu erstellen
var ueberschreiben = false;
var DEBUG = false; // auf false setzen wenn alles läuft
// Hauptdatenpunkt unterhalb javascript
var datenpunkt = "ShellyVerbrauch.";
var javascript_instanz = "javascript.0.";
// Shelly-Adapter Basis
var shelly_dp = "shelly.0";
// Verbrauchs-Objekte mit Beschreibung
var felder = [
{ key: "gesamt", desc: "Gesamter Verbrauch des Shelly", init: false },
{ key: "dieses_jahr", desc: "Verbrauch aktuelles Jahr", init: false },
{ key: "letztes_jahr", desc: "Verbrauch letztes Jahr", init: false },
{ key: "letzter_monat", desc: "Verbrauch letzten Monat", init: false },
{ key: "dieser_monat", desc: "Verbrauch aktueller Monat", init: false },
{ key: "letzte_woche", desc: "Verbrauch letzte Woche", init: false },
{ key: "diese_woche", desc: "Verbrauch diese Woche", init: false },
{ key: "gestern", desc: "Verbrauch gestern", init: false },
{ key: "heute", desc: "Verbrauch heute", init: false },
{ key: "alter_wert", desc: "Messwert alt", init: true },
{ key: "aktueller_wert", desc: "Messwert neu", init: true }
];
// Shelly-Namen
var shellyDpsName = $('state[id=' + shelly_dp + '.*.name]');
// Relevante Energie-State-Endungen
var energySuffixes = [
{ suffix: ".Energy", extended: false, label: "Energy" },
{ suffix: ".Total", extended: false, label: "Total" },
{ suffix: ".Total_Returned", extended: true, label: "Total_Returned" },
{ suffix: ".TotalActiveEnergy", extended: false, label: "TotalActiveEnergy" },
{ suffix: ".TotalActiveReturnEnergy", extended: true, label: "TotalActiveReturnEnergy" }
];
// --------------------------------------------------
// Hilfsfunktionen
// --------------------------------------------------
function endsWithExact(str, suffix) {
return str.slice(-suffix.length) === suffix;
}
function getAllEnergyStates() {
var result = [];
// gezielte Abfrage pro Suffix statt alle States durchlaufen
for (var x = 0; x < energySuffixes.length; x++) {
var entry = energySuffixes[x];
$('state[id=' + shelly_dp + '.*' + entry.suffix + ']').each(function (id) {
if (endsWithExact(id, entry.suffix)) {
result.push({
id: id,
extended: entry.extended,
label: entry.label
});
}
});
}
return result;
}
function safeNumber(val, fallback) {
var n = parseFloat(val);
return isNaN(n) ? fallback : n;
}
// --------------------------------------------------
// Zeitbasierte Verschiebungen
// --------------------------------------------------
function shelly_verbrauch_tag() {
shelly_verbrauch_update();
var heute = new Date();
verschiebe_verbrauch_objekt("heute", "gestern");
log("Shelly Verbrauch: Werte fuer gestern und heute aktualisiert!");
if (heute.getDay() === 1) {
verschiebe_verbrauch_objekt("diese_woche", "letzte_woche");
log("Shelly Verbrauch: Werte fuer diese und letzte Woche aktualisiert!");
}
if (heute.getDate() === 1) {
verschiebe_verbrauch_objekt("dieser_monat", "letzter_monat");
log("Shelly Verbrauch: Werte fuer diesen und letzten Monat aktualisiert!");
}
if (heute.getDate() === 1 && heute.getMonth() === 0) {
verschiebe_verbrauch_objekt("dieses_jahr", "letztes_jahr");
log("Shelly Verbrauch: Werte fuer dieses und letztes Jahr aktualisiert!");
}
}
// --------------------------------------------------
// Hauptupdate
// --------------------------------------------------
function shelly_verbrauch_update() {
var anzahl_updates = 0;
var anzahl_reboots = 0;
var anzahl_gleich = 0;
var anzahl_verarbeitet = 0;
var anzahl_gefunden = 0;
var anzahl_ohne_objekt = 0;
var states = getAllEnergyStates();
anzahl_gefunden = states.length;
states.forEach(function (entry) {
var id = entry.id;
var shelly_verbrauch = getState(id).val;
if (DEBUG) {
log("DEBUG: Shellys gefundener State -> " + id + " | Wert: " + shelly_verbrauch);
}
if (shelly_verbrauch === null || shelly_verbrauch === undefined) return;
shelly_verbrauch = safeNumber(shelly_verbrauch, NaN);
if (isNaN(shelly_verbrauch)) return;
var basis_dp = shelly_DP(id, entry.extended);
if (!existsState(basis_dp + "aktueller_wert")) {
anzahl_ohne_objekt++;
if (DEBUG) {
log("DEBUG: Shellys Ziel-State fehlt -> " + basis_dp + "aktueller_wert");
}
return;
}
var aktueller_wert = 0;
var aktueller_state = getState(basis_dp + "aktueller_wert");
if (aktueller_state && aktueller_state.val !== null && aktueller_state.val !== undefined) {
aktueller_wert = safeNumber(aktueller_state.val, 0);
}
var alter_wert = 0;
if (shelly_verbrauch > aktueller_wert) {
setState(basis_dp + "alter_wert", aktueller_wert, true);
alter_wert = aktueller_wert;
anzahl_updates++;
} else if (aktueller_wert > shelly_verbrauch) {
setState(basis_dp + "alter_wert", 0, true);
alter_wert = 0;
anzahl_reboots++;
} else {
alter_wert = aktueller_wert;
anzahl_gleich++;
}
setState(basis_dp + "aktueller_wert", shelly_verbrauch, true);
var verbrauch = shelly_verbrauch - alter_wert;
if (verbrauch < 0) verbrauch = 0;
aktualisiere_verbrauch_objekt(basis_dp, "heute", verbrauch);
aktualisiere_verbrauch_objekt(basis_dp, "diese_woche", verbrauch);
aktualisiere_verbrauch_objekt(basis_dp, "dieser_monat", verbrauch);
aktualisiere_verbrauch_objekt(basis_dp, "dieses_jahr", verbrauch);
aktualisiere_verbrauch_objekt(basis_dp, "gesamt", verbrauch);
anzahl_verarbeitet++;
});
aktualisiere_namen();
log(
"Shelly Verbrauch: gefunden=" + anzahl_gefunden +
" | verarbeitet=" + anzahl_verarbeitet +
" | ohne_objekt=" + anzahl_ohne_objekt +
" | updates=" + anzahl_updates +
" | resets/reboots=" + anzahl_reboots +
" | unveraendert=" + anzahl_gleich
);
}
// --------------------------------------------------
// Verbrauch addieren
// --------------------------------------------------
function aktualisiere_verbrauch_objekt(dp, objektname, wert) {
var state = getState(dp + objektname);
var alter_verbrauch = (state && state.val !== null && state.val !== undefined) ? parseFloat(state.val) : 0;
if (isNaN(alter_verbrauch)) alter_verbrauch = 0;
if (isNaN(wert)) wert = 0;
var verbrauch = alter_verbrauch + wert;
setState(dp + objektname, Math.round(verbrauch * 100) / 100, true);
}
// --------------------------------------------------
// Verschieben
// --------------------------------------------------
function verschiebe_verbrauch_objekt(von, nach) {
$('state[id=*.' + datenpunkt + '*.*.' + von + ']').each(function (id, i) {
var tmp_dp = id.slice(0, -(von.length));
var verbrauch = getState(id).val;
if (verbrauch !== null && verbrauch !== undefined) {
setState(tmp_dp + nach, verbrauch, true);
}
setState(id, 0, true);
});
}
// --------------------------------------------------
// Namen aktualisieren
// --------------------------------------------------
function aktualisiere_namen() {
if (typeof extendObject === "function") {
shellyDpsName.each(function (id, i) {
if (existsState(id)) {
var name = String(getState(id).val);
setState(shelly_DP_Name(id), name, true);
extendObject(shelly_DP_Name_Main(id), {
common: {
name: name,
desc: name
},
type: "channel"
});
}
});
}
}
// --------------------------------------------------
// Datenpunkte erstellen
// --------------------------------------------------
function datenpunkte_erstellen() {
var anzahl_gesamt = 0;
var bereits_erstellt = {};
var states = getAllEnergyStates();
states.forEach(function (entry) {
var id = entry.id;
var basis_dp = shelly_DP(id, entry.extended);
if (bereits_erstellt[basis_dp]) return;
bereits_erstellt[basis_dp] = true;
var initial_wert = safeNumber(getState(id).val, 0.0);
for (var i = 0; i < felder.length; i++) {
var startwert = felder[i].init ? initial_wert : 0.0;
createState(basis_dp + felder[i].key, startwert, ueberschreiben, {
name: felder[i].desc,
desc: felder[i].desc,
type: "number",
role: "value.power",
unit: "Wh"
});
}
anzahl_gesamt++;
});
shellyDpsName.each(function (id, j) {
createState(shelly_DP_Name(id), "", ueberschreiben, {
name: "Name des Shelly",
desc: "Name des Shelly",
type: "string",
role: "value",
unit: ""
});
});
log("Shelly Verbrauch: Datenpunkte erstellt! Anzahl Energie-Datenpunkte: " + anzahl_gesamt);
setTimeout(shelly_verbrauch_update, 30000);
}
// --------------------------------------------------
// Pfadbildung
// --------------------------------------------------
function shelly_DP(dp, extended) {
if (extended === undefined) extended = false;
dp = dp.split(".");
if (dp.length < 5) {
return javascript_instanz + datenpunkt + "unbekannt.unbekannt.";
}
var basis = javascript_instanz + datenpunkt + dp[2] + "." + dp[3];
if (extended) {
basis += "_Returned.";
} else {
basis += ".";
}
return basis;
}
function shelly_DP_Name(dp) {
dp = dp.split(".");
if (dp.length < 4) return javascript_instanz + datenpunkt + "unbekannt.name";
return javascript_instanz + datenpunkt + dp[2] + ".name";
}
function shelly_DP_Name_Main(dp) {
dp = dp.split(".");
if (dp.length < 3) return javascript_instanz + datenpunkt + "unbekannt";
return javascript_instanz + datenpunkt + dp[2];
}
// --------------------------------------------------
// Initialisierung
// --------------------------------------------------
function shelly_verbrauch_erster_start() {
log("Shelly Verbrauch: Erster Start des Skriptes! Datenpunkte werden erstellt!");
datenpunkte_erstellen();
}
shelly_verbrauch_erster_start();
schedule('*/15 * * * *', shelly_verbrauch_update);
schedule('0 0 * * *', shelly_verbrauch_tag);


März 31st, 2026
admin | 2 Besucher
Posted in
Tags: