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
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user