Dynamically update masks and zones for cameras (#18359)

* Include config publisher in api

* Call update topic for passed topics

* Update zones dynamically

* Update zones internally

* Support zone and mask reset

* Handle updating objects config

* Don't put status for needing to restart Frigate

* Cleanup http tests

* Fix tests
This commit is contained in:
Nicolas Mowen
2025-08-16 10:20:33 -05:00
committed by Blake Blackshear
parent dc187eee1c
commit 4dc526761c
16 changed files with 100 additions and 118 deletions
@@ -163,6 +163,7 @@ export default function MotionMaskEditPane({
axios
.put(`config/set?${queryString}`, {
requires_restart: 0,
update_topic: `config/cameras/${polygon.camera}/motion`,
})
.then((res) => {
if (res.status === 200) {
@@ -196,6 +196,7 @@ export default function ObjectMaskEditPane({
axios
.put(`config/set?${queryString}`, {
requires_restart: 0,
update_topic: `config/cameras/${polygon.camera}/objects`,
})
.then((res) => {
if (res.status === 200) {
+5 -1
View File
@@ -329,6 +329,7 @@ export default function ZoneEditPane({
`config/set?cameras.${polygon.camera}.zones.${polygon.name}${renameAlertQueries}${renameDetectionQueries}`,
{
requires_restart: 0,
update_topic: `config/cameras/${polygon.camera}/zones`,
},
);
@@ -412,7 +413,10 @@ export default function ZoneEditPane({
axios
.put(
`config/set?cameras.${polygon?.camera}.zones.${zoneName}.coordinates=${coordinates}${inertiaQuery}${loiteringTimeQuery}${speedThresholdQuery}${distancesQuery}${objectQueries}${alertQueries}${detectionQueries}`,
{ requires_restart: 0 },
{
requires_restart: 0,
update_topic: `config/cameras/${polygon.camera}/zones`,
},
)
.then((res) => {
if (res.status === 200) {
+2 -18
View File
@@ -1,14 +1,7 @@
import { FrigateConfig } from "@/types/frigateConfig";
import useSWR from "swr";
import ActivityIndicator from "@/components/indicators/activity-indicator";
import {
useCallback,
useContext,
useEffect,
useMemo,
useRef,
useState,
} from "react";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { PolygonCanvas } from "@/components/settings/PolygonCanvas";
import { Polygon, PolygonType } from "@/types/canvas";
import { interpolatePoints, parseCoordinates } from "@/utils/canvasUtil";
@@ -36,7 +29,6 @@ import ObjectMaskEditPane from "@/components/settings/ObjectMaskEditPane";
import PolygonItem from "@/components/settings/PolygonItem";
import { Link } from "react-router-dom";
import { isDesktop } from "react-device-detect";
import { StatusBarMessagesContext } from "@/context/statusbar-provider";
import { useSearchEffect } from "@/hooks/use-overlay-state";
import { useTranslation } from "react-i18next";
@@ -72,8 +64,6 @@ export default function MasksAndZonesView({
const [activeLine, setActiveLine] = useState<number | undefined>();
const [snapPoints, setSnapPoints] = useState(false);
const { addMessage } = useContext(StatusBarMessagesContext)!;
const cameraConfig = useMemo(() => {
if (config && selectedCamera) {
return config.cameras[selectedCamera];
@@ -196,13 +186,7 @@ export default function MasksAndZonesView({
setAllPolygons([...(editingPolygons ?? [])]);
setHoveredPolygonIndex(null);
setUnsavedChanges(false);
addMessage(
"masks_zones",
t("masksAndZones.restart_required"),
undefined,
"masks_zones",
);
}, [t, editingPolygons, setUnsavedChanges, addMessage]);
}, [editingPolygons, setUnsavedChanges]);
useEffect(() => {
if (isLoading) {