Patrik b3b0ca0ce5 REFACTOR-PLUGINS: shared helpers + deutsche Strings durchgaengig
weather.py:
- Custom _draw_compass (~50 Zeilen) entfernt, nutzt jetzt draw_compass
  aus plugins/base.py (mit color=RED statt fonts-Argument-Bug)
- Custom temp_color-Logik (ORANGE/BLU/FG) ersetzt durch temp_color() aus palette
- Stunden-Vorhersage zeigt jetzt Wetter-Icon pro Zelle via draw_weather_icon
- Auch im compact-mode: Wetter-Icon oben rechts
- Strings: 'Hum' -> 'Feuchte', 'Dir' -> 'Richtung', 'Aktuelles Wetter' -> 'Vorhersage'

strava.py:
- Doppeltes label='Strava Aktivitäten' am Dateiende entfernt (mojibake-Copy-Paste)
- description: 'Rides' -> 'Fahrten', 'Setze ... unten' sauberer
- Strings: 'rides' -> 'Fahrten' (3x), 'hike' -> 'Wandern' (2x),
  'YTD' -> 'Jahr', 'in {year}' -> 'im Jahr {year}', 'Total' -> 'Gesamt'

system.py:
- _fmt_uptime: 'd/h/m' -> 'T/h/min' (deutsche Tages-Notation)
- Strings: 'up ' -> 'laeuft ' (in wide + standard), 'load ' -> 'Last '

minimax.py:
- _fmt_timedelta_short: 'now' -> 'jetzt', 'Xd Yh' -> 'XT Yh', 'Ym' -> 'Ymin'
  (deutsche Kurz-Laufzeit, konsistent mit system.py)

clock_wordclock.py:
- Locale-abhaengige strftime('%A') / strftime('%e. %b %Y') durch
  de_weekday_long() / de_date() aus palette ersetzt
- Vorher: auf nicht-de_DE-Systemen wurde 'Wednesday' statt 'Mittwoch' angezeigt

Verifikation: alle 9 Plugins importieren sauber, weather rendert mit
shared helpers (docs/test_weather.png).
2026-08-31 01:03:15 +02:00

epaper-dashboard

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.

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)   │
├──────────────────┴──────────────────────────┤
│  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                                │
└─────────────────────────────────────────────┘

Quick Start

Pi vorbereiten

sudo apt update && sudo apt install -y python3-pil python3-numpy python3-flask git
sudo raspi-config  # → Interface Options → SPI → Enable
sudo reboot

Setup

# 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):

{
  "version": 2,
  "refresh_interval_s": 180,
  "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
  • 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 —
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)
hello statisch text, color, size

Eigenes Plugin schreiben

# plugins/my_widget.py
from plugins.base import Widget
from palette import FG, BG

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!)
        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

Services

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.

Dort kannst du ein neues WLAN konfigurieren. Details in RECOVERY.md.

Lizenz

Apache 2.0

S
Description
Plugin-based ePaper dashboard for 7.3" ACeP 7-Color display on Raspberry Pi 4
Readme
887 KiB
Languages
Python 71.6%
HTML 24.6%
JavaScript 3.8%