Weather Station / ECOWITT / DNT
0

Configure Feed

Select the types of activity you want to include in your feed.

at master 262 lines 9.6 kB View raw View rendered
1# Ecowitt Weather Dashboard 2 3Dashboard fuer Ecowitt- und DNT-WLAN-Wetterstationen mit Live-Daten, lokaler CSV-Historie, Statistiken und Forecast-Vergleich. Die Anwendung laeuft als Next.js-App mit Node.js-Routen, liest Wetterstationsdateien aus `DNT/`, materialisiert sie als Parquet und fragt Live- sowie Forecast-Daten serverseitig ab. 4 5## Funktionsumfang 6 7- **Echtzeit**: aktuelle Ecowitt-API-v3-Daten ueber einen serverseitigen Proxy und Cache. 8- **Grafik**: Gauges fuer Temperatur, Luftfeuchte, Wind, Luftdruck, Regen, Solarstrahlung, UV und CH1-CH8. 9- **Prognose**: Forecasts aus Geosphere Austria, Open-Meteo DWD ICON, optional Meteoblue und OpenWeatherMap. 10- **Analyse**: Forecast-Genauigkeit gegen lokal gemessene Wetterdaten mit MAE/RMSE. 11- **Gespeicherte Daten**: interaktive Chart.js-Zeitreihen fuer Main- und Allsensors-CSV-Daten. 12- **Statistik**: Jahres-, Monats-, Bereichs- und Kanalstatistiken aus DuckDB/Parquet. 13- **Internationalisierung**: Deutsch und Englisch via `i18next`. 14 15## Screenshots 16 17| Grafik | Grafik 2 | 18| --- | --- | 19| ![Grafik](Grafik.png) | ![Grafik 2](Grafik2.png) | 20 21| Echtzeit | Archiv | 22| --- | --- | 23| ![Echtzeit](Echtzeit.png) | ![Archiv](Archiv.png) | 24 25## Technik 26 27- Next.js `16.2.4` mit App Router 28- React `19.2` 29- TypeScript `6` 30- Tailwind CSS `4` 31- DuckDB via `@duckdb/node-api` 32- Chart.js mit `chartjs-plugin-zoom` 33- `suncalc` fuer Sonnen-/Mondzeiten 34 35Alle API-Routen, die lokale Dateien oder DuckDB nutzen, laufen im Node.js-Runtime. Das Projekt ist daher fuer einen Server/VPS oder Docker mit persistenten Volumes gedacht, nicht fuer eine serverlose Umgebung ohne persistentes Dateisystem. 36 37## Schnellstart 38 39```bash 40npm install 41 42cp env.example .env 43cp eco.example.ts eco.ts 44 45mkdir -p DNT data 46cp 202501A.CSV 202501Allsensors_A.CSV DNT/ 47 48npm run dev 49``` 50 51Danach die App unter `http://localhost:3000` oeffnen. 52 53Wichtig: `npm run dev` startet zuerst `npm run prewarm`. Wenn `DNT/` fehlt, kann das Vorwaermen der CSV-Daten nicht laufen. Fuer einen ersten Test koennen die beiden Beispiel-CSV-Dateien aus dem Repository nach `DNT/` kopiert werden. 54 55## Konfiguration 56 57### Ecowitt-Zugangsdaten 58 59`eco.example.ts` nach `eco.ts` kopieren und ausfuellen: 60 61```ts 62applicationKey: "YOUR_APPLICATION_KEY_HERE", 63apiKey: "YOUR_API_KEY_HERE", 64mac: "AA:BB:CC:DD:EE:FF", 65server: "api.ecowitt.net" 66``` 67 68`eco.ts` wird nur serverseitig importiert und ist in `.gitignore` ausgeschlossen. 69 70### Umgebungsvariablen 71 72`env.example` nach `.env` kopieren. Relevante Variablen: 73 74| Variable | Bedeutung | 75| --- | --- | 76| `RT_REFRESH_MS` | Intervall des serverseitigen Live-Pollers in Millisekunden, Default `300000`. | 77| `NEXT_PUBLIC_RT_REFRESH_MS` | Clientseitiges Refresh-Intervall im Realtime-Tab. | 78| `FORECAST_STATION_ID` | Geosphere-Station fuer Forecast-Speicherung und Analyse, Default `11035`. `ALL` verarbeitet alle Stationen. | 79| `OPENWEATHER_API_KEY` | Optional, aktiviert OpenWeatherMap-Forecasts. | 80| `METEOBLUE_API_KEY` | Optional, aktiviert Meteoblue-Forecast und Meteogramm. | 81| `ADMIN_API_TOKEN` | Token fuer administrative API-Routen. | 82| `WEATHER_ADMIN_TOKEN` | Fallback-Name fuer denselben Admin-Token. | 83 84Admin-Routen akzeptieren entweder `Authorization: Bearer <token>` oder `x-admin-token: <token>`. 85 86### Kanalnamen 87 88Die Anzeigenamen fuer CH1-CH8 stehen in `src/config/channels.json`: 89 90```json 91{ 92 "ch1": { "name": "Vorratskammer" }, 93 "ch2": { "name": "Kueche" } 94} 95``` 96 97Nicht konfigurierte Kanaele fallen auf ihre ID zurueck. 98 99## Datenablage 100 101Die Anwendung erwartet lokale CSV-Dateien im Ordner `DNT/`. 102 103Typische Dateinamen: 104 105- Main-Daten: `YYYYMMA.CSV`, zum Beispiel `202501A.CSV` 106- Kanal-Daten: `YYYYMMAllsensors_A.CSV`, zum Beispiel `202501Allsensors_A.CSV` 107 108Beobachtete CSV-Eigenschaften: 109 110- Komma als Trennzeichen 111- `--` als Platzhalter fuer fehlende Werte 112- Zeitspalten wie `Zeit`, `Time`, `DateUTC` oder `DateTimeUTC` 113- Zeitformate wie `YYYY/M/D H:MM`, ISO-nahe Varianten und `DD.MM.YYYY HH:MM` 114- deutsche oder englische Sensornamen mit Einheiten in Klammern 115 116Generierte Laufzeitdaten: 117 118- `data/weather.duckdb` 119- `data/parquet/main/YYYYMM.parquet` 120- `data/parquet/allsensors/YYYYMM.parquet` 121- `data/statistics.json` 122- `DNT/rt-last.json` 123- `temp-minmax-data.json` 124 125Diese Datenpfade sind in `.gitignore` ausgeschlossen. 126 127## Hintergrundjobs 128 129`src/instrumentation.ts` registriert beim Serverstart mehrere Jobs: 130 131- Live-Poller: fragt Ecowitt API v3 ab, schreibt `DNT/rt-last.json` und archiviert Messwerte in monatliche Main-/Allsensors-CSV-Dateien. 132- Statistik-Warmup: berechnet Statistik-Caches beim Start und danach taeglich neu. 133- Forecast-Poller: speichert Forecasts fuer `FORECAST_STATION_ID` taeglich im Zeitfenster 20:00-20:30 und fuehrt beim Start/Catchup nach Bedarf einen Lauf aus. 134- Forecast-Analyse: vergleicht gespeicherte Forecasts mit lokalen Main-Daten und schreibt Ergebnisse in DuckDB. 135 136## Scripts 137 138```bash 139npm run prewarm # CSVs aus DNT/ als Parquet materialisieren 140npm run dev # prewarm + Next.js Dev-Server 141npm run build # Produktionsbuild mit Webpack 142npm run start # prewarm + Next.js Production Server 143``` 144 145`prewarm` prueft pro Monat die CSV- und Parquet-Mtime und baut nur fehlende oder veraltete Parquet-Dateien neu. 146 147## API-Ueberblick 148 149### Live und Geraet 150 151- `GET /api/config/channels` - CH1-CH8 Anzeigenamen aus `src/config/channels.json` 152- `GET /api/rt/last` - letzter gecachter Live-Datensatz 153- `GET /api/rt` - direkter Ecowitt-Proxy fuer eine kleine Auswahl 154- `GET /api/rt?all=1` - direkter Ecowitt-Proxy fuer den vollen Payload 155- `GET /api/device/info` - Zeitzone, Latitude und Longitude der Station 156- `GET /api/temp-minmax` - lokale Temperatur-Min/Max-Daten 157 158### Historische Daten 159 160- `GET /api/data/months` - erkannte Monate aus `DNT/` 161- `GET /api/data/extent` - globaler Zeitbereich 162- `GET /api/data/main?month=YYYYMM&resolution=minute|hour|day` 163- `GET /api/data/main?start=YYYY-MM-DDTHH:MM&end=YYYY-MM-DDTHH:MM&resolution=minute|hour|day` 164- `GET /api/data/allsensors?month=YYYYMM&resolution=minute|hour|day` 165- `GET /api/data/allsensors?start=YYYY-MM-DDTHH:MM&end=YYYY-MM-DDTHH:MM&resolution=minute|hour|day` 166 167Beispiel: 168 169```bash 170curl 'http://localhost:3000/api/data/main?month=202501&resolution=day' 171curl 'http://localhost:3000/api/data/allsensors?start=2025-01-01T00:00&end=2025-01-31T23:59&resolution=hour' 172``` 173 174### Statistik 175 176- `GET /api/statistics` 177- `GET /api/statistics?year=2025` 178- `GET /api/statistics/daily?year=2025` 179- `GET /api/statistics/range?month=YYYYMM` 180- `GET /api/statistics/range?start=YYYY-MM-DDTHH:MM&end=YYYY-MM-DDTHH:MM` 181- `GET /api/statistics/channels?ch=ch1&month=YYYYMM` 182- `GET /api/statistics/channels?ch=ch1&start=YYYY-MM-DDTHH:MM&end=YYYY-MM-DDTHH:MM` 183 184Admin: 185 186- `POST /api/statistics/update` 187- `POST /api/temp-minmax/update` 188 189### Forecast und Analyse 190 191- `GET /api/forecast?action=stations` 192- `GET /api/forecast?action=forecast&stationId=11035` - Geosphere Austria 193- `GET /api/forecast?action=openmeteo&stationId=11035` - Open-Meteo DWD ICON 194- `GET /api/forecast?action=openweather&stationId=11035` - OpenWeatherMap, braucht API-Key 195- `GET /api/forecast?action=meteoblue&stationId=11035` - Meteoblue, braucht API-Key 196- `GET /api/forecast?action=meteogram&stationId=11035` - Meteoblue-WebP-Meteogramm 197- `GET /api/forecast/analysis?stationId=11035&days=30` 198- `GET /api/forecast/compare?stationId=11035&days=30` - Legacy-On-Demand-Vergleich 199- `GET /api/config/forecast-station` 200 201Admin: 202 203- `POST /api/forecast/store` 204- `POST /api/forecast/analyze` 205- `POST /api/forecast/backfill` 206- `GET /api/dforecast` 207- `GET /api/debug/db` 208 209Admin-Beispiel: 210 211```bash 212curl -X POST 'http://localhost:3000/api/forecast/store' \ 213 -H 'Authorization: Bearer <ADMIN_API_TOKEN>' \ 214 -H 'Content-Type: application/json' \ 215 -d '{"stationId":"11035"}' 216``` 217 218## Projektstruktur 219 220```text 221src/app/ Next.js Seiten, Layout und API-Routen 222src/components/ React-Komponenten fuer Tabs, Charts, Gauges und Statistik 223src/contexts/ Realtime-Context fuer Clientdaten 224src/lib/ CSV-, Zeit-, Statistik-, Astro-, Realtime- und DB-Logik 225src/lib/db/ DuckDB-Verbindung und CSV->Parquet-Ingestion 226src/config/channels.json CH1-CH8 Anzeigenamen 227src/locales/ i18next-Uebersetzungen 228src/scripts/prewarm.ts Parquet-Vorwaermung 229``` 230 231## Docker 232 233```bash 234cp env.example .env 235cp eco.example.ts eco.ts 236mkdir -p DNT data 237 238docker compose up --build -d 239``` 240 241`docker-compose.yml` bindet folgende Pfade ein: 242 243- `./DNT:/app/DNT` 244- `./data:/app/data` 245- `./src/config:/app/src/config` 246- `./eco.ts:/app/eco.ts` 247 248Die App lauscht im Compose-Setup auf `127.0.0.1:3010`. 249 250## Fehlersuche 251 252- **`DNT/` fehlt**: Ordner anlegen und CSVs hineinkopieren; `prewarm` liest direkt aus diesem Pfad. 253- **Keine Monate gefunden**: Dateinamen muessen mit `YYYYMM` beginnen und auf `.CSV` enden. 254- **Leere Charts**: CSV-Header, Zeitformat und fehlende Werte (`--`) pruefen. 255- **Forecast-Quelle fehlt**: Open-Meteo und Geosphere funktionieren ohne eigenen Key; Meteoblue und OpenWeatherMap brauchen `.env`-Keys. 256- **Admin-Route liefert 503**: `ADMIN_API_TOKEN` oder `WEATHER_ADMIN_TOKEN` ist nicht gesetzt. 257- **DuckDB/native binding Fehler**: `@duckdb/node-api` muss installiert sein; fuer Builds werden die DuckDB-Pakete in `next.config.ts` serverseitig externalisiert. 258- **Serverless Deployment verliert Daten**: `DNT/`, `data/` und `eco.ts` muessen persistent gemountet werden. 259 260## Sicherheit 261 262`.env*`, `eco.ts`, `DNT/`, `data/`, DuckDB-Dateien und generierte Temperaturdaten werden nicht versioniert. Echte API-Keys und Stationsdaten sollten nicht committet werden.