Hi, falls jemand Interesse hat hier mal zwei Diagramme zum Nachbauen für flexcharts
Jahr:
// ============================================================================
// Tibber Jahresübersicht + eCharts VIS-Widget
// ----------------------------------------------------------------------------
// - Erstellt 12 Datenpunkte für Kosten, Verbrauch, Preis
// - Liest tibber Monthly JSON aus
// - Ergänzt/überschreibt aktuellen Monat aus 0_userdata-Datenpunkten
// - Erstellt eCharts-Konfiguration für VIS
// - Tooltip mit 2 Nachkommastellen
// ============================================================================
// =================== KONFIG ===================
const jsonMonthlyDP = 'tibberlink.0.Homes.xxxxxxxxxxxxx.Consumption.jsonMonthly';
const rootDP = '0_userdata.0.Tibber.Jahreswerte';
const visDP = `${rootDP}.eCharts_Monatsbalken`;
// Userdata aktuelle Monatswerte
const dpPriceThisMonth = '0_userdata.0.Tibber.AvgUnitPriceThisMonth';
const dpConsThisMonth = '0_userdata.0.Tibber.SumConsumptionThisMonth';
const dpCostThisMonth = '0_userdata.0.Tibber.SumUnitCostThisMonth';
// =================== 12 Monats-Datenpunkte erzeugen ===================
function createMonthDPs() {
for (let m = 1; m <= 12; m++) {
createState(`${rootDP}.Cost.M${m}`, 0, { name: `Kosten Monat ${m}`, type: 'number', unit: '€', role: 'value' });
createState(`${rootDP}.Cons.M${m}`, 0, { name: `Verbrauch Monat ${m}`, type: 'number', unit: 'kWh', role: 'value' });
createState(`${rootDP}.Price.M${m}`,0, { name: `Durchschnittspreis M${m}`, type: 'number', unit: '€/kWh', role: 'value' });
}
createState(visDP, '', { name: 'eCharts Config Monatsbalken', type: 'string', role: 'text' });
}
createMonthDPs();
// =================== Hauptfunktion ===================
function updateYearValues() {
try {
const raw = getState(jsonMonthlyDP).val;
if (!raw) return log("Keine Monatsdaten vorhanden", "warn");
const data = JSON.parse(raw);
const currentYear = new Date().getFullYear();
const currentMonth = new Date().getMonth() + 1;
let arrCost = Array(12).fill(0);
let arrCons = Array(12).fill(0);
let arrPrice = Array(12).fill(0);
// ========== JSON durchlaufen ==========
data.forEach(entry => {
if (!entry.from) return;
const d = new Date(entry.from);
const year = d.getFullYear();
const month = d.getMonth() + 1;
if (year !== currentYear) return;
const cost = parseFloat(entry.totalCost) || 0;
const cons = parseFloat(entry.consumption) || 0;
const price = parseFloat(entry.unitPrice) || 0;
arrCost[month - 1] = parseFloat(cost.toFixed(2));
arrCons[month - 1] = parseFloat(cons.toFixed(2));
arrPrice[month - 1] = parseFloat(price.toFixed(2));
setState(`${rootDP}.Cost.M${month}`, cost, true);
setState(`${rootDP}.Cons.M${month}`, cons, true);
setState(`${rootDP}.Price.M${month}`, price, true);
});
// =============================================================
// **AKTUELLEN MONAT MIT USERDATA ÜBERSCHREIBEN**
// =============================================================
const uPrice = parseFloat(getState(dpPriceThisMonth).val) || 0;
const uCons = parseFloat(getState(dpConsThisMonth).val) || 0;
const uCost = parseFloat(getState(dpCostThisMonth).val) || 0;
arrCost[currentMonth - 1] = parseFloat(uCost.toFixed(2));
arrCons[currentMonth - 1] = parseFloat(uCons.toFixed(2));
arrPrice[currentMonth - 1] = parseFloat(uPrice.toFixed(2));
setState(`${rootDP}.Cost.M${currentMonth}`, uCost, true);
setState(`${rootDP}.Cons.M${currentMonth}`, uCons, true);
setState(`${rootDP}.Price.M${currentMonth}`, uPrice, true);
// =====================================================================
// eCharts VIS-Konfiguration
// =====================================================================
const option = {
textStyle: { color: '#FFFFFF' },
tooltip: {
trigger: 'axis',
textStyle: { color: '#525252' },
formatter: function(params) {
return params.map(p => {
let unit = '€/kWh';
if (p.seriesName.includes('€')) unit = '€';
else if (p.seriesName.includes('kWh')) unit = 'kWh';
return `${p.seriesName}: ${p.value.toFixed(2)} ${unit}`;
}).join('<br/>');
}
},
legend: {
textStyle: { color: '#FFFFFF' }
},
xAxis: {
type: 'category',
data: ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],
axisLabel: { color: '#FFFFFF' }
},
yAxis: [
{
type: 'value',
name: 'Kosten / Verbrauch',
axisLabel: { color: '#FFFFFF' },
nameTextStyle: { color: '#FFFFFF' },
splitLine: { show: true, lineStyle: { color: '#525252' } },
axisLine: { lineStyle: { color: '#ccc' } }
},
{
type: 'value',
name: 'Preis',
position: 'right',
axisLabel: { color: '#FFFFFF' },
nameTextStyle: { color: '#FFFFFF' },
splitLine: { show: true, lineStyle: { color: '#525252' } },
axisLine: { lineStyle: { color: '#ccc' } }
}
],
series: [
{ name: 'Kosten (€)', type: 'bar', data: arrCost },
{ name: 'Verbrauch (kWh)', type: 'bar', data: arrCons },
{ name: 'Preis (€/kWh)', type: 'line', yAxisIndex: 1, data: arrPrice }
]
};
setState(visDP, JSON.stringify(option), true);
log("Jahreswerte + aktueller Monat + eCharts VIS aktualisiert", "info");
} catch (e) {
log("Fehler JSON: " + e, "error");
}
}
// =================== TRIGGER ===================
updateYearValues();
on({ id: jsonMonthlyDP, change: 'any' }, () => updateYearValues());
on({ id: [dpPriceThisMonth, dpConsThisMonth, dpCostThisMonth], change: 'ne' }, () => updateYearValues());
Monat:
// ============================================================================
// Tibber Daily Übersicht für VIS eCharts
// ----------------------------------------------------------------------------
// - ALLE Daten aus Tibbers jsonDaily
// - Linke Achse: Kosten (€) + Verbrauch (kWh)
// - Rechte Achse: Preis (€/kWh)
// - Schriftfarbe X/Y weiß, Y-Hilfslinien #525252
// - Rechte Y-Achse Maximalwert auf 3 Nachkommastellen
// - Preislinie nicht geglättet
// ============================================================================
const jsonDailyDP = 'tibberlink.0.Homes.xxxxxxxxxxx.Consumption.jsonDaily';
const dpBase = '0_userdata.0.Tibber.Daily.';
const dpDates = dpBase + 'Dates';
const dpCost = dpBase + 'Cost';
const dpUsage = dpBase + 'Usage';
const dpUnitPrice = dpBase + 'UnitPrice';
const dpEchart = dpBase + 'EchartConfig';
// =================== Hilfsfunktion ===================
function ensureDP(id) {
if (!existsState(id)) createState(id, '', { type: 'string', read: true, write: true });
}
[dpDates, dpCost, dpUsage, dpUnitPrice, dpEchart].forEach(ensureDP);
// =================== Datum formatieren TT.MM. ===================
function formatDateTTMM(fromStr) {
const d = new Date(fromStr);
if (isNaN(d)) return '';
const day = ('0' + d.getDate()).slice(-2);
const month = ('0' + (d.getMonth() + 1)).slice(-2);
return `${day}.${month}`;
}
// =================== Hauptfunktion ===================
async function buildTibberDailyChart() {
const raw = await getStateAsync(jsonDailyDP);
if (!raw || !raw.val) {
log('⚠ jsonDaily leer oder nicht verfügbar', 'warn');
return;
}
let daily;
try {
daily = JSON.parse(raw.val);
if (!Array.isArray(daily)) {
log('❌ JSON ist kein Array', 'error');
return;
}
} catch (e) {
log('❌ Fehler beim Parsen von jsonDaily: ' + e, 'error');
return;
}
const dates = [];
const cost = [];
const usage = [];
const price = [];
daily.forEach(entry => {
dates.push(formatDateTTMM(entry.from));
cost.push(Number(entry.totalCost || 0).toFixed(2));
usage.push(Number(entry.consumption || 0).toFixed(2));
price.push(Number(entry.unitPrice || 0).toFixed(3));
});
// Datenpunkte aktualisieren
setState(dpDates, JSON.stringify(dates), true);
setState(dpCost, JSON.stringify(cost), true);
setState(dpUsage, JSON.stringify(usage), true);
setState(dpUnitPrice, JSON.stringify(price), true);
// Rechte Y-Achse Maximalwert für Preis berechnen (3 Nachkommastellen)
let maxPrice = Math.max(...price.map(p => Number(p))) * 1.1; // 10% Puffer
maxPrice = Number(maxPrice.toFixed(3));
// Linke Achse: Maximalwert für Kosten und Verbrauch
const maxLeft = Math.max(
...cost.map(c => Number(c)),
...usage.map(u => Number(u))
) * 1.1;
const echartConfig = {
textStyle: { color: '#FFFFFF' },
tooltip: {
trigger: 'axis',
textStyle: { color: '#525252' },
formatter: function(params) {
const day = params[0].axisValue;
const kosten = params.find(p => p.seriesName === 'Kosten (€)')?.value || 0;
const verbrauch = params.find(p => p.seriesName === 'Verbrauch (kWh)')?.value || 0;
const preis = params.find(p => p.seriesName === 'Preis (€/kWh)')?.value || 0;
return `${day} → Kosten: ${Number(kosten).toFixed(2)} € | Verbrauch: ${Number(verbrauch).toFixed(2)} kWh | Preis: ${Number(preis).toFixed(3)} €/kWh`;
}
},
legend: { textStyle: { color: '#FFFFFF' }, data: ['Kosten (€)', 'Verbrauch (kWh)', 'Preis (€/kWh)'] },
xAxis: { type: 'category', data: dates, axisLabel: { color: '#FFFFFF' } },
yAxis: [
{
type: 'value',
name: 'Kosten / Verbrauch',
min: 0,
max: maxLeft,
axisLabel: { color: '#FFFFFF' },
nameTextStyle: { color: '#FFFFFF', align: 'center' }, // linksbündig
splitLine: { show: true, lineStyle: { color: '#525252' } }
},
{
type: 'value',
name: 'Preis',
position: 'right',
min: 0,
max: maxPrice,
axisLabel: {
color: '#FFFFFF',
formatter: function(value) { return Number(value).toFixed(3) + ' €/kWh'; }
},
nameTextStyle: { color: '#FFFFFF' },
splitLine: { show: true, lineStyle: { color: '#525252' } }
}
],
series: [
{ name: 'Kosten (€)', type: 'bar', data: cost, yAxisIndex: 0 },
{ name: 'Verbrauch (kWh)', type: 'bar', data: usage, yAxisIndex: 0 },
{ name: 'Preis (€/kWh)', type: 'line', data: price, yAxisIndex: 1 } // nicht geglättet
]
};
setState(dpEchart, JSON.stringify(echartConfig), true);
log('✔ Tibber Daily für VIS aktualisiert – ' + daily.length + ' Einträge');
}
// =================== Trigger ===================
on({ id: jsonDailyDP, change: 'any' }, () => buildTibberDailyChart());
buildTibberDailyChart();
[image: 1764762204365-98722c8f-52b3-4fd1-9b07-5c78fd6ea9c3-image.png]
[image: 1764762241930-3600ee57-f496-4ba8-a5cc-36fb941763eb-image.png]