admin 46c8057155 E-Auto-Lade-Erkennung im 31d-Diagramm
Markiert im 31d-Diagramm die Tage rot, an denen das E-Auto geladen wurde:
Leistung (Feld 'leistung', W) lag laenger als LADEN_MIN_HOURS (Default 2h)
ununterbrochen ueber LADEN_THRESHOLD_KW (Default 11 kW).

- Erkennung serverseitig per Flux stateDuration auf den Sekundendaten
  (24h Vorlauf fuer ueber Mitternacht laufende Ladungen an der Monatsgrenze)
- /api/laden?month=YYYY-MM, Ergebnis gecacht (abgeschlossene Monate dauerhaft,
  laufender Monat 5 min) -> ~15s nur beim ersten Aufruf
- Markierung wird asynchron nachgeladen, Balken erscheinen sofort
- Schwelle/Dauer per Env (LADEN_THRESHOLD_KW, LADEN_MIN_HOURS) einstellbar
- BarChart: optionales highlight-Set faerbt passende Balken

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 14:49:44 +02:00
2026-06-28 14:49:44 +02:00
2026-06-28 14:49:44 +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

E-Auto-Lade-Erkennung (31d)

Im 31d-Diagramm werden Tage rot markiert, an denen das E-Auto geladen wurde: Die Leistung (Feld leistung, W) lag länger als LADEN_MIN_HOURS (Default 2 h) ununterbrochen über LADEN_THRESHOLD_KW (Default 11 kW) — dem Anschlusswert des Autos. Erkennung serverseitig per Flux stateDuration auf den Sekundendaten (/api/laden?month=YYYY-MM); läuft ~15 s je Monat und wird daher gecacht (abgeschlossene Monate dauerhaft). Die Markierung wird asynchron nachgeladen, sodass die Balken sofort erscheinen. Schwelle/Dauer sind per Env einstellbar.

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%