diff --git a/.env.example b/.env.example index 8f6cd8e..0d5ffff 100644 --- a/.env.example +++ b/.env.example @@ -20,10 +20,10 @@ LOG_LEVEL=info CAMERA_BACKEND=picamera2 # Frontend Configuration -# Set HOST_IP to the Pi's local IP for network access (e.g. 10.0.0.133). -# Leave unset or use localhost for local dev — docker-compose.yml defaults to localhost. +# Set HOST_IP to the Pi's hostname or IP for network access (e.g. digitool.local or 10.0.0.133). +# Leave unset or use localhost for local dev. HOST_IP=localhost -PUBLIC_API_BASE=http://${HOST_IP}:8000 -# Add the Pi's IP here so the backend accepts requests from network devices. -# For local dev, the defaults (localhost:3000 and :5173) are used automatically. -CORS_ORIGINS=["http://localhost:5173","http://localhost:3000"] +# Browser-side API calls are routed through Nginx (/api → backend:8000) +PUBLIC_API_BASE=http://${HOST_IP}/api +# Add origins for both the port-80 Nginx URL and the direct port-3000 fallback. +CORS_ORIGINS=["http://localhost","http://localhost:5173","http://localhost:3000"] diff --git a/.gitignore b/.gitignore index b6008f7..32040b5 100644 --- a/.gitignore +++ b/.gitignore @@ -28,7 +28,11 @@ _logs/ temp/ # Working files -docs/RP-008156-DS-2-picamera2-manual.txt +docs/*.txt # External tools -fisqua/ \ No newline at end of file +fisqua/ + +# Symlinks +dtk-sym +logs-sym diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..268c3a9 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,42 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on Keep a Changelog, and this project uses pre-1.0 semantic versioning. + +## [0.0.0-pre.2] - 2026-05-31 + +### Added + +- **DSLR camera support via gPhoto2** — Canon EOS and compatible USB cameras now work alongside picamera2. Backend auto-selects via `CAMERA_BACKEND=gphoto2` env var. +- **RAW (CR2) capture** — Selecting RAW or RAW+JPEG format now correctly saves `.cr2` files. Previously the camera silently fell back to JPEG on every capture. +- **Orientation / rotation control** — Per-camera post-capture rotation (0°, 90°, 180°, 270° CW) for scanning manuscripts in portrait orientation. JPEG captures are pixel-rotated via Pillow; CR2 files receive an EXIF Orientation tag via piexif so RAW converters auto-rotate. +- **Live preview rotation** — The camera feed in the live-preview viewport reflects the selected rotation in real time so operators can frame shots correctly before capturing. +- **Floating rotation buttons on each camera feed** — Quick-access ↺ / ↻ buttons float over each camera feed (bottom-centre). Clicking them updates both the live preview rotation and the capture rotation without opening the sidebar. State stays in sync with the sidebar orientation control. +- **Nginx reverse proxy** — All traffic now routes through Nginx on port 80 (`/api/*` → backend, `/*` → frontend). Eliminates hard-coded port references in the browser. +- **Network discoverability** — Raspberry Pi is accessible on the local network by hostname (`digitool.local`) and by IP. `HOST_IP` and CORS origins are configured dynamically at startup. +- **Documentation service** — Quarto-based docs rendered and served via Docker; includes device-setup guides for CM4 and Pi 5 + IMX519. +- **SD card distribution guide** — New developer documentation for distributing pre-imaged SD cards. +- **gPhoto2 device-setup guide** — Step-by-step instructions for connecting Canon DSLR cameras. + +### Fixed + +- **CR2 thumbnail in record viewer** — The modal image viewer (`img-viewer-frame`) now shows a renderable JPEG instead of sending the `.cr2` file directly to the browser (which browsers cannot display). The `_preview.jpg` sidecar is served when available. +- **`image_format` reverse mapping** — Camera configuration now correctly returns human-readable values (`JPEG`, `RAW`, `RAW+JPEG`) instead of internal PTP strings. +- **Capture path mismatch** — `GPhoto2Backend.capture_image()` previously returned the originally requested `.jpg` path even when the camera had saved a `.cr2` file. It now returns the actual saved path. +- **imageformat reset on every capture** — `apply_dslr_config()` was overwriting the camera's format setting to JPEG on every shot when no explicit format was configured. It now skips the PTP write when `image_format` is `None`, leaving the camera's own setting intact. +- **Record `format` field hardcoded to `"jpg"`** — The format stored in the database now reflects the actual file extension (e.g. `"cr2"`). + +### Notes + +- Project remains pre-alpha pending replication and validation on additional machines. +- Default capture orientation is 90° (portrait) to match typical book/manuscript scanning setups. +- piexif must be present in the pixi environment (`pixi run python -c "import piexif"`) for CR2 EXIF rotation to apply. + +## [0.0.0-pre.1] + +### Added + +- Initial pre-alpha release baseline. + +[0.0.0-pre.1]: https://github.com/UCSB-AMPLab/digitization-toolkit/releases/tag/pre-alpha diff --git a/README.md b/README.md index 1b0676f..740945c 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,10 @@ An open-source, modular digitization toolkit designed for low-cost, high-quality > Project currently in development. Kick-off: September 2025 > Alpha prototype planned for deployment at SBMAL in June 2026. +## Release History + +See [CHANGELOG.md](CHANGELOG.md) for version history and release notes. + *** ## Quick Start diff --git a/backend b/backend index d9de326..7e25bb6 160000 --- a/backend +++ b/backend @@ -1 +1 @@ -Subproject commit d9de326f17a4e3a67445f4780b50aee292b3b314 +Subproject commit 7e25bb6f212e0e2425987ad416488eb34ffb4941 diff --git a/docker-compose.pi.yml b/docker-compose.pi.yml index b90277f..0c4dc9e 100644 --- a/docker-compose.pi.yml +++ b/docker-compose.pi.yml @@ -9,3 +9,27 @@ services: # Override portable folders with appliance paths - /var/lib/dtk:/var/lib/dtk - /var/log/dtk:/var/log/dtk + + frontend: + environment: + # Route browser-side API calls through Nginx (same-origin, fixes Chrome PNA policy) + # http://digitool.local/api/* → Nginx strips /api → backend:8000/* + - PUBLIC_API_BASE=http://${HOST_IP:-localhost}/api + # ORIGIN must match the URL users open (port 80 via Nginx, no explicit port) + - ORIGIN=http://${HOST_IP:-localhost} + + # ── Nginx reverse proxy ──────────────────────────────────────────────────── + # Puts frontend (:3000) and backend (:8000) behind a single origin (port 80). + # This eliminates the cross-port request that Chrome's Private Network Access + # (PNA) policy blocks when the client is on a .local HTTP address. + # Access the app at: http://digitool.local (instead of :3000) + nginx: + image: nginx:1.25-alpine + ports: + - "80:80" + volumes: + - ./nginx.conf:/etc/nginx/nginx.conf:ro + extra_hosts: + - "host.docker.internal:host-gateway" + depends_on: + - frontend diff --git a/docker-compose.yml b/docker-compose.yml index e9eada5..9ab9c9d 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -84,6 +84,15 @@ services: - NODE_ENV=production # No depends_on db — the frontend is a Node.js API proxy and never connects # to Postgres directly. Removing this lets db and frontend start in parallel. + # No depends_on db — the frontend is a Node.js API proxy and never connects + # to Postgres directly. Removing this lets db and frontend start in parallel. + + docs: + build: + context: ./docs + dockerfile: Dockerfile + ports: + - "8080:80" volumes: postgres_data: diff --git a/docs/.dockerignore b/docs/.dockerignore new file mode 100644 index 0000000..2bb29dd --- /dev/null +++ b/docs/.dockerignore @@ -0,0 +1,4 @@ +# Exclude pre-rendered output and cache from build context. +# The Dockerfile re-renders docs fresh with `quarto render`. +.quarto/ +**/*.quarto_ipynb diff --git a/docs/Dockerfile b/docs/Dockerfile new file mode 100644 index 0000000..0047828 --- /dev/null +++ b/docs/Dockerfile @@ -0,0 +1,8 @@ +FROM ghcr.io/quarto-dev/quarto:1.9.37 AS build +COPY . /site +WORKDIR /site +RUN quarto render --output-dir /site + +FROM nginx:alpine +COPY site/ /usr/share/nginx/html +EXPOSE 80 \ No newline at end of file diff --git a/docs/_quarto.yml b/docs/_quarto.yml index 6f285e1..0c6573c 100644 --- a/docs/_quarto.yml +++ b/docs/_quarto.yml @@ -27,6 +27,9 @@ website: contents: - href: users/external-storage.qmd text: "External Storage" + - section: "Cameras Setup" + contents: + - href: users/setting-up-gphoto2-cams.qmd - section: "Developer Guides" contents: - section: "Hardware Setup Guides" @@ -35,6 +38,10 @@ website: text: "Device Setup: Raspberry Pi CM4 with Cameras" - href: developers/device_setup_pi5_imx519.qmd text: "Device Setup: Raspberry Pi 5 with IMX519 Camera" + - section: "Software Setup Guides" + contents: + - href: developers/sd_card_distribution.qmd + text: "SD Card Distribution" page-footer: center: "Documentation site built: {{< meta date >}}" diff --git a/docs/_static/imgs/cannon-EOS-RebelT7-Mode.jpg b/docs/_static/imgs/cannon-EOS-RebelT7-Mode.jpg new file mode 100644 index 0000000..f5c5be1 Binary files /dev/null and b/docs/_static/imgs/cannon-EOS-RebelT7-Mode.jpg differ diff --git a/docs/_static/imgs/cannon-EOS-RebelT7-config-menu.jpg b/docs/_static/imgs/cannon-EOS-RebelT7-config-menu.jpg new file mode 100644 index 0000000..4fa8398 Binary files /dev/null and b/docs/_static/imgs/cannon-EOS-RebelT7-config-menu.jpg differ diff --git a/docs/_static/imgs/cannon-EOS-RebelT7-flash.jpg b/docs/_static/imgs/cannon-EOS-RebelT7-flash.jpg new file mode 100644 index 0000000..2299b78 Binary files /dev/null and b/docs/_static/imgs/cannon-EOS-RebelT7-flash.jpg differ diff --git a/docs/_static/imgs/cannon-EOS-RebelT7-lensMF.jpg b/docs/_static/imgs/cannon-EOS-RebelT7-lensMF.jpg new file mode 100644 index 0000000..e96470c Binary files /dev/null and b/docs/_static/imgs/cannon-EOS-RebelT7-lensMF.jpg differ diff --git a/docs/_static/imgs/cannon-EOS-RebelT7-usb4cam.JPG b/docs/_static/imgs/cannon-EOS-RebelT7-usb4cam.JPG new file mode 100644 index 0000000..8fe0a35 Binary files /dev/null and b/docs/_static/imgs/cannon-EOS-RebelT7-usb4cam.JPG differ diff --git a/docs/_static/imgs/cannon_EOS-RebelT7-usb2RPi.JPG b/docs/_static/imgs/cannon_EOS-RebelT7-usb2RPi.JPG new file mode 100644 index 0000000..2c86bff Binary files /dev/null and b/docs/_static/imgs/cannon_EOS-RebelT7-usb2RPi.JPG differ diff --git a/docs/developers/device_setup_CM4.qmd b/docs/developers/device_setup_CM4.qmd index ecc9e4e..e492eb4 100644 --- a/docs/developers/device_setup_CM4.qmd +++ b/docs/developers/device_setup_CM4.qmd @@ -2,6 +2,7 @@ title: "Raspberry Pi Compute Module 4 Dual Camera Setup" date-modified: last-modified format: html +lightbox: true --- *** diff --git a/docs/developers/device_setup_pi5_imx519.qmd b/docs/developers/device_setup_pi5_imx519.qmd index b991987..886c701 100644 --- a/docs/developers/device_setup_pi5_imx519.qmd +++ b/docs/developers/device_setup_pi5_imx519.qmd @@ -2,6 +2,7 @@ title: "Raspberry Pi 5 IMX519 Camera Setup" date-modified: last-modified format: html +lightbox: true --- *** diff --git a/docs/developers/sd_card_distribution.qmd b/docs/developers/sd_card_distribution.qmd new file mode 100644 index 0000000..8e5ec6c --- /dev/null +++ b/docs/developers/sd_card_distribution.qmd @@ -0,0 +1,156 @@ +--- +title: "SD Card Distribution" +date-modified: last-modified +format: html +--- + +*** + +This guide explains how to prepare and ship a Raspberry Pi SD card image with the Digitization Toolkit pre-installed, so the recipient can plug it in and access the application from any device on the same network — without any manual IP configuration. + +--- + +## How It Works + +The Raspberry Pi broadcasts its hostname over the local network using **mDNS** (via the Avahi daemon, pre-installed on Raspberry Pi OS). This means any device on the same network can reach the Pi at `http://.local` without knowing its IP address. + +The application is configured to use this hostname instead of a hardcoded IP, so the image works on any network regardless of what IP the router assigns. + +--- + +## Preparing the Master Image + +### 1. Set a meaningful hostname + +Choose a hostname that identifies the device. The current convention is `digitool`: + +```bash +sudo hostnamectl set-hostname digitool +``` + +Verify: + +```bash +hostname +# digitool +``` + +The Pi will be reachable at `http://digitool.local` on the destination network. + +### 2. Confirm Avahi is running + +Avahi (mDNS) is pre-installed on Raspberry Pi OS. Confirm it is active: + +```bash +systemctl is-enabled avahi-daemon +systemctl is-active avahi-daemon +``` + +Both should return `enabled` / `active`. If not: + +```bash +sudo systemctl enable --now avahi-daemon +``` + +### 3. Update `.env` to use the hostname + +In `/home/pi/dtk/.env`, set `HOST_IP` to the `.local` hostname: + +```bash +HOST_IP=digitool.local +CORS_ORIGINS=["http://digitool.local:5173","http://digitool.local:3000","http://localhost:5173","http://localhost:3000"] +``` + +`PUBLIC_API_BASE` resolves automatically from `HOST_IP`: + +```bash +PUBLIC_API_BASE=http://${HOST_IP}:8000 +``` + +### 4. Rebuild and verify the frontend container + +The `PUBLIC_API_BASE` variable is baked into the compiled frontend at build time. After editing `.env`, rebuild: + +```bash +cd /home/pi/dtk +docker compose -f docker-compose.yml -f docker-compose.pi.yml up -d --build --force-recreate +``` + +Open `http://digitool.local:3000` from another device on the same network to confirm it loads. + +### 5. Image the SD card + +Once the system is working correctly, shut down the Pi cleanly and image the SD card from another machine: + +**macOS / Linux:** +```bash +# Identify the SD card device (e.g. /dev/disk4 or /dev/sdb) +diskutil list # macOS +lsblk # Linux + +# Create compressed image +sudo dd if=/dev/sdX bs=4M status=progress | gzip > dtk-$(date +%Y%m%d).img.gz +``` + +**Windows:** Use [Raspberry Pi Imager](https://www.raspberrypi.com/software/) or [Win32DiskImager](https://win32diskimager.org/) to read the card to a `.img` file. + +::: {.callout-tip} +## Shrink before imaging +Tools like [PiShrink](https://github.com/Drewsif/PiShrink) can reduce the image size significantly before compression by trimming unused filesystem space. +::: + +--- + +## Flashing and Delivering the Image + +Flash the image onto a new SD card: + +```bash +# Linux / macOS +gzip -dc dtk-YYYYMMDD.img.gz | sudo dd of=/dev/sdX bs=4M status=progress +``` + +Or use Raspberry Pi Imager → *Use custom image* → select the `.img.gz` file. + +--- + +## What the Recipient Needs to Do + +Nothing, in most cases. They: + +1. Insert the SD card and power on the Pi. +2. Connect the Pi to their local network (Ethernet or Wi-Fi configured before imaging). +3. Open `http://digitool.local:3000` from any browser on the same network. + +::: {.callout-note} +## Wi-Fi pre-configuration +If the destination uses Wi-Fi (not Ethernet), configure the network credentials on the SD card **before** shipping. The easiest way is via Raspberry Pi Imager's *Advanced options* when flashing, or by placing a `wpa_supplicant.conf` in the `/boot` partition after flashing. +::: + +--- + +## Troubleshooting + +**`digitool.local` doesn't resolve** + +- Windows requires [Bonjour](https://support.apple.com/kb/DL999) (installed automatically with iTunes or iCloud). Windows 10 (1803+) supports mDNS natively. +- Try pinging: `ping digitool.local` +- As a fallback, find the IP via the router's DHCP client list and use it directly. + +**CORS errors in the browser** + +The frontend origin must match `CORS_ORIGINS` in `.env`. If you changed the hostname or port, update that list and restart the backend: + +```bash +cd /home/pi/dtk/backend && pixi run dev +``` + +**Two Pis on the same network** + +mDNS hostnames must be unique per network. Change the hostname on one of them: + +```bash +sudo hostnamectl set-hostname digitool-2 +``` + +And update `HOST_IP` and `CORS_ORIGINS` in `.env` accordingly, then rebuild the frontend container. diff --git a/docs/site/developers/device_setup_CM4.html b/docs/site/developers/device_setup_CM4.html index 27d8a2e..36d1ea4 100644 --- a/docs/site/developers/device_setup_CM4.html +++ b/docs/site/developers/device_setup_CM4.html @@ -6,7 +6,7 @@ - + Raspberry Pi Compute Module 4 Dual Camera Setup – Digitization Toolkit Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+ + +
+ + + +
+ +
+
+

