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
This commit is contained in:
Patrik
2026-08-31 01:03:26 +02:00
parent b3b0ca0ce5
commit 5e98b71b82
4 changed files with 252 additions and 48 deletions
+78 -31
View File
@@ -2,7 +2,8 @@
Plugin-based dashboard for the **Waveshare 7.3" ACeP 7-Color e-Paper (F) HAT** on Raspberry Pi 4.
Rendert alle 180s (oder konfigurierbar) ein 800×480px Vollbild auf dem Display.
Rendert regelmäßig (Standard 180s, oder konfigurierbar; im DeepSleep-Modus nur zu
Weckzeiten) ein 800×480px Vollbild auf dem Display.
## Hardware
@@ -13,26 +14,44 @@ Rendert alle 180s (oder konfigurierbar) ein 800×480px Vollbild auf dem Display.
## Architektur
```
┌─────────────────────────────────────────────┐
│ epaper-dashboard │
├──────────────────┬──────────────────────────┤
│ dashboard.py │ admin.py │
│ (Renderer) │ (Web Admin UI :8080) │
├──────────────────┴──────────────────────────┤
│ layout.py · 4×4 Grid · Pack-Algorithmus │
├────────────────────────────────────────────┤
│ plugins/ (eines pro Widget) │
│ clock · weather · system · spotify │
│ strava · gmail · minimax · hello │
├────────────────────────────────────────────┤
│ network_watchdog.py │
│ (WiFi AP/Client Management) │
├────────────────────────────────────────────┤
│ waveshare_epd/ (Vendor-Treiber) │
│ epd7in3f.py │
└─────────────────────────────────────────────┘
┌──────────────────────────────────────────────┐
│ 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
@@ -54,7 +73,7 @@ cd epaper-dashboard
cp config.example.json config.json
# → config.json editieren (Plugins + Layout)
#waveshare_epd Treiber
# waveshare_epd Treiber
git clone https://github.com/waveshareteam/Waveshare_GPIO.git waveshare_epd_lib
# oder: den waveshare_epd Ordner vom vorherigen Setup übernehmen
@@ -71,6 +90,11 @@ chmod +x install_services.sh
{
"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": [
@@ -96,6 +120,7 @@ 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
@@ -104,23 +129,40 @@ Default Login: `admin` / `admin` — in `.env` mit `EPAPER_ADMIN_PASSWORD` setze
## Plugins
| Plugin | Datenquelle | Config-Felder |
|--------|-------------|---------------|
| `clock` | Systemzeit | — |
| `weather` | Open-Meteo (kein API-Key) | `location` (lat,lon), `show_uv`, `show_forecast_hours` |
| `system` | Pi CPU/RAM/Uptime | `show_uptime`, `show_load`, `show_temp` |
| `spotify` | Spotify Web API | `client_id`, `client_secret` (via Spotify Dev Portal) |
| `strava` | Strava API | `access_token`, `club_id` |
| `gmail` | Gmail API | `credentials_json` (OAuth2) |
| `minimax` | MiniMax AI | `api_key`, `model`, `prompt` |
| `netatmo` | Netatmo Weather API (OAuth2) | `client_id`, `client_secret`, `username`, `password` (Details: [NETATMO.md](plugins/NETATMO.md)) |
| `hello` | statisch | `text`, `color`, `size` |
|---|---|---|
| `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
from palette import FG, BG, de_weekday_date
class Widget(Widget):
name = "my_widget"
@@ -140,12 +182,17 @@ class Widget(Widget):
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