diff --git a/.gitignore b/.gitignore index f749670..406a7a6 100644 --- a/.gitignore +++ b/.gitignore @@ -19,7 +19,6 @@ BASE_TEMPLATE.HTML *.swp /.settings/ -#/.pydevproject #src/images/*_* #src/alert_manager/twistd* @@ -27,6 +26,7 @@ BASE_TEMPLATE.HTML #src/common/migrations/0* #src/common/migrations_LOCAL/0* #src/monitoring/plc_config.json +src/core/pyros_django/majordome/doc/AgentMajordome_object_diag_error.html # LOGS /config/logs/* @@ -85,4 +85,4 @@ src/core/pyros_django/misc/fixtures/tests/test_import_seq.yml *.moi *.moi.* -privatedev/plugin/agent/triton/triton/CATALOGUES \ No newline at end of file +privatedev/plugin/agent/triton/triton/CATALOGUES diff --git a/.pydevproject b/.pydevproject deleted file mode 100644 index d3066d6..0000000 --- a/.pydevproject +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - Default - - - - - - - - python interpreter - - - - - - - - - - /${PROJECT_DIR_NAME}/src - - /${PROJECT_DIR_NAME}/simulators - - - - - - - - - - - DJANGO_MANAGE_LOCATION - src/core/pyros_django/manage.py - DJANGO_SETTINGS_MODULE - core.pyros_django.pyros.settings - PY - 37 - - - - - - - - - - /Users/epallier/Documents/_W_more/PROJECTS/GFT/SOFT/PYROS_SOFT/PYROS201806/venv/venv_py3_pyros/lib/python3.7/site-packages - - diff --git a/cp_private_dev_to_private.sh b/cp_private_dev_to_private.sh index da37fa4..7cae752 100755 --- a/cp_private_dev_to_private.sh +++ b/cp_private_dev_to_private.sh @@ -1,6 +1,7 @@ cp -p src/core/pyros_django/agent/AgentBasic.py privatedev/plugin/agent/AgentBasic.py -rsync -avh --delete privatedev/ private/ +rsync -avh --delete --exclude '.gitignore' --exclude 'plugin/README' --exclude 'config/README' privatedev/ private/ + #cp -r ./privatedev/* ./private/ diff --git a/private/.gitignore b/private/.gitignore index 8e0aa32..c6268f8 100644 --- a/private/.gitignore +++ b/private/.gitignore @@ -1,7 +1,7 @@ # Ignore everything in those directories -plugins/* +plugin/* config/* -# Except this file +# Except these files !.gitignore -!plugins/README -!config/README \ No newline at end of file +!plugin/README +!config/README diff --git a/privatedev/plugin/agent/AgentBasic.py b/privatedev/plugin/agent/AgentBasic.py index 6ed3949..8afe520 100755 --- a/privatedev/plugin/agent/AgentBasic.py +++ b/privatedev/plugin/agent/AgentBasic.py @@ -47,7 +47,7 @@ class AgentBasic(Agent): # on DEV #COMMIT_ONLY = False # on commit only - COMMIT_ONLY = False + COMMIT_ONLY = True # @override _TEST_COMMANDS_LIST = [ diff --git a/src/core/pyros_django/agent/Agent.py b/src/core/pyros_django/agent/Agent.py index 09f45c3..4c74cdb 100755 --- a/src/core/pyros_django/agent/Agent.py +++ b/src/core/pyros_django/agent/Agent.py @@ -626,8 +626,6 @@ class Agent: _my_client_agents_aliases = [] _my_client_agents = {} - _iter_num = None - # Log object _log = None @@ -645,13 +643,13 @@ class Agent: # Declaration of Instance attributes, default values #self.UP_SINCE = datetime.utcnow() self.__UP_SINCE = datetime.now(tz=timezone.utc) - self.__current_cmd = None + self.__current_cmd :AgentCmd = None self.name = "Generic Agent" - self.__status = None - self.__mode = None + self.__status :str = None + self.__mode :str = None self.unit = None self.TEST_COMMANDS = None - + self.__iter_num :int = 0 #print(AgentSurvey.MODE_CHOICES.IDLE) #sys.exit() @@ -1030,82 +1028,68 @@ class Agent: ###############@ # REPEAT UNTIL not DO_RESTART_LOOP self.DO_RESTART_LOOP = True + while self.DO_RESTART_LOOP: - - log.info("*"*10+ " STARTING RESTART LOOP "+ "*"*10+ '\n') - # By default, no restart after exit from main loop self.DO_RESTART_LOOP = False - - self.start_time = time.time() - #log.debug("on est ici: " + os.getcwd()) - - self.__load_config() - - self.__print_TEST_MODE() - - self._init() - ''' testing log: - self.log_e("ERROR") - self.log_c("FATAL critical ERROR") - ''' - #self.log_w("WARNING", "watch your step !") - #log.warning("WARNING"+ "watch your step !") - - # Avoid blocking on false "running" commands - # (old commands that stayed with "running" status when agent was killed) - AgentCmd.delete_commands_with_running_status_for_agent(self.name) - - self._iter_num = 1 - - ############# - # MAIN loop # - ############@ - self.DO_MAIN_LOOP = True - while self.DO_MAIN_LOOP: - try: - self.__main_loop(nb_iter,FOR_REAL) - #if not self.DO_MAIN_LOOP: break - except KeyboardInterrupt: # CTRL-C - # In case of CTRL-C, kill the current thread (process) before dying (in error) - #log.info("CTRL-C Interrupted, I kill the current thread (process) before exiting (if exists)") - log.info("CTRL-C Interrupted, trying to stop cleanly") - #self._kill_running_device_cmd_if_exists("USER_CTRLC") - #self.do_things_before_exit("USER_CTRLC") - ##self._cleanup_before_exit("USER_CTRLC") - self.do_stop("asap") - exit(1) - - # TEST mode only - self.__TEST_test_results() - #if self._DO_EXIT: exit(0) + try: + self.__restart_loop(nb_iter,FOR_REAL) + except KeyboardInterrupt: # CTRL-C + # In case of CTRL-C, kill the current thread (process) before dying (in error) + #log.info("CTRL-C Interrupted, I kill the current thread (process) before exiting (if exists)") + log.info("CTRL-C Interrupted, trying to stop cleanly") + break + #self._kill_running_device_cmd_if_exists("USER_CTRLC") + #self.do_things_before_exit("USER_CTRLC") + ##self._cleanup_before_exit("USER_CTRLC") + ###self.do_stop("asap") + ###exit(1) + + # exit + self.do_stop("asap") + def __restart_loop(self, nb_iter:int=None, FOR_REAL:bool=True): + log.info("*"*10+ " STARTING RESTART LOOP "+ "*"*10+ '\n') - def __cleanup_before_exit(self, stopper_agent_name:str=None): - if not stopper_agent_name: stopper_agent_name = self.name - #self._set_status(self.STATUS_EXIT) - ##self._log_agent_state() + self.start_time = time.time() + #log.debug("on est ici: " + os.getcwd()) - log.info("Trying to stop cleanly") - log.info("Before exiting, Here are (if exists) the current (still) pending commands (time ordered) :") - #commands = AgentCmd.get_commands_sent_to_agent(self.name) - commands = AgentCmd.get_pending_and_running_commands_for_agent(self.name) - AgentCmd.show_commands(commands, True) - ##self.do_flush_commands() - #if self.TEST_MODE and self.TEST_WITH_FINAL_TEST and self.TEST_COMMANDS_DEST == "myself": self.simulator_test_results() - if self.TEST_MODE and self.TEST_WITH_FINAL_TEST: - self.__TEST_test_results() - #self._DO_EXIT=True - #exit(0) + self.__load_config() - self._do_things_before_exit(stopper_agent_name) - ##self._set_and_log_status(self.AGT_STATUS.EXITING) + self.__print_TEST_MODE() - #def _kill_running_device_cmd_if_exists(self, abort_cmd_sender): - # to be overriden by subclass - def _do_things_before_exit(self, stopper_agent_name:str=None): - pass + self._init() + ''' testing log: + self.log_e("ERROR") + self.log_c("FATAL critical ERROR") + ''' + #self.log_w("WARNING", "watch your step !") + #log.warning("WARNING"+ "watch your step !") + + # Avoid blocking on false "running" commands + # (old commands that stayed with "running" status when agent was killed) + AgentCmd.delete_commands_with_running_status_for_agent(self.name) + + ############# + # MAIN loop # + ############@ + self.__iter_num = 1 + self.DO_MAIN_LOOP = True + while self.DO_MAIN_LOOP: + # EXIT because of nb of iterations ? + if nb_iter is not None: + # Bad number of iterations or nb iterations reached => exit + if nb_iter <= 0 or nb_iter < self.__iter_num: + log.info(f"Exit because number of iterations asked ({nb_iter}) has been reached") + break + self.__main_loop(nb_iter,FOR_REAL) + self.__iter_num += 1 + #if not self.DO_MAIN_LOOP: break + + # TEST mode only + self.__TEST_test_results() + #if self._DO_EXIT: exit(0) def __main_loop(self, nb_iter:int=None, FOR_REAL:bool=True): @@ -1204,26 +1188,53 @@ class Agent: self.__main_loop_end() - self._iter_num += 1 + def __cleanup_before_exit(self, stopper_agent_name:str=None): + if not stopper_agent_name: stopper_agent_name = self.name + #self._set_status(self.STATUS_EXIT) + ##self._log_agent_state() + + log.info("Trying to stop cleanly") + log.info("Before exiting, Here are (if exists) the current (still) pending commands (time ordered) :") + #commands = AgentCmd.get_commands_sent_to_agent(self.name) + commands = AgentCmd.get_pending_and_running_commands_for_agent(self.name) + AgentCmd.show_commands(commands, True) + ##self.do_flush_commands() + #if self.TEST_MODE and self.TEST_WITH_FINAL_TEST and self.TEST_COMMANDS_DEST == "myself": self.simulator_test_results() + if self.TEST_MODE and self.TEST_WITH_FINAL_TEST: + self.__TEST_test_results() + #self._DO_EXIT=True + #exit(0) + + self._do_things_before_exit(stopper_agent_name) + ##self._set_and_log_status(self.AGT_STATUS.EXITING) + + #def _kill_running_device_cmd_if_exists(self, abort_cmd_sender): + # to be overriden by subclass + def _do_things_before_exit(self, stopper_agent_name:str=None): + pass + + def __main_loop_start(self, nb_iter:int=None): for i in range(3): print() #self.printd("-"*80) log.info("*"*90) - log.info("*"*20 + f" {self.name} : MAIN LOOP ITERATION {self._iter_num} (START) " + "*"*20) + log.info("*"*20 + f" {self.name} : MAIN LOOP ITERATION #{self.__iter_num} (START) " + "*"*20) log.info("*"*90 + '\n') #self.print(f"Iteration {self._iter_num}") + ''' # EXIT because of nb of iterations ? if nb_iter is not None: # Bad number of iterations or nb iterations reached => exit - if nb_iter <= 0 or nb_iter < self._iter_num: + if nb_iter <= 0 or nb_iter < self.__iter_num: log.info(f"Exit because number of iterations asked ({nb_iter}) has been reached") self.DO_MAIN_LOOP = False return + ''' # Temporizing (delay) : Wait a random number of sec before starting iteration # (to avoid to busy to much the processor) @@ -1552,7 +1563,7 @@ class Agent: # def get_state(self): - return f"MODE is {self.__get_mode()} ; STATUS is {self.get_status()} ; ITERATION #{self._iter_num}" + return f"MODE is {self.__get_mode()} ; STATUS is {self.get_status()} ; ITERATION #{self.__iter_num}" def show_state(self): log.info(self.get_state()) @@ -1824,7 +1835,7 @@ class Agent: #self._agent_survey = AgentSurvey.objects.get(name=self.name) self.__agent_survey.mode = self.__get_mode() self.__agent_survey.status = self.get_status() - self.__agent_survey.iteration = self._iter_num + self.__agent_survey.iteration = self.__iter_num self.__agent_survey.save() #self._agent_survey.save(update_fields=["mode", "status"]) diff --git a/src/core/pyros_django/agent/AgentA.py b/src/core/pyros_django/agent/AgentA.py index d94d069..69633e6 100755 --- a/src/core/pyros_django/agent/AgentA.py +++ b/src/core/pyros_django/agent/AgentA.py @@ -77,8 +77,8 @@ class AgentA(Agent): self._log.print("init done") # @override - def init(self): - super().init() + def _init(self): + super()._init() # --- Set the mode according the startmode value ##agent_alias = self.__class__.__name__ ##self.set_mode_from_config(agent_alias) diff --git a/src/core/pyros_django/agent/AgentB.py b/src/core/pyros_django/agent/AgentB.py index 25c2ec1..d40c53a 100755 --- a/src/core/pyros_django/agent/AgentB.py +++ b/src/core/pyros_django/agent/AgentB.py @@ -62,8 +62,8 @@ class AgentB(Agent): self._log.print("init done") # @override - def init(self): - super().init() + def _init(self): + super()._init() # --- Set the mode according the startmode value ##agent_alias = self.__class__.__name__ ##self.set_mode_from_config(agent_alias) diff --git a/src/core/pyros_django/agent/AgentBasic.py b/src/core/pyros_django/agent/AgentBasic.py index 6ed3949..8afe520 100755 --- a/src/core/pyros_django/agent/AgentBasic.py +++ b/src/core/pyros_django/agent/AgentBasic.py @@ -47,7 +47,7 @@ class AgentBasic(Agent): # on DEV #COMMIT_ONLY = False # on commit only - COMMIT_ONLY = False + COMMIT_ONLY = True # @override _TEST_COMMANDS_LIST = [ diff --git a/src/core/pyros_django/agent/AgentC.py b/src/core/pyros_django/agent/AgentC.py index 3900c8d..6f4349a 100755 --- a/src/core/pyros_django/agent/AgentC.py +++ b/src/core/pyros_django/agent/AgentC.py @@ -84,8 +84,8 @@ class AgentC(Agent): ###self._log.print("init done") # @override - def init(self): - super().init() + def _init(self): + super()._init() # --- Set the mode according the startmode value ##agent_alias = self.__class__.__name__ ##self.set_mode_from_config(agent_alias) diff --git a/src/core/pyros_django/agent/AgentDevice.py b/src/core/pyros_django/agent/AgentDevice.py index bdaea73..a3d5e70 100755 --- a/src/core/pyros_django/agent/AgentDevice.py +++ b/src/core/pyros_django/agent/AgentDevice.py @@ -205,9 +205,9 @@ class AgentDevice(Agent): pass # @override - def init(self): + def _init(self): - super().init() + super()._init() # --- Set the mode according the startmode value ##agent_alias = self.__class__.__name__ ##self.set_mode_from_config(agent_alias) @@ -307,7 +307,7 @@ class AgentDevice(Agent): def is_device_level_cmd(self, cmd: AgentCmd): return self._device_ctrl.is_valid_cmd(DeviceCmd(cmd.full_name)) - def process_device_level_cmd(self): + def _process_device_level_cmd(self): log.info("(DEVICE LEVEL CMD)") try: self.exec_device_cmd_if_possible(cmd) @@ -331,7 +331,7 @@ class AgentDevice(Agent): # @override superclass (Agent) method def exec_device_cmd_if_possible(self, cmd:AgentCmd): - self._set_status(self.STATUS_SPECIFIC_PROCESS) + self.__set_status(self.STATUS_SPECIFIC_PROCESS) #self.print(f"Starting execution of a DEVICE cmd {cmd}") self.print("Starting execution of a DEVICE cmd...") self.printd(cmd) @@ -421,7 +421,7 @@ class AgentDevice(Agent): # @override superclass (Agent) - def TEST_test_results_other(self, commands): + def _TEST_test_results_other(self, commands): # (EP) moved from Agent # Now test that any "AD get_xx" following a "AD set_xx value" command has result = value for i,cmd_set in enumerate(commands): @@ -435,7 +435,7 @@ class AgentDevice(Agent): # @override parent class (Agent) - def do_things_before_exit(self, abort_cmd_sender): + def _do_things_before_exit(self, abort_cmd_sender): self._kill_running_device_cmd_if_exists(abort_cmd_sender) def _kill_running_device_cmd_if_exists(self, abort_cmd_sender): diff --git a/src/core/pyros_django/agent/AgentDeviceGemini.py b/src/core/pyros_django/agent/AgentDeviceGemini.py index a6cc4dd..092bbf5 100755 --- a/src/core/pyros_django/agent/AgentDeviceGemini.py +++ b/src/core/pyros_django/agent/AgentDeviceGemini.py @@ -102,8 +102,8 @@ class AgentDeviceGemini(AgentDevice): ##self._log.self.printd(f"init done for {name}") - def init(self): - super().init() + def _init(self): + super()._init() # Telescope (long) init # TODO: diff --git a/src/core/pyros_django/agent/AgentDeviceSBIG.py b/src/core/pyros_django/agent/AgentDeviceSBIG.py index 6ab603d..bada667 100755 --- a/src/core/pyros_django/agent/AgentDeviceSBIG.py +++ b/src/core/pyros_django/agent/AgentDeviceSBIG.py @@ -101,8 +101,8 @@ class AgentDeviceSBIG(AgentDevice): ##self._log.self.printd(f"init done for {name}") - def init(self): - super().init() + def _init(self): + super()._init() # Telescope (long) init # TODO: diff --git a/src/core/pyros_django/agent/AgentMultiRequester.py b/src/core/pyros_django/agent/AgentMultiRequester.py index 200ad00..8e86053 100755 --- a/src/core/pyros_django/agent/AgentMultiRequester.py +++ b/src/core/pyros_django/agent/AgentMultiRequester.py @@ -293,8 +293,8 @@ class AgentMultiRequester(Agent): self.printd(f"init done") # @override - def init(self): - super().init() + def _init(self): + super()._init() # --- Set the mode according the startmode value ##agent_alias = self.__class__.__name__ ##self.set_mode_from_config(agent_alias) @@ -403,7 +403,7 @@ class AgentMultiRequester(Agent): ''' # @override - def TEST_test_results_main(self, commands): + def _TEST_test_results_main(self, commands): #nb_asserted = super().simulator_test_results_main(commands) nb_asserted = 0 ''' diff --git a/src/core/pyros_django/agent/AgentTelescopeRequester.py b/src/core/pyros_django/agent/AgentTelescopeRequester.py index f05d1db..7f981f6 100755 --- a/src/core/pyros_django/agent/AgentTelescopeRequester.py +++ b/src/core/pyros_django/agent/AgentTelescopeRequester.py @@ -78,8 +78,8 @@ class AgentTelescopeRequester(Agent): self._log.print(f"init done") # @override - def init(self): - super().init() + def _init(self): + super()._init() # --- Set the mode according the startmode value ##agent_alias = self.__class__.__name__ ##self.set_mode_from_config(agent_alias) diff --git a/src/core/pyros_django/agent/AgentX.py b/src/core/pyros_django/agent/AgentX.py index d30982d..17f6e77 100755 --- a/src/core/pyros_django/agent/AgentX.py +++ b/src/core/pyros_django/agent/AgentX.py @@ -9,7 +9,7 @@ import sys #from common.models import Command sys.path.append("..") -from agent.Agent import Agent, extract_parameters +from agent.Agent import Agent, __extract_parameters @@ -55,8 +55,8 @@ class AgentX(Agent): super().__init__(name, config_filename, RUN_IN_THREAD) # @override - def init(self): - super().init() + def _init(self): + super()._init() # --- Set the mode according the startmode value ##agent_alias = self.__class__.__name__ ##self.set_mode_from_config(agent_alias) @@ -168,7 +168,7 @@ if __name__ == "__main__": # with process #RUN_IN_THREAD=False - TEST_MODE, configfile = extract_parameters() + TEST_MODE, configfile = __extract_parameters() #agent = AgentX() agent = AgentX("AgentX", configfile, RUN_IN_THREAD) agent.setSimulatorMode(TEST_MODE) diff --git a/src/core/pyros_django/agent/doc/AgentDevice_class_diag.pu b/src/core/pyros_django/agent/doc/AgentDevice_class_diag.pu deleted file mode 100755 index d1853bd..0000000 --- a/src/core/pyros_django/agent/doc/AgentDevice_class_diag.pu +++ /dev/null @@ -1,46 +0,0 @@ - -@startuml - -/' -UML class Diagram : can be displayed with PlantUML (plugin for Eclipse or for PyCharm) - -PlantUML: -- How to install : https://projects.irap.omp.eu/projects/pyros/wiki/Project_Development#PlantUML -- Eclipse plugin : http://plantuml.com/eclipse -- class diagrams : http://plantuml.com/class-diagram -- sequence diagrams : http://plantuml.com/sequence-diagram -- state diagrams : http://plantuml.com/state-diagram -- Use Case diagrams : http://plantuml.com/use-case-diagram -- OLD Activity diagrams : http://plantuml.com/activity-diagram-legacy -- NEW Activity diagrams : http://plantuml.com/activity-diagram-beta -- Pre-processing (include...) : http://plantuml.com/preprocessing -- GANTT diagrams : http://plantuml.com/gantt-diagram -- REAL WORLD EXAMPLES !!! : https://real-world-plantuml.com/ -- For Python: - - https://github.com/SamuelMarks/python-plantuml - - https://pythonhosted.org/plantuml/ - -UML diagrams theory : https://www.ibm.com/developerworks/rational/library/content/RationalEdge/sep04/bell/index.html -'/ - -title -__**AgentDevice class diagram**__ -end title - - - -/' Abstract Devices Controllers '/ - -Agent <|-- AgentDevice -AgentDevice --> DeviceController - -AgentDevice <|-- AgentDeviceTelescopeGemini -AgentDevice <|-- AgentDeviceSBIG - -AgentDeviceTelescopeGemini --> TelescopeGeminiController -TelescopeGeminiController o-- TelescopeGeminiSimulator - -AgentDeviceSBIG --> SBIGController -SBIGController o-- SBIGSimulator - -@enduml diff --git a/src/core/pyros_django/agent/doc/AgentDevice_sequence_diag.pu b/src/core/pyros_django/agent/doc/AgentDevice_sequence_diag.pu deleted file mode 100644 index b37d62a..0000000 --- a/src/core/pyros_django/agent/doc/AgentDevice_sequence_diag.pu +++ /dev/null @@ -1,146 +0,0 @@ - -@startuml - -' --- Agent SEQUENCE DIAGRAM (plantUML) --- - -' Syntax => http://plantuml.com/fr/sequence-diagram - -' What is the current version of PlantUML (and Java) used ? -' startuml -' version -' enduml - - -title -__**AgentDevice Sequence Diagram (example with AgentDeviceSBIG)**__ -Version 19-11-2019 - -end title -'(E. Pallier) - -autonumber - -/' 5 participants (actors) '/ -participant AgentDeviceSBIG -participant DC_SBIG -participant Channel -participant DCC as "DCC (DC_Filter, DC_Shutter, or DC_Sensor...)" -participant SBIG as "DS_SBIG (or real SBIG DEVICE)" #red - - -== _init_(config_filename) # python __init_() == -'group NEW INSTANCE(config_filename) # (python init()) - AgentDeviceSBIG --> AgentDeviceSBIG: Initializes superclass\n (AgentDevice and then Agent)\n with my config_filename,\n my DC class (i.e. DC_SBIG),\n my host and my port - AgentDeviceSBIG --> AgentDeviceSBIG: (Agent:) self.config =\n ConfigPyros(config_filename) - AgentDeviceSBIG --> AgentDeviceSBIG: (Agent:) _set_mode_from_config() -'end - -'group run() # infinite loop - -== run() # infinite loop== - - == run.init() == - 'group init() - 'create DC_SBIG - AgentDeviceSBIG --> DC_SBIG** : Create instance of my DC\n with my host and port - DC_SBIG --> DC_SBIG: initializes superclass\n (DeviceController) with\n my channel_type, protocol,\n commands... - 'create Channel - DC_SBIG --> Channel** : (DeviceController:) my_channel =\n new Channel(channel_type, host, port) - DC_SBIG --> SBIG** : (DeviceController, if simulator mode:)\n Launch simulator DS_SBIG in thread - 'create DCC - DC_SBIG --> DCC** : Create my dcc1, dcc2, ..., dccN instance(s) - DCC --> DCC: Initializes my superclass\n (DeviceController) with\n given DC_SBIG my_channel,\n protocol, commands... - AgentDeviceSBIG --> DC_SBIG: _connect_to_device() - DC_SBIG --> Channel: _my_channel._connect_to_server() - Channel --> SBIG: mysock.connect(HOST, PORT) - 'end group init() - - == run.main_loop() # infinite loop == - 'group main_loop() # infinite loop - AgentDeviceSBIG --> AgentDeviceSBIG: _load_config() # reload only if changed - AgentDeviceSBIG --> AgentDeviceSBIG: _log_agent_status() - group routine_process() - group get_device_status() # DIRECT execution, NO THREAD (see details below in THREAD section) - AgentDeviceSBIG --> DC_SBIG: execute_cmd(ROUTINE_COMMAND) - note left #aqua - DIRECT execution, - NO THREAD - end note - DC_SBIG --> SBIG: REQUEST - ... - 'DC_SBIG <-- SBIG: ANSWER - return ANSWER - AgentDeviceSBIG <-- DC_SBIG: ANSWER - AgentDeviceSBIG --> AgentDeviceSBIG: Save status in DB - end - end - - - group command_process_if_exists() - alt if new COMMAND - - alt AGENT LEVEL COMMAND (i.e. Agent level, immediate short execution, GENERAL or SPECIFIC) - AgentDeviceSBIG --> AgentDeviceSBIG: _exec_agent_cmd(cmd) - - else DEVICE LEVEL COMMAND (i.e. DC level, execution will be in thread) - - group exec_device_cmd_if_possible() - - alt AgentDevice is IDLE => SKIP command (ignored) - - else A device command is already running in a thread => do not execute COMMAND for now (try again at next iteration) - - else COMMAND is not implemented => UnimplementedGenericCmdException - - else ELSE => RUN COMMAND in a THREAD (running _thread_exec_device_cmd() which runs exec_device_cmd(COMMAND)) - AgentDeviceSBIG --> DC_SBIG: execute_cmd(COMMAND) - note left #aqua - EXECUTION - IN A THREAD - end note - - /' in DC_SBIG : '/ - autonumber stop - alt NATIVE COMMAND (i.e. SBIG grammar) - group execute_native_cmd(COMMAND) - DC_SBIG --> SBIG: REQUEST - 'DC_SBIG <-- SBIG: ANSWER - return ANSWER - end group - - else GENERIC COMMAND (i.e. PYROS grammar) - group execute_generic_cmd(COMMAND) - alt COMMAND is GENERAL (i.e. DC_SBIG level) - DC_SBIG --> SBIG: REQUEST - 'DC_SBIG <-- SBIG: ANSWER - return ANSWER - else COMMAND is SPECIFIC (i.e. for one of my dcc's, ex: DC_Filter) - DC_SBIG --> DCC: execute_generic_cmd(COMMAND) - DCC --> SBIG: REQUEST - 'DCC <-- SBIG: ANSWER - return ANSWER - DC_SBIG <-- DCC: ANSWER - end alt - end group - - end alt NATIVE or GENERIC ? - - AgentDeviceSBIG <-- DC_SBIG: ANSWER - - end group RUN COMMAND in a THREAD - - end group exec_device_cmd_if_possible() - - else BAD COMMAND => COMMAND is ignored - - end alt GENERAL or SPECIFIC ? - - end alt new COMMAND ? - end group command_process_if_exists() - - 'end group main_loop() - -'end group run() - - -@enduml diff --git a/src/core/pyros_django/agent/doc/Agent_activity_diag_SIMPLE.pu b/src/core/pyros_django/agent/doc/Agent_activity_diag_SIMPLE.pu new file mode 100644 index 0000000..fc57062 --- /dev/null +++ b/src/core/pyros_django/agent/doc/Agent_activity_diag_SIMPLE.pu @@ -0,0 +1,109 @@ + +@startuml + + +' --- Agent & AgentDevice ACTIVIY DIAGRAM (plantUML) --- + +' NEW syntax => http://plantuml.com/fr/activity-diagram-beta +' OLD syntax => http://plantuml.com/fr/activity-diagram-legacy +' (See also https://plantweb.readthedocs.io) +' (See also https://pythonhosted.org/plantuml) + +' What is the current version of PlantUML (and Java) used ? +' startuml +' version +' enduml + +' Exemple de skin utilisable (celui de ChemCam) : +' skinparam activity { +' StartColor red +' EndColor Silver +' BackgroundColor Peru +' BackgroundColor<< Begin >> Olive +' BorderColor Peru +' FontName Impact +' } + +title +__**Agent (Activity Diagram, simplified)**__ +Version 03-10-2022 (E. Pallier) + +end title + + +'|Agent| +start + +skinparam LegendBackgroundColor yellow +skinparam LegendBorderColor red +legend top right + Every important step is logged in database, + with these information : + mode, status, and #iteration +endlegend + + + + +:RESTART = False; +note right + By default, do not restart +end note + +repeat + :load_config(); + :init(); + :MAIN_LOOP = True; + note right + By default, redo main loop + end note + repeat + partition main_loop() { + :reload_config_if_changed(); + ':log_agent_status(); + 'note right + ' Log this agent state in DB : (mode, status, and #iteration) + 'end note + + '#green:routine_process_before(); + :**routine_process_before()**; + note right + Only if NOT in IDLE mode + Only if previous routine_process_before() finished + Only if routine_process_after() finished (can be run in parallel) + end note + + :**exec_next_valid_cmd_if_exists()**; + note right + Only if new command received + Only if previous command finished (can be run in parallel) + Command can be of 3 types : + - Agent General cmd : always executed (sequential exec) + - Agent Specific cmd : only executed if in ATTENTIVE mode + - Other cmd (device) : only executed if in ATTENTIVE mode + Exceptions can be raised : CmdInvalid, CmdUnimplemented, CmdExecError, CmdExecTimeout + end note + + 'if (DO_RESTART or DO_STOP ?) then (yes) + ' :MAIN_LOOP = False; + ' if (DO_RESTART ?) then (yes) + ' :RESTART = True; + ' endif + 'else (no) + '#green:process_routine_after(); + :**process_routine_after()**; + note right + Only if NOT in IDLE mode + Only if previous process_routine_after() finished + Only if routine_process_before() finished (can be run in parallel) + (not executed if cmd was STOP or RESTART, or if exception occurred) + end note + 'endif + + } + repeat while (MAIN_LOOP ?) is (yes) not (no) +repeat while (RESTART ?) is (yes) not (no) + +stop + +@enduml diff --git a/src/core/pyros_django/common/doc/models_Command_state_diag.pu b/src/core/pyros_django/common/doc/models_Command_state_diag.pu index fc6ba02..4bdbe7d 100644 --- a/src/core/pyros_django/common/doc/models_Command_state_diag.pu +++ b/src/core/pyros_django/common/doc/models_Command_state_diag.pu @@ -1,42 +1,60 @@ -@startuml +@startuml Command state diagram ' --- Command STATE DIAGRAM --- ' (see http://plantuml.com/fr/state-diagram) title __**models.Command class : State Diagram**__ +Version : 13/09/2022 (EP) end title -[*] --> PENDING : **created by sender** +[*] --> CMD_PENDING : ** cmd created by sender** ' --- (1) PENDING --- -PENDING: + s_deposit_time \n+ r_read_time -PENDING --> RUNNING : **launched** -PENDING --> SKIPPED: **recipient is IDLE** -PENDING --> EXPIRED: **command is too old** -PENDING --> INVALIDATED: **cancelled by sender** +CMD_PENDING: + s_deposit_time \n+ r_read_time -' --- (2) RUNNING, SKIPPED, or EXPIRED --- -RUNNING: + r_start_time -RUNNING --> EXECUTED : **finished** -RUNNING --> KILLED: \l**aborted** \n(by sender or other allowed agent, \nwith command "abort" or "exit") +' Normal case +CMD_PENDING --> CMD_RUNNING : **launched** -SKIPPED: + end_time -SKIPPED --> [*] +' Exception cases +CMD_PENDING --> CMD_INVALID : **invalid cmd** \n(unknown or bad args) +CMD_PENDING --> CMD_UNIMPLEMENTED : **cmd known but**\n **not implemented** +CMD_PENDING --> CMD_SKIPPED: **recipient agent**\n **is IDLE** +CMD_PENDING --> CMD_EXPIRED: **cmd is expired** \n(no more valid) -EXPIRED --> [*] -EXPIRED: + end_time \n+ killer_agent_name +CMD_INVALID: + r_end_time +CMD_INVALID --> [*] -INVALIDATED --> [*] -INVALIDATED: + end_time \n+ killer_agent_name +CMD_UNIMPLEMENTED: + r_end_time +CMD_UNIMPLEMENTED --> [*] -' --- (3) PROCESSED or KILLED --- -EXECUTED: + end_time -EXECUTED --> [*] +CMD_SKIPPED: + r_end_time +CMD_SKIPPED --> [*] -KILLED --> [*] -KILLED: + end_time \n+ killer_agent_name +CMD_EXPIRED: + r_end_time +CMD_EXPIRED --> [*] + + +' --- (2) RUNNING --- +CMD_RUNNING: + r_start_time +CMD_RUNNING --> CMD_EXECUTED : **(OK)**\n **finished** +CMD_RUNNING --> CMD_EXEC_ERROR : **(KO)**\n **execution error** +CMD_RUNNING --> CMD_EXEC_TIMEOUT : **(KO)**\n **execution timeout** +CMD_RUNNING --> CMD_EXEC_KILLED: \l**(KO)**\n **aborted (by other agent)** \n (with "do_stop_current cmd" or "do_stop now") + +' --- PROCESSED or interrupted --- +CMD_EXECUTED: + r_end_time +CMD_EXECUTED --> [*] + +CMD_EXEC_ERROR : + r_end_time +CMD_EXEC_ERROR --> [*] + +CMD_EXEC_TIMEOUT : + r_end_time +CMD_EXEC_TIMEOUT --> [*] + +CMD_EXEC_KILLED: + r_end_time \n+ killer_agent_name +CMD_EXEC_KILLED --> [*] @enduml diff --git a/src/core/pyros_django/routine_manager/doc/ObservationSequence_SO_state_diag.pu b/src/core/pyros_django/routine_manager/doc/ObservationSequence_SO_state_diag.pu index ff8285a..dfdd63f 100644 --- a/src/core/pyros_django/routine_manager/doc/ObservationSequence_SO_state_diag.pu +++ b/src/core/pyros_django/routine_manager/doc/ObservationSequence_SO_state_diag.pu @@ -6,7 +6,7 @@ title __**Observation Sequence (SO) - State Diagram**__ -Version 7-2-2022 (E. Pallier) +Version 9-2-2022 (E. Pallier) end title @@ -47,11 +47,10 @@ TBP --> SF07_PLN state SF07_PLN as "SF07-PLN - Observation Sequence Planning" #cyan state PLND as "PLANNED (PLND)": planned for current/coming night -state UNPL as "UNPLANNABLE (UNPL)": unplannable \n neither for current/coming night\n neither for next one +state UNPL as "UNPLANNABLE (UNPL)": unplannable for current/coming night state End_SF07 <> -SF07_PLN --> SF07_PLN: **PLAN/SCHEDULE** \n(unplannable for current/coming night, \n but ok for next one) -SF07_PLN --> UNPL: **PLAN/SCHEDULE** +SF07_PLN --> UNPL UNPL --> End_SF07 SF07_PLN --> PLND: **PLAN/SCHEDULE** @@ -65,14 +64,14 @@ PLND --> SF08_EXE '/ state SF08_EXE as "SF08-EXE - Observation Sequence Execution" #cyan -state E_RUN as "REC_DOING (R_RUN)": Sequence exec running... +state E_RUN as "REC_RUNNING (R_RUN)": Sequence exec running... state E_CCLD as "REC_STOPPED (R_CCLD)": Sequence exec cancelled -state E_END as "REC_DONE (R_END)": Sequence exec finished +state E_END as "REC_FINISHED (R_END)": Sequence exec finished state can_exec <> SF08_EXE -d-> can_exec can_exec --> E_RUN: [can be executed]\n **EXEC** -can_exec --> TBP: [can't be executed] \n (too late or \n observing conditions not met) +can_exec --> TBP: [can't be executed] \n (too late or \n observing conditions \n not good enough) E_RUN --> E_CCLD: **exec cancelled** E_CCLD --> TBP: **go back to planning**\n (don't keep incomplete Sequence) @@ -88,16 +87,12 @@ E_END --> SF11_IPC '/ state SF11_IPC as "SF11-IPC - Sequence Images ProCessing" #cyan -state P_RUN as "PROC_DOING (P_RUN)": Sequence process running... -state P_STOP as "PROC_STOPPED (P_STOP)": Sequence process temporarily stopped -state P_CCLD as "PROC_CANCELLED (P_CCLD)": Sequence process definitively cancelled/aborted -state P_END as "PROC_DONE (P_END)": Sequence process finished -state End_SF11 <> +state P_RUN as "PROC_RUNNING (P_RUN)": Sequence process running... +state P_STOP as "PROC_STOPPED (P_STOP)": Sequence process stopped +state P_END as "PROC_FINISHED (P_END)": Sequence process finished SF11_IPC --> P_RUN: **PROCESS** -P_RUN --> P_CCLD: **process cancelled** -P_CCLD --> End_SF11 P_RUN --> P_STOP: **process stopped** P_STOP --> E_END P_RUN --> P_END: **process finished** @@ -112,15 +107,11 @@ P_END --> SF12_IAN '/ state SF12_IAN as "SF12-IAN - Sequence Images ANalysis" #cyan -state A_RUN as "ANL_DOING (A_RUN)": Sequence analysis running... +state A_RUN as "ANL_RUNNING (A_RUN)": Sequence analysis running... state A_STOP as "ANL_STOPPED (A_STOP)": Sequence analysis temporarily stopped -state A_CCLD as "ANL_CANCELLED (A_CCLD)": Sequence analysis definitively cancelled/aborted -state A_END as "ANL_DONE (A_END)": Sequence analysis finished -state End_SF12 <> +state A_END as "ANL_FINISHED (A_END)": Sequence analysis finished SF12_IAN --> A_RUN: **ANALYSE** -A_RUN --> A_CCLD: **analysis cancelled** -A_CCLD --> End_SF12 A_RUN --> A_STOP: **process stopped** A_STOP --> P_END A_RUN --> A_END: **analysis finished** @@ -135,14 +126,11 @@ A_END --> SF13_IAF '/ state SF13_IAF as "SF13-IAF - Sequence Images Archiving & Fetching" #cyan -state Z_RUN as "ZIP_DOING (Z_RUN)": Sequence archiving running... +state Z_RUN as "ZIP_RUNNING (Z_RUN)": Sequence archiving running... state Z_STOP as "ZIP_STOPPED (Z_STOP)": Sequence archiving temporarily stopped -state Z_CCLD as "ZIP_CANCELLED (Z_CCLD)": Sequence archiving definitively cancelled/aborted -state Z_END as "ZIP_DONE (Z_END)": Sequence archiving finished +state Z_END as "ZIP_FINISHED (Z_END)": Sequence archiving finished SF13_IAF --> Z_RUN: **ARCHIVE** -Z_RUN --> Z_CCLD: **archiving cancelled** -Z_CCLD --> [*] Z_RUN --> Z_STOP: **archiving stopped** Z_STOP --> A_END Z_RUN --> Z_END: **archiving finished** diff --git a/src/device_controller/concrete_component/gemini/proof_of_concept_for_Protocol.py b/src/device_controller/concrete_component/gemini/proof_of_concept_for_Protocol.py index d32f39d..0f347e0 100644 --- a/src/device_controller/concrete_component/gemini/proof_of_concept_for_Protocol.py +++ b/src/device_controller/concrete_component/gemini/proof_of_concept_for_Protocol.py @@ -63,10 +63,14 @@ class DCGem(DC): self.dc1.encap() -dcg = DCGem() -print ("gem toto is", dcg.toto) -print ("dc1 toto is", dcg.dc1.toto) -#dcg.Protoc.encap(dcg) -##dcg.encap() +def main(): + dcg = DCGem() + print ("gem toto is", dcg.toto) + print ("dc1 toto is", dcg.dc1.toto) + #dcg.Protoc.encap(dcg) + ##dcg.encap() +if __name__ == "__main__": + """Comment on Main function execution""" + main() diff --git a/src/device_controller/concrete_component/gemini/proof_of_concept_for_logging/proof_of_concept_for_logging.py b/src/device_controller/concrete_component/gemini/proof_of_concept_for_logging/proof_of_concept_for_logging.py index bb4ccd6..bbead9c 100644 --- a/src/device_controller/concrete_component/gemini/proof_of_concept_for_logging/proof_of_concept_for_logging.py +++ b/src/device_controller/concrete_component/gemini/proof_of_concept_for_logging/proof_of_concept_for_logging.py @@ -70,14 +70,20 @@ def do_logs(): # logger.debug(), info(), warning(), error(), critical() -print("\nlevel is DEBUG:") -logger.setLevel(logging.DEBUG) -do_logs() +def main(): + print("\nlevel is DEBUG:") + logger.setLevel(logging.DEBUG) + do_logs() -print("\nlevel is INFO:") -logger.setLevel(logging.INFO) -do_logs() + print("\nlevel is INFO:") + logger.setLevel(logging.INFO) + do_logs() -print("\nlevel is CRITICAL:") -logger.setLevel(logging.CRITICAL) -do_logs() \ No newline at end of file + print("\nlevel is CRITICAL:") + logger.setLevel(logging.CRITICAL) + do_logs() + + +if __name__ == "__main__": + """Comment on Main function execution""" + main() diff --git a/src/device_controller/concrete_component/gemini/proof_of_concept_for_multi_inherit.py b/src/device_controller/concrete_component/gemini/proof_of_concept_for_multi_inherit.py index cd5b91b..e99b0db 100644 --- a/src/device_controller/concrete_component/gemini/proof_of_concept_for_multi_inherit.py +++ b/src/device_controller/concrete_component/gemini/proof_of_concept_for_multi_inherit.py @@ -74,16 +74,21 @@ class DCSBIG(DCGeneral, DC1,DC2,DC3): print("DCSBIG toto") -print(DCSBIG.mro()) -#dc1 = DC1('toto') -#dc1.print_name() -#print(DCGem.__mro__) -dcs = DCSBIG() -dcs.print_name() -print(dcs.a) -print(dcs.b) -dcs.printall() - -# DC1 goto -#dcs.goto() - +def main(): + print(DCSBIG.mro()) + #dc1 = DC1('toto') + #dc1.print_name() + #print(DCGem.__mro__) + dcs = DCSBIG() + dcs.print_name() + print(dcs.a) + print(dcs.b) + dcs.printall() + + # DC1 goto + #dcs.goto() + + +if __name__ == "__main__": + """Comment on Main function execution""" + main() diff --git a/src/device_controller/concrete_component/gemini/server_telescope_gemini_simulator_run.py b/src/device_controller/concrete_component/gemini/server_telescope_gemini_simulator_run.py index 8521d3f..45ab146 100755 --- a/src/device_controller/concrete_component/gemini/server_telescope_gemini_simulator_run.py +++ b/src/device_controller/concrete_component/gemini/server_telescope_gemini_simulator_run.py @@ -2,10 +2,12 @@ import sys +##sys.path.append("..") +sys.path.append("../..") -sys.path.append("..") +from channels.server_udp_or_tcp import get_SocketServer_UDP_TCP +##from device_simulator_common.server_udp_or_tcp import get_SocketServer_UDP_TCP #from device_controller.concrete_component.device_simulator_common.server_udp_or_tcp import get_SocketServer_UDP_TCP -from device_simulator_common.server_udp_or_tcp import get_SocketServer_UDP_TCP #from server.server_udp_or_tcp import get_SocketServer_UDP_TCP HOST, PORT = "localhost", 11110 -- libgit2 0.21.2