SD Card Distribution

+
+ + + +
+ + +
+
Published
+
+

May 30, 2026

+
+
+ +
+
Modified
+
+

May 30, 2026

+
+
+ +
+ + + +
+ + +
+

This guide explains how to prepare and ship a Raspberry Pi SD card image with the Digitization Toolkit pre-installed, so the recipient can plug it in and access the application from any device on the same network — without any manual IP configuration.

+
+
+

How It Works

+

The Raspberry Pi broadcasts its hostname over the local network using mDNS (via the Avahi daemon, pre-installed on Raspberry Pi OS). This means any device on the same network can reach the Pi at http://<hostname>.local without knowing its IP address.

+

The application is configured to use this hostname instead of a hardcoded IP, so the image works on any network regardless of what IP the router assigns.

+
+
+
+

Preparing the Master Image

+
+

1. Set a meaningful hostname

+

Choose a hostname that identifies the device. The current convention is digitool:

+
sudo hostnamectl set-hostname digitool
+

Verify:

+
hostname
+# digitool
+

The Pi will be reachable at http://digitool.local on the destination network.

+
+
+

2. Confirm Avahi is running

+

Avahi (mDNS) is pre-installed on Raspberry Pi OS. Confirm it is active:

+
systemctl is-enabled avahi-daemon
+systemctl is-active avahi-daemon
+

