A image server for the ESP32 PhotoFrame project. This server acts as a bridge between the E-paper display and various photo sources (Google Photos, Immich, Synology Photos, Unsplash, Pexels, and more), handling image processing, resizing, dithering, and overlay generation.
Your Synology NAS (DSM 7) — sync albums, including ones other users shared with your account. Shared Space (FotoTeam) folders are not supported yet (#55); Shared Space photos do sync when they are in an album.
**Google OAuth Restriction**: Google does not allow `.local` domains or private IP addresses in OAuth redirect URIs. If running on Home Assistant, you must use one of these methods:
- **Port Forwarding** (recommended for one-time setup): `ssh -L 9607:localhost:9607 [email protected] -p 22222`
- **Public Domain**: Use a domain name with Cloudflare Tunnel or similar
Go to Settings → Data Sources and open the Synology tab.
Enter your NAS URL (e.g., https://192.168.1.10:5001), Account, and Password.
If using 2FA, enter the OTP Code, then click Connect.
Click Refresh albums and pick the albums to sync. Albums other DSM users shared with your account are listed too, badged Shared with me. Album and photo listings are paged, so large libraries (hundreds of albums, thousands of photos per album) sync in full.
Click Sync Now to import metadata, or enable Auto Sync Album to keep it current.
Note
Shared Space (FotoTeam) folders can't be picked as a source yet — see [#55](https://github.com/aitjcize/esp32-photoframe-server/issues/55). Photos from the Shared Space do sync when they are in an album.
A frame can require a password on its own web interface and API (firmware newer than v2.18.0; set under the frame's Advanced network settings). The server needs that password to reach the frame:
Adding a protected frame: in Add Device, tick This frame requires a password and enter it next to the host. Without it the frame can't be read, and the device is added with placeholder settings until you supply the password.
Recording a password the frame already has: Edit Device → General → Advanced network settings → Frame password. Saving it only tells the server what the frame has; Forget password drops it again.
Changing it from the dashboard: under Password on the frame, Set a password on the frame / Change password on the frame signs in to the frame with the stored password, sets the new one (typed twice), and stores it; Turn off password on the frame removes it. If the frame doesn't accept the change, nothing changes on either side. Give the new password to the Home Assistant integration and the mobile app too.
When a frame starts refusing the server's password — it was turned on or changed from the frame itself — the device row shows a Password required chip and the dashboard asks for the password. Enter it (or choose Not now) and syncing and pushing resume; until then, settings saved in the dashboard reach the frame only with its next image fetch.
The frame keeps its clock with a POSIX TZ rule, so a zone with daylight-saving time stays right all year, and the rotation schedule runs in that zone. In Edit Device → General, pick the zone by name from the Time zone list (IANA names such as Europe/Berlin; the POSIX rule the frame will get is shown beneath), or click Use this browser's time zone. For a rule the list can't name, tick Advanced: POSIX TZ rule and type any rule the frame's tzset() accepts, e.g. EST5EDT,M3.2.0,M11.1.0 (fixed offsets count hours west: UTC-8 is UTC+8).
GET /image: The endpoint frames use. The device is identified by its bearer token and served its server-assigned source (cropped and dithered for its panel). Configure the source under Settings → Devices; a device with no source assigned gets an error.
GET /image/<source>: A legacy URL form still routed for older firmware — the <source> is ignored. A device is only ever served the source assigned to it in the server, never one it isn't assigned.