#!/usr/bin/env python3 import sys ##import utils.Logger as L ##from .Agent import Agent sys.path.append("..") from agent.Agent import Agent, build_agent ##log = L.setupLogger("AgentXTaskLogger", "AgentX") class AgentMultiRequester(Agent): # FOR TEST ONLY # Run this agent in simulator mode TEST_MODE = True # Run the assertion tests at the end TEST_WITH_FINAL_TEST = True #TEST_MAX_DURATION_SEC = None TEST_MAX_DURATION_SEC = 200 # Who should I send commands to ? #TEST_COMMANDS_DEST = "myself" #TEST_COMMANDS_DEST = "AgentDeviceTelescopeGemini" # This agent SPECIFIC commands # @override _AGENT_SPECIFIC_COMMANDS = { # Format : “cmd_name” : (timeout, exec_mode, tooltip) } # This agent TEST scenario (automatically executed in TEST mode) # @override TEST_COMMANDS_LIST_GEMINI_AND_SBIG_SIMPLE = [ # Format : (DO_IT, "self cmd_name cmd_args", validity, "expected_result", expected_status), # ex : (True, "self do_process_image i.fit", 200, None, Agent.CMD_STATUS.CMD_EXECUTED), 'ad_mount do_flush_commands', ##'ad_filtersel do_flush_commands', # Not executed because not known by Mount (but by the general DC Gemini only) 'ad_mount get_date', # for test purpose only ##'ad_sensor get_date', ##'ad_sensor set_date 21/10/19', ##'ad_sensor get_date', 'ad_mount get_ra', #'ad_mount get_dec', #'ad_mount get_radec', 'ad_mount set_ra 14:20:51', 'ad_mount get_dec', 'ad_mount set_dec +86:57:48', 'ad_mount get_ra', 'ad_mount get_ra', 'ad_mount get_dec', 'ad_mount get_radec', 'ad_mount set_radec 15:20:51 +87:57:48', 'ad_mount get_radec', # Optional 'ad_mount do_exit', ##'ad_filtersel do_exit', ] TEST_COMMANDS_LIST_GEMINI_AND_SBIG = [ # Ask receiver to delete all its previous commands 'ad_mount do_flush_commands', 'ad_filtersel do_flush_commands', 'ad_shutter do_flush_commands', 'ad_sensor do_flush_commands', 'ad_mount set_state active', # Because of this command, the receiver agent : # - will no more send any new command # - will only execute "generic" commands (and not the "specific" ones) ##'ad_mount set_state idle', # Commands ok for REAL GEMINI (not the simulator, but the REAL hardware telescope) 'ad_mount get_ra', 'ad_mount get_dec', 'ad_mount get_radec', # another alias to the same DC and same DCC (ad_mount2 is the same as ad_mount, both point to AD_Gemini.Mount) 'ad_mount2 get_radec', # another alias to the same DC but not the same DCC 'ad_mount3 get_radec', #'ad_mount set_ra 14:20:51' #'ad_mount set_dec +86:57:48' #'ad_mount set_radec 14:20:51 +86:57:48', #'ad_mount do_goto_radec 14:20:51 +86:57:48', # Because of this command, the receiver agent(s) # will now be able to send new commands ##'ad_mount:set_state:active', ##'ad_filtersel:set_state:active', ##'ad_shutter:set_state:active', ##'ad_sensor:set_state:active', # !!! UNSAFE FOR REAL DEVICES !!! 'ad_mount do_init', 'ad_filtersel do_init', ###'ad_shutter do_init', ###'ad_sensor do_init', # ERROR cases # Unknown AD alias 'ad_unknown get_dec', # Unknown generic command 'ad_mount do_unknown', # Unimplemented generic command 'ad_mount do_unimplemented', # AD specific command implemented (OK) 'ad_mount do_ad_gemini_specific1', # AD specific command UNimplemented (KO) 'ad_mount do_ad_gemini_specific3_unimplemented', # AD specific command implemented (OK) ##'ad_mount set_ad_gemini_specific2', ##'ad_mount do_goto_radec 15 20', 'ad_filtersel do_goto 3', 'ad_shutter do_open', 'ad_sensor do_start_acq 7000', 'ad_shutter do_close', ##'ad_sensor:do_shutdown' # Now stop all my device agent clients: 'ad_mount do_exit', 'ad_filtersel do_exit', ###'ad_shutter do_exit', ###'ad_sensor do_exit', ] ''' TEST_COMMANDS_LIST_GEMINI_AND_SBIG = [ 'ad_mount do_unimplemented', 'ad_mount do_exit', 'ad_filtersel do_exit', ] ''' TEST_COMMANDS_LIST_SBIG_ONLY = [ # Ask receiver to delete all its previous commands 'ad_filtersel do_flush_commands', 'ad_shutter do_flush_commands', 'ad_sensor do_flush_commands', #'ad_mount:go_active', #'ad_filterselect set_state active', # Because of this command, the receiver agent : # - will no more send any new command # - will only execute "generic" commands (and not the "specific" ones) ##'ad_mount:set_state:idle', # Because of this command, the receiver agent(s) # will now be able to send new commands ##'ad_mount:set_state:active', ##'ad_filterselect:set_state:active', ##'ad_shutter:set_state:active', ##'ad_sensor:set_state:active', #TODO: special cas à traiter 'ad_sensor UNKNOWN_NATIVE_CMD', 'ad_filtersel do_unimplemented', 'ad_filtersel do_ad_sbig_specific1', 'ad_filtersel do_ad_sbig_specific3_unimplemented', 'ad_filtersel do_unknown', 'ad_filtersel set_ad_sbig_specific2', 'ad_shutter do_unimplemented', 'ad_filtersel do_ad_sbig_specific4_unimplemented', 'ad_sensor do_unimplemented', #'ad_mount do_init', #'ad_filtersel do_init', ##'ad_shutter:do_init', ##'ad_sensor:do_init', #'ad_mount do_goto_radec 15 20', 'ad_filtersel do_goto 3', 'ad_shutter do_open', 'ad_sensor do_start_acq 7000', 'ad_shutter do_close', ##'ad_sensor:do_shutdown' # Now stop all my device agent clients: #'ad_mount do_exit', 'ad_filtersel do_exit', ##'ad_shutter:do_exit', ##'ad_sensor:do_exit', ] TEST_COMMANDS_LIST_BASIC_OLD = [ # Ask receiver to delete all its previous commands 'AgentDeviceTelescope1:flush_commands', 'AgentDeviceFilterSelector1:flush_commands', 'AgentDeviceShutter1:flush_commands', 'AgentDeviceSensor1:flush_commands', 'AgentDeviceTelescope1:go_active', # Because of this command, the receiver agent : # - will no more send any new command # - will only execute "generic" commands (and not the "specific" ones) 'AgentDeviceTelescope1:go_idle', # Not executed (skipped) because receiver agent is now "idle" #"specific0", # Because of this command, the receiver agent # will now be able to send new commands 'AgentDeviceTelescope1:go_active', # Executed because recipient agent is now "active" #"specific1", 'AgentDeviceTelescope1:get radec', # should abort previous command (specific1) #"abort", # Executed completely because no abort #"specific2", # fully executed, result is 7 #"eval 4+3", 'AgentDeviceTelescope1:go_idle', # Now stop all my device agent clients: 'AgentDeviceTelescope1:exit', 'AgentDeviceFilterSelector1:exit', 'AgentDeviceShutter1:exit', 'AgentDeviceSensor1:exit', ] TEST_COMMANDS_LIST = TEST_COMMANDS_LIST_GEMINI_AND_SBIG_SIMPLE TEST_COMMANDS_LIST = TEST_COMMANDS_LIST_SBIG_ONLY TEST_COMMANDS_LIST = TEST_COMMANDS_LIST_GEMINI_AND_SBIG """ ================================================================= FUNCTIONS RUN INSIDE MAIN THREAD ================================================================= """ #TODO: Avirer def _set_agent_device_aliases_from_config(self, agent_alias): self._my_client_agents = { 'ad_mount': 'AgentDeviceGemini.Mount', 'ad_mount2': 'AgentDeviceGemini.Mount', 'ad_mount3': 'AgentDeviceGemini.MountBis', 'ad_filtersel': 'AgentDeviceSBIG.FilterSelector', 'ad_shutter': 'AgentDeviceSBIG.DetectorShutter', 'ad_sensor': 'AgentDeviceSBIG.DetectorSensor', } # @override #def __init__(self, name:str=None, config_filename=None, RUN_IN_THREAD=True): def __init__(self, config_filename=None, RUN_IN_THREAD=True, DEBUG_MODE=False): ##if name is None: name = self.__class__.__name__ #super().__init__(name, config_filename, RUN_IN_THREAD) #super().__init__(config_filename, RUN_IN_THREAD, DEBUG_MODE=DEBUG_MODE) self._my_client_agents_aliases = [ 'ad_mount', 'ad_mount2', 'ad_mount3', 'ad_filtersel', 'ad_shutter', 'ad_sensor', ] super().__init__(config_filename, RUN_IN_THREAD) #TODO: : à mettre dans la config """ 'AgentDeviceTelescope1': 'AgentDeviceTelescopeGemini', 'AgentDeviceFilterSelector1': 'AgentDeviceSBIG', 'AgentDeviceShutter1': 'AgentDeviceSBIG', 'AgentDeviceSensor1': 'AgentDeviceSBIG', """ #'ad_filterselect': 'AgentDeviceSBIG.DeviceControllerFilterSelector', #'ad_mount': 'AgentDeviceTelescopeGemini.Telescope', #'ad_mount': 'AgentDeviceTelescopeGemini', ''' self._my_client_agents = { 'ad_mount': 'AgentDeviceGemini.DC_Mount', 'ad_filtersel': 'AgentDeviceSBIG.DC_FilterSelector', 'ad_shutter': 'AgentDeviceSBIG.DC_DetectorShutter', 'ad_sensor': 'AgentDeviceSBIG.DC_DetectorSensor', } ''' #self._log.self.printd(f"init done for {self.name}") self.printd(f"init done") # @override def _init(self): pass # --- Set the mode according the startmode value ##agent_alias = self.__class__.__name__ ##self.set_mode_from_config(agent_alias) ''' # @override def load_config(self): super().load_config() ''' ''' # @override def update_survey(self): super().update_survey() ''' ''' # @override def get_next_command(self): return super().get_next_command() ''' # @override def do_log(self): super().do_log() """ ================================================================= FUNCTIONS RUN INSIDE A SUB-THREAD (OR A PROCESS) (thread_*()) ================================================================= """ # Define your own command step(s) here def cmd_step1(self, step:int): cmd = self._current_specific_cmd cmd.result = f"in step #{step}/{self._thread_total_steps_number}" cmd.save() """ if self.RUN_IN_THREAD: self.printd("(save from thread)") cmd.save() else: #@transaction.atomic self.printd("(save from process)") with transaction.atomic(): cmd.save() #Command.objects.select_for_update() """ def cmd_step2(self, step:int): self.cmd_step1(step) def cmd_step3(self, step:int): self.cmd_step1(step) def cmd_step4(self, step:int): self.cmd_step1(step) """ # @override def thread_exec_specific_cmd_step(self, step:int, sleep_time:float=1.0): self.thread_stop_if_asked() cmd = self._current_specific_cmd self.printd(f">>>>> Thread (cmd {cmd.name}): step #{step}/5") self.sleep(sleep_time) """ ''' # @override def exec_specific_cmd_start(self, cmd:Command, from_thread=True): super().exec_specific_cmd_start(cmd, from_thread) ''' # @override def thread_exec_specific_cmd_main(self): # This is optional self.thread_set_total_steps_number(5) # HERE, write your own scenario # scenario OK self.thread_exec_specific_cmd_step(1, self.cmd_step1, 1) self.thread_exec_specific_cmd_step(2, self.cmd_step2, 3) self.thread_exec_specific_cmd_step(3, self.cmd_step1, 5) self.thread_exec_specific_cmd_step(4, self.cmd_step3, 10) self.thread_exec_specific_cmd_step(5, self.cmd_step1, 4) # ... as many as you need """ autre scenario self.thread_exec_specific_cmd_step(1, self.cmd_step1, 1) self.thread_exec_specific_cmd_step(2, self.cmd_step2, 2) self.thread_exec_specific_cmd_step(3, self.cmd_step1, 2) self.thread_exec_specific_cmd_step(4, self.cmd_step3, 2) self.thread_exec_specific_cmd_step(5, self.cmd_step1, 3) """ ''' # @override def exec_specific_cmd_end(self, cmd:Command, from_thread=True): super().exec_specific_cmd_end(cmd, from_thread) ''' # @override def _TEST_test_results_main(self, commands): #nb_asserted = super().simulator_test_results_main(commands) nb_asserted = 0 ''' for cmd in commands: if cmd.name == "flush_commands": assert cmd.is_executed() nb_asserted+=1 # 2 times if cmd.name == "go_active": assert cmd.is_executed() nb_asserted+=1 # 2 times if cmd.name == "go_idle": assert cmd.is_executed() nb_asserted+=1 if cmd.name == "get radec": assert cmd.is_executed() #assert cmd.result == "06:10:38,+89:41:02" nb_asserted+=1 """ if cmd.name == "specific0": assert cmd.is_skipped() assert cmd.result == "in step #5/5" nb_asserted+=1 if cmd.name == "specific1": assert cmd.is_killed() nb_asserted+=1 if cmd.name == "specific2": assert cmd.is_executed() assert cmd.result == "in step #5/5" nb_asserted+=1 if cmd.name == "eval 4+3": assert cmd.is_executed() assert cmd.get_result() == "7" nb_asserted+=1 if cmd.name in ("abort"): assert cmd.is_executed() nb_asserted+=1 """ if cmd.name in ("exit"): assert cmd.is_executed() nb_asserted+=1 ''' return nb_asserted """ ================================================================= MAIN FUNCTION ================================================================= """ if __name__ == "__main__": # with thread RUN_IN_THREAD=True # with process #RUN_IN_THREAD=False agent = build_agent(AgentMultiRequester, RUN_IN_THREAD=RUN_IN_THREAD) ''' TEST_MODE, WITH_SIM, configfile = extract_parameters() #agent = AgentX() agent = AgentTelescopeRequester("AgentTelescopeRequester", configfile, RUN_IN_THREAD) agent.setSimulatorMode(TEST_MODE) self.printd(agent) ''' agent.run()