NEWS
Test Adapter fronius-solarweb
-
@TimoWald sagte in Test Adapter fronius-solarweb:
Genauso Ähnlich wollte ich es auch aufbauen.
Damit du nicht ganz von vorne anfangen musst, hier meine oben beschriebene Lösung in Form eines JavaScripts ..
let partsDate = {jahr: '', monat: '', tag: ''} let eventPV = null let eventFromGrid = null let eventEnergyTotal = null function setPartsDate() { let alleMonate = ['Januar', 'Februar', 'Maerz', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'] let d = new Date() partsDate = {jahr: d.getFullYear().toString(), monat: alleMonate[d.getMonth()], tag: d.getDate().toString()} } setPartsDate() schedule({hour: 0, minute: 0}, function () { setPartsDate() //TagesStartwert für PV setState(`0_userdata.0.Fronius.Modbus.atHome.startDayWhPV`,getState(`modbus.2.holdingRegisters.1.40186_ActWh`).val,true) setState(`0_userdata.0.Counter.Strom.startTagPV`,getState(`modbus.2.holdingRegisters.1.40186_ActWh`).val,true) //TagesStartwert für Export setState(`0_userdata.0.Fronius.Modbus.toGrid.startDayWh`,getState(`modbus.2.holdingRegisters.200.40107_TotWhExp`).val,true) setState(`0_userdata.0.Counter.Strom.startTagVerkaufStrom`,getState(`modbus.2.holdingRegisters.200.40107_TotWhExp`).val,true) //TagesStartwert für Import setState(`0_userdata.0.Fronius.Modbus.fromGrid.startDayWh`,getState(`modbus.2.holdingRegisters.200.40115_TotWhImp`).val,true) setState(`0_userdata.0.Counter.Strom.startTagBezugStrom`,getState(`modbus.2.holdingRegisters.200.40115_TotWhImp`).val,true) //TagesStartWert für Gas setState('0_userdata.0.Counter.Gas.startTagGas',getState('0_userdata.0.Counter.Gas.volGas').val,true) }) eventFromGrid = on({id: `modbus.2.holdingRegisters.200.40115_TotWhImp`, change: 'gt'}, (obj) => { let aktImp = obj.state.val - getState(`0_userdata.0.Fronius.Modbus.fromGrid.startDayWh`).val setState(`0_userdata.0.Fronius.Modbus.fromGrid.tmpDayWh`,aktImp,true) let tmpPV = JSON.parse(getState(`0_userdata.0.Fronius.Monatstabellen.${partsDate.jahr}.${partsDate.monat}.fromGridWh`).val) tmpPV[Number(partsDate.tag)-1] = aktImp setState(`0_userdata.0.Fronius.Monatstabellen.${partsDate.jahr}.${partsDate.monat}.fromGridWh`,JSON.stringify(tmpPV),true) }) eventPV = on({id: `modbus.2.holdingRegisters.200.40107_TotWhExp`, change: 'gt'}, (obj) => { let aktExp = obj.state.val - getState(`0_userdata.0.Fronius.Modbus.toGrid.startDayWh`).val setState('0_userdata.0.Fronius.Modbus.toGrid.tmpDayWh',aktExp,true) let tmpPV = JSON.parse(getState(`0_userdata.0.Fronius.Monatstabellen.${partsDate.jahr}.${partsDate.monat}.toGridWh`).val) tmpPV[Number(partsDate.tag)-1] = aktExp setState(`0_userdata.0.Fronius.Monatstabellen.${partsDate.jahr}.${partsDate.monat}.toGridWh`,JSON.stringify(tmpPV),true) }) eventEnergyTotal = on({id: `modbus.2.holdingRegisters.1.40186_ActWh`, change: 'gt'}, (obj) => { let aktGen = obj.state.val - getState(`0_userdata.0.Fronius.Modbus.atHome.startDayWhPV`).val setState(`0_userdata.0.Fronius.Modbus.atHome.tmpDayWhPV`,aktGen,true) let tmpPV = JSON.parse(getState(`0_userdata.0.Fronius.Monatstabellen.${partsDate.jahr}.${partsDate.monat}.solarWh`).val) tmpPV[Number(partsDate.tag)-1] = aktGen setState(`0_userdata.0.Fronius.Monatstabellen.${partsDate.jahr}.${partsDate.monat}.solarWh`,JSON.stringify(tmpPV),true) })Da ich keinen Ohmpilot habe, musst du dir hierzu die Register leider selbst suchen.
@legro Hallo .Danke für die Inspiration . Die Tageswerte bekomme ich so super abgefragt. Leider bekomme ich das mit der Aufsummierung in den Monatswerten nicht hin. Ich habe zwar Objekte für den jeweiligen Tageswerte erstellt aber er wird nicht gefüllt . Wenn möglich bitte um genaues Vorgehen bzgl. der Monatswerte. Vielen Dank.
-
Hallo. Oha, da ist mir ein Fehler im Post unterlaufen . Die Tageswerte werden sehr wohl gefüllt. Die Monatswerte nur nicht. . Danke für die Hilfe.👍
0_userdata.0.Fronius.Monatstabellen.2026.01.fromGridWh
So ist der Objektpunkt der Monatswerte benannt und ist vom Typ Liste.
LG. -
H Homoran verschob dieses Thema von Tester am
-
H Homoran verschob dieses Thema von ...nicht in offiziellem Repo am
-
Hallo
ich habe hier nichts gefunden oder übersehn.
Liefert der Adapter den Autarkiegrad, bzw. wie wird der aus den vorhandenen DP berechnet?
-
er liefert nur was in der app angezeigt wird
hab es jetzt per Script berechnet
/** * ----------------------------------------------------------------------------- * Fronius SolarWeb Autarkiegrad * ----------------------------------------------------------------------------- * Version: 1.1.0 * Author: Christian Wimmer * Copyright: (c) 2026 Christian Wimmer * License: MIT * * Description: * Berechnet den aktuellen Autarkiegrad anhand der Fronius SolarWeb Daten * und schreibt das Ergebnis nach: * * 0_userdata.0.Fronius.Autarkiegrad * * Es wird automatisch der letzte verfügbare Tag mit gültigen Daten * verwendet, damit der Wert nach Mitternacht nicht auf 0 % fällt. * * Formel: * (EnergyDirectConsumption + EnergyBattDischarge) * / EnergyConsumptionTotal * 100 * ----------------------------------------------------------------------------- */ const VERSION = '1.1.0'; const base = 'fronius-solarweb.0.6f41428b-0208-4f01-ab38-c11b57543b46.day'; const dpResult = '0_userdata.0.Fronius.Autarkiegrad'; log(`Fronius Autarkiegrad v${VERSION} gestartet`, 'info'); // Datenpunkt anlegen falls nicht vorhanden if (!existsState(dpResult)) { createState(dpResult, 0, { name: 'PV Autarkiegrad', type: 'number', role: 'value.percent', unit: '%', read: true, write: false }); } function getValue(dp) { if (!existsState(dp)) { return 0; } const state = getState(dp); if (!state || state.val === null || state.val === undefined) { return 0; } const val = parseFloat(state.val); return isNaN(val) ? 0 : val; } function calculateAutarkie() { let day = new Date().getDate(); // Letzten Tag mit Verbrauchsdaten suchen while (day > 0) { const consumptionTest = getValue( `${base}.EnergyConsumptionTotal.values.${day}` ); if (consumptionTest > 0) { break; } day--; } if (day === 0) { log('Keine gültigen Fronius-Daten gefunden.', 'warn'); return; } const consumption = getValue( `${base}.EnergyConsumptionTotal.values.${day}` ); const direct = getValue( `${base}.EnergyDirectConsumption.values.${day}` ); const battery = getValue( `${base}.EnergyBattDischarge.values.${day}` ); let autarkie = 0; if (consumption > 0) { autarkie = ((direct + battery) / consumption) * 100; } autarkie = Math.round(autarkie * 10) / 10; setState(dpResult, autarkie, true); log( `Autarkiegrad: ${autarkie}% | Tag=${day} | Verbrauch=${consumption} | Direkt=${direct} | Batterie=${battery}`, 'info' ); } // Alle 15 Minuten aktualisieren schedule('*/15 * * * *', calculateAutarkie); // Beim Start sofort berechnen calculateAutarkie(); -
Mittlerweile habe ich unsere Visualisierung zum dritten Mal überarbeitet. Herausgekommen ist u.a. dabei eine View mit vier Ansichten: Kosten, Energie (AC), Quoten und Energie (DC).



Die Berechnung der Quoten (Autarkie und Eigenverbrauch) habe ich aus den Daten der AC-Werte errechnet; diese sind somit echte Werte, nicht etwa die etwas geschönten aus der App, die auf den DC-Werten basieren. Der Gesamtwirkungsgrad (AC/DC) beinhaltet somit alle Verluste aus AC->DC Wandlung und in/aus Batterie. Da bei uns nur ein geringer Teil der Energie in der Batterie zwischengespeichert wird, ist der Wirkungsgrad mit über 91% recht hoch.
Die in den Views angegebenen Wirkungsgrade beruhen ebenfalls auf AC-Werten. Sie basieren aus mittlerweile über drei Jahre gesammelten Daten.
In den Zeilen 71 bis 78 findet man die Berechnung der Werte für Autarkie und Eigenquote. Die verwendeten Daten stammen zwar aus den ECharts-Diagrammen (s. FlexCharts-Adapter von @jrbwh ), aber ihre Herkunft findet man in den Zeilen 53 - 69 erläutert.
Bei weiteren Fragen - insbesondere zu dem im Skript nicht dokumentierten Programmcode - helfe ich gerne weiter.
function getAktMonthYear() { return { month: G_getMonthAsNumber(getState('0_userdata.0.Fronius.flexCharts.selMonth').val), year: getState('0_userdata.0.Fronius.flexCharts.selYear').val } } function checkTarifStrom(d) { let arr = JSON.parse(getState('0_userdata.0.Energie_Tarife.Strom.StromBezug').val) for(let i=0; i<arr.length; i++) { if(new Date(arr[i].Zeitraum.Start) <= d && d <= new Date(arr[i].Zeitraum.Ende)) { return {Verkaufspreis: arr[i].Verkaufspreis, Energiepreis: arr[i].Energiepreis} } } return 0 } //############################ chartEnergieYear: Monatsenergien ############################ function refreshYear() { let aktYear = getState('0_userdata.0.Fronius.flexCharts.selYear').val let dataMonths = [] //Diagramm Energien in KWh im RAM allokieren let jsonChartKWh = '0_userdata.0.Fronius.flexCharts.chartEnergieYear' let yearChartKWh = JSON.parse(getState(jsonChartKWh).val) //Diagramm Autarkie&Effizienz in % im RAM allokieren let jsonChartAutPrc = '0_userdata.0.Fronius.flexCharts.chartEffienzYear' let yearChartAutPrc = JSON.parse(getState(jsonChartAutPrc).val) //Diagramm Kosten im RAM allokieren let jsonChartKosten = '0_userdata.0.Fronius.flexCharts.chartKostenYear' let yearChartKosten = JSON.parse(getState(jsonChartKosten).val) //Diagramm Energie DC im RAM allokieren let jsonChartYearDC = '0_userdata.0.Fronius.flexCharts.chartYearDC' let yearChartDC = JSON.parse(getState(jsonChartYearDC).val) yearChartKWh.series[0].data = [] //fromGridKWh yearChartKWh.series[1].data = [] //toGridKWh yearChartKWh.series[2].data = [] //fromSolarKWh (Eigenverbrauch) yearChartAutPrc.series[0].data = [] //Autarkie yearChartAutPrc.series[1].data = [] //Eigenverbrauch yearChartKosten.series[0].data = [] //fromGridEuro yearChartKosten.series[1].data = [] //toGridEuro yearChartKosten.series[2].data = [] //EigenverbrauchEuro yearChartDC.series[0].data =[] //dcGartenhaus yearChartDC.series[1].data =[] //dcTerrasse for (let i=1;i<13;i++) { //Monatstarif - Der Stromtarif ändert sich nur zum Monatswechsel let tarif = checkTarifStrom(new Date(`${aktYear}-('0'+ ${('0' + i).slice(-2)}-15`)) //fromGrid let fromGridKWh = JSON.parse(getState(`0_userdata.0.Fronius.Monatstabellen.${aktYear}.${G_getMonthLongName(i)}.fromGridWh`).val) yearChartKWh.series[0].data.push(G_runden(fromGridKWh.reduce((sum, item) => sum + item, 0) / 1000,3)) yearChartKosten.series[0].data.push(G_runden(tarif.Energiepreis * yearChartKWh.series[0].data[i-1],3)) //toGrid let toGridKWh = JSON.parse(getState(`0_userdata.0.Fronius.Monatstabellen.${aktYear}.${G_getMonthLongName(i)}.toGridWh`).val) yearChartKWh.series[1].data.push(G_runden(toGridKWh.reduce((sum, item) => sum + item, 0) / 1000,3)) yearChartKosten.series[1].data.push(G_runden(tarif.Verkaufspreis * yearChartKWh.series[1].data[i-1],3)) //fromSolar bzw. Eigenverbrauch let fromSolarKWh = JSON.parse(getState(`0_userdata.0.Fronius.Monatstabellen.${aktYear}.${G_getMonthLongName(i)}.solarWh`).val) yearChartKWh.series[2].data.push(G_runden(fromSolarKWh.reduce((sum, item) => sum + item, 0) / 1000 - yearChartKWh.series[1].data[i-1],3)) yearChartKosten.series[2].data.push(G_runden(tarif.Energiepreis * yearChartKWh.series[2].data[i-1],3)) //Autarkie let gesamtVerbrauch = yearChartKWh.series[0].data[i-1] + yearChartKWh.series[2].data[i-1] let eigenVerbrauch = yearChartKWh.series[2].data[i-1] let autarkieQuote = eigenVerbrauch / gesamtVerbrauch let gesamtSolar = yearChartKWh.series[2].data[i-1] + yearChartKWh.series[1].data[i-1] let eigenQuote = eigenVerbrauch / gesamtSolar yearChartAutPrc.series[0].data.push(G_runden(100*autarkieQuote,2)) yearChartAutPrc.series[1].data.push(G_runden(100*eigenQuote,2)) //Energien DC let dcGartenhausKWh = JSON.parse(getState(`0_userdata.0.Fronius.Monatstabellen.${aktYear}.${G_getMonthLongName(i)}.dcGartenhausKWh`).val) dcGartenhausKWh ||= [] yearChartDC.series[0].data.push(G_runden(dcGartenhausKWh.reduce((sum, item) => sum + item,0) / 1000,3)) let dcTerrasseKWh = JSON.parse(getState(`0_userdata.0.Fronius.Monatstabellen.${aktYear}.${G_getMonthLongName(i)}.dcTerrasseKWh`).val) dcTerrasseKWh ||= [] yearChartDC.series[1].data.push(G_runden(dcTerrasseKWh.reduce((sum, item) => sum + item,0) / 1000,3)) } //Jahresummen // - fromGrid let fromGridKWhJahressumme = yearChartKWh.series[0].data.reduce((sum, item) => sum + item, 0) setStateAsync('0_userdata.0.Fronius.flexCharts.summeJahrFromGridKWh', fromGridKWhJahressumme, true) let fromGridEuroJahressumme = yearChartKosten.series[0].data.reduce((sum, item) => sum + item, 0) setStateAsync('0_userdata.0.Fronius.flexCharts.summeJahrFromGridEuro', fromGridEuroJahressumme, true) // - toGrid let toGridKWhJahressumme = yearChartKWh.series[1].data.reduce((sum, item) => sum + item, 0) setStateAsync('0_userdata.0.Fronius.flexCharts.summeJahrToGridKWh', toGridKWhJahressumme, true) let toGridEuroJahressumme = yearChartKosten.series[1].data.reduce((sum, item) => sum + item, 0) setStateAsync('0_userdata.0.Fronius.flexCharts.summeJahrToGridEuro', toGridEuroJahressumme, true) // - eigenverbrauch let eigenverbrauchKWhJahressumme = yearChartKWh.series[2].data.reduce((sum, item) => sum + item, 0) setStateAsync('0_userdata.0.Fronius.flexCharts.summeJahrEigenverbrauchKWh', eigenverbrauchKWhJahressumme, true) let eigenverbrauchEuroJahressumme = yearChartKosten.series[2].data.reduce((sum, item) => sum + item, 0) setStateAsync('0_userdata.0.Fronius.flexCharts.summeJahrEigenverbrauchEuro', eigenverbrauchEuroJahressumme, true) //Gesamtverbrauch setStateAsync('0_userdata.0.Fronius.flexCharts.summeJahrKonsumKWh', eigenverbrauchKWhJahressumme + fromGridKWhJahressumme, true) setStateAsync('0_userdata.0.Fronius.flexCharts.summeJahrKonsumEuro', eigenverbrauchEuroJahressumme + fromGridEuroJahressumme, true) //Titelzeilen yearChartKWh.title.text = 'elektrische Energien in ' + aktYear yearChartKosten.title.text = 'Energienkosten in ' + aktYear yearChartAutPrc.title.text = 'Autarkie/Eigenquoten in ' + aktYear yearChartDC.title.text = 'elektrische Energie DC in ' + aktYear //x-Achse beschriften yearChartKWh.xAxis[0].data = Array.from({length: 12}, (tmp,i) => G_shrtMonths[i]) //yearChartKWh.xAxis[0].data = Array.from({length: 12}, (tmp,i) => i+1) //Diagrammm als JSON im Objektbaum ablegen setState(jsonChartKWh,JSON.stringify(yearChartKWh),true) setState(jsonChartAutPrc,JSON.stringify(yearChartAutPrc),true) setState(jsonChartKosten,JSON.stringify(yearChartKosten),true) setState(jsonChartYearDC,JSON.stringify(yearChartDC),true) } //############################ chartEnergieMonth : Tagesenergien ############################ function refreshMonth() { let aktMonthYear = getAktMonthYear() let tarif = checkTarifStrom(new Date(`${aktMonthYear.year}-('0'+ ${('0' + aktMonthYear.month).slice(-2)}-15`)) //Diagramm Energien in KWh im RAM allokieren let jsonChartKWh = '0_userdata.0.Fronius.flexCharts.chartEnergieMonth' let monthChartKWh = JSON.parse(getState(jsonChartKWh).val) //Diagramm Autarkie&Effizienz in % im RAM allokieren let jsonChartAutPrc = '0_userdata.0.Fronius.flexCharts.chartEffizienzMonth' let monthChartAutPrc = JSON.parse(getState(jsonChartAutPrc).val) //Diagramm Kosten in € im RAM allokieren let jsonChartKosten = '0_userdata.0.Fronius.flexCharts.chartKostenMonth' let monthChartKosten = JSON.parse(getState(jsonChartKosten).val) //Diagramm Energie DC im RAM allokieren let jsonChartMonthDC = '0_userdata.0.Fronius.flexCharts.chartMonthDC' let monthChartDC = JSON.parse(getState(jsonChartMonthDC).val) //Tabelle fromGridKWh in KWh im RAM allokieren let fromGridKWh = JSON.parse(getState(`0_userdata.0.Fronius.Monatstabellen.${aktMonthYear.year}.${G_getMonthLongName(aktMonthYear.month)}.fromGridWh`).val) fromGridKWh = fromGridKWh.map(item => item / 1000) //Tabelle toGridKWh in KWh im RAM allokieren let toGridKWh = JSON.parse(getState(`0_userdata.0.Fronius.Monatstabellen.${aktMonthYear.year}.${G_getMonthLongName(aktMonthYear.month)}.toGridWh`).val) toGridKWh = toGridKWh.map(item => G_runden(item/1000,3)) let fromSolarKWh = JSON.parse(getState(`0_userdata.0.Fronius.Monatstabellen.${aktMonthYear.year}.${G_getMonthLongName(aktMonthYear.month)}.solarWh`).val) fromSolarKWh = fromSolarKWh.map(item => item / 1000) //erzeugte Solarenergie AC //Tabelle eigenVerbrauch let eigenVerbrauchKWh = fromSolarKWh.map((item, i) => G_runden(item - toGridKWh[i],3)) //Eigenverbrauch AC let gesamtVerbrauchKWh = eigenVerbrauchKWh.map((item, i) => G_runden(item + fromGridKWh[i],3)) //Gesamtverbrauch AC //Tabelle dcGartenhausKWh und dcTerrasseKWh in KWh im RAM allokieren let dcGartenhausKWh = JSON.parse(getState(`0_userdata.0.Fronius.Monatstabellen.${aktMonthYear.year}.${G_getMonthLongName(aktMonthYear.month)}.dcGartenhausKWh`).val) dcGartenhausKWh ||= [] dcGartenhausKWh = dcGartenhausKWh.map(item => G_runden(item / 1000,3)) let dcTerrasseKWh = JSON.parse(getState(`0_userdata.0.Fronius.Monatstabellen.${aktMonthYear.year}.${G_getMonthLongName(aktMonthYear.month)}.dcTerrasseKWh`).val) dcTerrasseKWh ||= [] dcTerrasseKWh = dcTerrasseKWh.map(item => G_runden(item / 1000,3)) //Energiesummen // - fromGrid let fromGridKWhSum = fromGridKWh.reduce((sum, item) => sum + item, 0) let fromGridEuroSum = fromGridKWhSum * tarif.Energiepreis // - toGrid let toGridKWhSum = toGridKWh.reduce((sum, item) => sum + item, 0) let toGridEuroSum = toGridKWhSum * tarif.Verkaufspreis // - Eigenverbrauch let eigenverbrauchKWhSum = fromSolarKWh.reduce((sum, item) => sum + item) - toGridKWhSum let eigenverbrauchEuroSum = eigenverbrauchKWhSum * tarif.Energiepreis //Gesamtverbrauch bzw. Konsum let konsumKWhSum = fromGridKWhSum + eigenverbrauchKWhSum let konsumEuroSum = konsumKWhSum * tarif.Energiepreis //Energien DC //Summen in Objekte Speichern // - fromGrid setStateAsync('0_userdata.0.Fronius.flexCharts.sumMonatFromGridKWh',fromGridKWhSum,true) setStateAsync('0_userdata.0.Fronius.flexCharts.sumMonatFromGridEuro',fromGridEuroSum,true) // - toGrid setStateAsync('0_userdata.0.Fronius.flexCharts.sumMonatToGridKWh',toGridKWhSum,true) setStateAsync('0_userdata.0.Fronius.flexCharts.sumMonatToGridEuro',toGridEuroSum,true) // - Eigenverbrauch setStateAsync('0_userdata.0.Fronius.flexCharts.sumMonatEigenverbrauchKWh',eigenverbrauchKWhSum,true) setStateAsync('0_userdata.0.Fronius.flexCharts.sumMonatEigenverbrauchEuro',eigenverbrauchEuroSum,true) // - Konsum setStateAsync('0_userdata.0.Fronius.flexCharts.sumMonatKonsumKWh',konsumKWhSum,true) setStateAsync('0_userdata.0.Fronius.flexCharts.sumMonatKonsumEuro',konsumEuroSum,true) //Titelzeilen //Energien AC monthChartKWh.title.text = 'elektrische Energien im ' monthChartKWh.title.text = (aktMonthYear.month == 3) ? monthChartKWh.title.text.concat('März') : monthChartKWh.title.text.concat(G_getMonthLongName(aktMonthYear.month)) monthChartKWh.title.text = monthChartKWh.title.text.concat(' (' + aktMonthYear.year + ')') //Kosten monthChartKosten.title.text = 'Stromkosten im ' monthChartKosten.title.text = (aktMonthYear.month == 3) ? monthChartKosten.title.text.concat('März') : monthChartKosten.title.text.concat(G_getMonthLongName(aktMonthYear.month)) monthChartKosten.title.text = monthChartKosten.title.text.concat(' (' + aktMonthYear.year + ')') //Quoten monthChartAutPrc.title.text = 'Autarkie&Eigenquote im ' monthChartAutPrc.title.text = (aktMonthYear.month == 3) ? monthChartAutPrc.title.text.concat('März') : monthChartAutPrc.title.text.concat(G_getMonthLongName(aktMonthYear.month)) monthChartAutPrc.title.text = monthChartAutPrc.title.text.concat(' (' + aktMonthYear.year + ')') //Energien DC monthChartDC.title.text = 'elektrische Energien DC im ' if (aktMonthYear.month == 3) { monthChartDC.title.text = monthChartDC.title.text + 'März' } else { monthChartDC.title.text = monthChartDC.title.text + G_getMonthLongName(aktMonthYear.month) } monthChartDC.title.text = monthChartDC.title.text +' (' + aktMonthYear.year + ')' //x-Achse beschriften //x-Achse monthChartKWh.xAxis[0].data = Array.from({length: G_getDaysOfMonth(aktMonthYear.year, aktMonthYear.month)}, (tmp,i) => i+1) monthChartKosten.xAxis[0].data = Array.from({length: G_getDaysOfMonth(aktMonthYear.year, aktMonthYear.month)}, (tmp,i) => i+1) monthChartAutPrc.xAxis[0].data = Array.from({length: G_getDaysOfMonth(aktMonthYear.year, aktMonthYear.month)}, (tmp,i) => i+1) monthChartDC.xAxis[0].data = Array.from({length: G_getDaysOfMonth(aktMonthYear.year, aktMonthYear.month)}, (tmp,i) => i+1) //y-Achsenwerte eintragen .. //Netzbezug, Einspeisung, Eigenverbrauch monthChartKWh.series[0].data = fromGridKWh monthChartKWh.series[1].data = toGridKWh monthChartKWh.series[2].data = eigenVerbrauchKWh //Kosten: Netzbezug, Einspeisung, Eigenverbrauch monthChartKosten.series[0].data = fromGridKWh.map((item,i) => item * tarif.Energiepreis) monthChartKosten.series[1].data = toGridKWh.map((item,i) => item * tarif.Verkaufspreis) monthChartKosten.series[2].data = eigenVerbrauchKWh.map((item,i) => item * tarif.Energiepreis) //Autarkie&Eigenverbrauch monthChartAutPrc.series[0].data = eigenVerbrauchKWh.map((item, i) => G_runden(100*item / gesamtVerbrauchKWh[i],1)) //Autarkie monthChartAutPrc.series[1].data = eigenVerbrauchKWh.map((item,i) => G_runden(100*item / fromSolarKWh[i],1)) //Eigenquote //Energien DC monthChartDC.series[0].data = dcGartenhausKWh monthChartDC.series[1].data = dcTerrasseKWh //Diagrammme als JSON im Objektbaum ablegen setState(jsonChartKWh,JSON.stringify(monthChartKWh),true) setState(jsonChartKosten,JSON.stringify(monthChartKosten),true) setState(jsonChartAutPrc,JSON.stringify(monthChartAutPrc),true) setState(jsonChartMonthDC,JSON.stringify(monthChartDC),true) } //############################ Scheduler & Trigger ############################ //alle 4 Minuten die Anzeige aktualisieren schedule('*/4 * * * *', () => { refreshMonth(); refreshYear() setState('0_userdata.0.Fronius.flexCharts.rfhButton',0,false) }); on({id:'0_userdata.0.Fronius.flexCharts.selMonth',change: 'any'},(obj) => { refreshMonth() setState('0_userdata.0.Fronius.flexCharts.rfhButton',0,false) }) on({id:'0_userdata.0.Fronius.flexCharts.selYear',change: 'any'},(obj) => { //G_setListYears('0_userdata.0.Fronius.Monatstabellen', '0_userdata.0.Fronius.Charts.lstYears') setStateAsync('0_userdata.0.Fronius.flexCharts.rfhButton',0,false) G_setListMonths(getState('0_userdata.0.Fronius.flexCharts.selYear').val, '0_userdata.0.Fronius.Monatstabellen', '0_userdata.0.Fronius.flexCharts.lstMonths') refreshYear(); refreshMonth() setState('0_userdata.0.Fronius.flexCharts.rfhButton', 0, false) }) on({id:'0_userdata.0.Fronius.flexCharts.buttonAktualisieren',change: 'any'},(obj) => { refreshMonth(); refreshYear() setState('0_userdata.0.Fronius.flexCharts.rfhButton',0,false) }) //############################ Skriptstart ############################ //listMonths des zugehörigen DropDown-Widgets füllen G_setListYears('0_userdata.0.Fronius.Monatstabellen', '0_userdata.0.Fronius.flexCharts.lstYear') //listYears des zugehörigen DropDown-Widgets füllen G_setListMonths(getState('0_userdata.0.Fronius.flexCharts.selYear').val, '0_userdata.0.Fronius.Monatstabellen', '0_userdata.0.Fronius.flexCharts.lstMonths') -
Mittlerweile habe ich unsere Visualisierung zum dritten Mal überarbeitet. Herausgekommen ist u.a. dabei eine View mit vier Ansichten: Kosten, Energie (AC), Quoten und Energie (DC).



Die Berechnung der Quoten (Autarkie und Eigenverbrauch) habe ich aus den Daten der AC-Werte errechnet; diese sind somit echte Werte, nicht etwa die etwas geschönten aus der App, die auf den DC-Werten basieren. Der Gesamtwirkungsgrad (AC/DC) beinhaltet somit alle Verluste aus AC->DC Wandlung und in/aus Batterie. Da bei uns nur ein geringer Teil der Energie in der Batterie zwischengespeichert wird, ist der Wirkungsgrad mit über 91% recht hoch.
Die in den Views angegebenen Wirkungsgrade beruhen ebenfalls auf AC-Werten. Sie basieren aus mittlerweile über drei Jahre gesammelten Daten.
In den Zeilen 71 bis 78 findet man die Berechnung der Werte für Autarkie und Eigenquote. Die verwendeten Daten stammen zwar aus den ECharts-Diagrammen (s. FlexCharts-Adapter von @jrbwh ), aber ihre Herkunft findet man in den Zeilen 53 - 69 erläutert.
Bei weiteren Fragen - insbesondere zu dem im Skript nicht dokumentierten Programmcode - helfe ich gerne weiter.
function getAktMonthYear() { return { month: G_getMonthAsNumber(getState('0_userdata.0.Fronius.flexCharts.selMonth').val), year: getState('0_userdata.0.Fronius.flexCharts.selYear').val } } function checkTarifStrom(d) { let arr = JSON.parse(getState('0_userdata.0.Energie_Tarife.Strom.StromBezug').val) for(let i=0; i<arr.length; i++) { if(new Date(arr[i].Zeitraum.Start) <= d && d <= new Date(arr[i].Zeitraum.Ende)) { return {Verkaufspreis: arr[i].Verkaufspreis, Energiepreis: arr[i].Energiepreis} } } return 0 } //############################ chartEnergieYear: Monatsenergien ############################ function refreshYear() { let aktYear = getState('0_userdata.0.Fronius.flexCharts.selYear').val let dataMonths = [] //Diagramm Energien in KWh im RAM allokieren let jsonChartKWh = '0_userdata.0.Fronius.flexCharts.chartEnergieYear' let yearChartKWh = JSON.parse(getState(jsonChartKWh).val) //Diagramm Autarkie&Effizienz in % im RAM allokieren let jsonChartAutPrc = '0_userdata.0.Fronius.flexCharts.chartEffienzYear' let yearChartAutPrc = JSON.parse(getState(jsonChartAutPrc).val) //Diagramm Kosten im RAM allokieren let jsonChartKosten = '0_userdata.0.Fronius.flexCharts.chartKostenYear' let yearChartKosten = JSON.parse(getState(jsonChartKosten).val) //Diagramm Energie DC im RAM allokieren let jsonChartYearDC = '0_userdata.0.Fronius.flexCharts.chartYearDC' let yearChartDC = JSON.parse(getState(jsonChartYearDC).val) yearChartKWh.series[0].data = [] //fromGridKWh yearChartKWh.series[1].data = [] //toGridKWh yearChartKWh.series[2].data = [] //fromSolarKWh (Eigenverbrauch) yearChartAutPrc.series[0].data = [] //Autarkie yearChartAutPrc.series[1].data = [] //Eigenverbrauch yearChartKosten.series[0].data = [] //fromGridEuro yearChartKosten.series[1].data = [] //toGridEuro yearChartKosten.series[2].data = [] //EigenverbrauchEuro yearChartDC.series[0].data =[] //dcGartenhaus yearChartDC.series[1].data =[] //dcTerrasse for (let i=1;i<13;i++) { //Monatstarif - Der Stromtarif ändert sich nur zum Monatswechsel let tarif = checkTarifStrom(new Date(`${aktYear}-('0'+ ${('0' + i).slice(-2)}-15`)) //fromGrid let fromGridKWh = JSON.parse(getState(`0_userdata.0.Fronius.Monatstabellen.${aktYear}.${G_getMonthLongName(i)}.fromGridWh`).val) yearChartKWh.series[0].data.push(G_runden(fromGridKWh.reduce((sum, item) => sum + item, 0) / 1000,3)) yearChartKosten.series[0].data.push(G_runden(tarif.Energiepreis * yearChartKWh.series[0].data[i-1],3)) //toGrid let toGridKWh = JSON.parse(getState(`0_userdata.0.Fronius.Monatstabellen.${aktYear}.${G_getMonthLongName(i)}.toGridWh`).val) yearChartKWh.series[1].data.push(G_runden(toGridKWh.reduce((sum, item) => sum + item, 0) / 1000,3)) yearChartKosten.series[1].data.push(G_runden(tarif.Verkaufspreis * yearChartKWh.series[1].data[i-1],3)) //fromSolar bzw. Eigenverbrauch let fromSolarKWh = JSON.parse(getState(`0_userdata.0.Fronius.Monatstabellen.${aktYear}.${G_getMonthLongName(i)}.solarWh`).val) yearChartKWh.series[2].data.push(G_runden(fromSolarKWh.reduce((sum, item) => sum + item, 0) / 1000 - yearChartKWh.series[1].data[i-1],3)) yearChartKosten.series[2].data.push(G_runden(tarif.Energiepreis * yearChartKWh.series[2].data[i-1],3)) //Autarkie let gesamtVerbrauch = yearChartKWh.series[0].data[i-1] + yearChartKWh.series[2].data[i-1] let eigenVerbrauch = yearChartKWh.series[2].data[i-1] let autarkieQuote = eigenVerbrauch / gesamtVerbrauch let gesamtSolar = yearChartKWh.series[2].data[i-1] + yearChartKWh.series[1].data[i-1] let eigenQuote = eigenVerbrauch / gesamtSolar yearChartAutPrc.series[0].data.push(G_runden(100*autarkieQuote,2)) yearChartAutPrc.series[1].data.push(G_runden(100*eigenQuote,2)) //Energien DC let dcGartenhausKWh = JSON.parse(getState(`0_userdata.0.Fronius.Monatstabellen.${aktYear}.${G_getMonthLongName(i)}.dcGartenhausKWh`).val) dcGartenhausKWh ||= [] yearChartDC.series[0].data.push(G_runden(dcGartenhausKWh.reduce((sum, item) => sum + item,0) / 1000,3)) let dcTerrasseKWh = JSON.parse(getState(`0_userdata.0.Fronius.Monatstabellen.${aktYear}.${G_getMonthLongName(i)}.dcTerrasseKWh`).val) dcTerrasseKWh ||= [] yearChartDC.series[1].data.push(G_runden(dcTerrasseKWh.reduce((sum, item) => sum + item,0) / 1000,3)) } //Jahresummen // - fromGrid let fromGridKWhJahressumme = yearChartKWh.series[0].data.reduce((sum, item) => sum + item, 0) setStateAsync('0_userdata.0.Fronius.flexCharts.summeJahrFromGridKWh', fromGridKWhJahressumme, true) let fromGridEuroJahressumme = yearChartKosten.series[0].data.reduce((sum, item) => sum + item, 0) setStateAsync('0_userdata.0.Fronius.flexCharts.summeJahrFromGridEuro', fromGridEuroJahressumme, true) // - toGrid let toGridKWhJahressumme = yearChartKWh.series[1].data.reduce((sum, item) => sum + item, 0) setStateAsync('0_userdata.0.Fronius.flexCharts.summeJahrToGridKWh', toGridKWhJahressumme, true) let toGridEuroJahressumme = yearChartKosten.series[1].data.reduce((sum, item) => sum + item, 0) setStateAsync('0_userdata.0.Fronius.flexCharts.summeJahrToGridEuro', toGridEuroJahressumme, true) // - eigenverbrauch let eigenverbrauchKWhJahressumme = yearChartKWh.series[2].data.reduce((sum, item) => sum + item, 0) setStateAsync('0_userdata.0.Fronius.flexCharts.summeJahrEigenverbrauchKWh', eigenverbrauchKWhJahressumme, true) let eigenverbrauchEuroJahressumme = yearChartKosten.series[2].data.reduce((sum, item) => sum + item, 0) setStateAsync('0_userdata.0.Fronius.flexCharts.summeJahrEigenverbrauchEuro', eigenverbrauchEuroJahressumme, true) //Gesamtverbrauch setStateAsync('0_userdata.0.Fronius.flexCharts.summeJahrKonsumKWh', eigenverbrauchKWhJahressumme + fromGridKWhJahressumme, true) setStateAsync('0_userdata.0.Fronius.flexCharts.summeJahrKonsumEuro', eigenverbrauchEuroJahressumme + fromGridEuroJahressumme, true) //Titelzeilen yearChartKWh.title.text = 'elektrische Energien in ' + aktYear yearChartKosten.title.text = 'Energienkosten in ' + aktYear yearChartAutPrc.title.text = 'Autarkie/Eigenquoten in ' + aktYear yearChartDC.title.text = 'elektrische Energie DC in ' + aktYear //x-Achse beschriften yearChartKWh.xAxis[0].data = Array.from({length: 12}, (tmp,i) => G_shrtMonths[i]) //yearChartKWh.xAxis[0].data = Array.from({length: 12}, (tmp,i) => i+1) //Diagrammm als JSON im Objektbaum ablegen setState(jsonChartKWh,JSON.stringify(yearChartKWh),true) setState(jsonChartAutPrc,JSON.stringify(yearChartAutPrc),true) setState(jsonChartKosten,JSON.stringify(yearChartKosten),true) setState(jsonChartYearDC,JSON.stringify(yearChartDC),true) } //############################ chartEnergieMonth : Tagesenergien ############################ function refreshMonth() { let aktMonthYear = getAktMonthYear() let tarif = checkTarifStrom(new Date(`${aktMonthYear.year}-('0'+ ${('0' + aktMonthYear.month).slice(-2)}-15`)) //Diagramm Energien in KWh im RAM allokieren let jsonChartKWh = '0_userdata.0.Fronius.flexCharts.chartEnergieMonth' let monthChartKWh = JSON.parse(getState(jsonChartKWh).val) //Diagramm Autarkie&Effizienz in % im RAM allokieren let jsonChartAutPrc = '0_userdata.0.Fronius.flexCharts.chartEffizienzMonth' let monthChartAutPrc = JSON.parse(getState(jsonChartAutPrc).val) //Diagramm Kosten in € im RAM allokieren let jsonChartKosten = '0_userdata.0.Fronius.flexCharts.chartKostenMonth' let monthChartKosten = JSON.parse(getState(jsonChartKosten).val) //Diagramm Energie DC im RAM allokieren let jsonChartMonthDC = '0_userdata.0.Fronius.flexCharts.chartMonthDC' let monthChartDC = JSON.parse(getState(jsonChartMonthDC).val) //Tabelle fromGridKWh in KWh im RAM allokieren let fromGridKWh = JSON.parse(getState(`0_userdata.0.Fronius.Monatstabellen.${aktMonthYear.year}.${G_getMonthLongName(aktMonthYear.month)}.fromGridWh`).val) fromGridKWh = fromGridKWh.map(item => item / 1000) //Tabelle toGridKWh in KWh im RAM allokieren let toGridKWh = JSON.parse(getState(`0_userdata.0.Fronius.Monatstabellen.${aktMonthYear.year}.${G_getMonthLongName(aktMonthYear.month)}.toGridWh`).val) toGridKWh = toGridKWh.map(item => G_runden(item/1000,3)) let fromSolarKWh = JSON.parse(getState(`0_userdata.0.Fronius.Monatstabellen.${aktMonthYear.year}.${G_getMonthLongName(aktMonthYear.month)}.solarWh`).val) fromSolarKWh = fromSolarKWh.map(item => item / 1000) //erzeugte Solarenergie AC //Tabelle eigenVerbrauch let eigenVerbrauchKWh = fromSolarKWh.map((item, i) => G_runden(item - toGridKWh[i],3)) //Eigenverbrauch AC let gesamtVerbrauchKWh = eigenVerbrauchKWh.map((item, i) => G_runden(item + fromGridKWh[i],3)) //Gesamtverbrauch AC //Tabelle dcGartenhausKWh und dcTerrasseKWh in KWh im RAM allokieren let dcGartenhausKWh = JSON.parse(getState(`0_userdata.0.Fronius.Monatstabellen.${aktMonthYear.year}.${G_getMonthLongName(aktMonthYear.month)}.dcGartenhausKWh`).val) dcGartenhausKWh ||= [] dcGartenhausKWh = dcGartenhausKWh.map(item => G_runden(item / 1000,3)) let dcTerrasseKWh = JSON.parse(getState(`0_userdata.0.Fronius.Monatstabellen.${aktMonthYear.year}.${G_getMonthLongName(aktMonthYear.month)}.dcTerrasseKWh`).val) dcTerrasseKWh ||= [] dcTerrasseKWh = dcTerrasseKWh.map(item => G_runden(item / 1000,3)) //Energiesummen // - fromGrid let fromGridKWhSum = fromGridKWh.reduce((sum, item) => sum + item, 0) let fromGridEuroSum = fromGridKWhSum * tarif.Energiepreis // - toGrid let toGridKWhSum = toGridKWh.reduce((sum, item) => sum + item, 0) let toGridEuroSum = toGridKWhSum * tarif.Verkaufspreis // - Eigenverbrauch let eigenverbrauchKWhSum = fromSolarKWh.reduce((sum, item) => sum + item) - toGridKWhSum let eigenverbrauchEuroSum = eigenverbrauchKWhSum * tarif.Energiepreis //Gesamtverbrauch bzw. Konsum let konsumKWhSum = fromGridKWhSum + eigenverbrauchKWhSum let konsumEuroSum = konsumKWhSum * tarif.Energiepreis //Energien DC //Summen in Objekte Speichern // - fromGrid setStateAsync('0_userdata.0.Fronius.flexCharts.sumMonatFromGridKWh',fromGridKWhSum,true) setStateAsync('0_userdata.0.Fronius.flexCharts.sumMonatFromGridEuro',fromGridEuroSum,true) // - toGrid setStateAsync('0_userdata.0.Fronius.flexCharts.sumMonatToGridKWh',toGridKWhSum,true) setStateAsync('0_userdata.0.Fronius.flexCharts.sumMonatToGridEuro',toGridEuroSum,true) // - Eigenverbrauch setStateAsync('0_userdata.0.Fronius.flexCharts.sumMonatEigenverbrauchKWh',eigenverbrauchKWhSum,true) setStateAsync('0_userdata.0.Fronius.flexCharts.sumMonatEigenverbrauchEuro',eigenverbrauchEuroSum,true) // - Konsum setStateAsync('0_userdata.0.Fronius.flexCharts.sumMonatKonsumKWh',konsumKWhSum,true) setStateAsync('0_userdata.0.Fronius.flexCharts.sumMonatKonsumEuro',konsumEuroSum,true) //Titelzeilen //Energien AC monthChartKWh.title.text = 'elektrische Energien im ' monthChartKWh.title.text = (aktMonthYear.month == 3) ? monthChartKWh.title.text.concat('März') : monthChartKWh.title.text.concat(G_getMonthLongName(aktMonthYear.month)) monthChartKWh.title.text = monthChartKWh.title.text.concat(' (' + aktMonthYear.year + ')') //Kosten monthChartKosten.title.text = 'Stromkosten im ' monthChartKosten.title.text = (aktMonthYear.month == 3) ? monthChartKosten.title.text.concat('März') : monthChartKosten.title.text.concat(G_getMonthLongName(aktMonthYear.month)) monthChartKosten.title.text = monthChartKosten.title.text.concat(' (' + aktMonthYear.year + ')') //Quoten monthChartAutPrc.title.text = 'Autarkie&Eigenquote im ' monthChartAutPrc.title.text = (aktMonthYear.month == 3) ? monthChartAutPrc.title.text.concat('März') : monthChartAutPrc.title.text.concat(G_getMonthLongName(aktMonthYear.month)) monthChartAutPrc.title.text = monthChartAutPrc.title.text.concat(' (' + aktMonthYear.year + ')') //Energien DC monthChartDC.title.text = 'elektrische Energien DC im ' if (aktMonthYear.month == 3) { monthChartDC.title.text = monthChartDC.title.text + 'März' } else { monthChartDC.title.text = monthChartDC.title.text + G_getMonthLongName(aktMonthYear.month) } monthChartDC.title.text = monthChartDC.title.text +' (' + aktMonthYear.year + ')' //x-Achse beschriften //x-Achse monthChartKWh.xAxis[0].data = Array.from({length: G_getDaysOfMonth(aktMonthYear.year, aktMonthYear.month)}, (tmp,i) => i+1) monthChartKosten.xAxis[0].data = Array.from({length: G_getDaysOfMonth(aktMonthYear.year, aktMonthYear.month)}, (tmp,i) => i+1) monthChartAutPrc.xAxis[0].data = Array.from({length: G_getDaysOfMonth(aktMonthYear.year, aktMonthYear.month)}, (tmp,i) => i+1) monthChartDC.xAxis[0].data = Array.from({length: G_getDaysOfMonth(aktMonthYear.year, aktMonthYear.month)}, (tmp,i) => i+1) //y-Achsenwerte eintragen .. //Netzbezug, Einspeisung, Eigenverbrauch monthChartKWh.series[0].data = fromGridKWh monthChartKWh.series[1].data = toGridKWh monthChartKWh.series[2].data = eigenVerbrauchKWh //Kosten: Netzbezug, Einspeisung, Eigenverbrauch monthChartKosten.series[0].data = fromGridKWh.map((item,i) => item * tarif.Energiepreis) monthChartKosten.series[1].data = toGridKWh.map((item,i) => item * tarif.Verkaufspreis) monthChartKosten.series[2].data = eigenVerbrauchKWh.map((item,i) => item * tarif.Energiepreis) //Autarkie&Eigenverbrauch monthChartAutPrc.series[0].data = eigenVerbrauchKWh.map((item, i) => G_runden(100*item / gesamtVerbrauchKWh[i],1)) //Autarkie monthChartAutPrc.series[1].data = eigenVerbrauchKWh.map((item,i) => G_runden(100*item / fromSolarKWh[i],1)) //Eigenquote //Energien DC monthChartDC.series[0].data = dcGartenhausKWh monthChartDC.series[1].data = dcTerrasseKWh //Diagrammme als JSON im Objektbaum ablegen setState(jsonChartKWh,JSON.stringify(monthChartKWh),true) setState(jsonChartKosten,JSON.stringify(monthChartKosten),true) setState(jsonChartAutPrc,JSON.stringify(monthChartAutPrc),true) setState(jsonChartMonthDC,JSON.stringify(monthChartDC),true) } //############################ Scheduler & Trigger ############################ //alle 4 Minuten die Anzeige aktualisieren schedule('*/4 * * * *', () => { refreshMonth(); refreshYear() setState('0_userdata.0.Fronius.flexCharts.rfhButton',0,false) }); on({id:'0_userdata.0.Fronius.flexCharts.selMonth',change: 'any'},(obj) => { refreshMonth() setState('0_userdata.0.Fronius.flexCharts.rfhButton',0,false) }) on({id:'0_userdata.0.Fronius.flexCharts.selYear',change: 'any'},(obj) => { //G_setListYears('0_userdata.0.Fronius.Monatstabellen', '0_userdata.0.Fronius.Charts.lstYears') setStateAsync('0_userdata.0.Fronius.flexCharts.rfhButton',0,false) G_setListMonths(getState('0_userdata.0.Fronius.flexCharts.selYear').val, '0_userdata.0.Fronius.Monatstabellen', '0_userdata.0.Fronius.flexCharts.lstMonths') refreshYear(); refreshMonth() setState('0_userdata.0.Fronius.flexCharts.rfhButton', 0, false) }) on({id:'0_userdata.0.Fronius.flexCharts.buttonAktualisieren',change: 'any'},(obj) => { refreshMonth(); refreshYear() setState('0_userdata.0.Fronius.flexCharts.rfhButton',0,false) }) //############################ Skriptstart ############################ //listMonths des zugehörigen DropDown-Widgets füllen G_setListYears('0_userdata.0.Fronius.Monatstabellen', '0_userdata.0.Fronius.flexCharts.lstYear') //listYears des zugehörigen DropDown-Widgets füllen G_setListMonths(getState('0_userdata.0.Fronius.flexCharts.selYear').val, '0_userdata.0.Fronius.Monatstabellen', '0_userdata.0.Fronius.flexCharts.lstMonths') -
-
Hey! Du scheinst an dieser Unterhaltung interessiert zu sein, hast aber noch kein Konto.
Hast du es satt, bei jedem Besuch durch die gleichen Beiträge zu scrollen? Wenn du dich für ein Konto anmeldest, kommst du immer genau dorthin zurück, wo du zuvor warst, und kannst dich über neue Antworten benachrichtigen lassen (entweder per E-Mail oder Push-Benachrichtigung). Du kannst auch Lesezeichen speichern und Beiträge positiv bewerten, um anderen Community-Mitgliedern deine Wertschätzung zu zeigen.
Mit deinem Input könnte dieser Beitrag noch besser werden 💗
Registrieren Anmelden



