Files
party-cam/README.md
Gabriel Kaszewski 4ec723ef40 fix bugs, harden server, strip-based dithering, update docs
Firmware:
- fix 90° rotation (was transpose)
- fix Adafruit_Thermal constructor (spurious DTR pin arg)
- wire up uploadImage; heatInterval now applied
- PSRAM-free strip dithering: 2-row buffers (~1KB) replace 153KB PSRAM alloc
- consolidate all pins into config.h; BUTTON_PIN → Config::PIN_BUTTON
- constrain contrast/brightness/heat in settings save handler
- uploadImage size param int → size_t

Server:
- canonicalize upload_dir at startup (fixes path traversal guard)
- path traversal guard in serve_image
- replace unwrap in gallery_data with error handling
- IMAGE_WIDTH/IMAGE_HEIGHT named constants

Gallery:
- innerHTML → createElement (XSS-safe)
- encodeURIComponent on image URLs
- replace("_"," ") → regex /_/g

Docs: rewrite README, clarify GUEST_MANUAL placeholders
2026-06-18 11:23:05 +02:00

132 lines
3.7 KiB
Markdown
Raw 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.
# Party Cam: Instant Thermal Camera & Digital Gallery
A DIY point-and-shoot that prints dithered lo-fi photos on thermal receipt paper and simultaneously uploads captures to a local Rust web server.
---
## Hardware BOM
| Part | Notes |
| :--- | :--- |
| ESP32-CAM (AI-Thinker) | Camera + WiFi module |
| Thermal Printer | TTL serial, 5V9V |
| 2× 18650 Li-Ion | In series = 7.4V; powers printer directly + 5V buck converter for ESP32 |
| Tactile button | Shutter trigger |
| FTDI adapter or Arduino Uno | For flashing only |
---
## Wiring
| ESP32-CAM Pin | Component | Function |
| :--- | :--- | :--- |
| **5V** | PSU 5V | Power in |
| **GND** | PSU GND | Common ground |
| **GPIO 12** | Button | Shutter (other leg → GND) |
| **GPIO 14** (U1T) | Printer RX | Data to printer |
| **GPIO 15** (U1R) | Printer TX | Data from printer |
| **GPIO 4** | Flash LED | Optional built-in flash |
All pin assignments are in `include/config.h`. Change them there if your wiring differs.
---
## Server Setup
Run the server on any machine on the same local network as the camera. It receives uploads and hosts the gallery.
### Option A: Docker Compose (recommended)
```bash
cd server
docker compose up -d
```
Images are saved to `server/party_images/` on the host. To change the gallery password, edit `GALLERY_PASSWORD` in `compose.yml`.
### Option B: Cargo (dev)
```bash
cd server
cargo run --release
```
Requires a `.env` file in the `server/` directory:
```ini
SERVER_HOST=0.0.0.0
SERVER_PORT=3000
GALLERY_PASSWORD=partytime
UPLOAD_DIR=./uploads
```
`GALLERY_PASSWORD` is required — the server panics at startup without it.
---
## Firmware Setup
### 1. Configure
Check `platformio.ini` and make sure `board` matches your actual hardware. The default is `4d_systems_esp32s3_gen4_r8n16` — change it to `ai_thinker_esp32-cam` if using a standard ESP32-CAM. Camera pin definitions in `include/config.h` are pre-set for AI-Thinker.
### 2. Flash (Arduino Uno as bridge)
Wire the Uno as a passthrough:
- Arduino RESET → Arduino GND (bypasses the Uno chip)
- Arduino Pin 0 (RX) → ESP32 U0R
- Arduino Pin 1 (TX) → ESP32 U0T
- **ESP32 IO0 → ESP32 GND** (enables download mode)
Click **Upload** in PlatformIO, then press RST on the ESP32 when "Connecting…" appears.
### 3. Boot
Disconnect IO0 from GND, press RST. The camera boots.
---
## First Boot Configuration
1. Power on. Camera broadcasts WiFi AP: **`PartyCam-Setup`**.
2. Connect your phone — a captive portal opens automatically (or go to `192.168.4.1`).
3. Select the venue WiFi and enter the password.
4. Set the **Upload URL** to `http://<server-machine-ip>:3000/upload`.
5. Adjust contrast/heat to taste. **Save & Reboot.**
The portal times out after 3 minutes. If it closes before you save, the camera boots in offline mode (printing still works, upload disabled).
---
## Settings Page
After first boot the settings page is always reachable at:
```
http://partycam.local
```
(or the camera's IP address on port 80). Use it to adjust contrast, brightness, flip/mirror, heat density, and the upload URL.
---
## Gallery
```
http://<server-ip>:3000/gallery
```
Open from any device on the same network. The browser will prompt for the gallery password. New photos appear automatically — the page polls every 5 seconds.
---
## Customisation
| What | Where |
| :--- | :--- |
| Pin assignments | `include/config.h` |
| Printer baud rate | `include/config.h``BAUD_RATE` |
| Default camera settings | `include/settings_service.h``AppSettings` struct defaults |
| Gallery password | `compose.yml` or `.env` |
| Capture resolution | `src/camera_service.cpp``config.frame_size` (update `IMAGE_WIDTH`/`IMAGE_HEIGHT` in `server/src/main.rs` to match) |