Commit 617aeab83295516c4aeaad6fb54e68a516bb6c12

Authored by Etienne Pallier
1 parent bf051e5f
Exists in dev

Ajout table unique AgentDeviceStatus pour tous les AgentDevice

Creation AgentDeviceTelescopeGemini qui herite de AgentDevice

Reste a créer un mode "simulateur" par defaut pour AgentDevice dont
heritera AgentDeviceTelescopeGemini
.gitignore
1 1 .DS_Store
2 2 /private
3   -/venv/
  3 +/venv*/
4 4 __pycache__
5 5 *.pyc
6 6 *.py.bak
7 7 *.png
  8 +*.log
8 9 /.settings/
9 10 #/.pydevproject
10 11  
... ... @@ -26,3 +27,7 @@ old/
26 27  
27 28 \.idea/
28 29  
  30 +out.*
  31 +
  32 +*_OLD*
  33 +*_ORIG*
... ...
HOWTO_TEST.txt
... ... @@ -16,7 +16,7 @@
16 16 - (1) Test with agentA and agentB sending commands to each other:
17 17 $ ./pyros.py -t start agentA,agentB
18 18 - (2) Test with agentTelescopeRequester sending commands to agentDevice:
19   - $ ./pyros.py -t start agentTelescopeRequester,agentDevice
  19 + $ ./pyros.py -t start agentTelescopeRequester,agentDeviceTelescopeGemini
