Commit 617aeab83295516c4aeaad6fb54e68a516bb6c12
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
Showing
7 changed files
with
107 additions
and
81 deletions
Show diff stats
.gitignore
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 |
pyros.py
@@ -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) |