Discovers ONVIF cameras (Hikvision/Annke) over WS-Discovery, keeps a server-side registry and an encrypted credential store, and serves info, snapshot and credentials routes for each camera. The home page is now a Server Component that lists known cameras from the registry on load, without a scan (vrek iss-a0hz0py). The snapshot refresh rate lives in the URL (?refresh=), and a scan refreshes the server-rendered list. Route input is validated with zod (iss-rjqy3hy), and /api/discover no longer returns raw error messages (iss-dbwgww8). Adds @tanstack/react-query and zod as dependencies, with a QueryClient provider in the root layout. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
36 lines
1.4 KiB
TypeScript
36 lines
1.4 KiB
TypeScript
// Checks ONVIF login, profiles and snapshot for one camera, outside of Next.js.
|
|
// The camera must be in .data/cameras.json (run a scan in the app first).
|
|
// Usage: npx tsx --env-file=.env.local --conditions=react-server scripts/camera-check.ts <id-or-ip>
|
|
import { readFileSync, writeFileSync } from "node:fs";
|
|
import { getCameraInfo, getSnapshot } from "../src/lib/camera";
|
|
import type { CameraRecord } from "../src/lib/camera-registry";
|
|
|
|
const [idOrHost] = process.argv.slice(2);
|
|
if (!idOrHost) {
|
|
console.error("Usage: scripts/camera-check.ts <id-or-ip>");
|
|
process.exit(1);
|
|
}
|
|
|
|
const registry: Record<string, CameraRecord> = JSON.parse(
|
|
readFileSync(".data/cameras.json", "utf8"),
|
|
);
|
|
const record = Object.values(registry).find((r) => r.id === idOrHost || r.host === idOrHost);
|
|
if (!record) {
|
|
console.error(`${idOrHost} is not in .data/cameras.json; scan the network first.`);
|
|
process.exit(1);
|
|
}
|
|
const target = { id: record.id, host: record.host, port: record.port };
|
|
console.log(`Camera ${record.id} at ${record.host}:${record.port}`);
|
|
|
|
(async () => {
|
|
try {
|
|
console.log(JSON.stringify(await getCameraInfo(target), null, 2));
|
|
const snap = await getSnapshot(target);
|
|
writeFileSync("snapshot.jpg", snap.body);
|
|
console.log(`Snapshot: ${snap.contentType}, ${snap.body.length} bytes -> snapshot.jpg`);
|
|
} catch (err) {
|
|
console.error(`Error (${(err as Error).name}):`, err instanceof Error ? err.message : err);
|
|
}
|
|
process.exit(0);
|
|
})();
|