Files
pictureFrame-webApp/CLAUDE.md
T
football2801 ff1ae79824
CI / test (push) Has been cancelled
docs(reset): "hold until the screen starts to flash" terminology
Renames the user-facing description of the BOOT-button factory reset
across the codebase. The threshold remains 5 s (RESET_HOLD_MS) but
"hold for 5 seconds" misled users: total wall-clock time-to-visible-
change includes ~20 s of e-ink redraw after the threshold fires, and
a too-short press now wakes the device into a normal poll cycle (a
side effect of the EXT0 wakeup we just added). "Until the screen
starts to flash" matches what the user actually sees.

  - Remove-this-frame modal gains a small aside describing the
    physical reset for the new owner, with the new terminology and
    a callout that a brief tap just refreshes the image.
  - CLAUDE.md and the operation.h comment near the EXT0 wake call
    use the same phrasing.
  - feedback_reset_terminology.md memory locks the rule for future
    edits — never write "hold for 5 seconds" in user copy.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 18:41:33 -04:00

52 lines
3.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# pictureFrame — web app
Handcrafted e-ink digital picture frame ecosystem — built as a meaningful gift. ESP32 firmware pulls pre-rendered images from a Symfony web app over WiFi; the companion web app handles image management, device configuration, and family sharing.
## Project goal
Build gifted e-ink frames that stay personal and current over time, with no ongoing effort required from the recipient. One image per configured interval, cycling through a curated pool of family uploads and shared photos. Setup: scan two QR codes. Ongoing: nothing unless the recipient wants it.
## Stack
- **Firmware:** PlatformIO + Arduino framework (C/C++), ESP32 dev board
- **Web app:** Symfony 8.0 (PHP 8.4+), PostgreSQL 16, Nginx-FPM
- **Local dev:** DDEV — mirrors `~/src/aqua-iq` setup
- **Git:** git.edholm.me (self-hosted Gitea/Forgejo)
- **Domain:** pictureframe.edholm.me
## Hardware
### Dev / V1 hardware (in hand)
- ESP32 dev board (`esp32dev`), dual-core 240MHz, 4MB flash
- Waveshare 7.3" 6-color e-ink (800×480)
- SPI pinout: SCK=18, MOSI=23, CS=5, DC=17, RST=16, BUSY=4
- 4bpp packed, palette: BLACK=0x0, WHITE=0x1, YELLOW=0x2, RED=0x3, BLUE=0x5, GREEN=0x6 (same map as Spectra 6; 0x4 unused)
### Target / V2 hardware (on order)
- Waveshare ESP32-S3-ePaper-13.3E6 — 13.3" **Spectra 6** (6-color), ESP32-S3 onboard
- Spectra 6 palette: same as above — BLACK=0x0, WHITE=0x1, YELLOW=0x2, RED=0x3, BLUE=0x5, GREEN=0x6
- Battery or plugin at recipient's choice
## Design decisions
- Server pre-renders all images to display-ready 4bpp per device model/orientation — ESP32 never transforms images
- Device pull model: `GET /api/device/{mac}/image` → 200 (binary), 204 (no ready image), 404 (unknown MAC)
- Atomic image write: display only refreshes after complete confirmed transfer; last good image persists through outages
- Deep sleep between pull cycles (see ESP32 deep sleep memory)
- Status via border color: yellow = sync fail, red = no WiFi
- Holding the BOOT button until the screen starts to flash triggers re-provisioning (config wipe + AP mode). Threshold is 5 s in firmware (RESET_HOLD_MS), but user-facing terminology is "hold until the screen flashes" because total wall-clock time-to-visible-change includes a ~20 s e-ink redraw, and a too-short press just wakes the device into a normal poll cycle.
- Two-phase provisioning: AP mode (WiFi credentials) → STA mode (QR to account setup page)
- Async image processing: Symfony Messenger (Doctrine transport), `max_retries: 1`
- Image storage: `storage/images/{id}/{model}_{orientation}.bin`, relative paths in DB
- PHP 8.1 backed enums for `RenderStatus`, `TokenType`, `Orientation`
- Imagick for Floyd-Steinberg dithering (not GD)
- No OTA firmware updates in V1 — API contract must not break without reflash
## Infrastructure reference
For Docker/DDEV config, server location, and SSH details: `~/src/aqua-iq`
## Full spec
See `_bmad-output/planning-artifacts/` — PRD, architecture, epics all complete as of 2026-04-27. Symfony web app scaffold + Vue SPA frontend scaffolded. Firmware fully rewritten with WiFi, provisioning, and deep sleep (`firmware/src/`).