Kareem Horstink f60e7b5ad1
Build Server .exe / build (push) Failing after 2m30s
Switch from venv to conda for environment management
- 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+
2026-07-03 08:38:34 +00:00
2026-07-01 14:51:46 +02:00

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.

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-Configurationconfig.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)

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

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

    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

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

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.

cd android
./gradlew assembleDebug
# APK at: app/build/outputs/apk/debug/app-debug.apk

Install via ADB:

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 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 for details.

S
Description
No description provided
Readme MIT 183 KiB
Languages
Python 53.1%
JavaScript 21.9%
HTML 10.6%
CSS 10.5%
Kotlin 2.4%
Other 1.5%