From 55596a2bacdafed11b356dcfb89da21061576c21 Mon Sep 17 00:00:00 2001 From: Claude Bot Date: Thu, 16 Jul 2026 22:35:21 +0200 Subject: [PATCH] fix(pv-system-roi): clean timeseries legend labels The union-based timeseries series were named via set(_field, ...), which Grafana's InfluxDB frontend rendered as "_value {_start=...}" instead of the intended labels (and broke the byName color overrides). Data was correct; only the legend/colors were affected. Switch to the keep(columns:[_time,_value]) |> rename(_value -> "Name") pattern (as used in heatpump-roi), which names each series cleanly. Verified in Grafana Explore. No data/logic change. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01QiLCinB7NLp7YdCjGYzvfh --- .../monitoring/dashboards/pv-system-roi.json | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/kubernetes/apps/monitoring/dashboards/pv-system-roi.json b/kubernetes/apps/monitoring/dashboards/pv-system-roi.json index 2638eb71..f9a693ac 100644 --- a/kubernetes/apps/monitoring/dashboards/pv-system-roi.json +++ b/kubernetes/apps/monitoring/dashboards/pv-system-roi.json @@ -225,9 +225,9 @@ "id": 20, "options": {"legend": {"calcs": ["mean", "max", "lastNotNull"], "displayMode": "table", "placement": "right", "showLegend": true}, "tooltip": {"mode": "multi", "sort": "desc"}}, "targets": [ - {"datasource": {"type": "influxdb", "uid": "influxdb"}, "query": "union(tables: [\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"W\" and r._field == \"value\" and r.entity_id == \"e3_vitocharge_03_solar_power\") |> map(fn: (r) => ({_time: r._time, _value: r._value})),\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"W\" and r._field == \"value\" and r.entity_id == \"vitocharge_vx3_vx3_pv_power\") |> map(fn: (r) => ({_time: r._time, _value: r._value}))])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false) |> set(key: \"_field\", value: \"Solar Power\")", "refId": "A"}, - {"datasource": {"type": "influxdb", "uid": "influxdb"}, "query": "union(tables: [\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"W\" and r._field == \"value\" and r.entity_id == \"e3_vitocharge_03_battery_power_in_absolute\") |> map(fn: (r) => ({_time: r._time, _value: r._value})),\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"W\" and r._field == \"value\" and r.entity_id == \"vitocharge_vx3_vx3_battery_power\") |> map(fn: (r) => ({_time: r._time, _value: if r._value < 0.0 then -r._value else 0.0}))])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false) |> set(key: \"_field\", value: \"Battery Charge\")", "refId": "B"}, - {"datasource": {"type": "influxdb", "uid": "influxdb"}, "query": "union(tables: [\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"W\" and r._field == \"value\" and r.entity_id == \"e3_vitocharge_03_battery_power_out_absolute\") |> map(fn: (r) => ({_time: r._time, _value: r._value})),\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"W\" and r._field == \"value\" and r.entity_id == \"vitocharge_vx3_vx3_battery_power\") |> map(fn: (r) => ({_time: r._time, _value: if r._value > 0.0 then r._value else 0.0}))])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false) |> set(key: \"_field\", value: \"Battery Discharge\")", "refId": "C"} + {"datasource": {"type": "influxdb", "uid": "influxdb"}, "query": "union(tables: [\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"W\" and r._field == \"value\" and r.entity_id == \"e3_vitocharge_03_solar_power\") |> map(fn: (r) => ({_time: r._time, _value: r._value})),\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"W\" and r._field == \"value\" and r.entity_id == \"vitocharge_vx3_vx3_pv_power\") |> map(fn: (r) => ({_time: r._time, _value: r._value}))])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false) |> keep(columns: [\"_time\", \"_value\"]) |> rename(columns: {_value: \"Solar Power\"})", "refId": "A"}, + {"datasource": {"type": "influxdb", "uid": "influxdb"}, "query": "union(tables: [\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"W\" and r._field == \"value\" and r.entity_id == \"e3_vitocharge_03_battery_power_in_absolute\") |> map(fn: (r) => ({_time: r._time, _value: r._value})),\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"W\" and r._field == \"value\" and r.entity_id == \"vitocharge_vx3_vx3_battery_power\") |> map(fn: (r) => ({_time: r._time, _value: if r._value < 0.0 then -r._value else 0.0}))])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false) |> keep(columns: [\"_time\", \"_value\"]) |> rename(columns: {_value: \"Battery Charge\"})", "refId": "B"}, + {"datasource": {"type": "influxdb", "uid": "influxdb"}, "query": "union(tables: [\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"W\" and r._field == \"value\" and r.entity_id == \"e3_vitocharge_03_battery_power_out_absolute\") |> map(fn: (r) => ({_time: r._time, _value: r._value})),\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"W\" and r._field == \"value\" and r.entity_id == \"vitocharge_vx3_vx3_battery_power\") |> map(fn: (r) => ({_time: r._time, _value: if r._value > 0.0 then r._value else 0.0}))])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false) |> keep(columns: [\"_time\", \"_value\"]) |> rename(columns: {_value: \"Battery Discharge\"})", "refId": "C"} ], "title": "Solar & Battery Power", "type": "timeseries" @@ -250,7 +250,7 @@ "id": 21, "options": {"legend": {"calcs": ["mean", "min", "max"], "displayMode": "table", "placement": "right", "showLegend": true}, "tooltip": {"mode": "multi", "sort": "desc"}}, "targets": [ - {"datasource": {"type": "influxdb", "uid": "influxdb"}, "query": "union(tables: [\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"W\" and r._field == \"value\" and r.entity_id == \"e3_vitocharge_03_power_exchange_with_grid\") |> map(fn: (r) => ({_time: r._time, _value: r._value})),\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"W\" and r._field == \"value\" and r.entity_id == \"vitocharge_vx3_vx3_grid_power\") |> map(fn: (r) => ({_time: r._time, _value: r._value}))])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false) |> set(key: \"_field\", value: \"Grid Exchange\")", "refId": "A"} + {"datasource": {"type": "influxdb", "uid": "influxdb"}, "query": "union(tables: [\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"W\" and r._field == \"value\" and r.entity_id == \"e3_vitocharge_03_power_exchange_with_grid\") |> map(fn: (r) => ({_time: r._time, _value: r._value})),\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"W\" and r._field == \"value\" and r.entity_id == \"vitocharge_vx3_vx3_grid_power\") |> map(fn: (r) => ({_time: r._time, _value: r._value}))])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false) |> keep(columns: [\"_time\", \"_value\"]) |> rename(columns: {_value: \"Grid Exchange\"})", "refId": "A"} ], "title": "Grid Exchange (+ Import / - Export)", "type": "timeseries" @@ -271,7 +271,7 @@ "id": 22, "options": {"legend": {"calcs": ["mean", "min", "max"], "displayMode": "table", "placement": "right", "showLegend": true}, "tooltip": {"mode": "multi", "sort": "desc"}}, "targets": [ - {"datasource": {"type": "influxdb", "uid": "influxdb"}, "query": "union(tables: [\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"%\" and r._field == \"value\" and r.entity_id == \"e3_vitocharge_03_battery\") |> map(fn: (r) => ({_time: r._time, _value: r._value})),\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"%\" and r._field == \"value\" and r.entity_id == \"vitocharge_vx3_vx3_battery_soc\") |> map(fn: (r) => ({_time: r._time, _value: r._value}))])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false) |> set(key: \"_field\", value: \"Battery Level\")", "refId": "A"} + {"datasource": {"type": "influxdb", "uid": "influxdb"}, "query": "union(tables: [\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"%\" and r._field == \"value\" and r.entity_id == \"e3_vitocharge_03_battery\") |> map(fn: (r) => ({_time: r._time, _value: r._value})),\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"%\" and r._field == \"value\" and r.entity_id == \"vitocharge_vx3_vx3_battery_soc\") |> map(fn: (r) => ({_time: r._time, _value: r._value}))])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false) |> keep(columns: [\"_time\", \"_value\"]) |> rename(columns: {_value: \"Battery Level\"})", "refId": "A"} ], "title": "Battery State of Charge", "type": "timeseries" @@ -304,9 +304,9 @@ "id": 23, "options": {"legend": {"calcs": ["min", "max", "lastNotNull"], "displayMode": "table", "placement": "right", "showLegend": true}, "tooltip": {"mode": "multi", "sort": "desc"}}, "targets": [ - {"datasource": {"type": "influxdb", "uid": "influxdb"}, "query": "union(tables: [\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"kWh\" and r._field == \"value\" and r.entity_id == \"e3_vitocharge_03_solar_energy_production_total\") |> map(fn: (r) => ({_time: r._time, _value: r._value})),\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"Wh\" and r._field == \"value\" and r.entity_id == \"vitocharge_vx3_vx3_pv_production_total\") |> map(fn: (r) => ({_time: r._time, _value: r._value / 1000.0}))])\n |> aggregateWindow(every: v.windowPeriod, fn: last, createEmpty: false) |> set(key: \"_field\", value: \"Solar Production\")", "refId": "A"}, - {"datasource": {"type": "influxdb", "uid": "influxdb"}, "query": "union(tables: [\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"Wh\" and r._field == \"value\" and r.entity_id == \"e3_vitocharge_03_energy_export_to_grid\") |> map(fn: (r) => ({_time: r._time, _value: r._value / 1000.0})),\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"kWh\" and r._field == \"value\" and r.entity_id == \"vitocharge_vx3_vx3_grid_feed_in_energy\") |> map(fn: (r) => ({_time: r._time, _value: r._value}))])\n |> aggregateWindow(every: v.windowPeriod, fn: last, createEmpty: false) |> set(key: \"_field\", value: \"Grid Export\")", "refId": "B"}, - {"datasource": {"type": "influxdb", "uid": "influxdb"}, "query": "union(tables: [\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"Wh\" and r._field == \"value\" and r.entity_id == \"e3_vitocharge_03_energy_import_from_grid\") |> map(fn: (r) => ({_time: r._time, _value: r._value / 1000.0})),\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"kWh\" and r._field == \"value\" and r.entity_id == \"vitocharge_vx3_vx3_grid_supplied_energy\") |> map(fn: (r) => ({_time: r._time, _value: r._value}))])\n |> aggregateWindow(every: v.windowPeriod, fn: last, createEmpty: false) |> set(key: \"_field\", value: \"Grid Import\")", "refId": "C"} + {"datasource": {"type": "influxdb", "uid": "influxdb"}, "query": "union(tables: [\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"kWh\" and r._field == \"value\" and r.entity_id == \"e3_vitocharge_03_solar_energy_production_total\") |> map(fn: (r) => ({_time: r._time, _value: r._value})),\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"Wh\" and r._field == \"value\" and r.entity_id == \"vitocharge_vx3_vx3_pv_production_total\") |> map(fn: (r) => ({_time: r._time, _value: r._value / 1000.0}))])\n |> aggregateWindow(every: v.windowPeriod, fn: last, createEmpty: false) |> keep(columns: [\"_time\", \"_value\"]) |> rename(columns: {_value: \"Solar Production\"})", "refId": "A"}, + {"datasource": {"type": "influxdb", "uid": "influxdb"}, "query": "union(tables: [\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"Wh\" and r._field == \"value\" and r.entity_id == \"e3_vitocharge_03_energy_export_to_grid\") |> map(fn: (r) => ({_time: r._time, _value: r._value / 1000.0})),\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"kWh\" and r._field == \"value\" and r.entity_id == \"vitocharge_vx3_vx3_grid_feed_in_energy\") |> map(fn: (r) => ({_time: r._time, _value: r._value}))])\n |> aggregateWindow(every: v.windowPeriod, fn: last, createEmpty: false) |> keep(columns: [\"_time\", \"_value\"]) |> rename(columns: {_value: \"Grid Export\"})", "refId": "B"}, + {"datasource": {"type": "influxdb", "uid": "influxdb"}, "query": "union(tables: [\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"Wh\" and r._field == \"value\" and r.entity_id == \"e3_vitocharge_03_energy_import_from_grid\") |> map(fn: (r) => ({_time: r._time, _value: r._value / 1000.0})),\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"kWh\" and r._field == \"value\" and r.entity_id == \"vitocharge_vx3_vx3_grid_supplied_energy\") |> map(fn: (r) => ({_time: r._time, _value: r._value}))])\n |> aggregateWindow(every: v.windowPeriod, fn: last, createEmpty: false) |> keep(columns: [\"_time\", \"_value\"]) |> rename(columns: {_value: \"Grid Import\"})", "refId": "C"} ], "title": "Cumulative Energy", "type": "timeseries" @@ -331,9 +331,9 @@ "id": 24, "options": {"legend": {"calcs": ["min", "max", "lastNotNull"], "displayMode": "table", "placement": "right", "showLegend": true}, "tooltip": {"mode": "multi", "sort": "desc"}}, "targets": [ - {"datasource": {"type": "influxdb", "uid": "influxdb"}, "query": "solar = union(tables: [\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"kWh\" and r._field == \"value\" and r.entity_id == \"e3_vitocharge_03_solar_energy_production_total\") |> map(fn: (r) => ({_time: r._time, _value: r._value})),\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"Wh\" and r._field == \"value\" and r.entity_id == \"vitocharge_vx3_vx3_pv_production_total\") |> map(fn: (r) => ({_time: r._time, _value: r._value / 1000.0}))])\n |> aggregateWindow(every: v.windowPeriod, fn: last, createEmpty: false) |> set(key: \"src\", value: \"solar\")\nexport_kwh = union(tables: [\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"Wh\" and r._field == \"value\" and r.entity_id == \"e3_vitocharge_03_energy_export_to_grid\") |> map(fn: (r) => ({_time: r._time, _value: r._value / 1000.0})),\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"kWh\" and r._field == \"value\" and r.entity_id == \"vitocharge_vx3_vx3_grid_feed_in_energy\") |> map(fn: (r) => ({_time: r._time, _value: r._value}))])\n |> aggregateWindow(every: v.windowPeriod, fn: last, createEmpty: false) |> set(key: \"src\", value: \"export\")\nprice = from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"EUR/kWh\" and r._field == \"value\" and r.entity_id == \"strompreis\") |> aggregateWindow(every: v.windowPeriod, fn: last, createEmpty: false) |> keep(columns: [\"_time\", \"_value\"]) |> set(key: \"src\", value: \"price\")\nunion(tables: [solar, export_kwh, price]) |> pivot(rowKey: [\"_time\"], columnKey: [\"src\"], valueColumn: \"_value\") |> filter(fn: (r) => exists r.solar and exists r.export and exists r.price) |> map(fn: (r) => ({_time: r._time, _value: (r.solar - r.export) * r.price, _field: \"Self-Use Savings\"}))", "refId": "A"}, - {"datasource": {"type": "influxdb", "uid": "influxdb"}, "query": "union(tables: [\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"Wh\" and r._field == \"value\" and r.entity_id == \"e3_vitocharge_03_energy_export_to_grid\") |> map(fn: (r) => ({_time: r._time, _value: r._value / 1000.0})),\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"kWh\" and r._field == \"value\" and r.entity_id == \"vitocharge_vx3_vx3_grid_feed_in_energy\") |> map(fn: (r) => ({_time: r._time, _value: r._value}))])\n |> aggregateWindow(every: v.windowPeriod, fn: last, createEmpty: false) |> map(fn: (r) => ({_time: r._time, _value: r._value * ${feed_in_tariff}, _field: \"Feed-in Revenue\"}))", "refId": "B"}, - {"datasource": {"type": "influxdb", "uid": "influxdb"}, "query": "solar = union(tables: [\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"kWh\" and r._field == \"value\" and r.entity_id == \"e3_vitocharge_03_solar_energy_production_total\") |> map(fn: (r) => ({_time: r._time, _value: r._value})),\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"Wh\" and r._field == \"value\" and r.entity_id == \"vitocharge_vx3_vx3_pv_production_total\") |> map(fn: (r) => ({_time: r._time, _value: r._value / 1000.0}))])\n |> aggregateWindow(every: v.windowPeriod, fn: last, createEmpty: false) |> set(key: \"src\", value: \"solar\")\nexport_kwh = union(tables: [\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"Wh\" and r._field == \"value\" and r.entity_id == \"e3_vitocharge_03_energy_export_to_grid\") |> map(fn: (r) => ({_time: r._time, _value: r._value / 1000.0})),\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"kWh\" and r._field == \"value\" and r.entity_id == \"vitocharge_vx3_vx3_grid_feed_in_energy\") |> map(fn: (r) => ({_time: r._time, _value: r._value}))])\n |> aggregateWindow(every: v.windowPeriod, fn: last, createEmpty: false) |> set(key: \"src\", value: \"export\")\nprice = from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"EUR/kWh\" and r._field == \"value\" and r.entity_id == \"strompreis\") |> aggregateWindow(every: v.windowPeriod, fn: last, createEmpty: false) |> keep(columns: [\"_time\", \"_value\"]) |> set(key: \"src\", value: \"price\")\nunion(tables: [solar, export_kwh, price]) |> pivot(rowKey: [\"_time\"], columnKey: [\"src\"], valueColumn: \"_value\") |> filter(fn: (r) => exists r.solar and exists r.export and exists r.price) |> map(fn: (r) => ({_time: r._time, _value: (r.solar - r.export) * r.price + r.export * ${feed_in_tariff}, _field: \"Total Value\"}))", "refId": "C"} + {"datasource": {"type": "influxdb", "uid": "influxdb"}, "query": "solar = union(tables: [\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"kWh\" and r._field == \"value\" and r.entity_id == \"e3_vitocharge_03_solar_energy_production_total\") |> map(fn: (r) => ({_time: r._time, _value: r._value})),\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"Wh\" and r._field == \"value\" and r.entity_id == \"vitocharge_vx3_vx3_pv_production_total\") |> map(fn: (r) => ({_time: r._time, _value: r._value / 1000.0}))])\n |> aggregateWindow(every: v.windowPeriod, fn: last, createEmpty: false) |> set(key: \"src\", value: \"solar\")\nexport_kwh = union(tables: [\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"Wh\" and r._field == \"value\" and r.entity_id == \"e3_vitocharge_03_energy_export_to_grid\") |> map(fn: (r) => ({_time: r._time, _value: r._value / 1000.0})),\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"kWh\" and r._field == \"value\" and r.entity_id == \"vitocharge_vx3_vx3_grid_feed_in_energy\") |> map(fn: (r) => ({_time: r._time, _value: r._value}))])\n |> aggregateWindow(every: v.windowPeriod, fn: last, createEmpty: false) |> set(key: \"src\", value: \"export\")\nprice = from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"EUR/kWh\" and r._field == \"value\" and r.entity_id == \"strompreis\") |> aggregateWindow(every: v.windowPeriod, fn: last, createEmpty: false) |> keep(columns: [\"_time\", \"_value\"]) |> set(key: \"src\", value: \"price\")\nunion(tables: [solar, export_kwh, price]) |> pivot(rowKey: [\"_time\"], columnKey: [\"src\"], valueColumn: \"_value\") |> filter(fn: (r) => exists r.solar and exists r.export and exists r.price) |> map(fn: (r) => ({_time: r._time, _value: (r.solar - r.export) * r.price})) |> rename(columns: {_value: \"Self-Use Savings\"})", "refId": "A"}, + {"datasource": {"type": "influxdb", "uid": "influxdb"}, "query": "union(tables: [\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"Wh\" and r._field == \"value\" and r.entity_id == \"e3_vitocharge_03_energy_export_to_grid\") |> map(fn: (r) => ({_time: r._time, _value: r._value / 1000.0})),\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"kWh\" and r._field == \"value\" and r.entity_id == \"vitocharge_vx3_vx3_grid_feed_in_energy\") |> map(fn: (r) => ({_time: r._time, _value: r._value}))])\n |> aggregateWindow(every: v.windowPeriod, fn: last, createEmpty: false) |> map(fn: (r) => ({_time: r._time, _value: r._value * ${feed_in_tariff}})) |> rename(columns: {_value: \"Feed-in Revenue\"})", "refId": "B"}, + {"datasource": {"type": "influxdb", "uid": "influxdb"}, "query": "solar = union(tables: [\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"kWh\" and r._field == \"value\" and r.entity_id == \"e3_vitocharge_03_solar_energy_production_total\") |> map(fn: (r) => ({_time: r._time, _value: r._value})),\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"Wh\" and r._field == \"value\" and r.entity_id == \"vitocharge_vx3_vx3_pv_production_total\") |> map(fn: (r) => ({_time: r._time, _value: r._value / 1000.0}))])\n |> aggregateWindow(every: v.windowPeriod, fn: last, createEmpty: false) |> set(key: \"src\", value: \"solar\")\nexport_kwh = union(tables: [\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"Wh\" and r._field == \"value\" and r.entity_id == \"e3_vitocharge_03_energy_export_to_grid\") |> map(fn: (r) => ({_time: r._time, _value: r._value / 1000.0})),\n from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"kWh\" and r._field == \"value\" and r.entity_id == \"vitocharge_vx3_vx3_grid_feed_in_energy\") |> map(fn: (r) => ({_time: r._time, _value: r._value}))])\n |> aggregateWindow(every: v.windowPeriod, fn: last, createEmpty: false) |> set(key: \"src\", value: \"export\")\nprice = from(bucket: \"suedstr28\") |> range(start: v.timeRangeStart, stop: v.timeRangeStop) |> filter(fn: (r) => r._measurement == \"EUR/kWh\" and r._field == \"value\" and r.entity_id == \"strompreis\") |> aggregateWindow(every: v.windowPeriod, fn: last, createEmpty: false) |> keep(columns: [\"_time\", \"_value\"]) |> set(key: \"src\", value: \"price\")\nunion(tables: [solar, export_kwh, price]) |> pivot(rowKey: [\"_time\"], columnKey: [\"src\"], valueColumn: \"_value\") |> filter(fn: (r) => exists r.solar and exists r.export and exists r.price) |> map(fn: (r) => ({_time: r._time, _value: (r.solar - r.export) * r.price + r.export * ${feed_in_tariff}})) |> rename(columns: {_value: \"Total Value\"})", "refId": "C"} ], "title": "Cumulative Value", "type": "timeseries" -- 2.54.0