"""ESPresso Frame server: pulls photos from Immich, pre-processes them for the panel, and serves the ESP32 a ready-to-display frame.""" from __future__ import annotations import io import logging import time from datetime import datetime, timedelta from zoneinfo import ZoneInfo, available_timezones import httpx from fastapi import Depends, FastAPI, File, HTTPException, Form, Request, UploadFile from fastapi.responses import FileResponse, HTMLResponse, RedirectResponse, Response from fastapi.templating import Jinja2Templates from PIL import Image from pydantic import BaseModel from . import config, gitea_releases, photo_queue from .face_labels import compute_face_labels from .firmware import firmware_path, parse_app_version from .image_pipeline import render_frame from .immich_client import ImmichClient logger = logging.getLogger(__name__) app = FastAPI(title="ESPresso Frame Server") templates = Jinja2Templates(directory="app/templates") MIN_REFRESH_INTERVAL_S = 60 MAX_REFRESH_INTERVAL_S = 86400 MIN_QUEUE_TARGET_LEN = 5 MAX_QUEUE_TARGET_LEN = 5000 ORIENTATIONS = ("landscape", "portrait", "landscape_flipped", "portrait_flipped") # Populated once from the OS's zoneinfo database (installed via the # `tzdata` apt package in the Dockerfile) and offered as a