Files
epaper-dashboard/README.md
T
ki 28124c5617 Initial commit: epaper-dashboard for 7.3" ACeP 7-Color display
- dashboard.py: plugin-based renderer with 4x4 grid layout
- admin.py: web UI with layout editor + plugin configs
- layout.py: pack algorithm, item placement, grid system
- plugins/: clock, weather, system, spotify, strava, gmail, minimax, hello
- network_watchdog.py: WiFi AP/client mode management
- waveshare_epd_init.py: vendor driver stub
2026-08-26 14:12:43 +04:00

77 lines
2.7 KiB
Markdown

# 7.3" ePaper Dashboard
Plugin-basiertes Dashboard für Waveshare 7.3-inch ACeP 7-Color e-Paper (F) HAT auf einem Raspberry Pi 4.
## Architektur
- **Renderer (`dashboard.py`)**: Lädt `config.json`, instanziiert Plugins, refresht das Display alle `refresh_interval_s` Sekunden (≥180 empfohlen). Reagiert auf Live-Trigger via Unix-Socket.
- **Web-Admin (`admin.py`)**: HTTP Basic Auth, konfiguriert Slots, Plugins und Secrets im Browser. Triggert Live-Refresh.
- **Plugins (`plugins/`)**: Jedes Widget ist ein Python-Modul mit `Widget`-Klasse (siehe `plugins/base.py`). Eigenes Plugin = eine Datei in `plugins/`.
- **Templates (`templates/index.html`)**: Single-Page-UI, auto-reload-fähig.
## Setup
```bash
# Auf dem Pi:
sudo apt install python3-pil python3-numpy python3-flask git
git clone <dieses repo> # oder rsync von deinem Dev-Rechner
cd port/
# SPI in /boot/firmware/config.txt aktivieren (dtparam=spi=on)
# Reboot
python3 admin.py &
python3 dashboard.py &
```
Web-UI: <http://pi:8080/>
Default Login: `admin` / `admin` — bitte `EPAPER_ADMIN_PASSWORD` in `.env` setzen.
## Plugin schreiben
Eine Datei `plugins/my_widget.py`:
```python
from plugins.base import Widget
from palette import FG, INFO
class Widget(Widget):
name = "my_widget"
label = "Mein Widget"
description = "Zeigt etwas Nützliches"
category = "info"
config_schema = [
{"key": "api_key", "label": "API Key", "type": "secret"},
{"key": "interval", "label": "Intervall (Sekunden)", "type": "int", "default": 60},
{"key": "show_extra", "label": "Extra anzeigen", "type": "bool", "default": True},
]
default_config = {"api_key": "", "interval": 60, "show_extra": True}
def fetch(self):
# Daten holen (API call, etc.)
return {"value": 42}
def render(self, draw, fonts, x, y, w, h):
# In den Slot zeichnen
d = self.fetch()
draw.text((x + 10, y + 10), f"Value: {d['value']}", font=fonts["28"], fill=FG)
```
**Feld-Typen**: `string`, `int`, `float`, `bool`, `secret` (write-only), `select` (mit `choices`), `lat_lon`.
**Palette** (aus `palette.py`): `BLACK, WHITE, GREEN, BLUE, RED, YELLOW, ORANGE` + semantisch `FG, BG, OK, WARN, ALERT, INFO, ACCENT`.
## Mitgelieferte Plugins
- `clock` — Uhrzeit / Datum
- `weather` — Open-Meteo Wetter (kein API-Key)
- `system` — Pi CPU/RAM/Uptime
- `hello` — Demo
- `spotify` — Last.fm Scrobble
- `strava` — Strava Aktivitäten
- `gmail` — Gmail Unread
## Einschränkungen
- **Full Refresh only**: ACeP-Displays vertragen keine schnellen Partial-Refreshes (Verschleiß). Das Hersteller-empfohlene Minimum ist 180s.
- **Kein Live-Websocket**: Snapshot wird per Refresh-Now-Button ausgelöst. Bei Bedarf ergänzbar.