diff --git a/README.md b/README.md index 9686119..c15a61c 100644 --- a/README.md +++ b/README.md @@ -117,6 +117,11 @@ curl http://localhost:8000/health # → {"status":"ok"} curl -I http://localhost:3000 # → HTTP 200 ``` +> **Do the first run camera-less.** Complete steps 0–5 and pass the health +> checks above with no cameras attached, then connect the cameras (see the +> camera setup guides under `docs/`) and re-verify. When something fails, +> this isolates the fault to the camera layer instead of the whole build. + ### Creating an SD card image ```bash diff --git a/docs/developers/device_setup_pi5_imx519.qmd b/docs/developers/device_setup_pi5_imx519.qmd index 886c701..d514d6c 100644 --- a/docs/developers/device_setup_pi5_imx519.qmd +++ b/docs/developers/device_setup_pi5_imx519.qmd @@ -33,7 +33,7 @@ The actual camera connection looks like this: ![Camera Connection Actual](../_static/imgs/imx519_ribbon_connection.JPG) -Make sure the ribbon cable is properly seated in the connector with the **blue stiffener facing outward** (toward the Ethernet port) and the metal contacts facing inward toward the board. +Make sure the ribbon cable is fully and squarely seated in the connector before closing the retaining clip. Orientation on the Pi side is the same for both ports: the cable's **metal contacts face the Ethernet port**, with the blue stiffener toward the board's front edge (HDMI/USB-C side) — see the dual-camera photo below. ### Dual Camera Connection on Raspberry Pi 5 diff --git a/docs/developers/sd_card_distribution.qmd b/docs/developers/sd_card_distribution.qmd index 3d5d7e9..ab5d4e5 100644 --- a/docs/developers/sd_card_distribution.qmd +++ b/docs/developers/sd_card_distribution.qmd @@ -137,6 +137,7 @@ Raspberry Pi OS Bookworm replaced `dhcpcd` + `wpa_supplicant` with NetworkManage - **Preferred:** use Raspberry Pi Imager's *Advanced options* (gear icon, or `Ctrl+Shift+X`) when flashing to preconfigure the Wi-Fi SSID and password before the card is ever booted. - **Post-flash:** configure Wi-Fi via NetworkManager, e.g. `sudo nmcli device wifi connect "" password ""`, or by dropping a NetworkManager keyfile connection profile under `/etc/NetworkManager/system-connections/`. +- **Enable SSH in the same *Advanced options* screen** (public-key auth if possible). Headless provisioning is impossible without it: on a fresh Raspberry Pi OS Lite install SSH is off by default, and there is no way in afterwards short of attaching a keyboard and display. ::: --- diff --git a/docs/users/operator-card-rionegro.qmd b/docs/users/operator-card-rionegro.qmd index 339ab42..c76aa84 100644 --- a/docs/users/operator-card-rionegro.qmd +++ b/docs/users/operator-card-rionegro.qmd @@ -38,12 +38,12 @@ Cierre la sesión en la aplicación y vuelva a entrar. Casi siempre es suficient 1. Revise que el selector del lente esté en **MF** (ver arriba). 2. Apague y encienda esa cámara. -3. Presione **Ctrl+Alt+F2**, escriba `sudo systemctl restart dtk`, presione Enter y vuelva a la aplicación con **Ctrl+Alt+F1**. +3. Presione **Ctrl+Alt+F2**, escriba `sudo systemctl restart dtk` y presione Enter. **La pantalla no muestra nada después del comando: es normal.** Espere unos 30 segundos y vuelva a la aplicación con **Ctrl+Alt+F1**. 4. Solo si nada de esto funciona: apague todo de forma segura (ver arriba) y vuelva a encender. ## Si la aplicación se congela -Presione **Ctrl+Alt+F2**, escriba `sudo systemctl restart dtk`, presione Enter y vuelva a la aplicación con **Ctrl+Alt+F1**. +Presione **Ctrl+Alt+F2**, escriba `sudo systemctl restart dtk` y presione Enter. **La pantalla no muestra nada después del comando: es normal.** Espere unos 30 segundos y vuelva a la aplicación con **Ctrl+Alt+F1**. ## Contacto diff --git a/docs/users/setting-up-gphoto2-cams.qmd b/docs/users/setting-up-gphoto2-cams.qmd index 51799bd..eac1b7f 100644 --- a/docs/users/setting-up-gphoto2-cams.qmd +++ b/docs/users/setting-up-gphoto2-cams.qmd @@ -16,7 +16,11 @@ To be fully compatible with the Digitization Toolkit software, cameras should su ## Connect the cameras to the Raspberry Pi - **Requirements**: - - 2 x USB 2.0 Type-A to Mini-B (5-pin) cables + - 2 x USB 2.0 Type-A to Mini-B (5-pin) **data** cables + +::: {.callout-warning appearance="simple"} +Many mini-B cables sold today are **charge-only** and carry no data lines. A charge-only cable produces no symptom on the camera and nothing on the Pi — the camera simply never appears. Two brand-new cables failed exactly this way during hardware validation (one intermittent `error -71` in `dmesg`, then electrical silence). Use cables known to carry data, seat both ends firmly, and verify with `lsusb` (below) before suspecting anything else. +::: - **Connections**: - Camera side: Plug into the middle port (marked with the USB trident icon). @@ -26,6 +30,17 @@ To be fully compatible with the Digitization Toolkit software, cameras should su ![USB connection to the Raspberry Pi - dual camera setup in ports USB 3.0](../../_static/imgs/cannon_EOS-RebelT7-usb2RPi.JPG){width=400} +## Verify the connection + +With both cameras connected and **switched on**, run on the Pi: + +```bash +lsusb # expect one "Canon, Inc." line per camera body +gphoto2 --auto-detect # expect both cameras listed +``` + +If a camera is missing: reseat both cable ends, power-cycle the camera body, and check `dmesg | tail` — repeated `error -71` messages point to a bad cable or a poorly seated plug; total silence with a powered-on camera points to a charge-only cable. + ## Canon EOS Rebel T7 - Set the focus mode to "Manual Focus": On the lens switch, set the focus mode to MF (Manual Focus). @@ -48,3 +63,7 @@ To be fully compatible with the Digitization Toolkit software, cameras should su 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. ::: +::: {.callout-important appearance="simple"} +When Auto power off fires, the camera does not just sleep — it **drops off the USB bus entirely** (`lsusb` no longer lists it), and the software cannot wake it: a slept body looks exactly like a disconnected one, and the interface will show the camera as not connected. To bring it back, **half-press the shutter button** on the camera and wait a few seconds for it to re-enumerate. Keep this in mind before unplugging anything or restarting services. +::: + diff --git a/nginx.conf b/nginx.conf index 919f83d..e7995b8 100644 --- a/nginx.conf +++ b/nginx.conf @@ -31,7 +31,12 @@ http { proxy_buffering off; proxy_read_timeout 120s; - # Allow large uploads (captured documents / RAW files) + # Allow large uploads (captured documents / RAW files). + # Keep in lockstep with the app-level cap (MAX_UPLOAD_BYTES / + # DTK_MAX_UPLOAD_BYTES, backend app/core/config.py): nginx rejects + # oversized bodies before Starlette spools them to a temp file, so + # this is the effective guard; the in-app check is defense in depth + # for setups without nginx (dev). (NEH-177) client_max_body_size 100m; } diff --git a/scripts/install-kiosk-service.sh b/scripts/install-kiosk-service.sh index 7c339c6..98b293e 100755 --- a/scripts/install-kiosk-service.sh +++ b/scripts/install-kiosk-service.sh @@ -120,13 +120,17 @@ sudo systemctl enable triggerhappy >/dev/null 2>&1 || true sudo systemctl restart triggerhappy >/dev/null 2>&1 || true echo " Ctrl+Alt+F2 → tty2 shell, Ctrl+Alt+F1 → kiosk (verify 'ps -o user -C thd' shows root)" -# ── 2d. Chromium managed policy — disable the password manager (NEH-67) ───── -# The kiosk browser must never offer to save passwords or autofill payment / -# address data. A managed policy JSON enforces this regardless of the launch -# flags. Raspberry Pi OS ships Chromium under one of two policy roots depending -# on the build (chromium vs chromium-browser); installing into both is harmless -# and covers either. No network access is needed. -echo "→ Installing Chromium managed policy (disable password manager)..." +# ── 2d. Chromium managed policies — password manager (NEH-67), translate ──── +# (NEH-185). The kiosk browser must never offer to save passwords or autofill +# payment / address data, and must never show the "translate this page?" +# popup over the UI. Managed policy JSONs enforce this regardless of launch +# flags — which matters for translate: Chromium renamed the TranslateUI +# feature to Translate several versions ago, so a --disable-features flag +# silently rots; the policy is version-proof (verified on hardware, bench +# 2026-07-24). Raspberry Pi OS ships Chromium under one of two policy roots +# depending on the build (chromium vs chromium-browser); installing into both +# is harmless and covers either. No network access is needed. +echo "→ Installing Chromium managed policies (password manager, translate)..." for policy_dir in /etc/chromium/policies/managed /etc/chromium-browser/policies/managed; do sudo mkdir -p "$policy_dir" sudo tee "$policy_dir/dtk-no-password-manager.json" > /dev/null << 'EOF' @@ -135,9 +139,15 @@ for policy_dir in /etc/chromium/policies/managed /etc/chromium-browser/policies/ "AutofillAddressEnabled": false, "AutofillCreditCardEnabled": false } +EOF + sudo tee "$policy_dir/dtk-no-translate.json" > /dev/null << 'EOF' +{ + "TranslateEnabled": false +} EOF done echo " /etc/chromium{,-browser}/policies/managed/dtk-no-password-manager.json ✓" +echo " /etc/chromium{,-browser}/policies/managed/dtk-no-translate.json ✓" # ── 3. Remove old kiosk.service if present (replaced by .bash_profile) ────── if systemctl is-enabled kiosk.service &>/dev/null; then diff --git a/scripts/start-kiosk.sh b/scripts/start-kiosk.sh index dbc54d4..0a0578f 100755 --- a/scripts/start-kiosk.sh +++ b/scripts/start-kiosk.sh @@ -27,7 +27,6 @@ exec cage -- chromium-browser \ --noerrdialogs \ --disable-infobars \ --disable-session-crashed-bubble \ - --disable-features=TranslateUI \ --password-store=basic \ --overscroll-history-navigation=0 \ --check-for-update-interval=31536000 \