diff --git a/demo/README.md b/demo/README.md new file mode 100644 index 0000000..82d2cdd --- /dev/null +++ b/demo/README.md @@ -0,0 +1,131 @@ +# Raspberry Pi Webcam Capture Demo + +Automated picture capture and upload for Raspberry Pi 3 with a USB webcam (Logitech 1080p). + +## Quick Setup (5 minutes) + +### 1. Install Required Packages + +```bash +sudo apt update && sudo apt install -y fswebcam curl +``` + +### 2. Configure the Script + +```bash +# Copy the config template +cp picupper.conf.example picupper.conf + +# Edit with your settings +nano picupper.conf +``` + +Update `picupper.conf` with your API key and camera settings. + +### 3. Install & Enable + +```bash +# Make scripts executable +chmod +x capture-upload.sh install.sh + +# Run installer (sets up cron job) +./install.sh +``` + +That's it! Your Pi will now capture and upload one picture per minute. + +--- + +## Files Included + +| File | Purpose | +|------|---------| +| `capture-upload.sh` | Main script - captures photo and uploads | +| `picupper.conf.example` | Configuration template | +| `install.sh` | Installer script (sets up cron) | +| `uninstall.sh` | Removes cron job | + +## Configuration Options + +Edit `picupper.conf`: + +```bash +# PicUpper server URL +API_URL="https://dev.seedheads.de/picUploadApi/upload" + +# Your API key (from server admin) +API_KEY="your-api-key-here" + +# Camera identifier (unique name for this Pi) +CAMERA_ID="rpi-webcam-1" + +# Resolution (1920x1080 for full HD) +RESOLUTION="1920x1080" + +# Video device (usually /dev/video0) +VIDEO_DEVICE="/dev/video0" +``` + +## Manual Testing + +```bash +# Test capture only (saves to /tmp) +./capture-upload.sh --test + +# Run full capture and upload once +./capture-upload.sh +``` + +## Troubleshooting + +### Check if webcam is detected + +```bash +ls /dev/video* +v4l2-ctl --list-devices +``` + +### Test capture manually + +```bash +fswebcam -d /dev/video0 -r 1920x1080 --no-banner test.jpg +``` + +### Check logs + +```bash +# View recent capture logs +tail -f /var/log/picupper.log +``` + +### Common Issues + +| Problem | Solution | +|---------|----------| +| "No video device" | Replug USB webcam, check `dmesg` | +| "Permission denied" | Add user to video group: `sudo usermod -aG video $USER` | +| "Upload failed" | Check API key and network connection | + +## Changing Capture Frequency + +Default is 1 picture per minute. To change: + +```bash +# Edit cron job +crontab -e +``` + +Examples: +- Every 5 minutes: `*/5 * * * * /home/pi/picupper-demo/capture-upload.sh` +- Every 30 seconds: Use the included systemd timer (see advanced setup) + +## Hardware Requirements + +- Raspberry Pi 3 (any model) +- USB webcam (Logitech C920/C922/C270 recommended) +- SD card with Raspberry Pi OS +- Network connection (WiFi or Ethernet) + +## Network Notes + +The script retries failed uploads and logs all attempts. If your Pi loses network, captures continue and uploads resume when connectivity returns. diff --git a/demo/capture-upload.sh b/demo/capture-upload.sh new file mode 100644 index 0000000..356e7c1 --- /dev/null +++ b/demo/capture-upload.sh @@ -0,0 +1,168 @@ +#!/bin/bash +# capture-upload.sh - Capture from USB webcam and upload to PicUpper +# For Raspberry Pi 3 with Logitech USB webcam + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +CONFIG_FILE="${SCRIPT_DIR}/picupper.conf" + +# ============================================================================== +# Load Configuration +# ============================================================================== + +if [[ ! -f "$CONFIG_FILE" ]]; then + echo "ERROR: Configuration file not found: $CONFIG_FILE" + echo "Please copy picupper.conf.example to picupper.conf and configure it." + exit 1 +fi + +# shellcheck source=/dev/null +source "$CONFIG_FILE" + +# Validate required settings +if [[ -z "${API_KEY:-}" || "$API_KEY" == "your-api-key-here" ]]; then + echo "ERROR: API_KEY not configured in $CONFIG_FILE" + exit 1 +fi + +# Set defaults for optional settings +API_URL="${API_URL:-https://dev.seedheads.de/picUploadApi/upload}" +CAMERA_ID="${CAMERA_ID:-rpi-webcam}" +VIDEO_DEVICE="${VIDEO_DEVICE:-/dev/video0}" +RESOLUTION="${RESOLUTION:-1920x1080}" +SKIP_FRAMES="${SKIP_FRAMES:-5}" +TEMP_DIR="${TEMP_DIR:-/tmp}" +LOG_FILE="${LOG_FILE:-/var/log/picupper.log}" +TIMEOUT="${TIMEOUT:-30}" +MAX_RETRIES="${MAX_RETRIES:-3}" +RETRY_DELAY="${RETRY_DELAY:-5}" + +# ============================================================================== +# Helper Functions +# ============================================================================== + +log() { + local timestamp + timestamp=$(date '+%Y-%m-%d %H:%M:%S') + echo "[$timestamp] $*" | tee -a "$LOG_FILE" 2>/dev/null || echo "[$timestamp] $*" +} + +log_error() { + log "ERROR: $*" >&2 +} + +cleanup() { + rm -f "${TEMP_FILE:-}" 2>/dev/null || true +} + +trap cleanup EXIT + +# ============================================================================== +# Test Mode +# ============================================================================== + +if [[ "${1:-}" == "--test" ]]; then + echo "=== PicUpper Test Mode ===" + echo "Config file: $CONFIG_FILE" + echo "API URL: $API_URL" + echo "Camera ID: $CAMERA_ID" + echo "Video device: $VIDEO_DEVICE" + echo "Resolution: $RESOLUTION" + echo "" + + # Check video device + if [[ ! -e "$VIDEO_DEVICE" ]]; then + echo "❌ Video device not found: $VIDEO_DEVICE" + echo " Available devices:" + ls -la /dev/video* 2>/dev/null || echo " No video devices found" + exit 1 + fi + echo "✓ Video device exists: $VIDEO_DEVICE" + + # Check fswebcam + if ! command -v fswebcam &>/dev/null; then + echo "❌ fswebcam not installed. Run: sudo apt install fswebcam" + exit 1 + fi + echo "✓ fswebcam installed" + + # Try capture + TEST_FILE="${TEMP_DIR}/picupper_test_$(date +%s).jpg" + echo "Capturing test image to: $TEST_FILE" + + if fswebcam -d "$VIDEO_DEVICE" -r "$RESOLUTION" -S "$SKIP_FRAMES" --no-banner "$TEST_FILE" 2>/dev/null; then + FILE_SIZE=$(stat -f%z "$TEST_FILE" 2>/dev/null || stat -c%s "$TEST_FILE" 2>/dev/null) + echo "✓ Capture successful: $TEST_FILE (${FILE_SIZE} bytes)" + echo "" + echo "To view the image: gpicview $TEST_FILE" + else + echo "❌ Capture failed. Check webcam connection and permissions." + exit 1 + fi + + exit 0 +fi + +# ============================================================================== +# Main Capture & Upload +# ============================================================================== + +TEMP_FILE="${TEMP_DIR}/picupper_${CAMERA_ID}_$(date +%s).jpg" + +# Check video device +if [[ ! -e "$VIDEO_DEVICE" ]]; then + log_error "Video device not found: $VIDEO_DEVICE" + exit 1 +fi + +# Capture image +log "Capturing from $VIDEO_DEVICE ($RESOLUTION)" +if ! fswebcam -d "$VIDEO_DEVICE" -r "$RESOLUTION" -S "$SKIP_FRAMES" --no-banner "$TEMP_FILE" 2>/dev/null; then + log_error "Capture failed" + exit 1 +fi + +FILE_SIZE=$(stat -c%s "$TEMP_FILE" 2>/dev/null || echo "unknown") +log "Captured: $TEMP_FILE ($FILE_SIZE bytes)" + +# Upload with retry +upload_success=false +attempt=1 + +while [[ $attempt -le $MAX_RETRIES ]]; do + log "Upload attempt $attempt/$MAX_RETRIES" + + HTTP_RESPONSE=$(curl -s -w "\n%{http_code}" \ + --max-time "$TIMEOUT" \ + -X POST \ + -H "X-API-Key: $API_KEY" \ + -F "image=@$TEMP_FILE" \ + -F "cameraId=$CAMERA_ID" \ + "$API_URL" 2>/dev/null) || true + + HTTP_CODE=$(echo "$HTTP_RESPONSE" | tail -n1) + RESPONSE_BODY=$(echo "$HTTP_RESPONSE" | sed '$d') + + if [[ "$HTTP_CODE" == "200" ]]; then + log "Upload successful (HTTP $HTTP_CODE)" + upload_success=true + break + else + log_error "Upload failed (HTTP $HTTP_CODE): $RESPONSE_BODY" + + if [[ $attempt -lt $MAX_RETRIES ]]; then + log "Retrying in $RETRY_DELAY seconds..." + sleep "$RETRY_DELAY" + fi + fi + + ((attempt++)) +done + +if [[ "$upload_success" != "true" ]]; then + log_error "All upload attempts failed" + exit 1 +fi + +log "Done" diff --git a/demo/install.sh b/demo/install.sh new file mode 100644 index 0000000..c8d354f --- /dev/null +++ b/demo/install.sh @@ -0,0 +1,94 @@ +#!/bin/bash +# install.sh - Set up PicUpper webcam capture on Raspberry Pi +# Creates cron job for 1 picture per minute + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +CAPTURE_SCRIPT="${SCRIPT_DIR}/capture-upload.sh" +CONFIG_FILE="${SCRIPT_DIR}/picupper.conf" +LOG_FILE="/var/log/picupper.log" + +echo "=== PicUpper Installer ===" +echo "" + +# Check dependencies +echo "Checking dependencies..." + +if ! command -v fswebcam &>/dev/null; then + echo "❌ fswebcam not installed" + echo " Run: sudo apt update && sudo apt install -y fswebcam" + exit 1 +fi +echo "✓ fswebcam" + +if ! command -v curl &>/dev/null; then + echo "❌ curl not installed" + echo " Run: sudo apt update && sudo apt install -y curl" + exit 1 +fi +echo "✓ curl" + +# Check config +if [[ ! -f "$CONFIG_FILE" ]]; then + echo "" + echo "❌ Configuration file not found!" + echo " Please create it first:" + echo " cp picupper.conf.example picupper.conf" + echo " nano picupper.conf" + exit 1 +fi +echo "✓ Config file exists" + +# Check API key is configured +# shellcheck source=/dev/null +source "$CONFIG_FILE" +if [[ -z "${API_KEY:-}" || "$API_KEY" == "your-api-key-here" ]]; then + echo "" + echo "❌ API key not configured in picupper.conf" + echo " Edit the file and set your API key" + exit 1 +fi +echo "✓ API key configured" + +# Make scripts executable +chmod +x "$CAPTURE_SCRIPT" +chmod +x "${SCRIPT_DIR}/uninstall.sh" 2>/dev/null || true +echo "✓ Scripts are executable" + +# Create log file if needed +if [[ ! -f "$LOG_FILE" ]]; then + sudo touch "$LOG_FILE" + sudo chown "$USER:$USER" "$LOG_FILE" + echo "✓ Log file created: $LOG_FILE" +else + echo "✓ Log file exists: $LOG_FILE" +fi + +# Set up cron job +CRON_JOB="* * * * * $CAPTURE_SCRIPT >> $LOG_FILE 2>&1" + +echo "" +echo "Setting up cron job for 1 picture per minute..." + +# Check if cron job already exists +if crontab -l 2>/dev/null | grep -q "$CAPTURE_SCRIPT"; then + echo "⚠ Cron job already exists, skipping" +else + # Add to crontab + (crontab -l 2>/dev/null || true; echo "$CRON_JOB") | crontab - + echo "✓ Cron job added" +fi + +echo "" +echo "=== Installation Complete ===" +echo "" +echo "Your Raspberry Pi will now capture a picture every minute." +echo "" +echo "Useful commands:" +echo " View logs: tail -f $LOG_FILE" +echo " Test capture: $CAPTURE_SCRIPT --test" +echo " Run manually: $CAPTURE_SCRIPT" +echo " Uninstall: ${SCRIPT_DIR}/uninstall.sh" +echo "" +echo "To change frequency, edit crontab: crontab -e" diff --git a/demo/picupper.conf.example b/demo/picupper.conf.example new file mode 100644 index 0000000..f2c39c8 --- /dev/null +++ b/demo/picupper.conf.example @@ -0,0 +1,47 @@ +# PicUpper Configuration +# Copy this file to picupper.conf and update with your settings + +# ============================================================================== +# SERVER SETTINGS +# ============================================================================== + +# API endpoint URL +API_URL="https://dev.seedheads.de/picUploadApi/upload" + +# Your API key (get this from the PicUpper server admin) +API_KEY="your-api-key-here" + +# ============================================================================== +# CAMERA SETTINGS +# ============================================================================== + +# Unique identifier for this camera (no spaces, use hyphens) +CAMERA_ID="rpi-webcam-1" + +# Video device path (run 'ls /dev/video*' to find yours) +VIDEO_DEVICE="/dev/video0" + +# Capture resolution (common options: 1920x1080, 1280x720, 640x480) +RESOLUTION="1920x1080" + +# Skip first N frames (helps camera adjust exposure, default 5) +SKIP_FRAMES=5 + +# ============================================================================== +# ADVANCED SETTINGS (usually don't need to change) +# ============================================================================== + +# Temporary file location +TEMP_DIR="/tmp" + +# Log file location +LOG_FILE="/var/log/picupper.log" + +# Connection timeout in seconds +TIMEOUT=30 + +# Retry failed uploads (0 = no retry) +MAX_RETRIES=3 + +# Delay between retries in seconds +RETRY_DELAY=5 diff --git a/demo/uninstall.sh b/demo/uninstall.sh new file mode 100644 index 0000000..34efb31 --- /dev/null +++ b/demo/uninstall.sh @@ -0,0 +1,29 @@ +#!/bin/bash +# uninstall.sh - Remove PicUpper cron job + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +CAPTURE_SCRIPT="${SCRIPT_DIR}/capture-upload.sh" + +echo "=== PicUpper Uninstaller ===" +echo "" + +# Remove cron job +if crontab -l 2>/dev/null | grep -q "$CAPTURE_SCRIPT"; then + crontab -l | grep -v "$CAPTURE_SCRIPT" | crontab - + echo "✓ Cron job removed" +else + echo "⚠ No cron job found" +fi + +echo "" +echo "Uninstall complete." +echo "" +echo "Note: Log file and configuration are preserved." +echo " Config: ${SCRIPT_DIR}/picupper.conf" +echo " Logs: /var/log/picupper.log" +echo "" +echo "To completely remove, also delete:" +echo " rm -rf ${SCRIPT_DIR}" +echo " sudo rm /var/log/picupper.log"