mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-07-15 08:21:16 +03:00
Refactor profile to be a generic state setter API
This commit is contained in:
parent
ede8b74371
commit
a5a7523379
@ -34,7 +34,6 @@ from frigate.api.defs.query.app_query_parameters import AppTimelineHourlyQueryPa
|
|||||||
from frigate.api.defs.request.app_body import (
|
from frigate.api.defs.request.app_body import (
|
||||||
AppConfigSetBody,
|
AppConfigSetBody,
|
||||||
MediaSyncBody,
|
MediaSyncBody,
|
||||||
ProfileSetBody,
|
|
||||||
)
|
)
|
||||||
from frigate.api.defs.tags import Tags
|
from frigate.api.defs.tags import Tags
|
||||||
from frigate.config import FrigateConfig
|
from frigate.config import FrigateConfig
|
||||||
@ -244,24 +243,6 @@ def get_active_profile(request: Request):
|
|||||||
return JSONResponse(content={"active_profile": config_obj.active_profile})
|
return JSONResponse(content={"active_profile": config_obj.active_profile})
|
||||||
|
|
||||||
|
|
||||||
@router.put("/profile/set", dependencies=[Depends(require_role(["admin"]))])
|
|
||||||
def set_profile(request: Request, body: ProfileSetBody):
|
|
||||||
"""Activate or deactivate a profile."""
|
|
||||||
profile_manager = request.app.profile_manager
|
|
||||||
err = profile_manager.activate_profile(body.profile)
|
|
||||||
if err:
|
|
||||||
return JSONResponse(
|
|
||||||
content={"success": False, "message": err},
|
|
||||||
status_code=400,
|
|
||||||
)
|
|
||||||
request.app.dispatcher.publish("profile/state", body.profile or "none", retain=True)
|
|
||||||
return JSONResponse(
|
|
||||||
content={
|
|
||||||
"success": True,
|
|
||||||
"active_profile": body.profile,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@router.get("/ffmpeg/presets", dependencies=[Depends(allow_any_authenticated())])
|
@router.get("/ffmpeg/presets", dependencies=[Depends(allow_any_authenticated())])
|
||||||
def ffmpeg_presets():
|
def ffmpeg_presets():
|
||||||
|
|||||||
@ -23,6 +23,7 @@ from frigate.api.auth import (
|
|||||||
require_camera_access,
|
require_camera_access,
|
||||||
require_role,
|
require_role,
|
||||||
)
|
)
|
||||||
|
from frigate.api.defs.request.app_body import CameraSetBody
|
||||||
from frigate.api.defs.tags import Tags
|
from frigate.api.defs.tags import Tags
|
||||||
from frigate.config import FrigateConfig
|
from frigate.config import FrigateConfig
|
||||||
from frigate.config.camera.updater import (
|
from frigate.config.camera.updater import (
|
||||||
@ -1155,3 +1156,76 @@ async def delete_camera(
|
|||||||
},
|
},
|
||||||
status_code=200,
|
status_code=200,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
_SUB_COMMAND_FEATURES = {"motion_mask", "object_mask", "zone"}
|
||||||
|
|
||||||
|
|
||||||
|
@router.put(
|
||||||
|
"/camera/{camera_name}/set/{feature}",
|
||||||
|
dependencies=[Depends(require_role(["admin"]))],
|
||||||
|
)
|
||||||
|
@router.put(
|
||||||
|
"/camera/{camera_name}/set/{feature}/{sub_command}",
|
||||||
|
dependencies=[Depends(require_role(["admin"]))],
|
||||||
|
)
|
||||||
|
def camera_set(
|
||||||
|
request: Request,
|
||||||
|
camera_name: str,
|
||||||
|
feature: str,
|
||||||
|
body: CameraSetBody,
|
||||||
|
sub_command: str | None = None,
|
||||||
|
):
|
||||||
|
"""Set a camera feature state. Use camera_name='*' to target all cameras."""
|
||||||
|
dispatcher = request.app.dispatcher
|
||||||
|
frigate_config: FrigateConfig = request.app.frigate_config
|
||||||
|
|
||||||
|
if feature == "profile":
|
||||||
|
if camera_name != "*":
|
||||||
|
return JSONResponse(
|
||||||
|
content={
|
||||||
|
"success": False,
|
||||||
|
"message": "Profile feature requires camera_name='*'",
|
||||||
|
},
|
||||||
|
status_code=400,
|
||||||
|
)
|
||||||
|
dispatcher._receive("profile/set", body.value)
|
||||||
|
return JSONResponse(content={"success": True})
|
||||||
|
|
||||||
|
if feature not in dispatcher._camera_settings_handlers:
|
||||||
|
return JSONResponse(
|
||||||
|
content={"success": False, "message": f"Unknown feature: {feature}"},
|
||||||
|
status_code=400,
|
||||||
|
)
|
||||||
|
|
||||||
|
if sub_command and feature not in _SUB_COMMAND_FEATURES:
|
||||||
|
return JSONResponse(
|
||||||
|
content={
|
||||||
|
"success": False,
|
||||||
|
"message": f"Feature '{feature}' does not support sub-commands",
|
||||||
|
},
|
||||||
|
status_code=400,
|
||||||
|
)
|
||||||
|
|
||||||
|
if camera_name == "*":
|
||||||
|
cameras = list(frigate_config.cameras.keys())
|
||||||
|
elif camera_name not in frigate_config.cameras:
|
||||||
|
return JSONResponse(
|
||||||
|
content={
|
||||||
|
"success": False,
|
||||||
|
"message": f"Camera '{camera_name}' not found",
|
||||||
|
},
|
||||||
|
status_code=404,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
cameras = [camera_name]
|
||||||
|
|
||||||
|
for cam in cameras:
|
||||||
|
topic = (
|
||||||
|
f"{cam}/{feature}/{sub_command}/set"
|
||||||
|
if sub_command
|
||||||
|
else f"{cam}/{feature}/set"
|
||||||
|
)
|
||||||
|
dispatcher._receive(topic, body.value)
|
||||||
|
|
||||||
|
return JSONResponse(content={"success": True})
|
||||||
|
|||||||
@ -30,10 +30,8 @@ class AppPutRoleBody(BaseModel):
|
|||||||
role: str
|
role: str
|
||||||
|
|
||||||
|
|
||||||
class ProfileSetBody(BaseModel):
|
class CameraSetBody(BaseModel):
|
||||||
profile: Optional[str] = Field(
|
value: str = Field(..., description="The value to set for the feature")
|
||||||
default=None, description="Profile name to activate, or null to deactivate"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class MediaSyncBody(BaseModel):
|
class MediaSyncBody(BaseModel):
|
||||||
|
|||||||
@ -128,7 +128,7 @@ export default function GeneralSettings({ className }: GeneralSettingsProps) {
|
|||||||
|
|
||||||
const handleActivateProfile = async (profileName: string | null) => {
|
const handleActivateProfile = async (profileName: string | null) => {
|
||||||
try {
|
try {
|
||||||
await axios.put("profile/set", { profile: profileName || null });
|
await axios.put("camera/*/set/profile", { value: profileName ?? "none" });
|
||||||
await updateProfiles();
|
await updateProfiles();
|
||||||
toast.success(
|
toast.success(
|
||||||
profileName
|
profileName
|
||||||
|
|||||||
@ -207,8 +207,8 @@ export default function ProfilesView({
|
|||||||
async (profile: string | null) => {
|
async (profile: string | null) => {
|
||||||
setActivating(true);
|
setActivating(true);
|
||||||
try {
|
try {
|
||||||
await axios.put("profile/set", {
|
await axios.put("camera/*/set/profile", {
|
||||||
profile: profile || null,
|
value: profile ?? "none",
|
||||||
});
|
});
|
||||||
await updateProfiles();
|
await updateProfiles();
|
||||||
toast.success(
|
toast.success(
|
||||||
@ -244,7 +244,7 @@ export default function ProfilesView({
|
|||||||
try {
|
try {
|
||||||
// If this profile is active, deactivate it first
|
// If this profile is active, deactivate it first
|
||||||
if (activeProfile === deleteProfile) {
|
if (activeProfile === deleteProfile) {
|
||||||
await axios.put("profile/set", { profile: null });
|
await axios.put("camera/*/set/profile", { value: "none" });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the profile from all cameras and the top-level definition
|
// Remove the profile from all cameras and the top-level definition
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user