From 617aeab83295516c4aeaad6fb54e68a516bb6c12 Mon Sep 17 00:00:00 2001 From: Etienne Pallier Date: Fri, 12 Jul 2019 19:19:02 +0200 Subject: [PATCH] Ajout table unique AgentDeviceStatus pour tous les AgentDevice --- .gitignore | 7 ++++++- HOWTO_TEST.txt | 2 +- pyros.py | 3 ++- src/core/pyros_django/agent/AgentDevice.py | 131 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------------------------------------------------------- src/core/pyros_django/agent/AgentTelescopeRequester.py | 2 +- src/core/pyros_django/common/admin.py | 2 +- src/core/pyros_django/common/models.py | 41 ++++++++++++++++++++++++++++++++++++++++- 7 files changed, 107 insertions(+), 81 deletions(-) diff --git a/.gitignore b/.gitignore index 2880baa..540a84e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,11 @@ .DS_Store /private -/venv/ +/venv*/ __pycache__ *.pyc *.py.bak *.png +*.log /.settings/ #/.pydevproject @@ -26,3 +27,7 @@ old/ \.idea/ +out.* + +*_OLD* +*_ORIG* diff --git a/HOWTO_TEST.txt b/HOWTO_TEST.txt index 18490ad..5497c24 100644 --- a/HOWTO_TEST.txt +++ b/HOWTO_TEST.txt @@ -16,7 +16,7 @@ - (1) Test with agentA and agentB sending commands to each other: $ ./pyros.py -t start agentA,agentB - (2) Test with agentTelescopeRequester sending commands to agentDevice: - $ ./pyros.py -t start agentTelescopeRequester,agentDevice + $ ./pyros.py -t start agentTelescopeRequester,agentDeviceTelescopeGemini (C) Interactive testing: $ ./pyros.py shell diff --git a/pyros.py b/pyros.py index e0d2221..f193138 100755 --- a/pyros.py +++ b/pyros.py @@ -34,7 +34,8 @@ AGENTS = { "agentA" : "AgentA", "agentB" : "AgentB", "agentM" : "AgentM", - "agentDevice" : "AgentDevice", + #"agentDevice" : "AgentDevice", + "agentDeviceTelescopeGemini" : "agentDeviceTelescopeGemini", "agentTelescopeRequester" : "AgentTelescopeRequester", "webserver" : "webserver", "monitoring" : "monitoring", diff --git a/src/core/pyros_django/agent/AgentDevice.py b/src/core/pyros_django/agent/AgentDevice.py index a6f5a22..102248f 100755 --- a/src/core/pyros_django/agent/AgentDevice.py +++ b/src/core/pyros_django/agent/AgentDevice.py @@ -8,9 +8,8 @@ import time ##from .Agent import Agent sys.path.append("..") from agent.Agent import Agent, extract_parameters -from common.models import AgentDeviceTelescopeStatus, get_or_create_unique_row_from_model +from common.models import AgentDeviceStatus, get_or_create_unique_row_from_model sys.path.append("../../..") -from devices_controller.devices_controller_concrete.device_controller_Gemini.telescope_controller_gemini import TelescopeControllerGEMINI ##log = L.setupLogger("AgentXTaskLogger", "AgentX") @@ -18,7 +17,7 @@ from devices_controller.devices_controller_concrete.device_controller_Gemini.tel class AgentDevice(Agent): - _agent_device_telescope_status = None + _agent_device_status = None # FOR TEST ONLY # Run this agent in simulator mode @@ -73,27 +72,31 @@ class AgentDevice(Agent): """ # @override - def __init__(self, name:str=None, config_filename=None, RUN_IN_THREAD=True, device_controller=TelescopeControllerGEMINI): + #def __init__(self, name:str=None, config_filename=None, RUN_IN_THREAD=True, device_controller, host, port): + def __init__(self, name:str, config_filename, RUN_IN_THREAD, device_controller, host, port): if name is None: name = self.__class__.__name__ super().__init__(name, config_filename, RUN_IN_THREAD) # Initialize the device table status # If table is empty, create a default 1st row - self._agent_device_telescope_status = get_or_create_unique_row_from_model(AgentDeviceTelescopeStatus) + ##self._agent_device_status = get_or_create_unique_row_from_model(AgentDeviceStatus) + self._agent_device_status = AgentDeviceStatus.getStatusForAgent(name) """ if not AgentDeviceTelescopeStatus.objects.exists(): print("CREATE first row") - self._agent_device_telescope_status = AgentDeviceTelescopeStatus.objects.create(id=1) + self._agent_device_status = AgentDeviceTelescopeStatus.objects.create(id=1) # Get 1st row (will be updated at each iteration by routine_process() with current device status) print("GET first row") - self._agent_device_telescope_status = AgentDeviceTelescopeStatus.objects.get(id=1) + self._agent_device_status = AgentDeviceTelescopeStatus.objects.get(id=1) """ # Initialize the device socket # Port local AK 8085 = redirigé sur l’IP du tele 192.168.0.12 sur port 11110 - HOST, PORT = "82.64.28.71", 11110 + ##HOST, PORT = "82.64.28.71", 11110 #HOST, PORT = "localhost", 11110 - self.tele_ctrl = TelescopeControllerGEMINI(HOST, PORT, True) + #self._device_ctrl = TelescopeControllerGEMINI(host, port, True) + ##self._device_ctrl = device_controller(HOST, PORT, True) + self._device_ctrl = device_controller(host, port, True) self._log.print(f"init done for {name}") @@ -107,8 +110,8 @@ class AgentDevice(Agent): # Device socket init # (optional) Only useful for TCP (does nothing for UDP) - self.tele_ctrl._connect_to_device() - self.tele_ctrl.print_available_commands() + self._device_ctrl._connect_to_device() + self._device_ctrl.print_available_commands() # Telescope (long) init # TODO: @@ -139,53 +142,66 @@ class AgentDevice(Agent): # @override def routine_process(self): - self.print("ROUTINE PROCESS START: reading my dedicated device status information and storing it in DB)") - self.print("...") + self.print("ROUTINE PROCESS START: reading my dedicated device status information and storing it in DB)...") + # Save current device status to DB + #AgentDeviceTelescopeStatus.objects.create(radec=myradec) + self.save_device_status() + self.print("Status saved in DB") + + #time.sleep(3) + self.print("ROUTINE PROCESS END") + + + def save_device_status(self): + self._agent_device_status.status = self.get_device_status() + self._agent_device_status.save() + + + # To be overriden by subclass + def get_device_status(self): + """ cmd="get date" - res = self.tele_ctrl.execute_cmd(cmd) + res = self._device_ctrl.execute_cmd(cmd) print("result is", str(res)) if res.ok: print("OK") time.sleep(1) cmd="get time" - res = self.tele_ctrl.execute_cmd(cmd) + res = self._device_ctrl.execute_cmd(cmd) print("result is", str(res)) if res.ok: print("OK") time.sleep(1) cmd="get radec" - res = self.tele_ctrl.execute_cmd(cmd) + res = self._device_ctrl.execute_cmd(cmd) print("result is", str(res)) myradec = str(res) if res.ok: print("OK") time.sleep(1) - - # Save current device status to DB - #AgentDeviceTelescopeStatus.objects.create(radec=myradec) - self._agent_device_telescope_status.radec = myradec - self._agent_device_telescope_status.save() + """ + return 'Abstract status' - #time.sleep(3) - self.print("ROUTINE PROCESS END") # @override def kill_running_specific_cmd_if_exists(self, abort_sender): super().kill_running_specific_cmd_if_exists(abort_sender) - print("Close telescope socket") - self.tele_ctrl.close() + print("Close device socket") + self._device_ctrl.close() + """ # @override def specific_process(self, cmd): cmd.set_read_time() cmd.set_as_running() - res = self.tele_ctrl.execute_cmd(cmd.name) + res = self._device_ctrl.execute_cmd(cmd.name) cmd.set_result(str(res)) print("result is", str(res)) if res.ok: print("OK") cmd.set_as_processed() time.sleep(1) + """ """ ================================================================= @@ -194,61 +210,26 @@ class AgentDevice(Agent): """ # 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: - print("(save from thread)") - cmd.save() - else: - #@transaction.atomic - print("(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 - print(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) - ''' - + def cmd_step(self, step:int): + cmd = self._current_specific_cmd + cmd.set_read_time() + cmd.set_as_running() + res = self._device_ctrl.execute_cmd(cmd.name) + cmd.set_result(str(res)) + print("result is", str(res)) + if res.ok: print("OK") + cmd.set_as_processed() + time.sleep(1) + cmd.set_result(f"in step #{step}/{self._thread_total_steps_number}") # @override def thread_exec_specific_cmd_main(self): # This is optional - self.thread_set_total_steps_number(5) - + self.thread_set_total_steps_number(1) # 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) + self.thread_exec_specific_cmd_step(1, self.cmd_step, 1) # ... as many as you need - - """ autre scenario + """ other 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) diff --git a/src/core/pyros_django/agent/AgentTelescopeRequester.py b/src/core/pyros_django/agent/AgentTelescopeRequester.py index f4ccb5a..25a91d0 100755 --- a/src/core/pyros_django/agent/AgentTelescopeRequester.py +++ b/src/core/pyros_django/agent/AgentTelescopeRequester.py @@ -24,7 +24,7 @@ class AgentTelescopeRequester(Agent): SIMULATOR_MAX_DURATION_SEC = 100 # Who should I send commands to ? #SIMULATOR_COMMANDS_DEST = "myself" - SIMULATOR_COMMANDS_DEST = "AgentDevice" + SIMULATOR_COMMANDS_DEST = "AgentDeviceTelescopeGemini" # Scenario to be executed SIMULATOR_COMMANDS_LIST = [ # Ask receiver to delete all its previous commands diff --git a/src/core/pyros_django/common/admin.py b/src/core/pyros_django/common/admin.py index a0389b4..5dfb03d 100644 --- a/src/core/pyros_django/common/admin.py +++ b/src/core/pyros_django/common/admin.py @@ -236,7 +236,7 @@ class AlbumAdmin(PyrosModelAdmin): admin.site.register(Command) admin.site.register(AgentLogs) admin.site.register(AgentSurvey) -admin.site.register(AgentDeviceTelescopeStatus) +admin.site.register(AgentDeviceStatus) admin.site.register(Album, AlbumAdmin) diff --git a/src/core/pyros_django/common/models.py b/src/core/pyros_django/common/models.py index cfa50c0..0a8fb5d 100644 --- a/src/core/pyros_django/common/models.py +++ b/src/core/pyros_django/common/models.py @@ -162,7 +162,8 @@ class Company(models.Model): # --- Utility functions # --- def get_or_create_unique_row_from_model(model:models.Model): - return model.objects.get(id=1) if model.objects.exists() else model.objects.create(id=1) + #return model.objects.get(id=1) if model.objects.exists() else model.objects.create(id=1) + return model.objects.first() if model.objects.exists() else model.objects.create(id=1) """ @@ -219,6 +220,7 @@ class Request(models.Model): ------------------------ """ +#TODO: A VIRER car remplacé par AgentDeviceStatus class AgentDeviceTelescopeStatus(models.Model): #created = models.DateTimeField('status date', blank=True, null=True, auto_now_add=True) updated = models.DateTimeField('status date', blank=True, null=True, auto_now=True) @@ -235,6 +237,43 @@ class AgentDeviceTelescopeStatus(models.Model): return (f"Agent {self.name} at {self.updated} in mode {self.mode} and status {self.status}") """ + +class AgentDeviceStatus(models.Model): + """Table storing various status parameters for EACH Device. + + Attributes: + attr1 (str): Description of `attr1`. + attr2 (:obj:`int`, optional): Description of `attr2`. + + """ + #created = models.DateTimeField('status date', blank=True, null=True, auto_now_add=True) + agent = models.CharField('Name of the agent that saved this parameter', max_length=45, blank=True, null=True) + #radec = models.CharField('agent mode', max_length=30, blank=True) + status = models.CharField('status parameters json dictionnary (ex: {radec:..., speed:...})', max_length=300, blank=True, null=True) + date_updated = models.DateTimeField('status parameter date', blank=True, null=True, auto_now=True) + + class Meta: + managed = True + db_table = 'agent_device_status' + verbose_name = "agent device status" + verbose_name_plural = "agent devices status" + + def __str__(self): + return (f"Agent {self.agent} last status is ({self.status}) (saved at {self.date_updated})") + + @classmethod + def getStatusForAgent(cls, agent:str) -> str: + return cls.objects.filter(agent=agent)[0] if cls.objects.filter(agent=agent).exists() else cls.objects.create(agent=agent) + ''' + return cls.objects.filter(agent=agent)[0].status if cls.objects.filter(agent=agent).exists() else cls.objects.create(agent=agent).status + agent_status = cls.objects.filter(agent=agent) + if agent_status.exists(): + return agent_status[0].status + else: + return cls.objects.create(agent=agent) + ''' + + class AgentLogs(models.Model): created = models.DateTimeField(blank=True, null=True, auto_now_add=True) name = models.CharField(max_length=50) -- libgit2 0.21.2