mirror of
https://github.com/BetterCorp/BetterFrame.git
synced 2026-05-26 20:16:35 +00:00
fix(onvif): import discovered cameras as type=onvif with credentials
importDiscoveredCamera was hardcoded to type="rtsp", losing ONVIF identity. Camera edit showed RTSP fields, ONVIF event subscription skipped (checks cam_type=="onvif"), re-discovery impossible. Now creates type="onvif" with onvif_host/port/username/password stored on the camera row. Streams still go into camera_streams (unchanged). Bundle ships onvif fields → kiosk subscribes to PullPoint events. Also passes host + port as hidden form fields from discover results page so the add handler has them available. Basic manual camera creation via UI stays rtsp-only (simpler); discovery flow produces onvif type.
This commit is contained in:
parent
2e40e78413
commit
05ca368f29
2 changed files with 16 additions and 4 deletions
|
|
@ -174,6 +174,8 @@ function parseDiscoveredStreams(raw: string): DiscoverAddStream[] {
|
||||||
function importDiscoveredCamera(
|
function importDiscoveredCamera(
|
||||||
deps: AdminDeps,
|
deps: AdminDeps,
|
||||||
rawName: string,
|
rawName: string,
|
||||||
|
onvifHost: string,
|
||||||
|
onvifPort: number,
|
||||||
username: string,
|
username: string,
|
||||||
password: string,
|
password: string,
|
||||||
streams: DiscoverAddStream[],
|
streams: DiscoverAddStream[],
|
||||||
|
|
@ -185,9 +187,13 @@ function importDiscoveredCamera(
|
||||||
|
|
||||||
const cam = deps.repo.createCamera({
|
const cam = deps.repo.createCamera({
|
||||||
name,
|
name,
|
||||||
type: "rtsp",
|
type: "onvif",
|
||||||
rtsp_url: mainRtspUrl,
|
rtsp_url: mainRtspUrl,
|
||||||
});
|
onvif_host: onvifHost,
|
||||||
|
onvif_port: onvifPort,
|
||||||
|
onvif_username: username,
|
||||||
|
onvif_password: password,
|
||||||
|
} as any);
|
||||||
for (const stream of streams) {
|
for (const stream of streams) {
|
||||||
const width = stream.width == null ? null : Number(stream.width);
|
const width = stream.width == null ? null : Number(stream.width);
|
||||||
const height = stream.height == null ? null : Number(stream.height);
|
const height = stream.height == null ? null : Number(stream.height);
|
||||||
|
|
@ -587,6 +593,7 @@ export function registerAdminRoutes(app: H3, deps: AdminDeps): void {
|
||||||
return htmlPage(CameraDiscoverResultsPage({
|
return htmlPage(CameraDiscoverResultsPage({
|
||||||
user: user.username,
|
user: user.username,
|
||||||
host,
|
host,
|
||||||
|
port,
|
||||||
username,
|
username,
|
||||||
password,
|
password,
|
||||||
cameras,
|
cameras,
|
||||||
|
|
@ -603,6 +610,8 @@ export function registerAdminRoutes(app: H3, deps: AdminDeps): void {
|
||||||
|
|
||||||
app.post("/admin/cameras/discover/add", async (event) => {
|
app.post("/admin/cameras/discover/add", async (event) => {
|
||||||
const body = await readBody<Record<string, string | string[]>>(event);
|
const body = await readBody<Record<string, string | string[]>>(event);
|
||||||
|
const onvifHost = formValue(body?.["host"]).trim();
|
||||||
|
const onvifPort = parseInt(formValue(body?.["port"]) || "80", 10) || 80;
|
||||||
const username = formValue(body?.["username"]).trim();
|
const username = formValue(body?.["username"]).trim();
|
||||||
const password = formValue(body?.["password"]);
|
const password = formValue(body?.["password"]);
|
||||||
let imported = 0;
|
let imported = 0;
|
||||||
|
|
@ -613,7 +622,7 @@ export function registerAdminRoutes(app: H3, deps: AdminDeps): void {
|
||||||
const rawName = formValue(body?.[`camera_${idx}_name`]).trim() || "ONVIF camera";
|
const rawName = formValue(body?.[`camera_${idx}_name`]).trim() || "ONVIF camera";
|
||||||
const streams = parseDiscoveredStreams(formValue(body?.[`camera_${idx}_streams_json`]));
|
const streams = parseDiscoveredStreams(formValue(body?.[`camera_${idx}_streams_json`]));
|
||||||
if (streams.length === 0) continue;
|
if (streams.length === 0) continue;
|
||||||
const camId = importDiscoveredCamera(deps, rawName, username, password, streams);
|
const camId = importDiscoveredCamera(deps, rawName, onvifHost, onvifPort, username, password, streams);
|
||||||
if (camId != null) {
|
if (camId != null) {
|
||||||
deps.nodered.forward("camera.changed", { camera_id: camId, event: "created", source: "server" });
|
deps.nodered.forward("camera.changed", { camera_id: camId, event: "created", source: "server" });
|
||||||
}
|
}
|
||||||
|
|
@ -623,7 +632,7 @@ export function registerAdminRoutes(app: H3, deps: AdminDeps): void {
|
||||||
const rawName = formValue(body?.["name"]).trim() || "ONVIF camera";
|
const rawName = formValue(body?.["name"]).trim() || "ONVIF camera";
|
||||||
const streams = parseDiscoveredStreams(formValue(body?.["streams_json"]));
|
const streams = parseDiscoveredStreams(formValue(body?.["streams_json"]));
|
||||||
if (streams.length > 0) {
|
if (streams.length > 0) {
|
||||||
const camId = importDiscoveredCamera(deps, rawName, username, password, streams);
|
const camId = importDiscoveredCamera(deps, rawName, onvifHost, onvifPort, username, password, streams);
|
||||||
if (camId != null) {
|
if (camId != null) {
|
||||||
deps.nodered.forward("camera.changed", { camera_id: camId, event: "created", source: "server" });
|
deps.nodered.forward("camera.changed", { camera_id: camId, event: "created", source: "server" });
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -313,6 +313,7 @@ interface DiscoveredCameraRow {
|
||||||
interface CameraDiscoverResultsProps {
|
interface CameraDiscoverResultsProps {
|
||||||
user: string;
|
user: string;
|
||||||
host: string;
|
host: string;
|
||||||
|
port?: number;
|
||||||
username: string;
|
username: string;
|
||||||
password: string;
|
password: string;
|
||||||
cameras: DiscoveredCameraRow[];
|
cameras: DiscoveredCameraRow[];
|
||||||
|
|
@ -438,6 +439,8 @@ export function CameraDiscoverResultsPage(props: CameraDiscoverResultsProps) {
|
||||||
<div class="card" style="text-align:center; color:#999; padding:2rem">No profiles returned</div>
|
<div class="card" style="text-align:center; color:#999; padding:2rem">No profiles returned</div>
|
||||||
) : (
|
) : (
|
||||||
<form method="post" action="/admin/cameras/discover/add">
|
<form method="post" action="/admin/cameras/discover/add">
|
||||||
|
<input type="hidden" name="host" value={props.host} />
|
||||||
|
<input type="hidden" name="port" value={String(props.port ?? 80)} />
|
||||||
<input type="hidden" name="username" value={props.username} />
|
<input type="hidden" name="username" value={props.username} />
|
||||||
<input type="hidden" name="password" value={props.password} />
|
<input type="hidden" name="password" value={props.password} />
|
||||||
<div style="display:flex; gap:0.5rem; align-items:center; margin-bottom:1rem; flex-wrap:wrap">
|
<div style="display:flex; gap:0.5rem; align-items:center; margin-bottom:1rem; flex-wrap:wrap">
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue