f60e7b5ad1
Build Server .exe / build (push) Failing after 2m30s
- start.bat and start.sh now create conda env (paperdash, Python 3.11) - README updated with conda setup instructions - Fixes pyhwinfo installation issues on Python 3.12+
260 lines
9.3 KiB
Markdown
260 lines
9.3 KiB
Markdown
# E-INK Dashboard Ecosystem ~ Paperdash
|
|
|
|
A local network dashboard ecosystem designed for the **Onyx Boox Go 7 Color** (Android E-Ink display). It displays real-time Windows desktop states including media playback, audio mixer channels (Windows default output or Voicemeeter), system telemetry, and custom script notifications (progress bars and rich text alerts).
|
|
|
|
**Copyright (c) Imrayya (2026)** — MIT License
|
|
|
|
## Architecture
|
|
|
|
Paperdash bypasses heavyweight native Android UIs in favor of a lightweight, asynchronous Python server communicating via low-overhead WebSockets to a highly optimized E-Ink web client.
|
|
|
|
```mermaid
|
|
flowchart TD
|
|
subgraph WindowsHost["WINDOWS HOST PC"]
|
|
subgraph Subsystems["Subsystems"]
|
|
Media["WinRT Media API"]
|
|
Audio["Windows Audio / Core Audio"]
|
|
VM["Voicemeeter API"]
|
|
HW["HWiNFO Shared Memory"]
|
|
end
|
|
Server["FastAPI Server"]
|
|
StateAgg["State Aggregator"]
|
|
Auth["Token Auth Engine"]
|
|
end
|
|
|
|
subgraph External["EXTERNAL CLIENTS"]
|
|
Script["Custom Script / CLI"]
|
|
end
|
|
|
|
subgraph Boox["ONYX BOOX GO 7 COLOR (Android 13)"]
|
|
APK["Android WebView APK
|
|
(Kotlin)"]
|
|
style APK fill:#000,color:#fff
|
|
end
|
|
|
|
Media --> Server
|
|
Audio --> Server
|
|
VM --> Server
|
|
HW --> Server
|
|
Server --> StateAgg
|
|
Server --> Auth
|
|
Script -->|Bearer Token| Auth
|
|
StateAgg -->|WebSocket| WebView
|
|
Auth -->|PIN Auth| WebView
|
|
```
|
|
|
|
**Client-side optimizations:** PIN-authenticated WebSocket connection, static DOM updates (no smooth scrolling/fades), full-screen CSS Grid layout with static tap-and-swipe gestures.
|
|
|
|
## Tech Stack
|
|
|
|
### Server (Python 3.11+, Windows)
|
|
|
|
- **FastAPI + Uvicorn** — ASGI web framework with native async WebSocket handling
|
|
- **winsdk** — Windows Media API for GSMTC (Global System Media Transport Controls)
|
|
- **pysounddevice / pycaw** — Generic Windows Core Audio API for default output volume and mute
|
|
- **voicemeeter-api** — Voicemeeter Remote API wrapper for per-strip mixer controls
|
|
- **pyhwinfo** — Hardware telemetry via HWiNFO64 Shared Memory
|
|
- **PyInstaller** — Compiles the server to a standalone `.exe` with system tray icon
|
|
|
|
### Client (BOOX Go 7 Color, Android 13)
|
|
|
|
- **Custom Android WebView APK** — Kotlin app wrapping the web client in a full-screen WebView
|
|
- **Vanilla JavaScript (ES6+) + CSS** — configured for monochrome/high-contrast E-Ink palettes
|
|
|
|
## Features
|
|
|
|
- **Media Playback Tracking** — Song title, artist, playback percentage, and cover art via Windows GSMTC
|
|
- **Audio Mixer Control** — Real-time volume and mute from Windows default output or Voicemeeter per-strip gains, mutes, and track states
|
|
- **Hardware Telemetry** — CPU/GPU core temps, VRAM usage from HWiNFO64
|
|
- **Hardware Fallbacks** — Startup check reports which subsystems are available/unavailable
|
|
- **Custom Notifications** — External scripts can push progress bars or rich text alerts via `POST /api/v1/notify`
|
|
- **Settings Page** — Localhost-only web UI at `/settings` (accessed via tray icon) to edit PIN, token, host, port, log level, and PIN TTL
|
|
- **Secure PIN System** — 6-digit codes with 5-minute TTL, single-use, auto-generated on startup
|
|
- **Cryptographic API Token** — 256-bit entropy via `secrets.token_urlsafe(32)`
|
|
- **Auto-Configuration** — `config.yaml` created automatically on first run with detected local IP
|
|
- **Configuration Files** — Use `config.yaml`, `.env`, or environment variables
|
|
- **E-Ink Optimized UI** — High-contrast styling, discrete zone gestures, minimal refresh
|
|
- **System Tray .exe** — Runs unobtrusively in the Windows notification bar with Settings and Quit options
|
|
|
|
## Authentication
|
|
|
|
1. **Dashboard UI (Boox Tablet):** Time-limited PIN authentication via WebSocket handshake (`?pin=XXXX`). PINs are 6-digit, expire after 5 minutes (configurable), and can only be used once.
|
|
2. **External Scripts/CLI:** Cryptographic Bearer Token via `Authorization: Bearer <SECRET_TOKEN>` header (32 bytes / 256 bits of entropy)
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
e-ink-dash/
|
|
├── .pi/
|
|
│ ├── docs/design/ # Design decision records
|
|
│ └── paperdash_architecture_document.txt
|
|
├── server/ # Python FastAPI server
|
|
│ ├── main.py # Application entry point
|
|
│ ├── config.py # Configuration management (YAML/.env/env vars)
|
|
│ ├── pin_manager.py # Time-limited single-use PIN generation
|
|
│ ├── audio_mixer.py # Audio mixer abstraction (Windows + Voicemeeter)
|
|
│ ├── media.py # Media playback tracking (GSMTC)
|
|
│ ├── notifications.py # Notification system (progress + alerts)
|
|
│ ├── telemetry.py # Hardware telemetry (HWiNFO)
|
|
│ ├── tray_wrapper.py # System tray .exe wrapper
|
|
│ ├── settings.html # Settings page (localhost-only)
|
|
│ ├── settings.css # Settings page stylesheet
|
|
│ ├── build_exe.py # PyInstaller build script
|
|
│ ├── start.bat # Windows development startup
|
|
│ ├── start.sh # Linux/macOS development startup
|
|
│ ├── .env.example # Example environment file
|
|
│ ├── requirements.txt
|
|
│ └── tests/ # Test suite
|
|
├── client/ # E-Ink web client
|
|
│ ├── index.html
|
|
│ ├── style.css
|
|
│ └── app.js
|
|
├── README.md
|
|
├── LICENSE
|
|
└── .gitignore
|
|
```
|
|
|
|
## Getting Started
|
|
|
|
### Quick Start (Development)
|
|
|
|
```bash
|
|
cd server
|
|
bash start.bat # Windows
|
|
# or
|
|
bash start.sh # Linux/macOS
|
|
```
|
|
|
|
The scripts create a conda env (`paperdash` with Python 3.11), install dependencies, and start the server. On first run, `config.yaml` is auto-generated with:
|
|
|
|
- A random 6-digit PIN (logged to console)
|
|
- A random API token (logged to console)
|
|
- Detected local IP address
|
|
- Default port 8921
|
|
|
|
### Manual Setup
|
|
|
|
```bash
|
|
cd server
|
|
conda create -y -n paperdash python=3.11
|
|
conda activate paperdash
|
|
pip install -r requirements.txt
|
|
python -m uvicorn main:app --host 0.0.0.0 --port 8921
|
|
```
|
|
|
|
Configure via one of:
|
|
|
|
1. **Environment variables:**
|
|
- `DASHBOARD_PIN` — (optional, auto-generated if missing)
|
|
- `API_TOKEN` — Bearer token for external scripts
|
|
- `PIN_TTL` — PIN expiration in seconds (default: 300)
|
|
- `HOST` — Server bind address (default: detected local IP)
|
|
- `PORT` — Server port (default: 8921)
|
|
- `LOG_LEVEL` — Logging level (default: INFO)
|
|
|
|
2. **`.env` file** (in project root or exe directory):
|
|
|
|
```
|
|
API_TOKEN=your-token-here
|
|
PIN_TTL=300
|
|
HOST=192.168.1.100
|
|
PORT=8921
|
|
LOG_LEVEL=INFO
|
|
```
|
|
|
|
3. **`config.yaml`** (auto-created on first run, or manually):
|
|
|
|
```yaml
|
|
api_token: "your-token-here"
|
|
pin_ttl: 300
|
|
host: "192.168.1.100"
|
|
port: 8921
|
|
log_level: "INFO"
|
|
```
|
|
|
|
### Settings Page
|
|
|
|
Access the settings UI via the system tray icon → **Settings**. This opens `http://127.0.0.1:8921/settings` in your browser.
|
|
|
|
**Available only from localhost** — you must be on the PC running PaperDash.
|
|
|
|
Edit: PIN, API token, host, port, log level, and PIN TTL. Changes are saved to `config.yaml` and take effect on next restart.
|
|
|
|
### Build .exe
|
|
|
|
```bash
|
|
cd server
|
|
python build_exe.py
|
|
# Output: server/dist/PaperDash.exe
|
|
```
|
|
|
|
The `.exe` bundles `settings.html` and `settings.css` for the settings page.
|
|
|
|
### Build .exe
|
|
|
|
```bash
|
|
cd server
|
|
python build_exe.py
|
|
# Output: server/dist/PaperDash.exe
|
|
```
|
|
|
|
### Client (Android APK)
|
|
|
|
The web client is bundled into an Android APK. Open Android Studio, sync Gradle, and run on the BOOX Go 7 Color.
|
|
|
|
```bash
|
|
cd android
|
|
./gradlew assembleDebug
|
|
# APK at: app/build/outputs/apk/debug/app-debug.apk
|
|
```
|
|
|
|
Install via ADB:
|
|
|
|
```bash
|
|
adb install app/build/outputs/apk/debug/app-debug.apk
|
|
```
|
|
|
|
The WebView loads `file:///android_asset/index.html` and connects to the server via WebSocket at `ws://<pc-ip>:8921/ws`.
|
|
|
|
#### Localization
|
|
|
|
The app supports multiple languages via Android string resources. The web client loads strings from Android via a JavaScript interface.
|
|
|
|
**Adding a new language:**
|
|
|
|
1. Create a new values folder: `android/app/src/main/res/values-{lang}/`
|
|
- Example: `values-es/` for Spanish, `values-fr/` for French
|
|
2. Copy `values/strings.xml` to the new folder
|
|
3. Translate the string values
|
|
|
|
**Example `values-es/strings.xml`:**
|
|
|
|
```xml
|
|
<?xml version="1.0" encoding="utf-8"?>
|
|
<resources>
|
|
<string name="app_name">PaperDash</string>
|
|
<string name="login_title">PaperDash</string>
|
|
<string name="login_subtitle">Ingrese PIN para conectar</string>
|
|
<string name="login_placeholder">****</string>
|
|
<string name="login_button">Conectar</string>
|
|
<string name="login_error_enter_pin">Ingrese un PIN</string>
|
|
<string name="login_error_disconnected">Desconectado. Reingrese PIN.</string>
|
|
<string name="connecting">Conectando…</string>
|
|
<string name="no_playback">Sin reproducción</string>
|
|
<string name="mute">SILENCIAR</string>
|
|
<string name="muted">SILENCIADO</string>
|
|
<string name="no_notifications">Sin notificaciones</string>
|
|
<string name="eta_prefix">ETA:</string>
|
|
</resources>
|
|
```
|
|
|
|
The app automatically uses the device's language. No code changes needed.
|
|
|
|
### Design Decisions
|
|
|
|
See `.pi/docs/design/` for detailed design decision records covering architecture, audio mixer, notifications, and the .exe build.
|
|
|
|
## License
|
|
|
|
MIT — see [LICENSE](LICENSE) for details.
|