Update readme to increase readability

This commit is contained in:
Your Name
2026-06-25 21:21:55 -06:00
parent f544444864
commit 4703476c89

235
README.md
View File

@@ -1,65 +1,65 @@
# Spectra # Spectra
Display random Unsplash photos on an Inky Impression e-paper display, with a web interface for uploading your own images. Display random Unsplash photos on an Inky Impression e-paper display, with a web
interface for uploading your own images.
## Features ---
- Fetches random high-resolution photos from Unsplash (cached to gallery) - [Requirements](#requirements)
- Upload your own images via the web interface (drag-and-drop, multi-file) - [Quick start](#quick-start)
- Centres, scales, and rotates images to fit the display - [Configuration](#configuration)
- Colour saturation tuning for e-paper - [Display orientation](#display-orientation)
- Display orientation — configure the physical mounting direction (0°, 90°, 180°, 270°) - [MQTT](#mqtt)
— Unsplash orientation filter is auto-derived (portrait/landscape/squarish) - [Usage](#usage)
- Web dashboard with preview, gallery, rotation queue, and config editor - [Display loop](#display-loop)
- MQTT integration for remote commands and status reporting - [Web interface](#web-interface)
- Simulation mode for testing without hardware (configurable resolution) - [systemd services](#systemd-services)
- systemd integration for automatic updates on a schedule - [Running tests](#running-tests)
- Randomised update intervals to avoid predictable refreshes - [Project structure](#project-structure)
- Config hot-reload — no service restart needed for setting changes
---
## Requirements ## Requirements
- Raspberry Pi (any model with GPIO) - Raspberry Pi with GPIO
- [Pimoroni Inky Impression](https://shop.pimoroni.com/products/inky-impression) (4.0", 7.3", or 13.3") - [Pimoroni Inky Impression](https://shop.pimoroni.com/products/inky-impression) (4.0", 7.3", or 13.3")
- Python 3.9+ - Python 3.9+
- [Unsplash API access key](https://unsplash.com/developers) - [Unsplash API access key](https://unsplash.com/developers)
## Installation ## Quick start
Run the installer on a Raspberry Pi:
```bash
./install.sh
```
The installer will:
1. Install the Pimoroni Inky library (skipped if not a Raspberry Pi)
2. Install Python dependencies (including web server and MQTT)
3. Install the `spectra` package
4. Copy the default config to `/etc/spectra/config.yaml`
5. Install and enable both the display and web interface systemd services
### Manual installation
```bash ```bash
# Install
cp config.example.yaml config.yaml # edit with your Unsplash key
pip install -r requirements.txt pip install -r requirements.txt
pip install -e . pip install -e .
# Optional: install dev dependencies for running tests # Run once in simulation mode
pip install -e ".[dev]" spectra --once --simulate
# Start the web interface
spectra web
# Run the display loop continuously
spectra
```
Or on a Pi with systemd:
```bash
sudo ./install.sh
sudo systemctl start spectra spectra-web
``` ```
## Configuration ## Configuration
Copy `config.example.yaml` to `config.yaml` and fill in your Unsplash access key. spectra looks for `config.yaml` in this order:
spectra searches for `config.yaml` in this order:
1. `$PWD/config.yaml` 1. `$PWD/config.yaml`
2. `~/.config/spectra/config.yaml` 2. `~/.config/spectra/config.yaml`
3. `/etc/spectra/config.yaml` 3. `/etc/spectra/config.yaml`
Or pass a custom path: `spectra -c /path/to/config.yaml` Pass a custom path with `spectra -c /path/to/config.yaml`.
```yaml ```yaml
unsplash: unsplash:
@@ -69,7 +69,7 @@ unsplash:
display: display:
saturation: 0.5 saturation: 0.5
orientation: 0 # 0, 90, 180, 270 (degrees clockwise) orientation: 0
resolution: resolution:
width: 1600 width: 1600
height: 1200 height: 1200
@@ -91,83 +91,67 @@ paths:
cache: /var/cache/spectra cache: /var/cache/spectra
``` ```
> **Note:** The `unsplash.orientation` key is no longer used. The Unsplash ### Display orientation
> orientation filter (`landscape`/`portrait`/`squarish`) is now derived
> automatically from `display.orientation` + `display.resolution`. Set `display.orientation` to match how the panel is physically mounted. The
Unsplash orientation filter (`landscape`/`portrait`/`squarish`) is derived
automatically — the old `unsplash.orientation` config key is ignored.
| Value | Unsplash filter | Effect |
|-------|----------------|--------|
| 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 for the
physical panel. Preview and thumbnails reflect the configured orientation.
Change it live from Settings > Display Orientation or via config hot-reload.
### MQTT
When enabled, the display loop subscribes to `{prefix}/command/#` and publishes
status to `{prefix}/status`. See [MQTT integration docs](docs/mqtt.md) for
commands, Home Assistant examples, and debugging.
## Usage ## Usage
### Display loop ### Display loop
```bash ```bash
# Run once and exit spectra # run continuously
spectra --once spectra --once # fetch one photo and exit
spectra --once --simulate # save to /tmp/spectra_last.png
# Run once in simulation mode spectra --simulate --width 800 --height 480
spectra --once --simulate
# Simulate at a specific resolution
spectra --once --simulate --width 800 --height 480
# Run with a custom config
spectra -c /path/to/config.yaml spectra -c /path/to/config.yaml
# Run continuously
spectra
``` ```
### Web interface ### Web interface
```bash ```bash
# Start the web interface (default: http://0.0.0.0:5000) spectra web # http://0.0.0.0:5000
spectra web spectra web --port 8080
spectra web -v # verbose (debug mode only on localhost)
# With custom host/port
spectra web --host 0.0.0.0 --port 5000
# Verbose logging (debug mode is limited to localhost)
spectra web -v
``` ```
The web interface provides: | Page | What it does |
|------|-------------|
- **Dashboard** — display status, schedule info, quick actions (refresh, clear) | **Dashboard** | Display status, schedule, quick actions (refresh, clear) |
- **Gallery** — browse all uploaded and cached Unsplash images, trigger "show now" | **Gallery** | Browse images, trigger "show now", delete |
- **Upload** — drag-and-drop multiple image files with progress tracking | **Upload** | Drag-and-drop multi-file upload with progress |
- **Settings** — live-edit Unsplash, display (including orientation), schedule, and MQTT configuration | **Settings** | Live-edit Unsplash, display, schedule, MQTT |
- **Preview** — preview how an image will look on the display (respects current orientation) | **Preview** | See how an image looks on the display |
### 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
When MQTT is enabled in the config, the display loop subscribes to commands and publishes status. See [MQTT integration docs](docs/mqtt.md) for details.
## systemd services ## systemd services
Two systemd services are installed: Two units are installed by `install.sh`:
- `spectra.service` the display loop (fetches Unsplash, processes triggers) - `spectra.service` — display loop
- `spectra-web.service` the web interface (Flask + htmx) - `spectra-web.service` — web interface
```bash ```bash
sudo systemctl start spectra sudo systemctl start spectra
sudo systemctl stop spectra-web sudo systemctl stop spectra-web
sudo systemctl status spectra-web
# View logs
journalctl -u spectra -f journalctl -u spectra -f
journalctl -u spectra-web -f journalctl -u spectra-web -f
``` ```
@@ -180,48 +164,45 @@ pytest tests/
``` ```
107 tests covering config loading, display processing (crop, resize, rotation), 107 tests covering config loading, display processing (crop, resize, rotation),
trigger atomicity, MQTT parsing, and the full web API (all 19 routes). trigger atomicity, MQTT parsing, and all 19 API routes.
## Project structure ## Project structure
``` ```
spectra/ spectra/
├── config.example.yaml # Example config (copy to config.yaml) ├── config.example.yaml
├── .gitignore # Ignores config.yaml (contains secrets) ├── .gitignore
├── install.sh # Installer script ├── install.sh
├── pyproject.toml # Package metadata ├── pyproject.toml
├── requirements.txt # Python dependencies ├── requirements.txt
├── spectra/ ├── spectra/
│ ├── __init__.py │ ├── cli.py # CLI, display loop, config hot-reload
│ ├── __main__.py # python -m spectra entry point │ ├── config.py # Config loader with deep-merge
│ ├── cli.py # CLI argument parsing and main loop │ ├── config_manager.py # Config read/write
│ ├── config.py # Configuration loader │ ├── display.py # Image processing, rotation, hardware abstraction
│ ├── config_manager.py # Config read/write with YAML write-back │ ├── fetcher.py # Unsplash API client
│ ├── display.py # Inky display abstraction and image processing │ ├── library.py # Unsplash image caching to SQLite
│ ├── fetcher.py # Unsplash API client │ ├── mqtt.py # MQTT client (commands + heartbeat)
│ ├── library.py # Unsplash image caching to SQLite library │ ├── trigger.py # Thread-safe trigger file (web → display loop)
│ ├── mqtt.py # MQTT client (commands + status)
│ ├── trigger.py # Shared trigger file (web server → display loop)
│ └── web/ │ └── web/
│ ├── server.py # Flask app factory and API routes │ ├── server.py # Flask app, 19 API routes
│ ├── models.py # SQLAlchemy models │ ├── models.py # SQLAlchemy models
│ ├── templates/ # Jinja2 templates (6 pages) │ ├── templates/ # 6 Jinja2 pages
── static/ # CSS and JS ── static/ # CSS + JS
│ └── __init__.py
├── tests/ ├── tests/
│ ├── test_api.py # 42 API endpoint tests │ ├── test_api.py
│ ├── test_config.py # Config loading and deep-merge │ ├── test_config.py
│ ├── test_display.py # Display processing and orientation │ ├── test_display.py
│ ├── test_gallery.py # Upload + delete flow │ ├── test_gallery.py
│ ├── test_mqtt.py # MQTT path and lookup │ ├── test_mqtt.py
│ ├── test_orientation.py # Orientation edge cases │ ├── test_orientation.py
│ ├── test_trigger.py # Trigger atomicity │ ├── test_trigger.py
│ └── conftest.py # Test fixtures │ └── conftest.py
├── systemd/ ├── systemd/
│ ├── spectra.service # Display loop systemd unit │ ├── spectra.service
│ └── spectra-web.service # Web interface systemd unit │ └── spectra-web.service
└── docs/ └── docs/
├── display-orientation.md # Display orientation design doc ├── display-orientation.md
├── web-interface.md # Web interface documentation ├── web-interface.md
└── mqtt.md # MQTT integration documentation └── mqtt.md
``` ```