Both should return enabled / active. If not:

+
sudo systemctl enable --now avahi-daemon
+
+
+

3. Update .env to use the hostname

+

In /home/pi/dtk/.env, set HOST_IP to the .local hostname:

+
HOST_IP=digitool.local
+CORS_ORIGINS=["http://digitool.local:5173","http://digitool.local:3000","http://localhost:5173","http://localhost:3000"]
+

PUBLIC_API_BASE resolves automatically from HOST_IP:

+
PUBLIC_API_BASE=http://${HOST_IP}:8000
+
+
+

4. Rebuild and verify the frontend container

+

The PUBLIC_API_BASE variable is baked into the compiled frontend at build time. After editing .env, rebuild:

+
cd /home/pi/dtk
+docker compose -f docker-compose.yml -f docker-compose.pi.yml up -d --build --force-recreate
+

Open http://digitool.local:3000 from another device on the same network to confirm it loads.

+
+
+

5. Image the SD card

+

Once the system is working correctly, shut down the Pi cleanly and image the SD card from another machine:

+

macOS / Linux:

+
# Identify the SD card device (e.g. /dev/disk4 or /dev/sdb)
+diskutil list           # macOS
+lsblk                   # Linux
+
+# Create compressed image
+sudo dd if=/dev/sdX bs=4M status=progress | gzip > dtk-$(date +%Y%m%d).img.gz
+

