mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-04-27 09:07:41 +03:00
Use asyncio lock when checking camera status
get_camera_status() can be called during normal autotracking movement and from routine camera_maintenance(). Some cameras cause one of the status calls to hang, which then subsequently hangs autotracking. A lock serializes access and prevents the hang.
This commit is contained in:
parent
e9dc30235b
commit
78c45e347e
@ -48,6 +48,8 @@ class OnvifController:
|
|||||||
self.config = config
|
self.config = config
|
||||||
self.ptz_metrics = ptz_metrics
|
self.ptz_metrics = ptz_metrics
|
||||||
|
|
||||||
|
self.status_locks: dict[str, asyncio.Lock] = {}
|
||||||
|
|
||||||
# Create a dedicated event loop and run it in a separate thread
|
# Create a dedicated event loop and run it in a separate thread
|
||||||
self.loop = asyncio.new_event_loop()
|
self.loop = asyncio.new_event_loop()
|
||||||
self.loop_thread = threading.Thread(target=self._run_event_loop, daemon=True)
|
self.loop_thread = threading.Thread(target=self._run_event_loop, daemon=True)
|
||||||
@ -59,6 +61,7 @@ class OnvifController:
|
|||||||
continue
|
continue
|
||||||
if cam.onvif.host:
|
if cam.onvif.host:
|
||||||
self.camera_configs[cam_name] = cam
|
self.camera_configs[cam_name] = cam
|
||||||
|
self.status_locks[cam_name] = asyncio.Lock()
|
||||||
|
|
||||||
asyncio.run_coroutine_threadsafe(self._init_cameras(), self.loop)
|
asyncio.run_coroutine_threadsafe(self._init_cameras(), self.loop)
|
||||||
|
|
||||||
@ -764,6 +767,7 @@ class OnvifController:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
async def get_camera_status(self, camera_name: str) -> None:
|
async def get_camera_status(self, camera_name: str) -> None:
|
||||||
|
async with self.status_locks[camera_name]:
|
||||||
if camera_name not in self.cams.keys():
|
if camera_name not in self.cams.keys():
|
||||||
logger.error(f"ONVIF is not configured for {camera_name}")
|
logger.error(f"ONVIF is not configured for {camera_name}")
|
||||||
return
|
return
|
||||||
@ -802,7 +806,9 @@ class OnvifController:
|
|||||||
f"{camera_name}: Pan/tilt status: {pan_tilt_status}, Zoom status: {zoom_status}"
|
f"{camera_name}: Pan/tilt status: {pan_tilt_status}, Zoom status: {zoom_status}"
|
||||||
)
|
)
|
||||||
|
|
||||||
if pan_tilt_status == "IDLE" and (zoom_status is None or zoom_status == "IDLE"):
|
if pan_tilt_status == "IDLE" and (
|
||||||
|
zoom_status is None or zoom_status == "IDLE"
|
||||||
|
):
|
||||||
self.cams[camera_name]["active"] = False
|
self.cams[camera_name]["active"] = False
|
||||||
if not self.ptz_metrics[camera_name].motor_stopped.is_set():
|
if not self.ptz_metrics[camera_name].motor_stopped.is_set():
|
||||||
self.ptz_metrics[camera_name].motor_stopped.set()
|
self.ptz_metrics[camera_name].motor_stopped.set()
|
||||||
@ -861,7 +867,9 @@ class OnvifController:
|
|||||||
self.ptz_metrics[camera_name].stop_time.value = self.ptz_metrics[
|
self.ptz_metrics[camera_name].stop_time.value = self.ptz_metrics[
|
||||||
camera_name
|
camera_name
|
||||||
].frame_time.value
|
].frame_time.value
|
||||||
logger.warning(f"Camera {camera_name} is still in ONVIF 'MOVING' status.")
|
logger.warning(
|
||||||
|
f"Camera {camera_name} is still in ONVIF 'MOVING' status."
|
||||||
|
)
|
||||||
|
|
||||||
def close(self) -> None:
|
def close(self) -> None:
|
||||||
"""Gracefully shut down the ONVIF controller."""
|
"""Gracefully shut down the ONVIF controller."""
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user