From 573eeae666016117994bf272ef844894c84bd5b9 Mon Sep 17 00:00:00 2001 From: Etienne Pallier Date: Fri, 17 Jun 2022 20:02:07 +0200 Subject: [PATCH] Agent ne depend plus de AgentDevice, et TEST ok avec self pour envoyer commandes a soi meme --- src/core/pyros_django/agent/Agent.py | 33 ++++++++++++++++++++++++++------- src/core/pyros_django/common/models.py | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 87 insertions(+), 21 deletions(-) diff --git a/src/core/pyros_django/agent/Agent.py b/src/core/pyros_django/agent/Agent.py index 18ffc99..9da3237 100755 --- a/src/core/pyros_django/agent/Agent.py +++ b/src/core/pyros_django/agent/Agent.py @@ -302,13 +302,13 @@ class Agent: #"set_state", ] + # --- FOR TEST ONLY --- + # Maximum duration of this agent (only for SIMULATION mode) # If set to None, it will never exit except if asked (or CTRL-C) # If set to 20, it will exit after 20s TEST_MAX_DURATION_SEC = None #TEST_MAX_DURATION_SEC = 30 - - # FOR TEST ONLY # Run this agent in simulator mode TEST_MODE = True WITH_SIMULATOR = False @@ -316,12 +316,29 @@ class Agent: TEST_WITH_FINAL_TEST = False # Who should I send commands to ? TEST_COMMANDS_DEST = "myself" - # Default scenario to be executed + + # (EP 2022/06) Default scenario to be executed (only in TEST mode) + # + # List of commands to be sent by this agent to other agents ("self" means himself) + # + # Command format is : + # "[Recipient] Command [Args]" + # with : + # - [Recipient] optional, the name of the Agent the command is to be sent to (use "self" to mean himself) + # - Command, the command name + # - [Args] optional, the list of command arguments, separated by blanks : arg1 arg2 arg3 ... + # + # Ex : + # - "AgentScheduler set_state ATTENTIVE" => means to send the command "set_state ATTENTIVE" to the agent AgentScheduler + # - "AgentX set_state ATTENTIVE" => means to send the command "set_state ATTENTIVE" to the agent AgentX + # - "self set_state ATTENTIVE" => means to send the command "set_state ATTENTIVE" to MYSELF + # - "self do_restart_loop" => means to send the command "do_restart_loop" to MYSELF (no args) + # #TEST_COMMANDS = iter([ TEST_COMMANDS_LIST = [ "Agent set_state ATTENTIVE", - "Agent set_state ROUTINE", - "Agent set_state IDLE", + "self set_state ROUTINE", + "self set_state IDLE", ''' # specific0 not_executed_because_idle @@ -1656,7 +1673,7 @@ class Agent: cmd.set_as_running() log.info("(Agent level GENERAL CMD)") - _,cmd_name,cmd_args = cmd.get_full_name_parts() + cmd_name,cmd_args = cmd.get_name_and_args() #cmd_name, cmd_args = cmd.tokenize() #if cmd.name == "set_state:active": #elif cmd.name == "set_state:idle": @@ -1877,11 +1894,13 @@ class Agent: if cmd_full_name is None: return None if ' ' not in cmd_full_name: raise Exception('Command is malformed:', cmd_full_name) agent_recipient,cmd_name = cmd_full_name.split(' ', 1) + # Command is to be sent to myself ? + if agent_recipient == 'self': agent_recipient = self.name ##recipient_agent = self.name if self.TEST_COMMANDS_DEST=="myself" else self.TEST_COMMANDS_DEST #return Command(sender=self.name, recipient=recipient_agent, name=cmd_name) cmd = self.create_cmd_for(agent_recipient, cmd_name) # If no cmd created (because of error, bad AgentDevice name), call again this method for next cmd - if cmd is None: return self._TEST_get_next_command_to_send() + #if cmd is None: return self._TEST_get_next_command_to_send() return cmd """ diff --git a/src/core/pyros_django/common/models.py b/src/core/pyros_django/common/models.py index b735983..2fda904 100644 --- a/src/core/pyros_django/common/models.py +++ b/src/core/pyros_django/common/models.py @@ -8,7 +8,7 @@ from datetime import datetime, timedelta, date from dateutil.relativedelta import relativedelta import os import sys -from typing import List +from typing import List, Tuple from django.core.validators import MaxValueValidator, MinValueValidator # DJANGO imports @@ -423,8 +423,14 @@ class Alert(Request): class AgentCmd(models.Model): - """ + Command sent to an Agent + + Can be either : + - an "agent level" (general or specific) command + OR + - a "device level" command + | id | sender | recipient | name | validity_duration (default=60) | s_deposit_time | r_read_time See doc/models_Command_state_diag.pu for PlantUML state diagram @@ -459,11 +465,28 @@ class AgentCmd(models.Model): "CMD_OUTOFDATE" # cde périmée ) _AGENT_GENERAL_COMMANDS = [ - #"do_eval", "set_state:idle", "set_state:active", + # DO commands + # - Evaluate the expression given (ex: do_eval 4+3) "do_eval", + # GET commands + # - Get agent current state (idle, routine, attentive) + "get_state", + # SET commands + # - Set agent current state (idle, routine, attentive) "set_state", # Commands executed in priority (even if other pending commands exist) - "do_flush_commands", "do_abort", "do_exit", "do_restart_init" + # - Remove all your pending commands + "do_flush_commands", + # - Abort the command you are currently running + "do_abort_current_command", + # - do_abort_current_command and then stop immediately + "do_abort", + # - finish your current command and then make a normal clean stop + "do_exit", + # - restart your global loop (starting with init()) + "do_restart_loop", + # - restart completely an agent (only AgentSST can do this) : do_exit + start again + "do_restart_agent", ] #COMMANDS_PEREMPTION_HOURS = 48 COMMANDS_PEREMPTION_HOURS = 60/60 @@ -696,7 +719,7 @@ class AgentCmd(models.Model): return (f"Commmand '{self.full_name}' ({self.state}) sent to agent {self.recipient}{cmd_sent_time} [by agent {self.sender}]") @property - def device_command(self): + def device_command(self) -> DeviceCmd : if not self._device_command: self._device_command = DeviceCmd(self.full_name) #dc = self._device_command @@ -713,18 +736,42 @@ class AgentCmd(models.Model): return cmd_name_and_args ''' - def get_full_name_parts(self): - return self.device_command.get_full_name_parts() - ''' - cmd_name = self.full_name - cmd_type = None + + #def get_name_and_args(self) -> list(str, str) : + def get_name_and_args(self) -> list : + ''' Return command name and args if exist ''' + # By default, no args cmd_args = None - if '.' in cmd_name: - cmd_type, cmd_name = cmd_name.split('.') + cmd_name = self.full_name if ' ' in cmd_name: cmd_name, *cmd_args = cmd_name.split(' ') - return cmd_type, cmd_name, cmd_args - ''' + print(cmd_name, cmd_args) + return cmd_name, cmd_args + + + #def get_full_name_parts(self) -> tuple(str, str, str) : + def get_full_name_parts(self) -> list : + ''' Return command device type, name, and args from any command type (agent or device level) ''' + + # No device type by default for an Agent command + # cmd_type ? + dev_type = None + + # By default, no args + cmd_args = None + + cmd_name = self.full_name + + # Device command with device component type (dev_type) + if '.' in cmd_name: + return self.device_command.get_full_name_parts() + + # Simple command with args (no dev_type) + if ' ' in cmd_name: + cmd_name, *cmd_args = self.get_name_and_args() + + return dev_type, cmd_name, cmd_args + @property def name(self): -- libgit2 0.21.2