Files
epaper-dashboard/README.md
T
Patrik 5e98b71b82 DOCS-SYNC: README + RECOVERY + NETATMO.md aktualisiert, CHANGELOG neu
README.md:
- Architektur-Diagramm: clock_wordclock + netatmo ergaenzt
- Neue Sektion 'Shared Foundation' (palette.py + plugins/base.py)
- Neue Sektion 'DeepSleep / Energie' (Weckzeiten, CPU-Throttle, /power Route)
- Plugin-Tabelle korrigiert: alle Config-Felder auf aktuellen Stand
  (system: show_uptime/show_load/compact, strava: client_id/secret/refresh_token,
   spotify: Last.fm statt Spotify API, gmail: oauth_token_json,
   minimax: subscription_key, netatmo: client_id/secret/refresh_token)
- Eigenes-Plugin-Sektion: Hinweis auf shared helper-Nutzung
- Quick-Start config.json mit power-Block-Beispiel

RECOVERY.md:
- Neue Sektion 'Display-Refresh aus Admin-UI erzwingen' (POST /api/wake)
- Neue Sektion 'DeepSleep-Fehlkonfiguration' (manueller Fix via SSH/Recovery-AP)

plugins/NETATMO.md:
- Sektion 3: Slot-Tabelle aktualisiert (compact / compact_2x2 / full_4x4)
- Neues V1-Status-Update ASCII-Layout mit allen Sektionen
- Design-Regeln explizit aufgelistet
- Sektion 4 Optionen auf aktuellen Stand (refresh_token statt username/password,
   show_forecast statt show_secondary/show_compass, bar_gradient weg)
- Sektion 6 Technische Details: Forecast-Quelle Open-Meteo, neue interne
  Methoden (_render_compact_2x2, _render_full_4x4, _get_12h_history,
  _get_forecast), shared helper explizit aufgelistet

CHANGELOG.md (neu):
- Keep-a-Changelog-Format mit [Unreleased] fuer aktuelle Aenderungen
- FEAT-DEEPSLEEP + FEAT-NETATMO-06 + REFACTOR-PLUGINS dokumentiert
- 'Earlier' Sektion mit letztem Git-Log der NETATMO-Iterationen
2026-08-31 01:03:26 +02:00

