From 20647ce8911e3282d424cdea80167fd64c47ce24 Mon Sep 17 00:00:00 2001 From: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> Date: Tue, 6 May 2025 16:33:04 -0500 Subject: [PATCH] move coroutine call with loop to api --- frigate/api/media.py | 8 ++++++-- frigate/ptz/onvif.py | 33 ++++----------------------------- 2 files changed, 10 insertions(+), 31 deletions(-) diff --git a/frigate/api/media.py b/frigate/api/media.py index 6a2168ac8..27d87770a 100644 --- a/frigate/api/media.py +++ b/frigate/api/media.py @@ -1,5 +1,6 @@ """Image and video apis.""" +import asyncio import glob import logging import math @@ -110,9 +111,12 @@ def imagestream( @router.get("/{camera_name}/ptz/info") async def camera_ptz_info(request: Request, camera_name: str): if camera_name in request.app.frigate_config.cameras: - return JSONResponse( - content=request.app.onvif.get_camera_info(camera_name), + # Schedule get_camera_info in the OnvifController's event loop + future = asyncio.run_coroutine_threadsafe( + request.app.onvif.get_camera_info(camera_name), request.app.onvif.loop ) + result = future.result() + return JSONResponse(content=result) else: return JSONResponse( content={"success": False, "message": "Camera not found"}, diff --git a/frigate/ptz/onvif.py b/frigate/ptz/onvif.py index 36d38da84..37cb297ff 100644 --- a/frigate/ptz/onvif.py +++ b/frigate/ptz/onvif.py @@ -638,14 +638,9 @@ class OnvifController: Handle ONVIF commands by scheduling them in the event loop. This is the synchronous interface that schedules async work. """ - # Run the async command in the event loop - # logger.debug( - # f"Scheduling handle_command_async for {camera_name} with command {command}. {self.loop}" - # ) future = asyncio.run_coroutine_threadsafe( self.handle_command_async(camera_name, command, param), self.loop ) - # logger.debug(f"Scheduled handle_command_async for {camera_name}") try: # Wait with a timeout to prevent blocking indefinitely @@ -657,7 +652,7 @@ class OnvifController: f"Error executing command {command} for camera {camera_name}: {e}" ) - def get_camera_info(self, camera_name: str) -> dict[str, any]: + async def get_camera_info(self, camera_name: str) -> dict[str, any]: """ Get ptz capabilities and presets, attempting to reconnect if ONVIF is configured but not initialized. @@ -685,21 +680,8 @@ class OnvifController: } if camera_name not in self.cams.keys() and camera_name in self.config.cameras: - # Schedule _init_single_camera in the OnvifController's event loop - future = asyncio.run_coroutine_threadsafe( - self._init_single_camera(camera_name), self.loop - ) - try: - success = future.result(timeout=10) - if not success: - return {} - except asyncio.TimeoutError: - logger.error(f"_init_single_camera timed out for camera {camera_name}") - return {} - except Exception as e: - logger.error( - f"Error in _init_single_camera for camera {camera_name}: {e}" - ) + success = await self._init_single_camera(camera_name) + if not success: return {} # Reset retry count after timeout @@ -717,12 +699,7 @@ class OnvifController: f"Attempting ONVIF initialization for {camera_name} (retry {attempts + 1}/{self.max_retries})" ) try: - # Schedule _init_onvif in the OnvifController's event loop - future = asyncio.run_coroutine_threadsafe( - self._init_onvif(camera_name), self.loop - ) - success = future.result(timeout=10) - if success: + if await self._init_onvif(camera_name): if camera_name in self.failed_cams: del self.failed_cams[camera_name] return { @@ -732,8 +709,6 @@ class OnvifController: } else: logger.warning(f"ONVIF initialization failed for {camera_name}") - except asyncio.TimeoutError: - logger.error(f"_init_onvif timed out for camera {camera_name}") except Exception as e: logger.error( f"Error during ONVIF initialization for {camera_name}: {e}"