admin 3649bf4e22 Initiale Version: Stromverbrauch-Web-App (strom-next)
Next.js-App zur Visualisierung des Stromverbrauchs aus InfluxDB
(Bucket strom, measurement vzlogger, Feld arbeit = kumulativer
Zaehlerstand in Wh).

- 4 Balken-Diagramme: 24h (stuendlich), Woche (stuendlich),
  31 Tage (taeglich), Jahr (pro Monat, immer 12 Monate)
- Verbrauch via difference des Zaehlerstands, zeitzonen-korrekt
- 24h liest Rohdaten (aktuell), 7d/31d/365d den stuendlichen
  Downsampling-Rollup (arbeit_hourly) -> sub-sekunde
- Gesamtverbrauch je Zeitraum unter dem Chart
- Design/Layout angelehnt an Werte-Log "Verlauf"

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 14:05:27 +02:00

Stromverbrauch (strom-next)

Next.js-App zur Visualisierung des Stromverbrauchs aus einer InfluxDB. Design/Layout angelehnt an das Projekt Werte-Log (Ansicht „Verlauf").

Datenquelle

  • InfluxDB Bucket strom, Measurement vzlogger, Feld arbeit (Zählerstand in Wh)
  • Der Wert ist ein kumulativer Zählerstand; der Verbrauch je Intervall ergibt sich aus der Differenz aufeinanderfolgender Zählerstände (difference in Flux).
  • Die Rohdaten haben 1-Sekunden-Auflösung. Für die langen Zeiträume wäre die Live-Aggregation zu langsam (Jahr ≈ 70 s), daher gibt es einen Downsampling-Task.

Downsampling-Task (InfluxDB)

Ein InfluxDB-Task arbeit_hourly_rollup (stündlich, in der InfluxDB unter Tasks zu finden) schreibt fortlaufend den letzten Zählerstand je Stunde als Measurement arbeit_hourly (Feld arbeit) zurück in den Bucket strom:

option task = {name: "arbeit_hourly_rollup", every: 1h, offset: 2m}

from(bucket: "strom")
  |> range(start: -3h)
  |> filter(fn: (r) => r._measurement == "vzlogger" and r._field == "arbeit")
  |> aggregateWindow(every: 1h, fn: last, createEmpty: false)
  |> set(key: "_measurement", value: "arbeit_hourly")
  |> to(bucket: "strom")
  • 24h-Chart liest die Rohdaten (vzlogger) → immer top-aktuell.
  • 7d/31d/365d lesen den Rollup (arbeit_hourly) → sub-sekunden-schnell.
  • Tages-/Stundenwerte: erst difference (stündlicher Verbrauch), dann aggregateWindow(sum) pro Tag/Stunde (zeitzonen-korrekt via Europe/Berlin). Liefert exakt dieselben Werte wie die Rohdaten-Aggregation.

Backfill (einmalig, schon ausgeführt)

Die Historie ab 2022-10-09 wurde einmalig in arbeit_hourly geschrieben. Falls erneut nötig (z. B. nach Datenlücke), jahresweise:

from(bucket:"strom")
  |> range(start: 2025-01-01T00:00:00Z, stop: 2026-01-01T00:00:00Z)
  |> filter(fn:(r)=>r._measurement=="vzlogger" and r._field=="arbeit")
  |> aggregateWindow(every:1h, fn:last, createEmpty:false)
  |> set(key:"_measurement", value:"arbeit_hourly")
  |> to(bucket:"strom")

Diagramme (alle als Balken-Diagramme)

Zeitraum Balken Auswahl
Letzte 24 Stunden 1 / Stunde Tag (leer = letzte 24h ab jetzt)
Letzte 7 Tage 1 / Stunde Tag
Letzte 31 Tage 1 / Tag Monat
Letzte 365 Tage 1 / Tag Jahr

X-Achse: Datum/Zeit · Y-Achse: kWh

Setup

npm install
cp .env.local.example .env.local
# .env.local mit echtem INFLUX_TOKEN (und ggf. Feldname/Einheit) befüllen

.env.local

INFLUX_URL=http://nuccy:8086
INFLUX_TOKEN=...
INFLUX_ORG=citysensor
INFLUX_BUCKET=strom
INFLUX_MEASUREMENT=vzlogger
INFLUX_FIELD=arbeit
INFLUX_UNIT_FACTOR=0.001   # Zählerstand liegt in Wh vor

Den Feldnamen und die Einheit ggf. einmalig prüfen:

curl -s -XPOST "http://nuccy:8086/api/v2/query?org=citysensor" \
  -H "Authorization: Token $INFLUX_TOKEN" \
  -H "Accept: application/csv" \
  -H "Content-type: application/vnd.flux" \
  -d 'import "influxdata/influxdb/schema"
schema.fieldKeys(bucket: "strom", predicate: (r) => r._measurement == "arbeit")'

Starten

npm run dev      # http://localhost:3000
npm run build    # Produktionsbuild
npm start
S
Description
Grafik für den Stromverbrauch hier zu Hause
Readme 147 KiB
Languages
TypeScript 89.7%
Shell 4.1%
Dockerfile 3.6%
CSS 1.3%
JavaScript 1.3%