From bd1892e4af1912490925e1d37ea3953c1ea30ea5 Mon Sep 17 00:00:00 2001 From: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> Date: Wed, 15 Jul 2026 19:23:18 -0500 Subject: [PATCH] always create ONVIF status and service capabilities requests during init --- frigate/ptz/autotrack.py | 26 +++++++++++++++++++++++++- frigate/ptz/onvif.py | 19 ++++++++++--------- 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/frigate/ptz/autotrack.py b/frigate/ptz/autotrack.py index 7cb78fcc8e..e9bbda9889 100644 --- a/frigate/ptz/autotrack.py +++ b/frigate/ptz/autotrack.py @@ -198,7 +198,7 @@ class PtzAutoTrackerThread(threading.Thread): def run(self): while not self.stop_event.wait(1): - self.ptz_autotracker.config_subscriber.check_for_updates() + self.ptz_autotracker.check_for_updates() for camera, camera_config in list(self.config.cameras.items()): if not camera_config.enabled: @@ -257,6 +257,7 @@ class PtzAutoTracker: [ CameraConfigUpdateEnum.add, CameraConfigUpdateEnum.autotracking, + CameraConfigUpdateEnum.onvif, ], ) @@ -276,6 +277,29 @@ class PtzAutoTracker: # Wait for the coroutine to complete future.result() + def check_for_updates(self) -> None: + """Apply camera config updates and mirror autotracking state to ptz metrics. + + The camera processes read autotracker_enabled rather than the config, so it + has to follow every path that can change autotracking, not just the mqtt + toggle that writes it directly. + """ + updates = self.config_subscriber.check_for_updates() + + for cameras in updates.values(): + for camera in cameras: + camera_config = self.config.cameras.get(camera) + metrics = self.ptz_metrics.get(camera) + + # a camera added at runtime gets its metrics from the maintainer on + # another thread, which seeds them from this same config value + if camera_config is None or metrics is None: + continue + + metrics.autotracker_enabled.value = ( + camera_config.onvif.autotracking.enabled + ) + async def _autotracker_setup(self, camera_config: CameraConfig, camera: str): logger.debug(f"{camera}: Autotracker init") diff --git a/frigate/ptz/onvif.py b/frigate/ptz/onvif.py index d29923e239..3fa786c883 100644 --- a/frigate/ptz/onvif.py +++ b/frigate/ptz/onvif.py @@ -344,16 +344,17 @@ class OnvifController: autotracking_config.enabled_in_config and autotracking_config.enabled ) - # autotracking-only: status request and service capabilities - if autotracking_enabled: - status_request = ptz.create_type("GetStatus") - status_request.ProfileToken = profile.token - self.cams[camera_name]["status_request"] = status_request + # these are local and cost nothing to build, and autotracking can be enabled + # after a camera is initialized, so always create them rather than baking the + # current config value into init state + status_request = ptz.create_type("GetStatus") + status_request.ProfileToken = profile.token + self.cams[camera_name]["status_request"] = status_request - service_capabilities_request = ptz.create_type("GetServiceCapabilities") - self.cams[camera_name]["service_capabilities_request"] = ( - service_capabilities_request - ) + service_capabilities_request = ptz.create_type("GetServiceCapabilities") + self.cams[camera_name]["service_capabilities_request"] = ( + service_capabilities_request + ) # setup relative move request when FOV relative movement is supported if (