# ESPresso Frame Server Pulls photos from an [Immich](https://immich.app) album, resizes/dithers/quantizes them to the E Ink Spectra 6 panel's exact 6-color format, and serves the frame a ready-to-display image once an hour. All the image processing happens here so the ESP32 never has to decode a JPEG or run a dithering algorithm itself -- it just streams the response straight to the panel. ## Setup 1. **Get an Immich API key**: in Immich, go to Account Settings -> API Keys -> New API Key. Read-only access to albums/assets is enough. 2. **Run the server**: ``` docker compose up -d ``` 3. Open `http://:8420/` in a browser, enter your Immich URL and API key, click **Load Albums**, pick one, and **Save**. 4. On the ESP32's captive portal setup form, set the **Tools Server** field to `:8420`. ## Endpoints - `GET /` -- config UI - `GET /api/albums` -- lists Immich albums (used by the config UI) - `POST /api/config` -- saves Immich URL/API key/album/order - `GET /frame/image` -- returns the current photo pre-processed into the panel's raw 800x480, 4-bit-per-pixel, 2-pixels-per-byte format (`application/octet-stream`, exactly 192,000 bytes) - `GET /health` -- liveness check ## Notes - Config (including the Immich API key) is stored in `./data/config.json` on the host via the compose volume mount. - `/frame/image` isn't authenticated yet. That's fine on a trusted home LAN for now, but worth revisiting once the ESP32 side is wired up to send a shared device token. - The 6-color palette RGB values in `app/image_pipeline.py` are approximations, not measured values (Waveshare doesn't publish exact color primaries for this panel) -- tune them once you can compare a rendered test image against the real panel. ## Deploying a pre-built image Every push to `main` that touches `server/` triggers a Gitea Actions workflow (`.gitea/workflows/server-docker-build.yml`) that builds this image and pushes it to this repo's Gitea Container Registry at `git.thumeit.com/tfaour/espresso-frame-server`. `docker-compose.yml` already points at that image, so a deploy host doesn't need this repo's build context at all -- just the compose file: ``` docker compose pull docker compose up -d ``` `docker compose build` (or `up --build`) still works too, for local iteration against your own Dockerfile changes. ## Local development (without Docker) ``` python3 -m venv .venv source .venv/bin/activate pip install -r requirements.txt CONFIG_PATH=./data/config.json uvicorn app.main:app --reload --port 8420 ```