Windows: Use Raspberry Pi Imager or Win32DiskImager to read the card to a .img file.

+
+
+
+ +
+
+TipShrink before imaging +
+
+
+

Tools like PiShrink can reduce the image size significantly before compression by trimming unused filesystem space.

+
+
+
+
+
+
+

Flashing and Delivering the Image

+

Flash the image onto a new SD card:

+
# Linux / macOS
+gzip -dc dtk-YYYYMMDD.img.gz | sudo dd of=/dev/sdX bs=4M status=progress
+

Or use Raspberry Pi Imager → Use custom image → select the .img.gz file.

+
+
+
+

What the Recipient Needs to Do

+

Nothing, in most cases. They:

+
    +
  1. Insert the SD card and power on the Pi.
  2. +
  3. Connect the Pi to their local network (Ethernet or Wi-Fi configured before imaging).
  4. +
  5. Open http://digitool.local:3000 from any browser on the same network.
  6. +
+
+
+
+ +
+
+NoteWi-Fi pre-configuration +
+
+
+

If the destination uses Wi-Fi (not Ethernet), configure the network credentials on the SD card before shipping. The easiest way is via Raspberry Pi Imager’s Advanced options when flashing, or by placing a wpa_supplicant.conf in the /boot partition after flashing.

+
+
+
+
+
+

