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
This commit is contained in:
169
README.md
169
README.md
@@ -1,82 +1,131 @@
|
||||
# Party Cam: Instant Thermal Camera & Digital Gallery
|
||||
|
||||
A DIY point-and-shoot camera that prints dithered lo-fi photos on thermal receipts and instantly uploads high-res copies to a local Rust server.
|
||||
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
|
||||
|
||||
- **ESP32-CAM**
|
||||
- **Thermal Printer** (TTL Serial, 5V-9V)
|
||||
- **Batteries** (Recommended: 2x 18650 Li-Ion in series = 7.4V, powering printer directly + buck converter to 5V for ESP32)
|
||||
- **Button** (Tactile switch)
|
||||
- **Programmer**: FTDI Adapter or Arduino Uno (for flashing)
|
||||
| Part | Notes |
|
||||
| :--- | :--- |
|
||||
| ESP32-CAM (AI-Thinker) | Camera + WiFi module |
|
||||
| Thermal Printer | TTL serial, 5V–9V |
|
||||
| 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
|
||||
|
||||
### 1. Camera & Printer
|
||||
| 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 |
|
||||
|
||||
| ESP32-CAM Pin | Component | Function |
|
||||
| :---------------- | :--------- | :--------------------------------- |
|
||||
| **5V** | PSU 5V | Power In |
|
||||
| **GND** | PSU GND | Common Ground |
|
||||
| **GPIO 12** | Button | Trigger (Connect other leg to 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 |
|
||||
|
||||
### 2. Flashing (Using Arduino Uno as Bridge)
|
||||
|
||||
_See "How to Flash" section below._
|
||||
All pin assignments are in `include/config.h`. Change them there if your wiring differs.
|
||||
|
||||
---
|
||||
|
||||
## Setup Guide
|
||||
## Server Setup
|
||||
|
||||
### A. The Server (Rust)
|
||||
Run the server on any machine on the same local network as the camera. It receives uploads and hosts the gallery.
|
||||
|
||||
The server receives images and hosts the gallery for guests.
|
||||
### Option A: Docker Compose (recommended)
|
||||
|
||||
1. **Install Rust:** `curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh`
|
||||
2. **Configure:**
|
||||
Create a `.env` file in the `server` folder:
|
||||
```ini
|
||||
SERVER_HOST=0.0.0.0
|
||||
SERVER_PORT=3000
|
||||
GALLERY_PASSWORD=partytime
|
||||
UPLOAD_DIR=./uploads
|
||||
```
|
||||
3. **Run:**
|
||||
```bash
|
||||
cd server
|
||||
cargo run --release
|
||||
```
|
||||
_Server will listen on port 3000._
|
||||
```bash
|
||||
cd server
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
### B. The Camera (Firmware)
|
||||
Images are saved to `server/party_images/` on the host. To change the gallery password, edit `GALLERY_PASSWORD` in `compose.yml`.
|
||||
|
||||
1. **Open Project:** Open this folder in VS Code with the PlatformIO extension.
|
||||
2. **Flash Mode Wiring (Arduino Uno Method):**
|
||||
- **Arduino RESET** -> **Arduino GND** (Bypasses Arduino chip).
|
||||
- **Arduino Pin 0 (RX)** -> **ESP32 U0R** (Direct passthrough).
|
||||
- **Arduino Pin 1 (TX)** -> **ESP32 U0T** (Direct passthrough).
|
||||
- **ESP32 IO0** -> **ESP32 GND** (Enables Download Mode).
|
||||
3. **Upload:**
|
||||
- Connect via USB.
|
||||
- Click "Upload".
|
||||
- Press the **RST** button on ESP32 when "Connecting..." appears.
|
||||
4. **Run Mode:**
|
||||
- **Disconnect IO0 from GND.**
|
||||
- Press **RST** to boot.
|
||||
### 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.
|
||||
|
||||
---
|
||||
|
||||
## Configuration (First Boot)
|
||||
## Firmware Setup
|
||||
|
||||
1. **Power on** the camera.
|
||||
2. Connect your phone to the WiFi network: `PartyCam-Setup`.
|
||||
3. A captive portal should open (or go to `192.168.4.1`).
|
||||
4. **WiFi:** Select the venue's WiFi (or your phone hotspot).
|
||||
5. **Server URL:** Enter your laptop's IP (e.g., `http://192.168.1.15:3000/upload`).
|
||||
6. **Settings:** Adjust Contrast/Heat if the print is too faint or dark.
|
||||
7. **Save & Reboot.**
|
||||
### 1. Configure
|
||||
|
||||
The camera is now live!
|
||||
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) |
|
||||
|
||||
Reference in New Issue
Block a user