@@ -385,42 +385,54 @@ def open(self) -> None:
385385
386386 with type (self )._OPEN_LOCK :
387387 loaded , failed = self ._resolve_and_persist_ctis ()
388- infos = self ._acquire_shared_harvester (loaded )
389- if not infos :
390- self ._reset_harvester ()
391- raise RuntimeError (
392- "No GenTL cameras detected via Harvesters after loading producers.\n \n "
393- f"Loaded CTIs: { loaded } \n "
394- f"Failed CTIs: { failed } \n "
395- "Fix: ensure your camera vendor's GenTL producer is installed and working."
396- )
397-
398- selected_index , selected_serial , selected_info = self ._select_device (infos )
399- self .settings .index = int (selected_index )
400-
401- with self ._shared_entry .lock :
402- self ._acquirer = self ._create_image_acquirer (selected_serial , int (selected_index ))
403- node_map = self ._acquirer .remote_device .node_map
404- self ._device_label = self ._resolve_device_label (node_map )
405-
406- self ._configure_pixel_format (node_map )
407- self ._configure_trigger (node_map )
408- self ._configure_resolution (node_map )
409- self ._configure_exposure (node_map )
410- self ._configure_gain (node_map )
411- self ._configure_frame_rate (node_map )
412- self ._read_telemetry (node_map )
413- self ._persist_device_metadata (selected_info , selected_serial )
414-
415- if self ._fast_start :
416- LOG .info ("GenTL open() in fast_start probe mode: acquisition not started." )
417- return
418-
419- self ._acquirer .start ()
388+ try :
389+ infos = self ._acquire_shared_harvester (loaded )
390+ if not infos :
391+ self ._reset_harvester ()
392+ raise RuntimeError (
393+ "No GenTL cameras detected via Harvesters after loading producers.\n \n "
394+ f"Loaded CTIs: { loaded } \n "
395+ f"Failed CTIs: { failed } \n "
396+ "Fix: ensure your camera vendor's GenTL producer is installed and working."
397+ )
420398
421- LOG .debug (
422- "Opened GenTL camera index=%s serial=%s label=%s" , selected_index , selected_serial , self ._device_label
423- )
399+ selected_index , selected_serial , selected_info = self ._select_device (infos )
400+ self .settings .index = int (selected_index )
401+
402+ with self ._shared_entry .lock :
403+ self ._acquirer = self ._create_image_acquirer (selected_serial , int (selected_index ))
404+ node_map = self ._acquirer .remote_device .node_map
405+ self ._device_label = self ._resolve_device_label (node_map )
406+
407+ self ._configure_pixel_format (node_map )
408+ self ._configure_trigger (node_map )
409+ self ._configure_resolution (node_map )
410+ self ._configure_exposure (node_map )
411+ self ._configure_gain (node_map )
412+ self ._configure_frame_rate (node_map )
413+ self ._read_telemetry (node_map )
414+ self ._persist_device_metadata (selected_info , selected_serial )
415+
416+ if self ._fast_start :
417+ LOG .info ("GenTL open() in fast_start probe mode: acquisition not started." )
418+ return
419+
420+ self ._acquirer .start ()
421+
422+ LOG .debug (
423+ "Opened GenTL camera index=%s serial=%s label=%s" ,
424+ selected_index ,
425+ selected_serial ,
426+ self ._device_label ,
427+ )
428+ except Exception as exc :
429+ try :
430+ self .close ()
431+ except Exception :
432+ pass
433+ raise RuntimeError (
434+ f"Failed to open GenTL camera.\n \n Loaded CTIs: { loaded } \n Failed CTIs: { failed } \n Reason: { exc } "
435+ ) from exc
424436
425437 def read (self ) -> tuple [np .ndarray , float ]:
426438 if self ._acquirer is None :
@@ -681,12 +693,20 @@ def _select_device(self, infos: list) -> tuple[int, str | None, object]:
681693 selected_serial : str | None = None
682694
683695 if target_device_id :
684- selected_index , selected_serial = self ._match_device (infos , str (target_device_id ).strip ())
685-
686- if selected_index is None and self ._serial_number :
687- selected_index , selected_serial = self ._match_device (infos , str (self ._serial_number ).strip ())
688-
689- if selected_index is None :
696+ target = str (target_device_id ).strip ()
697+ selected_index , selected_serial = self ._match_device (infos , target )
698+ if selected_index is None :
699+ available = [str (self ._info_get (i , "serial_number" , "" ) or "" ).strip () for i in infos ]
700+ raise RuntimeError (f"GenTL device '{ target } ' not found. Available serials: { available } " )
701+
702+ elif self ._serial_number :
703+ serial = str (self ._serial_number ).strip ()
704+ selected_index , selected_serial = self ._match_device (infos , serial )
705+ if selected_index is None :
706+ available = [str (self ._info_get (i , "serial_number" , "" ) or "" ).strip () for i in infos ]
707+ raise RuntimeError (f"GenTL camera with serial '{ serial } ' not found. Available serials: { available } " )
708+
709+ else :
690710 if requested_index < 0 or requested_index >= len (infos ):
691711 raise RuntimeError (f"Camera index { requested_index } out of range for { len (infos )} GenTL device(s)" )
692712 selected_index = requested_index
0 commit comments