(function () { function restartPreview() { const img = document.getElementById("preview_img"); if (!img) { return; } img.src = `/preview.mjpg?t=${Date.now()}`; } function setResolutionInputs(width, height, fps) { document.getElementById("width_input").value = String(width || ""); document.getElementById("height_input").value = String(height || ""); document.getElementById("fps_input").value = String(fps || ""); const preset = `${width}x${height}@${fps}`; const sel = document.getElementById("resolution_select"); const hasPreset = Array.from(sel.options).some((opt) => opt.value === preset); sel.value = hasPreset ? preset : ""; } async function api(path) { const response = await fetch(path); if (!response.ok) { throw new Error(await response.text()); } return response.json(); } function fmtBytes(n) { if (n < 1024) { return `${n} B`; } if (n < 1024 * 1024) { return `${(n / 1024).toFixed(1)} KB`; } return `${(n / (1024 * 1024)).toFixed(1)} MB`; } async function refreshAll() { const [health, photos] = await Promise.all([api("/api/health"), api("/api/photos")]); const camera = health.camera || {}; const widthInput = document.getElementById("width_input"); if (widthInput.dataset.initialized !== "1") { setResolutionInputs(camera.requested_width, camera.requested_height, camera.requested_fps); widthInput.dataset.initialized = "1"; } document.getElementById("status").textContent = camera.ok ? `Camera OK\nSource: ${camera.source}\nBackend: ${camera.backend}\nActive: ${camera.profile || "-"}\nRequested: ${camera.requested_profile}\nPreferred RS Serial: ${camera.preferred_realsense_serial || "-"}\nConfig RS Serial: ${camera.config_realsense_serial || "-"}\nFallback RS Serial: ${camera.configured_realsense_serial || "-"}\nActive RS Serial: ${camera.realsense_serial || "-"}\nSamples: ${photos.items.length}` : `Camera not ready\nSource: ${camera.source}\nRequested: ${camera.requested_profile}\nPreferred RS Serial: ${camera.preferred_realsense_serial || "-"}\nConfig RS Serial: ${camera.config_realsense_serial || "-"}\nFallback RS Serial: ${camera.configured_realsense_serial || "-"}\nActive RS Serial: ${camera.realsense_serial || "-"}\nError: ${camera.last_error || "-"}`; document.getElementById("camera_status").textContent = JSON.stringify(health, null, 2); const gallery = document.getElementById("gallery"); gallery.innerHTML = ""; for (const item of photos.items) { const card = document.createElement("article"); card.className = "card"; card.innerHTML = `
${item.name}
${fmtBytes(item.size)}
Download
`; gallery.appendChild(card); } gallery.querySelectorAll("button.danger").forEach((btn) => { btn.addEventListener("click", async () => { const { name } = btn.dataset; await api(`/api/delete?name=${encodeURIComponent(name)}`); await refreshAll(); }); }); } document.getElementById("capture_btn").addEventListener("click", async () => { const status = document.getElementById("status"); status.textContent = "Capturing..."; try { const resp = await api("/api/capture"); status.textContent = `Saved: ${resp.name}`; await refreshAll(); } catch (e) { status.textContent = `Capture failed\n${e.message}`; } }); document.getElementById("resolution_select").addEventListener("change", (e) => { const value = e.target.value; const match = value.match(/^(\d+)x(\d+)@(\d+)$/); if (!match) { return; } setResolutionInputs(Number(match[1]), Number(match[2]), Number(match[3])); }); document.getElementById("apply_resolution_btn").addEventListener("click", async () => { const width = Number(document.getElementById("width_input").value); const height = Number(document.getElementById("height_input").value); const fps = Number(document.getElementById("fps_input").value); const status = document.getElementById("status"); status.textContent = `Applying resolution ${width}x${height}@${fps}...`; try { const resp = await api( `/api/set_resolution?width=${encodeURIComponent(width)}&height=${encodeURIComponent(height)}&fps=${encodeURIComponent(fps)}` ); const camera = resp.camera || {}; setResolutionInputs(camera.requested_width, camera.requested_height, camera.requested_fps); restartPreview(); await refreshAll(); } catch (e) { status.textContent = `Resolution change failed\n${e.message}`; } }); document.getElementById("refresh_btn").addEventListener("click", refreshAll); refreshAll().catch((e) => { document.getElementById("status").textContent = String(e); }); setInterval(() => { refreshAll().catch(() => {}); }, 10000); })();