Troubleshooting

+

digitool.local doesn’t resolve

+
    +
  • Windows requires Bonjour (installed automatically with iTunes or iCloud). Windows 10 (1803+) supports mDNS natively.
  • +
  • Try pinging: ping digitool.local
  • +
  • As a fallback, find the IP via the router’s DHCP client list and use it directly.
  • +
+

CORS errors in the browser

+

The frontend origin must match CORS_ORIGINS in .env. If you changed the hostname or port, update that list and restart the backend:

+
cd /home/pi/dtk/backend && pixi run dev
+

Two Pis on the same network

+

mDNS hostnames must be unique per network. Change the hostname on one of them:

+
sudo hostnamectl set-hostname digitool-2
+

And update HOST_IP and CORS_ORIGINS in .env accordingly, then rebuild the frontend container.

+ + +
+ +
+ +
+ + + + + + \ No newline at end of file diff --git a/docs/site/index.html b/docs/site/index.html index d30e68c..e011d12 100644 --- a/docs/site/index.html +++ b/docs/site/index.html @@ -6,7 +6,7 @@ - + Digitization Toolkit Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +
+ + +
+ + + +
+ +
+
+

Setting Up gPhoto2-Compatible Cameras

+
+ + + +
+ + +
+
Published
+
+

May 30, 2026

