Files
timi/AGENTS.md
2026-04-25 13:31:17 +03:00

6.0 KiB

AGENTS.md — SciCam Logger

What this is

Android camera app (scicam/) for scientific archiving. Captures images + JSON sidecars. Exposes a NanoHTTPD REST API so a host computer can trigger captures remotely.

Build & Deploy

Host build (requires ANDROID_HOME, JDK 17)

cd scicam
./gradlew assembleDebug
adb install app/build/outputs/apk/debug/app-debug.apk

Docker build (requires Docker; adb stays on host)

cd scicam
./docker-build.sh
adb install app/build/outputs/apk/debug/app-debug.apk
  • Min SDK 24, target SDK 34, JVM 17.
  • Build files are Groovy DSL (.gradle), not Kotlin DSL.

API

Server runs on device port 8080. Device IP is shown in the app UI.

api_spec.yaml at repo root is the OpenAPI 3.0 source of truth for endpoints.

Endpoint Method Purpose
/api GET API metadata
/status GET Current item_id, tags, locked, last_qr, last_capture, auto_capture, debug
/captures GET List all images and videos on device with sidecar status.
/photo/last GET Download the most recent capture as JPEG. Returns 404 if none.
/photo/<filename> GET Download a specific photo by filename (e.g. 20260101_120000_ITEM.jpg). Returns 404 if not found.
/video/last GET Download the most recent video as MP4. Returns 404 if none.
/video/<filename> GET Download a specific video by filename (e.g. 20260101_120000_ITEM.mp4). Returns 404 if not found.
/sidecar/<filename> GET Download JSON sidecar for a given base filename. Returns 404 if not found.
/settings POST Set item_id, tags, lock (boolean), debug (boolean). Returns updated state.
/capture POST Trigger photo. Use --max-time 15. Returns {success, filename, uri}.
/record POST Toggle video recording. Returns {recording, filename, duration_ms}.
/auto-capture POST Set enabled (boolean). Enables/disables QR auto-capture. Returns updated state.
/events GET SSE stream. Broadcasts capture results as data: <json>\n\n.

Critical: POST only for /capture, /settings, and /auto-capture. GET returns 404.

Testing

Run the API client test suite against a device on the same network:

./scicam_api_test.sh <device-ip>
  • Requires jq (used to parse capture-filename responses).
  • Add new API endpoints to this script as they are added to SciCamApiServer.kt.

Architecture Notes

  • MainActivity.kt implements SciCamApiServer.ApiListener. The server posts camera control to the UI thread but reads state fields directly.
  • Images → Pictures/SciCam/ (MediaStore, visible over MTP). Sidecars → Documents/SciCam/.
  • MetadataLogger.kt builds sidecar JSON with EXIF + camera_settings.
  • BoofCV is wired in for in-preview QR detection (replaced the ZXing Activity hop). CameraX + MediaStore storage unchanged.
  • capture() blocks up to 5 s waiting for the CameraX callback; curl callers should still use --max-time 15.

Clients

Cross-platform API clients live in clients/ as Git submodules. Upstreams point to Gitea tami/ org. On a fresh clone, run:

git submodule update --init

Gitea Workflow

  • Remotes point to https://git.telavivmakers.space. The tami org owns all repos (tami/timi, tami/go-scicam, tami/web-scicam).
  • Token lives at ~/.config/timi/gitea-token. ~/.bashrc exports it as GITEA_SERVER_TOKEN.
  • No tea CLI installed. For API operations (create/delete repos, transfer), use raw curl against the Gitea REST API:
    curl -s -X POST "https://git.telavivmakers.space/api/v1/org/tami/repos?token=$(cat ~/.config/timi/gitea-token)" \
         -H "Content-Type: application/json" -d '{"name":"repo-name","private":false}'
    
  • HTTPS push requires embedding the token in the URL, then stripping it afterward so credentials are not written to .git/config:
    git remote set-url origin "https://$(cat ~/.config/timi/gitea-token)@git.telavivmakers.space/tami/REPO.git"
    git push -u origin master
    git remote set-url origin https://git.telavivmakers.space/tami/REPO.git
    

Go CLI (clients/go-scicam/)

cd clients/go-scicam
go build -o go-scicam
go test ./...

# Usage
./go-scicam status 192.168.1.42
./go-scicam settings 192.168.1.42 -item-id=ITEM-001 -tags=archive,lab -lock=true
./go-scicam capture 192.168.1.42
./go-scicam snapshot 192.168.1.42 -o custom.jpg
./go-scicam watch 192.168.1.42 -auto-download
./go-scicam photo -filename=20260101_120000_ITEM.jpg -o output.jpg

The CLI reads default values from scicam/.env in the current working directory (key scicam_host_ip). The SCICAM_HOST environment variable overrides the file. scicam/.env is gitignored.

Web Client (clients/web-scicam/)

Static vanilla-JS page. Open index.html in a browser or serve with any static server.

cd clients/web-scicam
node --test test.js

Dashboard (dashboard/)

Terminal UI for monitoring and auto-syncing multiple SciCam devices to ~/timi/capture. Built in Rust with ratatui + tokio.

cd dashboard
cargo build --release
./target/release/scicam-dashboard

Key controls:

  • ↑/↓ j/k — Navigate devices
  • a — Add device (enter Name + IP)
  • d — Delete selected device
  • r / R — Refresh one / all devices
  • s / S — Sync one / all devices now
  • w — Toggle SSE watch (live capture events)
  • q — Quit

The dashboard polls registered devices every 10s. Devices marked auto_sync download missing .jpg, .mp4, and .json sidecars automatically. Manual syncs via s/S are always available.

Device registry and config live at timi.conf in the repo root (/home/user/timi/timi.conf). capture_dir defaults to ~/timi/capture.

Future Roadmap (do not break)

  • Database sync is planned. It must be non-destructive to images/sidecars.
  • This is an archive and dataset for audio-visual inventory. Treat existing files as immutable.
  • The API-first UI (api-first branch heritage) is the primary interface for automated capture.