Files
2026-08-09 15:56:20 +08:00

60 lines
1.9 KiB
Bash

#!/usr/bin/env bash
set -euo pipefail
camera_serial="${1:-}"
camera_label="${2:-camera}"
capture_width="${OMNI_CAMERA_DISCOVERY_WIDTH:-1280}"
capture_height="${OMNI_CAMERA_DISCOVERY_HEIGHT:-720}"
timeout_sec="${OMNI_CAMERA_DISCOVERY_TIMEOUT_SEC:-10}"
die() {
echo "[camera-discovery] ${camera_label}: $*" >&2
exit 1
}
[[ -n "${camera_serial}" ]] || die "camera serial is required"
[[ "${timeout_sec}" =~ ^[0-9]+$ ]] || die "OMNI_CAMERA_DISCOVERY_TIMEOUT_SEC must be a non-negative integer"
command -v udevadm >/dev/null 2>&1 || die "missing required command: udevadm"
command -v v4l2-ctl >/dev/null 2>&1 || die "missing required command: v4l2-ctl"
shopt -s nullglob
deadline=$((SECONDS + timeout_sec))
while true; do
matches=()
serial_nodes=()
for device in /dev/video*; do
[[ -c "${device}" ]] || continue
device_serial="$(
udevadm info --query=property --name="${device}" 2>/dev/null \
| sed -n 's/^ID_SERIAL_SHORT=//p' \
| head -1
)"
[[ "${device_serial}" == "${camera_serial}" ]] || continue
serial_nodes+=("${device}")
formats="$(v4l2-ctl -d "${device}" --list-formats-ext 2>/dev/null || true)"
grep -q "'MJPG'" <<<"${formats}" || continue
grep -q "Size: Discrete ${capture_width}x${capture_height}" <<<"${formats}" || continue
matches+=("${device}")
done
if (( ${#matches[@]} == 1 )); then
echo "[camera-discovery] ${camera_label}: serial=${camera_serial} -> ${matches[0]} (MJPG ${capture_width}x${capture_height})" >&2
printf '%s\n' "${matches[0]}"
exit 0
fi
if (( ${#matches[@]} > 1 )); then
die "serial=${camera_serial} matched multiple MJPG nodes: ${matches[*]}"
fi
if (( SECONDS >= deadline )); then
if (( ${#serial_nodes[@]} == 0 )); then
die "serial=${camera_serial} was not found under /dev/video*"
fi
die "serial=${camera_serial} has no MJPG ${capture_width}x${capture_height} node; serial nodes: ${serial_nodes[*]}"
fi
sleep 0.2
done