From f544444864437392eb7642f11ded3d5e27ca237b Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 25 Jun 2026 21:20:00 -0600 Subject: [PATCH] update readme to be comprehensive --- README.md | 110 ++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 81 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 1845a4f..cc4936d 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,10 @@ Display random Unsplash photos on an Inky Impression e-paper display, with a web - Fetches random high-resolution photos from Unsplash (cached to gallery) - Upload your own images via the web interface (drag-and-drop, multi-file) -- Centres and scales images to fit the display resolution +- Centres, scales, and rotates images to fit the display - Colour saturation tuning for e-paper +- Display orientation — configure the physical mounting direction (0°, 90°, 180°, 270°) + — Unsplash orientation filter is auto-derived (portrait/landscape/squarish) - Web dashboard with preview, gallery, rotation queue, and config editor - MQTT integration for remote commands and status reporting - Simulation mode for testing without hardware (configurable resolution) @@ -43,24 +45,34 @@ The installer will: ```bash pip install -r requirements.txt pip install -e . + +# Optional: install dev dependencies for running tests +pip install -e ".[dev]" ``` ## Configuration -Edit `/etc/spectra/config.yaml` (or `~/.config/spectra/config.yaml` or `config.yaml` in the current directory): +Copy `config.example.yaml` to `config.yaml` and fill in your Unsplash access key. +spectra searches for `config.yaml` in this order: + +1. `$PWD/config.yaml` +2. `~/.config/spectra/config.yaml` +3. `/etc/spectra/config.yaml` + +Or pass a custom path: `spectra -c /path/to/config.yaml` ```yaml unsplash: access_key: "your_access_key_here" query: "nature" - orientation: "landscape" collections: "" display: saturation: 0.5 - # resolution: - # width: 800 - # height: 480 + orientation: 0 # 0, 90, 180, 270 (degrees clockwise) + resolution: + width: 1600 + height: 1200 schedule: interval_hours: 1 @@ -79,6 +91,10 @@ paths: cache: /var/cache/spectra ``` +> **Note:** The `unsplash.orientation` key is no longer used. The Unsplash +> orientation filter (`landscape`/`portrait`/`squarish`) is now derived +> automatically from `display.orientation` + `display.resolution`. + ## Usage ### Display loop @@ -109,7 +125,7 @@ spectra web # With custom host/port spectra web --host 0.0.0.0 --port 5000 -# Verbose logging +# Verbose logging (debug mode is limited to localhost) spectra web -v ``` @@ -118,7 +134,22 @@ The web interface provides: - **Dashboard** — display status, schedule info, quick actions (refresh, clear) - **Gallery** — browse all uploaded and cached Unsplash images, trigger "show now" - **Upload** — drag-and-drop multiple image files with progress tracking -- **Settings** — live-edit Unsplash, display, schedule, and MQTT configuration +- **Settings** — live-edit Unsplash, display (including orientation), schedule, and MQTT configuration +- **Preview** — preview how an image will look on the display (respects current orientation) + +### Display orientation + +Set `display.orientation` in config or via Settings > Display > Display Orientation: + +| Value | Unsplash filter | Use case | +|-------|----------------|-------------------------| +| 0 | landscape | Default horizontal mount | +| 90 | portrait | Vertical mount | +| 180 | landscape | Upside-down horizontal | +| 270 | portrait | Upside-down vertical | + +Images are cropped to the effective aspect ratio, resized, then rotated to match +the physical panel. The preview and thumbnails reflect the configured orientation. ### MQTT @@ -141,35 +172,56 @@ journalctl -u spectra -f journalctl -u spectra-web -f ``` +## Running tests + +```bash +pip install -e ".[dev]" +pytest tests/ +``` + +107 tests covering config loading, display processing (crop, resize, rotation), +trigger atomicity, MQTT parsing, and the full web API (all 19 routes). + ## Project structure ``` spectra/ -├── config.yaml # Example configuration -├── install.sh # Installer script -├── pyproject.toml # Package metadata -├── requirements.txt # Python dependencies +├── config.example.yaml # Example config (copy to config.yaml) +├── .gitignore # Ignores config.yaml (contains secrets) +├── install.sh # Installer script +├── pyproject.toml # Package metadata +├── requirements.txt # Python dependencies ├── spectra/ │ ├── __init__.py -│ ├── __main__.py # python -m spectra entry point -│ ├── cli.py # CLI argument parsing and main loop -│ ├── config.py # Configuration loader -│ ├── config_manager.py # Config read/write with YAML write-back -│ ├── display.py # Inky display abstraction and image processing -│ ├── fetcher.py # Unsplash API client -│ ├── library.py # Unsplash image caching to SQLite library -│ ├── mqtt.py # MQTT client (commands + status) -│ ├── trigger.py # Shared trigger file (web server → display loop) +│ ├── __main__.py # python -m spectra entry point +│ ├── cli.py # CLI argument parsing and main loop +│ ├── config.py # Configuration loader +│ ├── config_manager.py # Config read/write with YAML write-back +│ ├── display.py # Inky display abstraction and image processing +│ ├── fetcher.py # Unsplash API client +│ ├── library.py # Unsplash image caching to SQLite library +│ ├── mqtt.py # MQTT client (commands + status) +│ ├── trigger.py # Shared trigger file (web server → display loop) │ └── web/ -│ ├── server.py # Flask app factory and API routes -│ ├── models.py # SQLAlchemy models -│ ├── templates/ # Jinja2 templates (6 pages) -│ ├── static/ # CSS and JS +│ ├── server.py # Flask app factory and API routes +│ ├── models.py # SQLAlchemy models +│ ├── templates/ # Jinja2 templates (6 pages) +│ ├── static/ # CSS and JS │ └── __init__.py +├── tests/ +│ ├── test_api.py # 42 API endpoint tests +│ ├── test_config.py # Config loading and deep-merge +│ ├── test_display.py # Display processing and orientation +│ ├── test_gallery.py # Upload + delete flow +│ ├── test_mqtt.py # MQTT path and lookup +│ ├── test_orientation.py # Orientation edge cases +│ ├── test_trigger.py # Trigger atomicity +│ └── conftest.py # Test fixtures ├── systemd/ -│ ├── spectra.service # Display loop systemd unit -│ └── spectra-web.service # Web interface systemd unit +│ ├── spectra.service # Display loop systemd unit +│ └── spectra-web.service # Web interface systemd unit └── docs/ - ├── web-interface.md # Web interface documentation - └── mqtt.md # MQTT integration documentation + ├── display-orientation.md # Display orientation design doc + ├── web-interface.md # Web interface documentation + └── mqtt.md # MQTT integration documentation ```