+
+
+ +
+
Modified
+
+

May 30, 2026

+
+
+ +
+ + + +
+ + +
+ +
+
+

For a comprehensive list of gPhoto2-supported cameras, visit the official support page.

+

To be fully compatible with the Digitization Toolkit software, cameras should support all of the following capabilities: Image Capture, Trigger Capture, Live View, and Configuration.

+
+
+
+
+

Connect the cameras to the Raspberry Pi

+
    +
  • Requirements: +
      +
    • 2 x USB 2.0 Type-A to Mini-B (5-pin) cables
    • +
  • +
  • Connections: +
      +
    • Camera side: Plug into the middle port (marked with the USB trident icon).
    • +
    • Raspberry Pi side: Plug into any USB-A port (preferably a blue USB 3.0 port).
    • +
  • +
+
+
+

USB connection from the camera side

+
USB connection from the camera side
+
+
+
+
+

USB connection to the Raspberry Pi - dual camera setup in ports USB 3.0

+
USB connection to the Raspberry Pi - dual camera setup in ports USB 3.0
+
+
+
+
+

Canon EOS Rebel T7

+
    +
  • Set the focus mode to “Manual Focus”: On the lens switch, set the focus mode to MF (Manual Focus).
  • +
+
+
+

Canon EF-S 18-55mm lens attached to a DSLR camera body

+
Canon EF-S 18-55mm lens attached to a DSLR camera body
+
+
+
    +
  • Set the mode to Manual: rotate the mode dial to M (Manual).
  • +
+
+
+

Canon EOS camera mode dial in manual mode

+
Canon EOS camera mode dial in manual mode
+
+
+
    +
  • Retract the built-in flash: If the flash pops up after turning on the camera, push the flash head down into the closed position.
  • +
+
+
+

Canon EOS camera built-in flash in closed position

+
Canon EOS camera built-in flash in closed position
+
+
+
    +
  • Set Auto power off: From the camera menu, find the Auto power off setting and set it to 15 minutes.
  • +
+
+
+

Canon EOS camera menu screen auto power off

+
Canon EOS camera menu screen auto power off
+
+
+
+
+
+ +
+
+

Disabling Auto power off can result in lens damage. The software will try to power off the camera after 15 minutes of inactivity to prevent this. However, if the Raspberry Pi crashes or is inadvertently powered off while Auto power off is disabled, the camera could remain on indefinitely.

