diff --git a/Camera/AbstractCamera.py b/Camera/AbstractCamera.py index 360273d..83a3513 100644 --- a/Camera/AbstractCamera.py +++ b/Camera/AbstractCamera.py @@ -60,6 +60,12 @@ def uid(self): # Methods ############################################################################### + def park(self): + self.logger.debug(f"Parking camera {self.camera_name}") + + def unpark(self): + self.logger.debug(f"Unparking camera {self.camera_name}") + def take_observation(self, observation, headers=None, filename=None, *args, **kwargs): """Take an observation diff --git a/Camera/IndiAbstractCamera.py b/Camera/IndiAbstractCamera.py index 06843a1..269ec40 100644 --- a/Camera/IndiAbstractCamera.py +++ b/Camera/IndiAbstractCamera.py @@ -23,6 +23,14 @@ def __init__(self, serv_time, config=None, connect_on_create=True): self.indi_camera_config = config + def park(self): + self.logger.debug(f"Parking camera {self.camera_name}") + self.disconnect() + + def unpark(self): + self.logger.debug(f"Unparking camera {self.camera_name}") + self.connect(connect_device=True) + # TODO TN: setup event based acquisition properly def shoot_asyncWithEvent(self, exp_time_sec, filename, exposure_event, **kwargs): diff --git a/Manager/Manager.py b/Manager/Manager.py index 148b3f4..1fd3e02 100644 --- a/Manager/Manager.py +++ b/Manager/Manager.py @@ -531,11 +531,16 @@ def close_observatory(self): def unpark(self): try: # unpark the observatory + self.observatory.power_all_equipments() self.observatory.unpark() # unpark the mount self.mount.unpark() + # unpark cameras + for camera_name, camera in self.cameras.items(): + camera.unpark() + # Launch guider server if self.guider is not None: self.guider.launch_server() @@ -554,11 +559,16 @@ def park(self): self.guider.disconnect_profile() self.guider.disconnect_server() + # unpark cameras + for camera_name, camera in self.cameras.items(): + camera.unpark() + # park the mount self.mount.park() # park the observatory self.observatory.park() + self.observatory.shutdown_equipments() return True except Exception as e: @@ -654,7 +664,9 @@ def _setup_mount(self): self.mount = getattr(mount_module, mount_name)( location=self.earth_location, serv_time=self.serv_time, - config=self.config['mount']) + config=self.config['mount'], + connect_on_create=False + ) except Exception as e: self.logger.error(f"Cannot load mount module: {e}") raise error.MountNotFound(f"Problem setting up mount") @@ -717,8 +729,8 @@ def setup_cameras(): cam = getattr(cam_module, cam_name)( serv_time=self.serv_time, config=cam_config, - connect_on_create=True) - cam.prepare_shoot() + connect_on_create=False) + #cam.prepare_shoot() self.cameras[cam.name] = cam except Exception as e: raise RuntimeError(f"Problem setting up camera: {e}") diff --git a/Mount/IndiAbstractMount.py b/Mount/IndiAbstractMount.py index 9b1c559..92022c0 100644 --- a/Mount/IndiAbstractMount.py +++ b/Mount/IndiAbstractMount.py @@ -109,6 +109,7 @@ def park(self): try: IndiMount.park(self) self._is_parked = True + self.disconnect() # Disconnect indi server except Exception as e: self.logger.warning('Problem with park') # by default, we assume that mount is in the "worst" situation @@ -125,6 +126,7 @@ def unpark(self): """ IndiMount.unpark(self) self._is_parked = False + self.connect(connect_device=True) # def slew_to_coord(self, coord): IndiMount.slew_to_coord_and_track(self, coord) diff --git a/Mount/IndiG11.py b/Mount/IndiG11.py index 36abb40..7ae9d8a 100644 --- a/Mount/IndiG11.py +++ b/Mount/IndiG11.py @@ -215,7 +215,7 @@ class IndiG11(IndiAbstractMount): Losmandy Gemini.STARTUP_MODE.WARM_RESTART=Off """ - def __init__(self, location, serv_time, config): + def __init__(self, location, serv_time, config, connect_on_create=False): if config is None: config = dict(mount_name="Losmandy Gemini") @@ -223,7 +223,7 @@ def __init__(self, location, serv_time, config): super().__init__(location=location, serv_time=serv_time, config=config, - connect_on_create=False) + connect_on_create=connect_on_create) def unpark(self): if not self.is_connected(): diff --git a/Observatory/AggregatedCustomScopeController.py b/Observatory/AggregatedCustomScopeController.py index 5f1e685..6ec3c30 100644 --- a/Observatory/AggregatedCustomScopeController.py +++ b/Observatory/AggregatedCustomScopeController.py @@ -9,7 +9,7 @@ from Base.Base import Base from helper.IndiDevice import IndiDevice from utils.error import ScopeControllerError - +from utils.error import IndiClientPredicateTimeoutError class UPBV2(IndiDevice, Base): """ @@ -516,24 +516,23 @@ def __init__(self, config=None, connect_on_create=True): config_upbv2=None, config_arduino=None, indi_driver_connect_delay_s=10, - indi_resetable_instruments_driver_name_list=dict( - driver_1="ZWO CCD ASI290MM Mini", - driver_2="Altair AA183MPRO", - driver_3="Shelyak SPOX", - driver_4="PlayerOne CCD Ares-M PRO", - driver_5="Arduino", - driver_6="Losmandy Gemini" - ), + indi_resetable_instruments_driver_map={ + "ZWO CCD": "ZWO CCD ASI290MM Mini", + "Altair": "Altair AA183MPRO", + "Shelyak SPOX": "Shelyak SPOX", + "PlayerOne CCD": "PlayerOne CCD Ares-M PRO", + "Arduino telescope controller": "Arduino" + }, indi_mount_driver_name="Losmandy Gemini", indi_webserver_host="localhost", - indi_webserver_port="8624",) + indi_webserver_port="8624") # Actual device config self.config_upbv2 = config["config_upbv2"] self.config_arduino = config["config_arduino"] # Local features - self._indi_resetable_instruments_driver_name_list = config["indi_resetable_instruments_driver_name_list"] + self._indi_resetable_instruments_driver_map = config["indi_resetable_instruments_driver_map"] self._indi_driver_connect_delay_s = config["indi_driver_connect_delay_s"] self._indi_mount_driver_name = config["indi_mount_driver_name"] self._indi_webserver_host = config["indi_webserver_host"] @@ -554,7 +553,7 @@ def __init__(self, config=None, connect_on_create=True): # Finished configuring self.logger.debug('configured successfully') - def initialize(self): + def power_all_equipments(self): # Restart all driver related to the aggregated devices self.start_all_drivers() @@ -571,7 +570,7 @@ def initialize(self): self._is_initialized = True - def deinitialize(self): + def power_off_all_equipments(self): """ :return: @@ -607,7 +606,20 @@ def close(self): self.logger.debug("Closing AggregatedCustomScopeController") self.close_finder_dustcap() self.close_scope_dustcap() - + + def probe_device_driver_connection(self, driver_name, device_name): + probe = IndiDevice( + device_name=device_name, + indi_client_config=self.config["indi_client"]) + # setup indi client + probe.connect(connect_device=False) + try: + probe.wait_for_any_property_vectors(timeout=5) + except IndiClientPredicateTimeoutError as e: + return False + else: + return True + def is_driver_started(self, driver_name): return driver_name in self.get_running_driver_list() @@ -714,13 +726,16 @@ def switch_on_instruments(self): """ blocking call: switch on cameras, calibration tools, finderscopes, etc... We also need to load the corresponding indi driver """ + if not self._is_initialized: + self.initialize() self.logger.debug("Switching on all instruments") self.upbv2.power_on_all_telescope_equipments() # Now we need to wait a bit before trying to connect driver # but _indi_driver_connect_delay_s was already waited for at previous step - for driver_name in self._indi_resetable_instruments_driver_name_list.values(): - self.restart_driver(driver_name) + for driver_name, device_name in self._indi_resetable_instruments_driver_map.items(): + if not self.probe_device_driver_connection(driver_name=driver_name, device_name=device_name): + self.restart_driver(driver_name) def switch_off_instruments(self): """ blocking call: switch off camera @@ -728,16 +743,16 @@ def switch_off_instruments(self): self.logger.debug("Switching off all equipments connected to upbv2") self.upbv2.power_off_all_telescope_equipments() - for driver_name in self._indi_resetable_instruments_driver_name_list.values(): + for driver_name, device_name in self._indi_resetable_instruments_driver_map.items(): self.stop_driver(driver_name) def start_all_drivers(self): - for driver_name in self._indi_resetable_instruments_driver_name_list.values(): + for driver_name, device_name in self._indi_resetable_instruments_driver_map.items(): self.start_driver(driver_name, check_started=True) self.start_driver(self._indi_mount_driver_name, check_started=True) def stop_all_drivers(self): - for driver_name in self._indi_resetable_instruments_driver_name_list.values(): + for driver_name, device_name in self._indi_resetable_instruments_driver_map.items(): self.stop_driver(driver_name) self.stop_driver(self._indi_mount_driver_name) diff --git a/Observatory/Observatory.py b/Observatory/Observatory.py index 3397e8a..43b572e 100644 --- a/Observatory/Observatory.py +++ b/Observatory/Observatory.py @@ -136,13 +136,21 @@ def has_scope(self): def park(self): self.logger.debug('Observatory: parking scope') + self.open_everything() + + def shutdown_equipments(self): + self.logger.debug('Observatory: shutting down all scope equipments') if self.has_scope: - self.scope_controller.close() + self.scope_controller.power_off_all_equipments() def unpark(self): self.logger.debug('Observatory: unparking scope') + self.close_everything() + + def power_all_equipments(self): + self.logger.debug('Observatory: powering all scope equipments') if self.has_scope: - self.scope_controller.open() + self.scope_controller.power_all_equipments() def open_everything(self): try: diff --git a/apps/prototyping/Camera/IndiASICameraDriverTest.py b/apps/prototyping/Camera/IndiASICameraDriverTest.py index edcb2a7..df0a7c7 100644 --- a/apps/prototyping/Camera/IndiASICameraDriverTest.py +++ b/apps/prototyping/Camera/IndiASICameraDriverTest.py @@ -12,6 +12,9 @@ from Camera.IndiASICamera import IndiASICamera from Service.NTPTimeService import HostTimeService +# Local +from utils.error import IndiClientPredicateTimeoutError + if __name__ == '__main__': config = dict( camera_name='ZWO CCD ASI120MC', @@ -50,7 +53,26 @@ probe = IndiDevice( device_name=config["camera_name"], indi_client_config=config["indi_client"]) - pass + # setup indi client + probe.connect(connect_device=False) + try: + probe.wait_for_any_property_vectors(timeout=5) + except IndiClientPredicateTimeoutError as e: + print(f"There was an error: {e}") + assert bool(probe.property_vectors) + print("test") + + + + + + + + + + + + diff --git a/conf_files/config_backyard.yaml b/conf_files/config_backyard.yaml index aee62fb..1e4b152 100644 --- a/conf_files/config_backyard.yaml +++ b/conf_files/config_backyard.yaml @@ -77,12 +77,12 @@ observatory: indi_host: localhost indi_port: 7625 indi_driver_connect_delay_s: 10 - indi_resetable_instruments_driver_name_list: - driver_1: ZWO CCD - driver_2: Altair - driver_3: Shelyak SPOX - driver_4: PlayerOne CCD - driver_5: Arduino telescope controller + indi_resetable_instruments_driver_map: + ZWO CCD: ZWO CCD ASI290MM Mini + Altair: Altair AA183MPRO + Shelyak SPOX: Shelyak SPOX + PlayerOne CCD: PlayerOne CCD Ares-M PRO + Arduino telescope controller: Arduino indi_mount_driver_name: Losmandy Gemini indi_webserver_host: localhost indi_webserver_port: 8624 diff --git a/helper/IndiClient.py b/helper/IndiClient.py index a0b227d..1ba0706 100644 --- a/helper/IndiClient.py +++ b/helper/IndiClient.py @@ -8,6 +8,7 @@ # Indi stuff from helper.client import INDIClient +from utils.error import IndiClientPredicateTimeoutError # Imaging and Fits stuff from astropy.io import fits @@ -130,9 +131,10 @@ def sync_with_predicate(self, predicate_checker, timeout=30): try: assert (future.result(timeout) is True) except concurrent.futures.TimeoutError: - logger.error(f"Waiting for predicate {predicate_checker} took too long...") + msg = f"Waiting for predicate {predicate_checker} took too long..." + logger.error(msg) future.cancel() - raise RuntimeError + raise IndiClientPredicateTimeoutError(msg) except Exception as exc: logger.error(f"Error while trying to wait for predicate: {exc!r}") raise RuntimeError diff --git a/helper/IndiDevice.py b/helper/IndiDevice.py index 30dc166..f4fe727 100644 --- a/helper/IndiDevice.py +++ b/helper/IndiDevice.py @@ -258,4 +258,14 @@ def wait_for_vector_light(self, vector_name, timeout=None): def wait_for_incoming_blob_vector(self, blob_vector_name=None, timeout=None): blob_checker = lambda: self.check_blob_vector(blob_vector_name) self.indi_client.sync_with_predicate(blob_checker, timeout=timeout) + return + + def wait_for_any_property_vectors(self, timeout=5): + """ + Wait until property vector is non-empty + :param timeout: + :return: + """ + light_checker = lambda: bool(self.property_vectors) + self.indi_client.sync_with_predicate(light_checker, timeout=timeout) return \ No newline at end of file diff --git a/utils/error.py b/utils/error.py index 11ed1f4..e982d95 100644 --- a/utils/error.py +++ b/utils/error.py @@ -31,6 +31,11 @@ class ImageAcquisitionError(Error): def __init(self, message="Error while camera is trying to acquire an image"): super().__init__(message) +class IndiClientPredicateTimeoutError(Error): + """ Error while trying to acquire image """ + def __init(self, message="Error while camwaiting a predicate"): + super().__init__(message) + class BLOBError(Error): """ Error for Indi Blob communication problem """ def __init(self, message="Indi BLOB Error"):