225 lines
8.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# epaper-dashboard
Plugin-based dashboard for the **Waveshare 7.3" ACeP 7-Color e-Paper (F) HAT** on Raspberry Pi 4.
Rendert regelmäßig (Standard 180s, oder konfigurierbar; im DeepSleep-Modus nur zu
Weckzeiten) ein 800×480px Vollbild auf dem Display.
## Hardware
- **Display:** Waveshare 7.3inch ACeP 7-Color e-Paper (F) HAT — 800×480, 7 Farben
- **Pi:** Raspberry Pi 4 (oder Zero 2 W mit Einschränkungen)
- **Interface:** SPI
## Architektur
```
┌──────────────────────────────────────────────┐
│ epaper-dashboard │
├──────────────────┬───────────────────────────┤
│ dashboard.py │ admin.py │
│ (Renderer + │ (Web Admin UI :8080) │
│ DeepSleep) │ │
├──────────────────┴───────────────────────────┤
│ layout.py · 4×4 Grid · Pack-Algorithmus │
├───────────────────────────────────────────────┤
│ plugins/ (eines pro Widget) │
│ clock · clock_wordclock · weather · system │
│ spotify · strava · gmail · minimax · │
│ netatmo · hello │
├───────────────────────────────────────────────┤
│ shared: palette.py · plugins/base.py │
│ (Farben, Formatter, Render-Helper) │
├───────────────────────────────────────────────┤
│ network_watchdog.py │
│ (WiFi AP/Client Management) │
├───────────────────────────────────────────────┤
│ waveshare_epd/ (Vendor-Treiber) │
│ epd7in3f.py │
└───────────────────────────────────────────────┘
```
### Shared Foundation (Single Source of Truth)
- **`palette.py`** — 7-Farben ACeP-Palette (`BLACK, WHITE, RED, GREEN, BLUE, YELLOW, ORANGE`),
semantische Aliase (`FG, BG, OK, WARN, ALERT, INFO, ACCENT`), deutsche Datums-Formatter
(`de_weekday_long`, `de_weekday_short`, `de_date`, `de_weekday_date`, `de_time`),
`temp_color()` / `co2_color()` / `batt_color()`, Wetter-Icon-Mapping (`wmo_to_icon`).
- **`plugins/base.py`** — `Widget`-Basisklasse, Render-Helper
(`draw_battery`, `draw_compass`, `draw_trend`, `draw_line_chart`, `draw_mini_bar`,
`draw_weather_icon`, `draw_zzz_indicator`, `draw_deepsleep_indicator`),
Layout-Utilities (`is_small`, `is_wide`, `is_tall`).
Alle Plugins nutzen diese Helper — keine duplizierte Render-Logik.
## Quick Start
### Pi vorbereiten
```bash
sudo apt update && sudo apt install -y python3-pil python3-numpy python3-flask git
sudo raspi-config # → Interface Options → SPI → Enable
sudo reboot
```
### Setup
```bash
# Repository klonen
git clone https://git.pkop.de/Vibecode/epaper-dashboard.git
cd epaper-dashboard
# Config erstellen
cp config.example.json config.json
# → config.json editieren (Plugins + Layout)
# waveshare_epd Treiber
git clone https://github.com/waveshareteam/Waveshare_GPIO.git waveshare_epd_lib
# oder: den waveshare_epd Ordner vom vorherigen Setup übernehmen
# Services installieren
chmod +x install_services.sh
./install_services.sh
```
### Config
`config.json` — Version 2 Format (empfohlen):
```json
{
"version": 2,
"refresh_interval_s": 180,
"power": {
"deepsleep_enabled": false,
"wake_times": ["07:00", "12:00", "18:00"],
"cpu_throttle": false
},
"layout": {
"grid": { "cols": 4, "rows": 4 },
"items": [
{ "id": "c1", "plugin": "clock", "x": 0, "y": 0, "w": 2, "h": 2 },
{ "id": "w1", "plugin": "weather", "x": 2, "y": 0, "w": 2, "h": 2 },
{ "id": "st1", "plugin": "system", "x": 0, "y": 2, "w": 2, "h": 2 },
{ "id": "h1", "plugin": "hello", "x": 2, "y": 2, "w": 2, "h": 2 }
]
},
"plugin_configs": {
"hello": { "text": "Edit me!", "size": 40 }
}
}
```
**Grid:** 4 Spalten × 4 Zeilen = 16 Zellen à 200×120px. `x,y` = Spalte/Zeile oben-links, `w,h` = Breite/Höhe in Zellen.
### Web Admin
```
http://pi:8080/
```
- **Layout-Editor** — Items per Klick hinzufügen, verschieben, Größe ändern, Auto-Pack
- **Plugin-Config** — API-Keys, Locations, etc. pro Widget
- **Energie-Tab** — DeepSleep-Modus, Weckzeiten, CPU-Throttle, manuelles Display-Aufwecken
- **Refresh Now** — sofortiger Display-Refresh
- **Netzwerk** — WLAN wechseln ohne SSH
Default Login: `admin` / `admin` — in `.env` mit `EPAPER_ADMIN_PASSWORD` setzen.
## Plugins
| Plugin | Datenquelle | Config-Felder |
|---|---|---|
| `clock` | Systemzeit | `format_24h`, `show_seconds`, `show_date`, `show_weekday`, `accent_color` |
| `clock_wordclock` | Systemzeit | `show_date`, `show_weekday`, `show_es_ist`, `invert`, `accent_color` (QlockTwo-Style Wort-Uhr) |
| `weather` | Open-Meteo (kein API-Key) | `location` (lat,lon), `show_uv`, `show_forecast_hours`, `show_wind_compass` |
| `system` | Pi CPU/RAM/Uptime | `show_uptime`, `show_load`, `compact`, `bar_thresholds`, `bar_gradient` |
| `spotify` | Last.fm Scrobble | `api_key`, `username` |
| `strava` | Strava API | `client_id`, `client_secret`, `refresh_token` |
| `gmail` | Gmail API | `oauth_token_json` |
| `minimax` | MiniMax Token Plan | `subscription_key`, `show_credits`, `api_base`, `bar_thresholds`, `bar_gradient` |
| `netatmo` | Netatmo Weather API (OAuth2) | siehe [plugins/NETATMO.md](plugins/NETATMO.md) |
| `hello` | statisch | `text`, `color` |
## DeepSleep / Energie
Das Dashboard unterstützt einen **DeepSleep-Modus** für stromsparenden 24/7-Betrieb:
- **Weckzeiten** (z.B. `["07:00", "12:00", "18:00"]`) — Display wacht zu diesen Zeiten auf,
rendert neu, schläft wieder.
- **CPU-Throttle** (Pi auf 600MHz im Sleep) — spart ~1.5W am Raspberry Pi.
- **Manuelles Wecken** — Button im Admin-UI unter `/power` triggert sofortigen Refresh.
- **ZZZ-Indikator** — `draw_zzz_indicator` aus `plugins/base.py` zeigt im Sleep-Zustand
dezent "zZz" oben links.
- **60s-Sleep-Chunks** — Main-Loop schläft in 1-Minuten-Häppchen statt eines langen
Intervalls, damit das Weck-Signal schnell greift.
Konfiguration in der Admin-UI (`/power`) oder direkt in `config.json` unter `power.*`.
Defaults werden beim ersten Start aus `POWER_DEFAULTS` in `palette.py` auto-gefüllt.
## Eigenes Plugin schreiben
```python
# plugins/my_widget.py
from plugins.base import Widget
from palette import FG, BG, de_weekday_date
class Widget(Widget):
name = "my_widget"
label = "Mein Widget"
description = "Zeigt etwas"
category = "info"
config_schema = [
{"key": "api_key", "label": "API Key", "type": "secret"},
{"key": "interval", "label": "Intervall (s)", "type": "int", "default": 60},
]
default_config = {"api_key": "", "interval": 60}
def fetch(self):
return {"value": 42}
def render(self, draw, fonts, x, y, w, h):
d = self.fetch()
# w, h sind Pixel (nicht Zellen!)
# Nutze die shared helper aus palette + base
draw.text((x + 10, y + 10), f"Value: {d['value']}",
font=fonts["28"], fill=FG)
```
**Palette:** `BLACK, WHITE, RED, GREEN, BLUE, YELLOW, ORANGE` + semantisch `FG, BG, OK, WARN, ALERT, INFO, ACCENT`
**Tipp:** Vermeide eigene `draw_compass`/`draw_weather_icon`/etc. — nutze die Helper
aus `plugins/base.py`. Sonst dupliziert sich die Render-Logik und das Design driftet
auseinander (siehe Commit-History FEAT-NETATMO-06).
## Services
```bash
systemctl --user enable --now epaper-dashboard
systemctl --user enable --now epaper-admin
journalctl --user -u epaper-dashboard -f # Logs
```
**Wichtig:** `PrivateTmp=no` in den Service-Files — sonst sieht der Admin-Socket `/tmp/epaper-dashboard.sock` nicht.
## Display-Einschränkungen
- **Nur Full-Refresh:** ACeP-Displays vertragen keine schnellen Partial-Refreshes. Minimum 180s.
- **Refresh-Dauer:** Ein Full-Refresh dauert ~35-65s. Währenddessen ist das Display leer/flackernd.
- **Ghosting:** Leichtes Ghosting bei manchen Farben normal. Display nicht bei direktem Sonnenlicht ablesen.
## Recovery
Falls das konfigurierte WLAN nicht erreichbar ist: der Pi startet automatisch einen **Recovery AP**.
- **SSID:** `epaper-recovery`
- **Passwort:** `recovery1234`
- **URL:** http://10.42.0.1:8080/
Dort kannst du ein neues WLAN konfigurieren. Details in `RECOVERY.md`.
## Lizenz
Apache 2.0