# 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 ```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, "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` | | `hello` | statisch | `text`, `color`, `size` | ## Eigenes Plugin schreiben ```python # 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 ```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