create cameras in same event loop that will use them

This commit is contained in:
Josh Hawkins 2025-05-05 18:55:28 -05:00
parent 70752b4193
commit 8a61ccfe61

View File

@ -52,13 +52,14 @@ class OnvifController:
self.loop_thread = threading.Thread(target=self._run_event_loop, daemon=True) self.loop_thread = threading.Thread(target=self._run_event_loop, daemon=True)
self.loop_thread.start() self.loop_thread.start()
self.camera_configs = {}
for cam_name, cam in config.cameras.items(): for cam_name, cam in config.cameras.items():
if not cam.enabled: if not cam.enabled:
continue continue
if cam.onvif.host: if cam.onvif.host:
result = self._create_onvif_camera(cam_name, cam) self.camera_configs[cam_name] = cam
if result:
self.cams[cam_name] = result asyncio.run_coroutine_threadsafe(self._init_cameras(), self.loop)
def _run_event_loop(self) -> None: def _run_event_loop(self) -> None:
"""Run the event loop in a separate thread.""" """Run the event loop in a separate thread."""
@ -68,33 +69,34 @@ class OnvifController:
except Exception as e: except Exception as e:
logger.error(f"Onvif event loop terminated unexpectedly: {e}") logger.error(f"Onvif event loop terminated unexpectedly: {e}")
def _create_onvif_camera(self, cam_name: str, cam) -> dict | None: async def _init_cameras(self) -> None:
"""Create an ONVIF camera instance and handle failures.""" """Create an ONVIF camera instance and handle failures."""
try: for cam_name, cam in self.camera_configs.items():
return { try:
"onvif": ONVIFCamera( self.cams[cam_name] = {
cam.onvif.host, "onvif": ONVIFCamera(
cam.onvif.port, cam.onvif.host,
cam.onvif.user, cam.onvif.port,
cam.onvif.password, cam.onvif.user,
wsdl_dir=str(Path(find_spec("onvif").origin).parent / "wsdl"), cam.onvif.password,
adjust_time=cam.onvif.ignore_time_mismatch, wsdl_dir=str(Path(find_spec("onvif").origin).parent / "wsdl"),
encrypt=not cam.onvif.tls_insecure, adjust_time=cam.onvif.ignore_time_mismatch,
), encrypt=not cam.onvif.tls_insecure,
"init": False, ),
"active": False, "init": False,
"features": [], "active": False,
"presets": {}, "features": [],
} "presets": {},
except (Fault, ONVIFError, TransportError, Exception) as e: }
logger.error(f"Failed to create ONVIF camera instance for {cam_name}: {e}") except (Fault, ONVIFError, TransportError, Exception) as e:
# track initial failures logger.error(
self.failed_cams[cam_name] = { f"Failed to create ONVIF camera instance for {cam_name}: {e}"
"retry_attempts": 0, )
"last_error": str(e), self.failed_cams[cam_name] = {
"last_attempt": time.time(), "retry_attempts": 0,
} "last_error": str(e),
return None "last_attempt": time.time(),
}
async def _init_onvif(self, camera_name: str) -> bool: async def _init_onvif(self, camera_name: str) -> bool:
onvif: ONVIFCamera = self.cams[camera_name]["onvif"] onvif: ONVIFCamera = self.cams[camera_name]["onvif"]