# 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`: ```flux 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: ```flux 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 ```bash 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: ```bash 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 (lokal) ```bash npm run dev # http://localhost:3000 npm run build # Produktionsbuild npm start ``` ## Docker / Deployment auf nuccy Die App läuft als Container auf **nuccy** im externen Docker-Netzwerk **`smarthome`** und erreicht die InfluxDB dort unter dem Host **`influxdb`** (`http://influxdb:8086`). ### Image bauen & in die Registry pushen (vom Entwicklungsrechner) ```bash ./deploy.sh # Tag latest ./deploy.sh v1.2.0 # eigener Tag ``` Baut für `linux/amd64` und pusht nach `docker.citysensor.de/strom-next:`. ### Auf nuccy starten `docker-compose.prod.yml` neben eine `.env` legen (aus `.env.production.example`) und das **InfluxDB-Read-Token** dort eintragen: ```bash # .env INFLUX_TOKEN=... # optional: STROM_PORT=3000 ``` Dann: ```bash docker compose -f docker-compose.prod.yml pull docker compose -f docker-compose.prod.yml up -d ``` Die App ist anschließend auf nuccy unter Port `3000` (bzw. `STROM_PORT`) erreichbar. Alle InfluxDB-/Lade-Einstellungen sind in `docker-compose.prod.yml` gesetzt; nur das Token kommt aus der `.env`.