20 20  
21 21 (C) Interactive testing:
22 22 $ ./pyros.py shell
... ...
pyros.py
... ... @@ -34,7 +34,8 @@ AGENTS = {
34 34 "agentA" : "AgentA",
35 35 "agentB" : "AgentB",
36 36 "agentM" : "AgentM",
37   - "agentDevice" : "AgentDevice",
  37 + #"agentDevice" : "AgentDevice",
  38 + "agentDeviceTelescopeGemini" : "agentDeviceTelescopeGemini",
38 39 "agentTelescopeRequester" : "AgentTelescopeRequester",
39 40 "webserver" : "webserver",
40 41 "monitoring" : "monitoring",
... ...
src/core/pyros_django/agent/AgentDevice.py
... ... @@ -8,9 +8,8 @@ import time
8 8 ##from .Agent import Agent
9 9 sys.path.append("..")
10 10 from agent.Agent import Agent, extract_parameters
11   -from common.models import AgentDeviceTelescopeStatus, get_or_create_unique_row_from_model
  11 +from common.models import AgentDeviceStatus, get_or_create_unique_row_from_model
12 12 sys.path.append("../../..")
13   -from devices_controller.devices_controller_concrete.device_controller_Gemini.telescope_controller_gemini import TelescopeControllerGEMINI
14 13  
15 14 ##log = L.setupLogger("AgentXTaskLogger", "AgentX")
16 15  
... ... @@ -18,7 +17,7 @@ from devices_controller.devices_controller_concrete.device_controller_Gemini.tel
18 17  
19 18 class AgentDevice(Agent):
20 19  
21   - _agent_device_telescope_status = None
  20 + _agent_device_status = None
22 21  
23 22 # FOR TEST ONLY
24 23 # Run this agent in simulator mode
... ... @@ -73,27 +72,31 @@ class AgentDevice(Agent):
73 72 """
74 73  
75 74 # @override
76   - def __init__(self, name:str=None, config_filename=None, RUN_IN_THREAD=True, device_controller=TelescopeControllerGEMINI):
  75 + #def __init__(self, name:str=None, config_filename=None, RUN_IN_THREAD=True, device_controller, host, port):
  76 + def __init__(self, name:str, config_filename, RUN_IN_THREAD, device_controller, host, port):
77 77 if name is None: name = self.__class__.__name__
78 78 super().__init__(name, config_filename, RUN_IN_THREAD)
79 79  
80 80 # Initialize the device table status
81 81 # If table is empty, create a default 1st row
82   - self._agent_device_telescope_status = get_or_create_unique_row_from_model(AgentDeviceTelescopeStatus)
  82 + ##self._agent_device_status = get_or_create_unique_row_from_model(AgentDeviceStatus)
  83 + self._agent_device_status = AgentDeviceStatus.getStatusForAgent(name)
83 84 """
84 85 if not AgentDeviceTelescopeStatus.objects.exists():
85 86 print("CREATE first row")
86   - self._agent_device_telescope_status = AgentDeviceTelescopeStatus.objects.create(id=1)
  87 + self._agent_device_status = AgentDeviceTelescopeStatus.objects.create(id=1)
87 88 # Get 1st row (will be updated at each iteration by routine_process() with current device status)
88 89 print("GET first row")
89   - self._agent_device_telescope_status = AgentDeviceTelescopeStatus.objects.get(id=1)
  90 + self._agent_device_status = AgentDeviceTelescopeStatus.objects.get(id=1)
90 91 """
91 92  
92 93 # Initialize the device socket
93 94 # Port local AK 8085 = redirigé sur l’IP du tele 192.168.0.12 sur port 11110
94   - HOST, PORT = "82.64.28.71", 11110
  95 + ##HOST, PORT = "82.64.28.71", 11110
95 96 #HOST, PORT = "localhost", 11110
96   - self.tele_ctrl = TelescopeControllerGEMINI(HOST, PORT, True)
  97 + #self._device_ctrl = TelescopeControllerGEMINI(host, port, True)
  98 + ##self._device_ctrl = device_controller(HOST, PORT, True)
  99 + self._device_ctrl = device_controller(host, port, True)
97 100 self._log.print(f"init done for {name}")
98 101  
99 102  
... ... @@ -107,8 +110,8 @@ class AgentDevice(Agent):
107 110  
108 111 # Device socket init
109 112 # (optional) Only useful for TCP (does nothing for UDP)
110   - self.tele_ctrl._connect_to_device()
111   - self.tele_ctrl.print_available_commands()
  113 + self._device_ctrl._connect_to_device()
  114 + self._device_ctrl.print_available_commands()
112 115  
113 116 # Telescope (long) init
114 117 # TODO:
... ... @@ -139,53 +142,66 @@ class AgentDevice(Agent):
139 142  
140 143 # @override
141 144 def routine_process(self):
142   - self.print("ROUTINE PROCESS START: reading my dedicated device status information and storing it in DB)")
143   - self.print("...")
  145 + self.print("ROUTINE PROCESS START: reading my dedicated device status information and storing it in DB)...")
144 146  
  147 + # Save current device status to DB
  148 + #AgentDeviceTelescopeStatus.objects.create(radec=myradec)
  149 + self.save_device_status()
  150 + self.print("Status saved in DB")
  151 +
  152 + #time.sleep(3)
  153 + self.print("ROUTINE PROCESS END")
  154 +
  155 +
  156 + def save_device_status(self):
  157 + self._agent_device_status.status = self.get_device_status()
  158 + self._agent_device_status.save()
  159 +
  160 +
  161 + # To be overriden by subclass
  162 + def get_device_status(self):
  163 + """
145 164 cmd="get date"
146   - res = self.tele_ctrl.execute_cmd(cmd)
  165 + res = self._device_ctrl.execute_cmd(cmd)
147 166 print("result is", str(res))
148 167 if res.ok: print("OK")
149 168 time.sleep(1)
150 169  
151 170 cmd="get time"
152   - res = self.tele_ctrl.execute_cmd(cmd)
  171 + res = self._device_ctrl.execute_cmd(cmd)
153 172 print("result is", str(res))
154 173 if res.ok: print("OK")
155 174 time.sleep(1)
156 175  
157 176 cmd="get radec"
158   - res = self.tele_ctrl.execute_cmd(cmd)
  177 + res = self._device_ctrl.execute_cmd(cmd)
159 178 print("result is", str(res))
160 179 myradec = str(res)
161 180 if res.ok: print("OK")
162 181 time.sleep(1)
163   -
164   - # Save current device status to DB
165   - #AgentDeviceTelescopeStatus.objects.create(radec=myradec)
166   - self._agent_device_telescope_status.radec = myradec
167   - self._agent_device_telescope_status.save()
  182 + """
  183 + return 'Abstract status'
168 184  
169 185  
170   - #time.sleep(3)
171   - self.print("ROUTINE PROCESS END")
172 186  
173 187 # @override
174 188 def kill_running_specific_cmd_if_exists(self, abort_sender):
175 189 super().kill_running_specific_cmd_if_exists(abort_sender)
176   - print("Close telescope socket")
177   - self.tele_ctrl.close()
  190 + print("Close device socket")
  191 + self._device_ctrl.close()
178 192  
  193 + """
179 194 # @override
180 195 def specific_process(self, cmd):
181 196 cmd.set_read_time()
182 197 cmd.set_as_running()
183   - res = self.tele_ctrl.execute_cmd(cmd.name)
  198 + res = self._device_ctrl.execute_cmd(cmd.name)
184 199 cmd.set_result(str(res))
185 200 print("result is", str(res))
186 201 if res.ok: print("OK")
187 202 cmd.set_as_processed()
188 203 time.sleep(1)
  204 + """
189 205  
190 206 """
191 207 =================================================================
... ... @@ -194,61 +210,26 @@ class AgentDevice(Agent):
194 210 """
195 211  
196 212 # Define your own command step(s) here
197   - def cmd_step1(self, step:int):
198   - cmd = self._current_specific_cmd
199   - cmd.result = f"in step #{step}/{self._thread_total_steps_number}"
200   - cmd.save()
201   - """
202   - if self.RUN_IN_THREAD:
203   - print("(save from thread)")
204   - cmd.save()
205   - else:
206   - #@transaction.atomic
207   - print("(save from process)")
208   - with transaction.atomic():
209   - cmd.save()
210   - #Command.objects.select_for_update()
211   - """
212   -
213   - def cmd_step2(self, step:int):
214   - self.cmd_step1(step)
215   - def cmd_step3(self, step:int):
216   - self.cmd_step1(step)
217   - def cmd_step4(self, step:int):
218   - self.cmd_step1(step)
219   -
220   - """
221   - # @override
222   - def thread_exec_specific_cmd_step(self, step:int, sleep_time:float=1.0):
223   - self.thread_stop_if_asked()
224   - cmd = self._current_specific_cmd
225   - print(f">>>>> Thread (cmd {cmd.name}): step #{step}/5")
226   - self.sleep(sleep_time)
227   - """
228   -
229   - '''
230   - # @override
231   - def exec_specific_cmd_start(self, cmd:Command, from_thread=True):
232   - super().exec_specific_cmd_start(cmd, from_thread)
233   - '''
234   -
  213 + def cmd_step(self, step:int):
  214 + cmd = self._current_specific_cmd
  215 + cmd.set_read_time()
  216 + cmd.set_as_running()
  217 + res = self._device_ctrl.execute_cmd(cmd.name)
  218 + cmd.set_result(str(res))
  219 + print("result is", str(res))
  220 + if res.ok: print("OK")
  221 + cmd.set_as_processed()
  222 + time.sleep(1)
  223 + cmd.set_result(f"in step #{step}/{self._thread_total_steps_number}")
235 224  
236 225 # @override
237 226 def thread_exec_specific_cmd_main(self):
238 227 # This is optional
239   - self.thread_set_total_steps_number(5)
240   -
  228 + self.thread_set_total_steps_number(1)
241 229 # HERE, write your own scenario
242   -
243   - # scenario OK
244   - self.thread_exec_specific_cmd_step(1, self.cmd_step1, 1)
245   - self.thread_exec_specific_cmd_step(2, self.cmd_step2, 3)
246   - self.thread_exec_specific_cmd_step(3, self.cmd_step1, 5)
247   - self.thread_exec_specific_cmd_step(4, self.cmd_step3, 10)
248   - self.thread_exec_specific_cmd_step(5, self.cmd_step1, 4)
  230 + self.thread_exec_specific_cmd_step(1, self.cmd_step, 1)
249 231 # ... as many as you need
250   -
251   - """ autre scenario
  232 + """ other scenario
252 233 self.thread_exec_specific_cmd_step(1, self.cmd_step1, 1)
253 234 self.thread_exec_specific_cmd_step(2, self.cmd_step2, 2)
254 235 self.thread_exec_specific_cmd_step(3, self.cmd_step1, 2)
... ...
src/core/pyros_django/agent/AgentTelescopeRequester.py
... ... @@ -24,7 +24,7 @@ class AgentTelescopeRequester(Agent):
24 24 SIMULATOR_MAX_DURATION_SEC = 100
25 25 # Who should I send commands to ?
26 26 #SIMULATOR_COMMANDS_DEST = "myself"
27   - SIMULATOR_COMMANDS_DEST = "AgentDevice"
  27 + SIMULATOR_COMMANDS_DEST = "AgentDeviceTelescopeGemini"
28 28 # Scenario to be executed
29 29 SIMULATOR_COMMANDS_LIST = [
30 30 # Ask receiver to delete all its previous commands
... ...
src/core/pyros_django/common/admin.py
... ... @@ -236,7 +236,7 @@ class AlbumAdmin(PyrosModelAdmin):
236 236 admin.site.register(Command)
237 237 admin.site.register(AgentLogs)
238 238 admin.site.register(AgentSurvey)
239   -admin.site.register(AgentDeviceTelescopeStatus)
  239 +admin.site.register(AgentDeviceStatus)
240 240  
241 241  
242 242 admin.site.register(Album, AlbumAdmin)
... ...
src/core/pyros_django/common/models.py
... ... @@ -162,7 +162,8 @@ class Company(models.Model):
162 162 # --- Utility functions
163 163 # ---
164 164 def get_or_create_unique_row_from_model(model:models.Model):
165   - return model.objects.get(id=1) if model.objects.exists() else model.objects.create(id=1)
  165 + #return model.objects.get(id=1) if model.objects.exists() else model.objects.create(id=1)
  166 + return model.objects.first() if model.objects.exists() else model.objects.create(id=1)
166 167  
167 168  
168 169 """
... ... @@ -219,6 +220,7 @@ class Request(models.Model):
219 220 ------------------------
220 221 """
221 222  
  223 +#TODO: A VIRER car remplacé par AgentDeviceStatus
222 224 class AgentDeviceTelescopeStatus(models.Model):
223 225 #created = models.DateTimeField('status date', blank=True, null=True, auto_now_add=True)
224 226 updated = models.DateTimeField('status date', blank=True, null=True, auto_now=True)
... ... @@ -235,6 +237,43 @@ class AgentDeviceTelescopeStatus(models.Model):
235 237 return (f"Agent {self.name} at {self.updated} in mode {self.mode} and status {self.status}")
236 238 """
237 239  
  240 +
  241 +class AgentDeviceStatus(models.Model):
  242 + """Table storing various status parameters for EACH Device.
  243 +
  244 + Attributes:
  245 + attr1 (str): Description of `attr1`.
  246 + attr2 (:obj:`int`, optional): Description of `attr2`.
  247 +
  248 + """
  249 + #created = models.DateTimeField('status date', blank=True, null=True, auto_now_add=True)
  250 + agent = models.CharField('Name of the agent that saved this parameter', max_length=45, blank=True, null=True)
  251 + #radec = models.CharField('agent mode', max_length=30, blank=True)
  252 + status = models.CharField('status parameters json dictionnary (ex: {radec:..., speed:...})', max_length=300, blank=True, null=True)
  253 + date_updated = models.DateTimeField('status parameter date', blank=True, null=True, auto_now=True)
  254 +
  255 + class Meta:
  256 + managed = True
  257 + db_table = 'agent_device_status'
  258 + verbose_name = "agent device status"
  259 + verbose_name_plural = "agent devices status"
  260 +
  261 + def __str__(self):
  262 + return (f"Agent {self.agent} last status is ({self.status}) (saved at {self.date_updated})")
  263 +
  264 + @classmethod
  265 + def getStatusForAgent(cls, agent:str) -> str:
  266 + return cls.objects.filter(agent=agent)[0] if cls.objects.filter(agent=agent).exists() else cls.objects.create(agent=agent)
  267 + '''
  268 + return cls.objects.filter(agent=agent)[0].status if cls.objects.filter(agent=agent).exists() else cls.objects.create(agent=agent).status
  269 + agent_status = cls.objects.filter(agent=agent)
  270 + if agent_status.exists():
  271 + return agent_status[0].status
  272 + else:
  273 + return cls.objects.create(agent=agent)
  274 + '''
  275 +
  276 +
238 277 class AgentLogs(models.Model):
239 278 created = models.DateTimeField(blank=True, null=True, auto_now_add=True)
240 279 name = models.CharField(max_length=50)
... ...