mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-05-01 11:07:41 +03:00
Simplify config updates
This commit is contained in:
parent
7e45371eed
commit
785e655ff5
@ -32,6 +32,7 @@ from frigate.config.camera.updater import (
|
||||
CameraConfigUpdateEnum,
|
||||
CameraConfigUpdateTopic,
|
||||
)
|
||||
from frigate.config.updater import GlobalConfigUpdateEnum, GlobalConfigUpdatePublisher
|
||||
from frigate.models import Event, Timeline
|
||||
from frigate.stats.prometheus import get_metrics, update_metrics
|
||||
from frigate.util.builtin import (
|
||||
@ -390,17 +391,23 @@ def config_set(request: Request, body: AppConfigSetBody):
|
||||
)
|
||||
|
||||
if body.requires_restart == 0 or body.update_topic:
|
||||
old_config = request.app.frigate_config
|
||||
request.app.frigate_config = config
|
||||
|
||||
if body.update_topic:
|
||||
if body.update_topic.startswith("config/cameras/"):
|
||||
_, _, camera, field = body.update_topic.split("/")
|
||||
if body.update_topic and body.update_topic.startswith("config/cameras/"):
|
||||
_, _, camera, field = body.update_topic.split("/")
|
||||
|
||||
if field == "add":
|
||||
settings = config.cameras[camera]
|
||||
elif field == "remove":
|
||||
|
||||
else:
|
||||
settings = config.get_nested_object(body.update_topic)
|
||||
request.app.config_publisher.publish_update(
|
||||
CameraConfigUpdateTopic(CameraConfigUpdateEnum[field], camera),
|
||||
settings,
|
||||
)
|
||||
|
||||
request.app.config_publisher.publish_update(
|
||||
CameraConfigUpdateTopic(CameraConfigUpdateEnum[field], camera),
|
||||
settings,
|
||||
)
|
||||
|
||||
return JSONResponse(
|
||||
content=(
|
||||
|
||||
@ -11,7 +11,10 @@ from multiprocessing.synchronize import Event as MpEvent
|
||||
from frigate.camera import CameraMetrics, PTZMetrics
|
||||
from frigate.config import FrigateConfig
|
||||
from frigate.config.camera import CameraConfig
|
||||
from frigate.config.updater import GlobalConfigUpdateEnum, GlobalConfigUpdateSubscriber
|
||||
from frigate.config.camera.updater import (
|
||||
CameraConfigUpdateEnum,
|
||||
CameraConfigUpdateSubscriber,
|
||||
)
|
||||
from frigate.const import SHM_FRAMES_VAR
|
||||
from frigate.models import Regions
|
||||
from frigate.util import Process as FrigateProcess
|
||||
@ -44,11 +47,10 @@ class CameraMaintainer(threading.Thread):
|
||||
self.ptz_metrics = ptz_metrics
|
||||
self.frame_manager = SharedMemoryFrameManager()
|
||||
self.region_grids: dict[str, list[list[dict[str, int]]]] = {}
|
||||
self.update_subscriber = GlobalConfigUpdateSubscriber(
|
||||
self.update_subscriber = CameraConfigUpdateSubscriber(
|
||||
[
|
||||
GlobalConfigUpdateEnum.add_camera,
|
||||
GlobalConfigUpdateEnum.debug_camera,
|
||||
GlobalConfigUpdateEnum.remove_camera,
|
||||
CameraConfigUpdateEnum.add,
|
||||
CameraConfigUpdateEnum.remove,
|
||||
]
|
||||
)
|
||||
self.shm_count = self.__calculate_shm_frame_count()
|
||||
@ -203,20 +205,20 @@ class CameraMaintainer(threading.Thread):
|
||||
while not self.stop_event.wait(1):
|
||||
updates = self.update_subscriber.check_for_updates()
|
||||
|
||||
for update_type, update_config in updates:
|
||||
if update_type == GlobalConfigUpdateEnum.add_camera:
|
||||
self.__start_camera_processor(
|
||||
update_config.name, update_config, runtime=True
|
||||
)
|
||||
self.__start_camera_capture(update_config.name, update_config)
|
||||
elif update_type == GlobalConfigUpdateEnum.debug_camera:
|
||||
pass
|
||||
elif update_type == GlobalConfigUpdateEnum.remove_camera:
|
||||
camera = update_config.name
|
||||
|
||||
if camera:
|
||||
self.__stop_camera_capture_process(camera)
|
||||
self.__stop_camera_process(camera)
|
||||
for update_type, updated_cameras in updates:
|
||||
if update_type == CameraConfigUpdateEnum.add.name:
|
||||
for camera in updated_cameras:
|
||||
self.__start_camera_processor(
|
||||
camera,
|
||||
self.update_subscriber.camera_configs[camera],
|
||||
runtime=True,
|
||||
)
|
||||
self.__start_camera_capture(
|
||||
camera, self.update_subscriber.camera_configs[camera]
|
||||
)
|
||||
elif update_type == CameraConfigUpdateEnum.remove.name:
|
||||
self.__stop_camera_capture_process(camera)
|
||||
self.__stop_camera_process(camera)
|
||||
|
||||
# ensure the capture processes are done
|
||||
for camera in self.camera_metrics.keys():
|
||||
|
||||
@ -11,6 +11,7 @@ from frigate.config import CameraConfig
|
||||
class CameraConfigUpdateEnum(str, Enum):
|
||||
"""Supported camera config update types."""
|
||||
|
||||
add = "add" # for adding a camera
|
||||
audio = "audio"
|
||||
audio_transcription = "audio_transcription"
|
||||
birdseye = "birdseye"
|
||||
@ -20,6 +21,7 @@ class CameraConfigUpdateEnum(str, Enum):
|
||||
notifications = "notifications"
|
||||
objects = "objects"
|
||||
record = "record"
|
||||
remove = "remove" # for removing a camera
|
||||
review = "review"
|
||||
snapshots = "snapshots"
|
||||
zones = "zones"
|
||||
@ -68,14 +70,21 @@ class CameraConfigUpdateSubscriber:
|
||||
def __update_config(
|
||||
self, camera: str, update_type: CameraConfigUpdateEnum, updated_config: Any
|
||||
) -> None:
|
||||
config = self.camera_configs[camera]
|
||||
if update_type == CameraConfigUpdateEnum.add:
|
||||
self.camera_configs[camera] = updated_config
|
||||
return
|
||||
elif update_type == CameraConfigUpdateEnum.remove:
|
||||
self.camera_configs.pop(camera)
|
||||
return
|
||||
|
||||
config = self.camera_configs.get(camera)
|
||||
|
||||
if not config:
|
||||
return
|
||||
|
||||
if update_type == CameraConfigUpdateEnum.audio:
|
||||
config.audio = updated_config
|
||||
if update_type == CameraConfigUpdateEnum.audio_transcription:
|
||||
elif update_type == CameraConfigUpdateEnum.audio_transcription:
|
||||
config.audio_transcription = updated_config
|
||||
elif update_type == CameraConfigUpdateEnum.birdseye:
|
||||
config.birdseye = updated_config
|
||||
|
||||
@ -1,69 +0,0 @@
|
||||
"""Convenience classes for updating global configurations dynamically."""
|
||||
|
||||
from dataclasses import dataclass
|
||||
from enum import Enum
|
||||
from typing import Any
|
||||
|
||||
from frigate.comms.config_updater import ConfigPublisher, ConfigSubscriber
|
||||
from frigate.config.camera import CameraConfig
|
||||
|
||||
|
||||
class GlobalConfigUpdateEnum(str, Enum):
|
||||
"""Supported global config update types."""
|
||||
|
||||
add_camera = "add_camera"
|
||||
debug_camera = "debug_camera"
|
||||
remove_camera = "remove_camera"
|
||||
|
||||
|
||||
@dataclass
|
||||
class GlobalConfigUpdateTopic:
|
||||
update_type: GlobalConfigUpdateEnum
|
||||
|
||||
@property
|
||||
def topic(self) -> str:
|
||||
return f"config/{self.update_type.name}"
|
||||
|
||||
|
||||
class GlobalConfigUpdatePublisher:
|
||||
def __init__(self):
|
||||
self.publisher = ConfigPublisher()
|
||||
|
||||
def publish_update(self, topic: GlobalConfigUpdateTopic, config: Any) -> None:
|
||||
self.publisher.publish(topic.topic, config)
|
||||
|
||||
def stop(self) -> None:
|
||||
self.publisher.stop()
|
||||
|
||||
|
||||
class GlobalConfigUpdateSubscriber:
|
||||
def __init__(
|
||||
self,
|
||||
topics: list[GlobalConfigUpdateEnum],
|
||||
):
|
||||
self.topics = topics
|
||||
self.subscriber = ConfigSubscriber(
|
||||
"config/",
|
||||
exact=False,
|
||||
)
|
||||
|
||||
def check_for_updates(self) -> list[tuple[GlobalConfigUpdateEnum, CameraConfig]]:
|
||||
updated_topics: list[tuple[GlobalConfigUpdateEnum, CameraConfig]] = []
|
||||
|
||||
# get all updates available
|
||||
while True:
|
||||
update_topic, update_config = self.subscriber.check_for_update()
|
||||
|
||||
if update_topic is None or update_config is None:
|
||||
break
|
||||
|
||||
_, raw_type = update_topic.split("/")
|
||||
update_type = GlobalConfigUpdateEnum[raw_type]
|
||||
|
||||
if update_type in self.topics:
|
||||
updated_topics.append((update_type, update_config))
|
||||
|
||||
return updated_topics
|
||||
|
||||
def stop(self) -> None:
|
||||
self.subscriber.stop()
|
||||
@ -32,7 +32,6 @@ from frigate.config.camera.updater import (
|
||||
CameraConfigUpdateEnum,
|
||||
CameraConfigUpdateSubscriber,
|
||||
)
|
||||
from frigate.config.updater import GlobalConfigUpdateEnum, GlobalConfigUpdateSubscriber
|
||||
from frigate.const import FAST_QUEUE_TIMEOUT, UPDATE_CAMERA_ACTIVITY
|
||||
from frigate.events.types import EventStateEnum, EventTypeEnum
|
||||
from frigate.models import Event, Timeline
|
||||
@ -67,12 +66,14 @@ class TrackedObjectProcessor(threading.Thread):
|
||||
self.last_motion_detected: dict[str, float] = {}
|
||||
self.ptz_autotracker_thread = ptz_autotracker_thread
|
||||
|
||||
self.global_config_subscriber = GlobalConfigUpdateSubscriber(
|
||||
[GlobalConfigUpdateEnum.add_camera, GlobalConfigUpdateEnum.remove_camera]
|
||||
)
|
||||
self.camera_config_subscriber = CameraConfigUpdateSubscriber(
|
||||
self.config.cameras,
|
||||
[CameraConfigUpdateEnum.enabled, CameraConfigUpdateEnum.zones],
|
||||
[
|
||||
CameraConfigUpdateEnum.add,
|
||||
CameraConfigUpdateEnum.enabled,
|
||||
CameraConfigUpdateEnum.remove,
|
||||
CameraConfigUpdateEnum.zones,
|
||||
],
|
||||
)
|
||||
|
||||
self.requestor = InterProcessRequestor()
|
||||
@ -590,16 +591,6 @@ class TrackedObjectProcessor(threading.Thread):
|
||||
|
||||
def run(self):
|
||||
while not self.stop_event.is_set():
|
||||
# check for global config updates
|
||||
for topic, payload in self.global_config_subscriber.check_for_updates():
|
||||
if topic == GlobalConfigUpdateEnum.add_camera:
|
||||
self.create_camera_state(payload["camera"])
|
||||
elif topic == GlobalConfigUpdateEnum.remove_camera:
|
||||
camera = payload["camera"]
|
||||
camera_state = self.camera_states[camera]
|
||||
camera_state.shutdown()
|
||||
del self.camera_states[camera]
|
||||
|
||||
# check for config updates
|
||||
updated_topics = self.camera_config_subscriber.check_for_updates()
|
||||
|
||||
@ -609,6 +600,17 @@ class TrackedObjectProcessor(threading.Thread):
|
||||
self.camera_states[camera].prev_enabled = self.config.cameras[
|
||||
camera
|
||||
].enabled
|
||||
elif "add" in updated_topics:
|
||||
for camera in updated_topics["add"]:
|
||||
self.config.cameras[camera] = (
|
||||
self.camera_config_subscriber.camera_configs[camera]
|
||||
)
|
||||
self.create_camera_state(camera)
|
||||
elif "remove" in updated_topics:
|
||||
for camera in updated_topics["remove"]:
|
||||
camera_state = self.camera_states[camera]
|
||||
camera_state.shutdown()
|
||||
self.camera_states.pop(camera)
|
||||
|
||||
# manage camera disabled state
|
||||
for camera, config in self.config.cameras.items():
|
||||
|
||||
Loading…
Reference in New Issue
Block a user