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
1 .DS_Store 1 .DS_Store
2 /private 2 /private
3 -/venv/ 3 +/venv*/
4 __pycache__ 4 __pycache__
5 *.pyc 5 *.pyc
6 *.py.bak 6 *.py.bak
7 *.png 7 *.png
  8 +*.log
8 /.settings/ 9 /.settings/
9 #/.pydevproject 10 #/.pydevproject
10 11
@@ -26,3 +27,7 @@ old/ @@ -26,3 +27,7 @@ old/
26 27
27 \.idea/ 28 \.idea/
28 29
  30 +out.*
  31 +
  32 +*_OLD*
  33 +*_ORIG*
HOWTO_TEST.txt
@@ -16,7 +16,7 @@ @@ -16,7 +16,7 @@
16 - (1) Test with agentA and agentB sending commands to each other: 16 - (1) Test with agentA and agentB sending commands to each other:
17 $ ./pyros.py -t start agentA,agentB 17 $ ./pyros.py -t start agentA,agentB
18 - (2) Test with agentTelescopeRequester sending commands to agentDevice: 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 (C) Interactive testing: 21 (C) Interactive testing:
22 $ ./pyros.py shell 22 $ ./pyros.py shell
@@ -34,7 +34,8 @@ AGENTS = { @@ -34,7 +34,8 @@ AGENTS = {
34 "agentA" : "AgentA", 34 "agentA" : "AgentA",
35 "agentB" : "AgentB", 35 "agentB" : "AgentB",
36 "agentM" : "AgentM", 36 "agentM" : "AgentM",
37 - "agentDevice" : "AgentDevice", 37 + #"agentDevice" : "AgentDevice",
  38 + "agentDeviceTelescopeGemini" : "agentDeviceTelescopeGemini",
38 "agentTelescopeRequester" : "AgentTelescopeRequester", 39 "agentTelescopeRequester" : "AgentTelescopeRequester",
39 "webserver" : "webserver", 40 "webserver" : "webserver",
40 "monitoring" : "monitoring", 41 "monitoring" : "monitoring",
src/core/pyros_django/agent/AgentDevice.py
@@ -8,9 +8,8 @@ import time @@ -8,9 +8,8 @@ import time
8 ##from .Agent import Agent 8 ##from .Agent import Agent
9 sys.path.append("..") 9 sys.path.append("..")
10 from agent.Agent import Agent, extract_parameters 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 sys.path.append("../../..") 12 sys.path.append("../../..")
13 -from devices_controller.devices_controller_concrete.device_controller_Gemini.telescope_controller_gemini import TelescopeControllerGEMINI  
14 13
15 ##log = L.setupLogger("AgentXTaskLogger", "AgentX") 14 ##log = L.setupLogger("AgentXTaskLogger", "AgentX")
16 15
@@ -18,7 +17,7 @@ from devices_controller.devices_controller_concrete.device_controller_Gemini.tel @@ -18,7 +17,7 @@ from devices_controller.devices_controller_concrete.device_controller_Gemini.tel
18 17
19 class AgentDevice(Agent): 18 class AgentDevice(Agent):
20 19
21 - _agent_device_telescope_status = None 20 + _agent_device_status = None
22 21
23 # FOR TEST ONLY 22 # FOR TEST ONLY
24 # Run this agent in simulator mode 23 # Run this agent in simulator mode
@@ -73,27 +72,31 @@ class AgentDevice(Agent): @@ -73,27 +72,31 @@ class AgentDevice(Agent):
73 """ 72 """
74 73
75 # @override 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 if name is None: name = self.__class__.__name__ 77 if name is None: name = self.__class__.__name__
78 super().__init__(name, config_filename, RUN_IN_THREAD) 78 super().__init__(name, config_filename, RUN_IN_THREAD)
79 79
80 # Initialize the device table status 80 # Initialize the device table status
81 # If table is empty, create a default 1st row 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 if not AgentDeviceTelescopeStatus.objects.exists(): 85 if not AgentDeviceTelescopeStatus.objects.exists():
85 print("CREATE first row") 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 # Get 1st row (will be updated at each iteration by routine_process() with current device status) 88 # Get 1st row (will be updated at each iteration by routine_process() with current device status)
88 print("GET first row") 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 # Initialize the device socket 93 # Initialize the device socket
93 # Port local AK 8085 = redirigé sur l’IP du tele 192.168.0.12 sur port 11110 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 #HOST, PORT = "localhost", 11110 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 self._log.print(f"init done for {name}") 100 self._log.print(f"init done for {name}")
98 101
99 102
@@ -107,8 +110,8 @@ class AgentDevice(Agent): @@ -107,8 +110,8 @@ class AgentDevice(Agent):
107 110
108 # Device socket init 111 # Device socket init
109 # (optional) Only useful for TCP (does nothing for UDP) 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 # Telescope (long) init 116 # Telescope (long) init
114 # TODO: 117 # TODO:
@@ -139,53 +142,66 @@ class AgentDevice(Agent): @@ -139,53 +142,66 @@ class AgentDevice(Agent):
139 142
140 # @override 143 # @override
141 def routine_process(self): 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 cmd="get date" 164 cmd="get date"
146 - res = self.tele_ctrl.execute_cmd(cmd) 165 + res = self._device_ctrl.execute_cmd(cmd)
147 print("result is", str(res)) 166 print("result is", str(res))
148 if res.ok: print("OK") 167 if res.ok: print("OK")
149 time.sleep(1) 168 time.sleep(1)
150 169
151 cmd="get time" 170 cmd="get time"
152 - res = self.tele_ctrl.execute_cmd(cmd) 171 + res = self._device_ctrl.execute_cmd(cmd)
153 print("result is", str(res)) 172 print("result is", str(res))
154 if res.ok: print("OK") 173 if res.ok: print("OK")
155 time.sleep(1) 174 time.sleep(1)
156 175
157 cmd="get radec" 176 cmd="get radec"
158 - res = self.tele_ctrl.execute_cmd(cmd) 177 + res = self._device_ctrl.execute_cmd(cmd)
159 print("result is", str(res)) 178 print("result is", str(res))
160 myradec = str(res) 179 myradec = str(res)
161 if res.ok: print("OK") 180 if res.ok: print("OK")
162 time.sleep(1) 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 # @override 187 # @override
174 def kill_running_specific_cmd_if_exists(self, abort_sender): 188 def kill_running_specific_cmd_if_exists(self, abort_sender):
175 super().kill_running_specific_cmd_if_exists(abort_sender) 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 # @override 194 # @override
180 def specific_process(self, cmd): 195 def specific_process(self, cmd):
181 cmd.set_read_time() 196 cmd.set_read_time()
182 cmd.set_as_running() 197 cmd.set_as_running()
183 - res = self.tele_ctrl.execute_cmd(cmd.name) 198 + res = self._device_ctrl.execute_cmd(cmd.name)
184 cmd.set_result(str(res)) 199 cmd.set_result(str(res))
185 print("result is", str(res)) 200 print("result is", str(res))
186 if res.ok: print("OK") 201 if res.ok: print("OK")
187 cmd.set_as_processed() 202 cmd.set_as_processed()
188 time.sleep(1) 203 time.sleep(1)
  204 + """
189 205
190 """ 206 """
191 ================================================================= 207 =================================================================
@@ -194,61 +210,26 @@ class AgentDevice(Agent): @@ -194,61 +210,26 @@ class AgentDevice(Agent):
194 """ 210 """
195 211
196 # Define your own command step(s) here 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 # @override 225 # @override
237 def thread_exec_specific_cmd_main(self): 226 def thread_exec_specific_cmd_main(self):
238 # This is optional 227 # This is optional
239 - self.thread_set_total_steps_number(5)  
240 - 228 + self.thread_set_total_steps_number(1)
241 # HERE, write your own scenario 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 # ... as many as you need 231 # ... as many as you need
250 -  
251 - """ autre scenario 232 + """ other scenario
252 self.thread_exec_specific_cmd_step(1, self.cmd_step1, 1) 233 self.thread_exec_specific_cmd_step(1, self.cmd_step1, 1)
253 self.thread_exec_specific_cmd_step(2, self.cmd_step2, 2) 234 self.thread_exec_specific_cmd_step(2, self.cmd_step2, 2)
254 self.thread_exec_specific_cmd_step(3, self.cmd_step1, 2) 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,7 +24,7 @@ class AgentTelescopeRequester(Agent):
24 SIMULATOR_MAX_DURATION_SEC = 100 24 SIMULATOR_MAX_DURATION_SEC = 100
25 # Who should I send commands to ? 25 # Who should I send commands to ?
26 #SIMULATOR_COMMANDS_DEST = "myself" 26 #SIMULATOR_COMMANDS_DEST = "myself"
27 - SIMULATOR_COMMANDS_DEST = "AgentDevice" 27 + SIMULATOR_COMMANDS_DEST = "AgentDeviceTelescopeGemini"
28 # Scenario to be executed 28 # Scenario to be executed
29 SIMULATOR_COMMANDS_LIST = [ 29 SIMULATOR_COMMANDS_LIST = [
30 # Ask receiver to delete all its previous commands 30 # Ask receiver to delete all its previous commands
src/core/pyros_django/common/admin.py
@@ -236,7 +236,7 @@ class AlbumAdmin(PyrosModelAdmin): @@ -236,7 +236,7 @@ class AlbumAdmin(PyrosModelAdmin):
236 admin.site.register(Command) 236 admin.site.register(Command)
237 admin.site.register(AgentLogs) 237 admin.site.register(AgentLogs)
238 admin.site.register(AgentSurvey) 238 admin.site.register(AgentSurvey)
239 -admin.site.register(AgentDeviceTelescopeStatus) 239 +admin.site.register(AgentDeviceStatus)
240 240
241 241
242 admin.site.register(Album, AlbumAdmin) 242 admin.site.register(Album, AlbumAdmin)
src/core/pyros_django/common/models.py
@@ -162,7 +162,8 @@ class Company(models.Model): @@ -162,7 +162,8 @@ class Company(models.Model):
162 # --- Utility functions 162 # --- Utility functions
163 # --- 163 # ---
164 def get_or_create_unique_row_from_model(model:models.Model): 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,6 +220,7 @@ class Request(models.Model):
219 ------------------------ 220 ------------------------
220 """ 221 """
221 222
  223 +#TODO: A VIRER car remplacé par AgentDeviceStatus
222 class AgentDeviceTelescopeStatus(models.Model): 224 class AgentDeviceTelescopeStatus(models.Model):
223 #created = models.DateTimeField('status date', blank=True, null=True, auto_now_add=True) 225 #created = models.DateTimeField('status date', blank=True, null=True, auto_now_add=True)
224 updated = models.DateTimeField('status date', blank=True, null=True, auto_now=True) 226 updated = models.DateTimeField('status date', blank=True, null=True, auto_now=True)
@@ -235,6 +237,43 @@ class AgentDeviceTelescopeStatus(models.Model): @@ -235,6 +237,43 @@ class AgentDeviceTelescopeStatus(models.Model):
235 return (f"Agent {self.name} at {self.updated} in mode {self.mode} and status {self.status}") 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 class AgentLogs(models.Model): 277 class AgentLogs(models.Model):
239 created = models.DateTimeField(blank=True, null=True, auto_now_add=True) 278 created = models.DateTimeField(blank=True, null=True, auto_now_add=True)
240 name = models.CharField(max_length=50) 279 name = models.CharField(max_length=50)