+
+
+
+ + +
+ +
+ +
+ + + + + + + \ No newline at end of file diff --git a/docs/users/setting-up-gphoto2-cams.qmd b/docs/users/setting-up-gphoto2-cams.qmd new file mode 100644 index 0000000..51799bd --- /dev/null +++ b/docs/users/setting-up-gphoto2-cams.qmd @@ -0,0 +1,50 @@ +--- +title: "Setting Up gPhoto2-Compatible Cameras" +date-modified: last-modified +format: html +lightbox: true +--- + +::: {.callout-note appearance="simple" collapse="true"} +## List of gPhoto2 compatible cameras + +For a comprehensive list of gPhoto2-supported cameras, visit the [official support page](http://gphoto.org/proj/libgphoto2/support.php). + +To be fully compatible with the Digitization Toolkit software, cameras should support all of the following capabilities: Image Capture, Trigger Capture, Live View, and Configuration. +::: + +## Connect the cameras to the Raspberry Pi + +- **Requirements**: + - 2 x USB 2.0 Type-A to Mini-B (5-pin) cables + +- **Connections**: + - Camera side: Plug into the middle port (marked with the USB trident icon). + - Raspberry Pi side: Plug into any USB-A port (preferably a blue USB 3.0 port). + +![USB connection from the camera side](../../_static/imgs/cannon-EOS-RebelT7-usb4cam.JPG){width=400} + +![USB connection to the Raspberry Pi - dual camera setup in ports USB 3.0](../../_static/imgs/cannon_EOS-RebelT7-usb2RPi.JPG){width=400} + +## Canon EOS Rebel T7 + +- Set the focus mode to "Manual Focus": On the lens switch, set the focus mode to MF (Manual Focus). + +![Canon EF-S 18-55mm lens attached to a DSLR camera body](../../_static/imgs/cannon-EOS-RebelT7-lensMF.jpg){width=400} + +- Set the mode to Manual: rotate the mode dial to M (Manual). + +![Canon EOS camera mode dial in manual mode](../../_static/imgs/cannon-EOS-RebelT7-Mode.jpg){width=400} + +- Retract the built-in flash: If the flash pops up after turning on the camera, push the flash head down into the closed position. + +![Canon EOS camera built-in flash in closed position](../../_static/imgs/cannon-EOS-RebelT7-flash.jpg){width=400} + +- Set Auto power off: From the camera menu, find the Auto power off setting and set it to 15 minutes. + +![Canon EOS camera menu screen auto power off](../../_static/imgs/cannon-EOS-RebelT7-config-menu.jpg){width=400} + +::: {.callout-caution appearance="simple"} +Disabling Auto power off can result in lens damage. The software will try to power off the camera after 15 minutes of inactivity to prevent this. However, if the Raspberry Pi crashes or is inadvertently powered off while Auto power off is disabled, the camera could remain on indefinitely. +::: + diff --git a/frontend b/frontend index e4b9723..d8d867a 160000 --- a/frontend +++ b/frontend @@ -1 +1 @@ -Subproject commit e4b9723c7d294f75cd748e7dc085849ca6480a17 +Subproject commit d8d867a66e7ad8dad1c013d53ccfd7601a425508 diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 0000000..b518666 --- /dev/null +++ b/nginx.conf @@ -0,0 +1,47 @@ +events { + worker_connections 1024; +} + +http { + server { + listen 80; + server_name _; + + # ── API — strip /api prefix, proxy to native backend on the host ── + # http://digitool.local/api/cameras → http://backend:8000/cameras + location /api/ { + proxy_pass http://host.docker.internal:8000/; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # FastAPI auto-redirects /foo → /foo/ using the Host header, producing + # e.g. Location: http://digitool.local/collections/ + # That would fall through to the frontend (404). Rewrite it so the + # path is prefixed with /api/ again before the browser follows it. + proxy_redirect ~^https?://[^/]+(/.*)$ http://$host/api$1; + + # Disable buffering so live-preview images stream through promptly + proxy_buffering off; + proxy_read_timeout 120s; + + # Allow large uploads (captured documents / RAW files) + client_max_body_size 100m; + } + + # ── Frontend — all other traffic goes to the SvelteKit Node server ── + location / { + proxy_pass http://frontend:3000; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + # WebSocket support (used by Vite HMR in dev mode) + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + } + } +} diff --git a/scripts/setup.sh b/scripts/setup.sh index 08cad4e..5111087 100644 --- a/scripts/setup.sh +++ b/scripts/setup.sh @@ -112,7 +112,20 @@ else fi # --------------------------------------------------------------------------- -# 6. Database initialisation & migrations +# 6. Installing packages and binaries for cameras +# --------------------------------------------------------------------------- + +# gPhoto2 +if sudo apt install -y gphoto2 + echo "gPhoto2 package installed" + echo "" +else + echo "gPhoto2 package not available in apt package manager." + echo "" +fi + +# --------------------------------------------------------------------------- +# 7. Database initialisation & migrations # --------------------------------------------------------------------------- cd "$PROJECT_ROOT" echo "→ Starting database for migration..."