Commit ff448d4329b07d1ced978bc76f93bcff8b1cc995
1 parent
675fb3d5
Exists in
master
and in
1 other branch
Update
Showing
29 changed files
with
208 additions
and
99 deletions
Show diff stats
@@ -0,0 +1 @@ | @@ -0,0 +1 @@ | ||
1 | +test |
pyros.py
@@ -363,6 +363,18 @@ class Pyros(AManager): | @@ -363,6 +363,18 @@ class Pyros(AManager): | ||
363 | help_message = "python neo.py" | 363 | help_message = "python neo.py" |
364 | init_fixture = "initial_fixture.json" | 364 | init_fixture = "initial_fixture.json" |
365 | 365 | ||
366 | + def signal_handler(self, signal, frame): | ||
367 | + self.printFullTerm(Colors.WARNING, "Ctrl-c catched") | ||
368 | + for p in self.subproc: | ||
369 | + proc, name = p | ||
370 | + self.printColor(Colors.BLUE, "Killing process " + str(name)) | ||
371 | + proc.kill() | ||
372 | + if self.current_command == "simulator" or self.current_command == "simulator_development": | ||
373 | + self.changeDirectory(self.path_dir_file) | ||
374 | + self.kill_simulation() | ||
375 | + self.printFullTerm(Colors.WARNING, "Exiting") | ||
376 | + sys.exit(0) | ||
377 | + | ||
366 | def install(self): | 378 | def install(self): |
367 | if (self.system == "Windows"): | 379 | if (self.system == "Windows"): |
368 | self.execProcess("python install/install.py install") | 380 | self.execProcess("python install/install.py install") |
@@ -496,6 +508,7 @@ class Pyros(AManager): | @@ -496,6 +508,7 @@ class Pyros(AManager): | ||
496 | def simulator_development(self): | 508 | def simulator_development(self): |
497 | self.changeDirectory("src") | 509 | self.changeDirectory("src") |
498 | self.replacePatternInFile("CELERY_TEST = False", "CELERY_TEST = True", "pyros/settings.py") | 510 | self.replacePatternInFile("CELERY_TEST = False", "CELERY_TEST = True", "pyros/settings.py") |
511 | + self.replacePatternInFile("SIMULATOR = False", "SIMULATOR = True", "pyros/settings.py") | ||
499 | self.execProcess("rm -f testdb.sqlite3") | 512 | self.execProcess("rm -f testdb.sqlite3") |
500 | self.changeDirectory("..") | 513 | self.changeDirectory("..") |
501 | self.migrate() | 514 | self.migrate() |
@@ -535,6 +548,7 @@ class Pyros(AManager): | @@ -535,6 +548,7 @@ class Pyros(AManager): | ||
535 | def simulator(self): | 548 | def simulator(self): |
536 | self.changeDirectory("src") | 549 | self.changeDirectory("src") |
537 | self.replacePatternInFile("CELERY_TEST = False", "CELERY_TEST = True", "pyros/settings.py") | 550 | self.replacePatternInFile("CELERY_TEST = False", "CELERY_TEST = True", "pyros/settings.py") |
551 | + self.replacePatternInFile("SIMULATOR = False", "SIMULATOR = True", "pyros/settings.py") | ||
538 | self.execProcess("rm -f testdb.sqlite3") | 552 | self.execProcess("rm -f testdb.sqlite3") |
539 | self.changeDirectory("..") | 553 | self.changeDirectory("..") |
540 | self.migrate() | 554 | self.migrate() |
@@ -569,6 +583,7 @@ class Pyros(AManager): | @@ -569,6 +583,7 @@ class Pyros(AManager): | ||
569 | def kill_simulation(self): | 583 | def kill_simulation(self): |
570 | self.changeDirectory("src") | 584 | self.changeDirectory("src") |
571 | self.replacePatternInFile("CELERY_TEST = True", "CELERY_TEST = False", "pyros/settings.py") | 585 | self.replacePatternInFile("CELERY_TEST = True", "CELERY_TEST = False", "pyros/settings.py") |
586 | + self.replacePatternInFile("SIMULATOR = True", "SIMULATOR = False", "pyros/settings.py") | ||
572 | if (self.system == "Windows"): | 587 | if (self.system == "Windows"): |
573 | self.execProcessAsync("taskkill /f /im python.exe") | 588 | self.execProcessAsync("taskkill /f /im python.exe") |
574 | self.execProcessAsync("rm -f testdb.sqlite3") | 589 | self.execProcessAsync("rm -f testdb.sqlite3") |
@@ -638,7 +653,7 @@ class Pyros(AManager): | @@ -638,7 +653,7 @@ class Pyros(AManager): | ||
638 | "update": self.update, | 653 | "update": self.update, |
639 | "server": self.server, | 654 | "server": self.server, |
640 | "clean": self.clean, | 655 | "clean": self.clean, |
641 | - "simulator_scheduler": self.simulator_development, | 656 | + "simulator_development": self.simulator_development, |
642 | "clean_logs": self.clean_logs, | 657 | "clean_logs": self.clean_logs, |
643 | "test": self.test, | 658 | "test": self.test, |
644 | "migrate": self.migrate, | 659 | "migrate": self.migrate, |
@@ -677,7 +692,7 @@ class Pyros(AManager): | @@ -677,7 +692,7 @@ class Pyros(AManager): | ||
677 | "start": "Stop the celery workers then the web server", | 692 | "start": "Stop the celery workers then the web server", |
678 | "stop": "stops the celery workers", | 693 | "stop": "stops the celery workers", |
679 | "simulator": "Launch a simulation", | 694 | "simulator": "Launch a simulation", |
680 | - "simulator_scheduler": "Simulation for the scheduler only", | 695 | + "simulator_development": "Simulation for the scheduler only", |
681 | "kill_simulation": "kill the simulators / celery workers / web server", | 696 | "kill_simulation": "kill the simulators / celery workers / web server", |
682 | "sims_launch": "Launch only the simulators", | 697 | "sims_launch": "Launch only the simulators", |
683 | } | 698 | } |
simulators/config/conf.json
@@ -40,6 +40,10 @@ | @@ -40,6 +40,10 @@ | ||
40 | "userSimulator" : "routine_request_10.xml" | 40 | "userSimulator" : "routine_request_10.xml" |
41 | }, | 41 | }, |
42 | { | 42 | { |
43 | + "time" : 200, | ||
44 | + "userSimulator" : "rou" | ||
45 | + }, | ||
46 | + { | ||
43 | "time" : 35, | 47 | "time" : 35, |
44 | "plcSimulator" : {"rain" : 5, "cloud" : 3} | 48 | "plcSimulator" : {"rain" : 5, "cloud" : 3} |
45 | }, | 49 | }, |
@@ -62,5 +66,9 @@ | @@ -62,5 +66,9 @@ | ||
62 | { | 66 | { |
63 | "time" : 42, | 67 | "time" : 42, |
64 | "telescopeSimulator" : {"status" : "ERROR"} | 68 | "telescopeSimulator" : {"status" : "ERROR"} |
69 | + }, | ||
70 | + { | ||
71 | + "time" : 200, | ||
72 | + "telescopeSimulator" : {"status" : "OFF"} | ||
65 | } | 73 | } |
66 | ] | 74 | ] |
simulators/resources/routine_request_01.xml
1 | <?xml version="1.0" ?> | 1 | <?xml version="1.0" ?> |
2 | <request submitted="1" relative="1" name="RequestSimulator" scientific_program="GRB" target_type="test"> | 2 | <request submitted="1" relative="1" name="RequestSimulator" scientific_program="GRB" target_type="test"> |
3 | - <sequence duration="200" jd1="6000" jd2="18000" name="Sequence1 (200secs)" target_coords="10"> | 3 | + <sequence duration="200" jd1="15" jd2="60000" name="Sequence1 (200secs)" target_coords="10"> |
4 | <album detector="Visible camera" name="alb"> | 4 | <album detector="Visible camera" name="alb"> |
5 | <plan duration="200" filter="First infrared filter" name="New plan" nb_images="5"/> | 5 | <plan duration="200" filter="First infrared filter" name="New plan" nb_images="5"/> |
6 | </album> | 6 | </album> |
simulators/resources/routine_request_02.xml
1 | <?xml version="1.0" ?> | 1 | <?xml version="1.0" ?> |
2 | <request submitted="1" relative="1" name="RequestSimulator" scientific_program="GRB" target_type="test"> | 2 | <request submitted="1" relative="1" name="RequestSimulator" scientific_program="GRB" target_type="test"> |
3 | - <sequence duration="100" jd1="6000" jd2="18000" name="Sequence2 (100 secs)" target_coords="10"> | 3 | + <sequence duration="100" jd1="60" jd2="60000" name="Sequence2 (100 secs)" target_coords="10"> |
4 | <album detector="Visible camera" name="alb"> | 4 | <album detector="Visible camera" name="alb"> |
5 | <plan duration="100" filter="First infrared filter" name="New plan" nb_images="5"/> | 5 | <plan duration="100" filter="First infrared filter" name="New plan" nb_images="5"/> |
6 | </album> | 6 | </album> |
simulators/resources/routine_request_03.xml
1 | <?xml version="1.0" ?> | 1 | <?xml version="1.0" ?> |
2 | <request submitted="1" relative="1" name="RequestSimulator" scientific_program="GRB" target_type="test"> | 2 | <request submitted="1" relative="1" name="RequestSimulator" scientific_program="GRB" target_type="test"> |
3 | - <sequence duration="40" jd1="10000" jd2="15000" name="Sequence3 (40secs)" target_coords="10"> | 3 | + <sequence duration="40" jd1="60" jd2="60000" name="Sequence3 (40secs)" target_coords="10"> |
4 | <album detector="Visible camera" name="alb"> | 4 | <album detector="Visible camera" name="alb"> |
5 | <plan duration="40" filter="First infrared filter" name="New plan" nb_images="5"/> | 5 | <plan duration="40" filter="First infrared filter" name="New plan" nb_images="5"/> |
6 | </album> | 6 | </album> |
simulators/resources/routine_request_04.xml
1 | <?xml version="1.0" ?> | 1 | <?xml version="1.0" ?> |
2 | <request submitted="1" relative="1" name="RequestSimulator" scientific_program="GRB" target_type="test"> | 2 | <request submitted="1" relative="1" name="RequestSimulator" scientific_program="GRB" target_type="test"> |
3 | - <sequence duration="500" jd1="12000" jd2="25000" name="Sequence 4 (500secs)" target_coords="10"> | 3 | + <sequence duration="500" jd1="12000" jd2="60000" name="Sequence 4 (500secs)" target_coords="10"> |
4 | <album detector="Visible camera" name="alb"> | 4 | <album detector="Visible camera" name="alb"> |
5 | <plan duration="500" filter="First infrared filter" name="New plan" nb_images="5"/> | 5 | <plan duration="500" filter="First infrared filter" name="New plan" nb_images="5"/> |
6 | </album> | 6 | </album> |
simulators/resources/routine_request_05.xml
1 | <?xml version="1.0" ?> | 1 | <?xml version="1.0" ?> |
2 | <request submitted="1" relative="1" name="RequestSimulator" scientific_program="GRB" target_type="test"> | 2 | <request submitted="1" relative="1" name="RequestSimulator" scientific_program="GRB" target_type="test"> |
3 | - <sequence duration="10" jd1="6000" jd2="22000" name="Sequence5 (10secs)" target_coords="10"> | 3 | + <sequence duration="10" jd1="60" jd2="60000" name="Sequence5 (10secs)" target_coords="10"> |
4 | <album detector="Visible camera" name="alb"> | 4 | <album detector="Visible camera" name="alb"> |
5 | <plan duration="10" filter="First infrared filter" name="plan vis" nb_images="1"/> | 5 | <plan duration="10" filter="First infrared filter" name="plan vis" nb_images="1"/> |
6 | </album> | 6 | </album> |
simulators/resources/routine_request_06.xml
1 | <?xml version="1.0" ?> | 1 | <?xml version="1.0" ?> |
2 | <request submitted="1" relative="1" name="RequestSimulator" scientific_program="GRB" target_type="test"> | 2 | <request submitted="1" relative="1" name="RequestSimulator" scientific_program="GRB" target_type="test"> |
3 | - <sequence duration="200" jd1="6000" jd2="18000" name="Sequence6 (200 secs)" target_coords="10"> | 3 | + <sequence duration="200" jd1="6000" jd2="60000" name="Sequence6 (200 secs)" target_coords="10"> |
4 | <album detector="Visible camera" name="alb"> | 4 | <album detector="Visible camera" name="alb"> |
5 | <plan duration="200" filter="First infrared filter" name="New plan" nb_images="5"/> | 5 | <plan duration="200" filter="First infrared filter" name="New plan" nb_images="5"/> |
6 | </album> | 6 | </album> |
simulators/resources/routine_request_07.xml
1 | <?xml version="1.0" ?> | 1 | <?xml version="1.0" ?> |
2 | <request submitted="1" relative="1" name="RequestSimulator" scientific_program="GRB" target_type="test"> | 2 | <request submitted="1" relative="1" name="RequestSimulator" scientific_program="GRB" target_type="test"> |
3 | - <sequence duration="200" jd1="6000" jd2="18000" name="Sequence7 (200secs)" target_coords="10"> | 3 | + <sequence duration="200" jd1="6000" jd2="60000" name="Sequence7 (200secs)" target_coords="10"> |
4 | <album detector="Visible camera" name="alb"> | 4 | <album detector="Visible camera" name="alb"> |
5 | <plan duration="200" filter="First infrared filter" name="New plan" nb_images="5"/> | 5 | <plan duration="200" filter="First infrared filter" name="New plan" nb_images="5"/> |
6 | </album> | 6 | </album> |
simulators/resources/routine_request_08.xml
1 | <?xml version="1.0" ?> | 1 | <?xml version="1.0" ?> |
2 | <request submitted="1" relative="1" name="RequestSimulator" scientific_program="GRB" target_type="test"> | 2 | <request submitted="1" relative="1" name="RequestSimulator" scientific_program="GRB" target_type="test"> |
3 | - <sequence duration="200" jd1="6000" jd2="18000" name="Sequence8 (200secs)" target_coords="10"> | 3 | + <sequence duration="200" jd1="19000" jd2="60000" name="Sequence8 (200secs)" target_coords="10"> |
4 | <album detector="Visible camera" name="alb"> | 4 | <album detector="Visible camera" name="alb"> |
5 | <plan duration="200" filter="First infrared filter" name="New plan" nb_images="5"/> | 5 | <plan duration="200" filter="First infrared filter" name="New plan" nb_images="5"/> |
6 | </album> | 6 | </album> |
simulators/resources/routine_request_09.xml
1 | <?xml version="1.0" ?> | 1 | <?xml version="1.0" ?> |
2 | <request submitted="1" relative="1" name="RequestSimulator" scientific_program="GRB" target_type="test"> | 2 | <request submitted="1" relative="1" name="RequestSimulator" scientific_program="GRB" target_type="test"> |
3 | - <sequence duration="200" jd1="6000" jd2="18000" name="Sequence9 (200secs)" target_coords="10"> | 3 | + <sequence duration="200" jd1="1000" jd2="60000" name="Sequence9 (200secs)" target_coords="10"> |
4 | <album detector="Visible camera" name="alb"> | 4 | <album detector="Visible camera" name="alb"> |
5 | <plan duration="200" filter="First infrared filter" name="New plan" nb_images="5"/> | 5 | <plan duration="200" filter="First infrared filter" name="New plan" nb_images="5"/> |
6 | </album> | 6 | </album> |
simulators/resources/routine_request_10.xml
1 | <?xml version="1.0" ?> | 1 | <?xml version="1.0" ?> |
2 | <request submitted="1" relative="1" name="RequestSimulator" scientific_program="GRB" target_type="test"> | 2 | <request submitted="1" relative="1" name="RequestSimulator" scientific_program="GRB" target_type="test"> |
3 | - <sequence duration="200" jd1="6000" jd2="18000" name="Sequence10 (200secs)" target_coords="10"> | 3 | + <sequence duration="200" jd1="200" jd2="60000" name="Sequence10 (200secs)" target_coords="10"> |
4 | <album detector="Visible camera" name="alb"> | 4 | <album detector="Visible camera" name="alb"> |
5 | <plan duration="200" filter="First infrared filter" name="New plan" nb_images="5"/> | 5 | <plan duration="200" filter="First infrared filter" name="New plan" nb_images="5"/> |
6 | </album> | 6 | </album> |
src/common/RequestBuilder.py
@@ -31,7 +31,7 @@ class RequestBuilder(): | @@ -31,7 +31,7 @@ class RequestBuilder(): | ||
31 | raise RuntimeError( | 31 | raise RuntimeError( |
32 | "start_new_request MUST be invoked before creating any sequence") | 32 | "start_new_request MUST be invoked before creating any sequence") |
33 | 33 | ||
34 | - sequence = Sequence(name=name, status=Sequence.OBSERVABLE, priority=priority, | 34 | + sequence = Sequence(name=name, status=Sequence.TOBEPLANNED, priority=priority, |
35 | jd1=jd1, jd2=jd2, t_prefered=t_prefered, duration=duration) | 35 | jd1=jd1, jd2=jd2, t_prefered=t_prefered, duration=duration) |
36 | self.sequences[self.sequence_id] = sequence | 36 | self.sequences[self.sequence_id] = sequence |
37 | self.sequence_id += 1 | 37 | self.sequence_id += 1 |
src/common/models.py
@@ -367,20 +367,19 @@ class Sequence(models.Model): | @@ -367,20 +367,19 @@ class Sequence(models.Model): | ||
367 | INCOMPLETE = "INCPL" | 367 | INCOMPLETE = "INCPL" |
368 | COMPLETE = "CPL" | 368 | COMPLETE = "CPL" |
369 | TOBEPLANNED = "TBP" | 369 | TOBEPLANNED = "TBP" |
370 | - OBSERVABLE = "OBS" | ||
371 | - UNPLANNABLE = "UNPLN" | 370 | + PLANNED = "PLND" |
372 | PENDING = "PNDG" | 371 | PENDING = "PNDG" |
373 | - EXECUTED = "EXD" | ||
374 | EXECUTING = "EXING" | 372 | EXECUTING = "EXING" |
373 | + EXECUTED = "EXD" | ||
375 | REJECTED = "RJTD" | 374 | REJECTED = "RJTD" |
376 | - CANCELLED = "CNCLD" | ||
377 | INVALID = "INVL" | 375 | INVALID = "INVL" |
378 | - DEVICE_ERROR = "DVER" | 376 | + CANCELLED = "CNCLD" |
377 | + UNPLANNABLE = "UNPLN" | ||
379 | STATUS_CHOICES = ( | 378 | STATUS_CHOICES = ( |
380 | (INCOMPLETE, "Incomplete"), | 379 | (INCOMPLETE, "Incomplete"), |
381 | (COMPLETE, "Complete"), | 380 | (COMPLETE, "Complete"), |
382 | (TOBEPLANNED, "To be planned"), | 381 | (TOBEPLANNED, "To be planned"), |
383 | - (OBSERVABLE, "Observable"), | 382 | + (PLANNED, "Planned"), |
384 | (UNPLANNABLE, "Unplannable"), | 383 | (UNPLANNABLE, "Unplannable"), |
385 | (PENDING, "Pending"), | 384 | (PENDING, "Pending"), |
386 | (EXECUTED, "Executed"), | 385 | (EXECUTED, "Executed"), |
@@ -388,7 +387,6 @@ class Sequence(models.Model): | @@ -388,7 +387,6 @@ class Sequence(models.Model): | ||
388 | (REJECTED, "Rejected"), | 387 | (REJECTED, "Rejected"), |
389 | (CANCELLED, "Cancelled"), | 388 | (CANCELLED, "Cancelled"), |
390 | (INVALID, "Invalid"), | 389 | (INVALID, "Invalid"), |
391 | - (DEVICE_ERROR, "Device error"), | ||
392 | ) | 390 | ) |
393 | 391 | ||
394 | request = models.ForeignKey( | 392 | request = models.ForeignKey( |
src/majordome/tasks.py
@@ -16,6 +16,7 @@ from django.conf import settings | @@ -16,6 +16,7 @@ from django.conf import settings | ||
16 | from utils.JDManipulator import * | 16 | from utils.JDManipulator import * |
17 | import utils.Logger as L | 17 | import utils.Logger as L |
18 | 18 | ||
19 | +DEBUG_FILE = False | ||
19 | log = L.setupLogger("MajordomeTaskLogger", "Majordome") | 20 | log = L.setupLogger("MajordomeTaskLogger", "Majordome") |
20 | 21 | ||
21 | ''' | 22 | ''' |
@@ -127,7 +128,7 @@ class Majordome(Task): | @@ -127,7 +128,7 @@ class Majordome(Task): | ||
127 | "schedule": self.timer_schedule, | 128 | "schedule": self.timer_schedule, |
128 | "sequence": self.timer_sequence | 129 | "sequence": self.timer_sequence |
129 | } | 130 | } |
130 | - if (settings.DEBUG): | 131 | + if (settings.DEBUG and DEBUG_FILE): |
131 | log.info("Majordome started with timers : " + str(self.timers)) | 132 | log.info("Majordome started with timers : " + str(self.timers)) |
132 | # Functions called during the loop | 133 | # Functions called during the loop |
133 | self.functions = { | 134 | self.functions = { |
@@ -162,10 +163,10 @@ class Majordome(Task): | @@ -162,10 +163,10 @@ class Majordome(Task): | ||
162 | self.logDB("Executing timer " + str(timer_name)) | 163 | self.logDB("Executing timer " + str(timer_name)) |
163 | self.functions[timer_name]() | 164 | self.functions[timer_name]() |
164 | else: | 165 | else: |
165 | - if (settings.DEBUG): | 166 | + if (settings.DEBUG and DEBUG_FILE): |
166 | log.info("Timer : " + str(timer_name) + "is not known by the Majordome") | 167 | log.info("Timer : " + str(timer_name) + "is not known by the Majordome") |
167 | self.logDB("Timer " + str(timer_name) + " unknown") | 168 | self.logDB("Timer " + str(timer_name) + " unknown") |
168 | - if (settings.DEBUG): | 169 | + if (settings.DEBUG and DEBUG_FILE): |
169 | log.info("Timer : " + str(timer_name) + " executed") | 170 | log.info("Timer : " + str(timer_name) + " executed") |
170 | return (0) | 171 | return (0) |
171 | 172 | ||
@@ -175,7 +176,7 @@ class Majordome(Task): | @@ -175,7 +176,7 @@ class Majordome(Task): | ||
175 | site_status = SiteWatch.objects.latest('updated') | 176 | site_status = SiteWatch.objects.latest('updated') |
176 | weather_status = WeatherWatch.objects.latest('updated') | 177 | weather_status = WeatherWatch.objects.latest('updated') |
177 | except ObjectDoesNotExist: | 178 | except ObjectDoesNotExist: |
178 | - if (settings.DEBUG): | 179 | + if (settings.DEBUG and DEBUG_FILE): |
179 | log.info("No site_status or weather_status found in database") | 180 | log.info("No site_status or weather_status found in database") |
180 | return (1) | 181 | return (1) |
181 | self.handlePLC(site_status, weather_status) | 182 | self.handlePLC(site_status, weather_status) |
@@ -192,29 +193,26 @@ class Majordome(Task): | @@ -192,29 +193,26 @@ class Majordome(Task): | ||
192 | 193 | ||
193 | def handleSequenceTimer(self): | 194 | def handleSequenceTimer(self): |
194 | self.timers["sequence"] = self.timer_sequence | 195 | self.timers["sequence"] = self.timer_sequence |
195 | - if (self.isValidStatus(self.status_tel)): | ||
196 | - if (self.executing_sequence != None): | ||
197 | - self.handleSequence(self.executing_sequence[0], | ||
198 | - self.executing_sequence[1], self.executing_sequence[2]) | ||
199 | - else: | ||
200 | - self.notifyTelescopeStatus("sequence") | 196 | + if (self.executing_sequence): |
197 | + self.handleSequence(self.executing_sequence[0], | ||
198 | + self.executing_sequence[1], self.executing_sequence[2]) | ||
201 | return (0) | 199 | return (0) |
202 | 200 | ||
203 | def handleScheduleTimer(self): | 201 | def handleScheduleTimer(self): |
204 | self.timers["schedule"] = self.timer_schedule | 202 | self.timers["schedule"] = self.timer_schedule |
205 | if (self.isValidStatus(self.status_tel)): | 203 | if (self.isValidStatus(self.status_tel)): |
206 | - if (self.schedule == None): | 204 | + if (self.schedule is None): |
207 | try: | 205 | try: |
208 | self.schedule = Schedule.objects.latest('created') | 206 | self.schedule = Schedule.objects.latest('created') |
209 | except ObjectDoesNotExist: | 207 | except ObjectDoesNotExist: |
210 | - if (settings.DEBUG): | 208 | + if (settings.DEBUG and DEBUG_FILE): |
211 | log.info("No schedule found in database") | 209 | log.info("No schedule found in database") |
212 | return (1) | 210 | return (1) |
213 | else: | 211 | else: |
214 | try: | 212 | try: |
215 | schedule = Schedule.objects.latest('created') | 213 | schedule = Schedule.objects.latest('created') |
216 | except ObjectDoesNotExist: | 214 | except ObjectDoesNotExist: |
217 | - if (settings.DEBUG): | 215 | + if (settings.DEBUG and DEBUG_FILE): |
218 | log.info("No schedule found in database") | 216 | log.info("No schedule found in database") |
219 | return (1) | 217 | return (1) |
220 | if (schedule.created != self.schedule.created): | 218 | if (schedule.created != self.schedule.created): |
@@ -256,52 +254,66 @@ class Majordome(Task): | @@ -256,52 +254,66 @@ class Majordome(Task): | ||
256 | Function called when a schedule has to be executed | 254 | Function called when a schedule has to be executed |
257 | ''' | 255 | ''' |
258 | def executeSchedule(self, shs_list): | 256 | def executeSchedule(self, shs_list): |
257 | + is_prev_planned = False | ||
259 | self.logDB("Trying to execute a sequence from current schedule") | 258 | self.logDB("Trying to execute a sequence from current schedule") |
260 | for shs in shs_list: # shs_list is sorted by tsp | 259 | for shs in shs_list: # shs_list is sorted by tsp |
261 | - if (shs.sequence.status == Sequence.OBSERVABLE and self.observable(shs.sequence)): | 260 | + if (shs.sequence.status == Sequence.PLANNED and self.observable(shs.sequence)): |
262 | countdown = self.getCountdown(shs) | 261 | countdown = self.getCountdown(shs) |
263 | - if countdown <= JulianSeconds(5) and countdown > 0: | ||
264 | - if (self.executing_sequence == None): | ||
265 | - self.executeSequence(shs, shs.sequence, countdown) | ||
266 | - else: | 262 | + # if (countdown <= 6): |
263 | + # TODO CHECK IF OBSERVABLE ELSE RESCHEDULE | ||
264 | + if countdown <= JulianSeconds(5): | ||
265 | + if self.executing_sequence is None: | ||
266 | + if self.switchSequence(): | ||
267 | + self.executeSequence(shs, shs.sequence, countdown) | ||
268 | + else: | ||
269 | + self.setNextSequence(shs, shs.sequence, countdown) | ||
270 | + elif self.next_sequence is None: | ||
267 | self.setNextSequence(shs, shs.sequence, countdown) | 271 | self.setNextSequence(shs, shs.sequence, countdown) |
268 | - else: | ||
269 | - if (settings.DEBUG): | ||
270 | - log.info("Sequence cannot be executed : countdown = " + str(countdown)) | ||
271 | - self.logDB("Sequence cannot be executed : countdown = " + str(countdown)) | 272 | + else: |
273 | + return 0 | ||
274 | + elif self.next_sequence is None: | ||
275 | + self.setNextSequence(shs, shs.sequence, countdown) | ||
272 | else: | 276 | else: |
273 | - if (settings.DEBUG): | 277 | + if (settings.DEBUG and DEBUG_FILE): |
274 | log.info("Sequence cannot be executed : Not observable") | 278 | log.info("Sequence cannot be executed : Not observable") |
275 | - self.logDB("Sequence cannot be executed : Not observable") | ||
276 | - return (0) | 279 | + self.logDB("Sequence "+shs.sequence.name+" cannot be executed : Not observable") |
280 | + return 0 | ||
277 | 281 | ||
278 | def observable(self, sequence): | 282 | def observable(self, sequence): |
279 | - if (sequence.jd2 - sequence.duration - getCurrentTime() <= 0): | ||
280 | - return (0) | ||
281 | - return (1) | 283 | + if (sequence.jd2 - sequence.duration - secondsToPreciseJulianDate(getPreciseCurrentTime()) <= 0): |
284 | + return 0 | ||
285 | + return 1 | ||
282 | 286 | ||
283 | ''' | 287 | ''' |
284 | Launch the observation tasks associated to a sequence | 288 | Launch the observation tasks associated to a sequence |
285 | ''' | 289 | ''' |
286 | def executeSequence(self, shs, sequence, countdown): | 290 | def executeSequence(self, shs, sequence, countdown): |
291 | + if (countdown > JulianSeconds(5)): | ||
292 | + if self.next_sequence and self.next_sequence[1].status == Sequence.PENDING: | ||
293 | + self.next_sequence[1].status = Sequence.PLANNED | ||
294 | + self.next_sequence[1].save() | ||
295 | + return 0 | ||
296 | + if self.next_sequence and self.next_sequence[1].status == Sequence.PLANNED: | ||
297 | + self.next_sequence[1].status = Sequence.PENDING | ||
298 | + self.next_sequence[1].save() | ||
299 | + | ||
287 | self.logDB("Executing sequence") | 300 | self.logDB("Executing sequence") |
288 | plans_results = [] | 301 | plans_results = [] |
289 | - | ||
290 | if sequence.albums.filter(detector__name="Cagire").exists(): | 302 | if sequence.albums.filter(detector__name="Cagire").exists(): |
291 | if (self.isValidStatus(self.status_nir)): | 303 | if (self.isValidStatus(self.status_nir)): |
292 | for plan in sequence.albums.get(detector__name="Cagire").plans.all(): | 304 | for plan in sequence.albums.get(detector__name="Cagire").plans.all(): |
293 | - res = observation_manager.tasks.execute_plan_nir.apply_async((plan.id, countdown)) | 305 | + res = observation_manager.tasks.execute_plan_nir.apply_async((plan.id, float(countdown))) |
294 | TaskId.objects.create(task_id=res.id, task="execute_plan") | 306 | TaskId.objects.create(task_id=res.id, task="execute_plan") |
295 | plans_results.append(res) | 307 | plans_results.append(res) |
296 | - else: | ||
297 | - self.notifyDeviceStatus("Cagire", "Sequence execution", self.status_nir) | ||
298 | - sequence.status = Sequence.DEVICE_ERROR | ||
299 | - sequence.save() | ||
300 | - return (1) | 308 | + else: |
309 | + self.notifyDeviceStatus("Cagire", "Sequence execution", self.status_nir) | ||
310 | + sequence.status = Sequence.DEVICE_ERROR | ||
311 | + sequence.save() | ||
312 | + return (1) | ||
301 | if sequence.albums.filter(detector__name="Visible camera").exists(): | 313 | if sequence.albums.filter(detector__name="Visible camera").exists(): |
302 | if (self.isValidStatus(self.status_vis)): | 314 | if (self.isValidStatus(self.status_vis)): |
303 | for plan in sequence.albums.get(detector__name="Visible camera").plans.all(): | 315 | for plan in sequence.albums.get(detector__name="Visible camera").plans.all(): |
304 | - res = observation_manager.tasks.execute_plan_vis.apply_async((plan.id, countdown)) | 316 | + res = observation_manager.tasks.execute_plan_vis.apply_async((plan.id, float(countdown))) |
305 | TaskId.objects.create(task_id=res.id, task="execute_plan") | 317 | TaskId.objects.create(task_id=res.id, task="execute_plan") |
306 | plans_results.append(res) | 318 | plans_results.append(res) |
307 | else: | 319 | else: |
@@ -320,20 +332,22 @@ class Majordome(Task): | @@ -320,20 +332,22 @@ class Majordome(Task): | ||
320 | Set the next sequence | 332 | Set the next sequence |
321 | ''' | 333 | ''' |
322 | def setNextSequence(self, shs, sequence, countdown): | 334 | def setNextSequence(self, shs, sequence, countdown): |
335 | + sequence.status = Sequence.PENDING | ||
323 | self.next_sequence = [shs, sequence, countdown] | 336 | self.next_sequence = [shs, sequence, countdown] |
337 | + sequence.save() | ||
324 | return (0) | 338 | return (0) |
325 | 339 | ||
326 | ''' | 340 | ''' |
327 | Switch sequences | 341 | Switch sequences |
328 | ''' | 342 | ''' |
329 | def switchSequence(self): | 343 | def switchSequence(self): |
330 | - if (self.next_sequence == None): | ||
331 | - self.executing_sequence = None | ||
332 | - else: | ||
333 | - self.executing_sequence = None | 344 | + self.executing_sequence = None |
345 | + if (self.next_sequence is not None): | ||
334 | self.executeSequence(self.next_sequence[0], | 346 | self.executeSequence(self.next_sequence[0], |
335 | self.next_sequence[1], self.next_sequence[2]) | 347 | self.next_sequence[1], self.next_sequence[2]) |
336 | self.next_sequence = None | 348 | self.next_sequence = None |
349 | + else: | ||
350 | + return 1 | ||
337 | return (0) | 351 | return (0) |
338 | 352 | ||
339 | ''' | 353 | ''' |
@@ -414,7 +428,7 @@ class Majordome(Task): | @@ -414,7 +428,7 @@ class Majordome(Task): | ||
414 | ''' | 428 | ''' |
415 | def getCountdown(self, shs): | 429 | def getCountdown(self, shs): |
416 | # TODO start sequence as soon as possible (a lot of verifications must be done there) | 430 | # TODO start sequence as soon as possible (a lot of verifications must be done there) |
417 | - current_time = secondsToJulianDate(getPreciseCurrentTime()); | 431 | + current_time = secondsToPreciseJulianDate(getPreciseCurrentTime()) |
418 | countdown = shs.tsp - current_time | 432 | countdown = shs.tsp - current_time |
419 | return countdown | 433 | return countdown |
420 | 434 |
3.27 KB
3.79 KB
src/observation_manager/tasks.py
@@ -6,6 +6,7 @@ from devices import CameraVIS as VIS | @@ -6,6 +6,7 @@ from devices import CameraVIS as VIS | ||
6 | from devices import CameraNIR as NIR | 6 | from devices import CameraNIR as NIR |
7 | from devices import Telescope | 7 | from devices import Telescope |
8 | import time | 8 | import time |
9 | +from utils.Logger import setupLogger | ||
9 | 10 | ||
10 | ''' | 11 | ''' |
11 | Super class for execute_plan_vis / _nir | 12 | Super class for execute_plan_vis / _nir |
@@ -13,6 +14,7 @@ import time | @@ -13,6 +14,7 @@ import time | ||
13 | class execute_plan(Task): | 14 | class execute_plan(Task): |
14 | 15 | ||
15 | def run(self, plan_id, countdown, type): | 16 | def run(self, plan_id, countdown, type): |
17 | + | ||
16 | if countdown > 0: | 18 | if countdown > 0: |
17 | time.sleep(countdown) | 19 | time.sleep(countdown) |
18 | TaskId.objects.filter(task_id=self.request.id).delete() | 20 | TaskId.objects.filter(task_id=self.request.id).delete() |
@@ -102,7 +104,10 @@ class execute_plan(Task): | @@ -102,7 +104,10 @@ class execute_plan(Task): | ||
102 | Send the images to the analyzer | 104 | Send the images to the analyzer |
103 | ''' | 105 | ''' |
104 | class execute_plan_vis(execute_plan): | 106 | class execute_plan_vis(execute_plan): |
107 | + logger = setupLogger("PlanVIS", "PlanVIS") | ||
108 | + | ||
105 | def run(self, plan_id, countdown): | 109 | def run(self, plan_id, countdown): |
110 | + self.log.info("------------------ RUNNING PLAN VIS ----------------------------") | ||
106 | super().run(plan_id, countdown, "VIS") | 111 | super().run(plan_id, countdown, "VIS") |
107 | 112 | ||
108 | 113 | ||
@@ -111,8 +116,11 @@ class execute_plan_vis(execute_plan): | @@ -111,8 +116,11 @@ class execute_plan_vis(execute_plan): | ||
111 | Send the images to the analyzer | 116 | Send the images to the analyzer |
112 | ''' | 117 | ''' |
113 | class execute_plan_nir(execute_plan): | 118 | class execute_plan_nir(execute_plan): |
119 | + log = setupLogger("PlanNIR", "PlanNIR") | ||
120 | + | ||
114 | def run(self, plan_id, countdown): | 121 | def run(self, plan_id, countdown): |
115 | super().run(plan_id, countdown, "NIR") | 122 | super().run(plan_id, countdown, "NIR") |
123 | + self.log.info("------------------ RUNNING PLAN NIR ----------------------------") | ||
116 | 124 | ||
117 | 125 | ||
118 | ''' | 126 | ''' |
@@ -120,6 +128,8 @@ class execute_plan_nir(execute_plan): | @@ -120,6 +128,8 @@ class execute_plan_nir(execute_plan): | ||
120 | When they are all finished, it creates the 'super' calibration files. | 128 | When they are all finished, it creates the 'super' calibration files. |
121 | ''' | 129 | ''' |
122 | class create_calibrations(Task): | 130 | class create_calibrations(Task): |
123 | - def run(self): | ||
124 | - # TODO: attendre que tout soit idle | ||
125 | - pass | 131 | + logger = setupLogger("Calibrations", "Calibrations") |
132 | + | ||
133 | + def run(self): | ||
134 | + self.log.info("------------------ RUNNING CALIBRATIONS ----------------------------") | ||
135 | + # TODO: attendre que tout soit idle |
src/pyros/settings.py.bak
@@ -119,7 +119,9 @@ LOGIN_URL = "/" | @@ -119,7 +119,9 @@ LOGIN_URL = "/" | ||
119 | 119 | ||
120 | # EP modif | 120 | # EP modif |
121 | 121 | ||
122 | -CELERY_TEST = True | 122 | +SIMULATOR = True |
123 | + | ||
124 | +CELERY_TEST = False | ||
123 | 125 | ||
124 | if not CELERY_TEST: | 126 | if not CELERY_TEST: |
125 | if not MYSQL: | 127 | if not MYSQL: |
src/routine_manager/RequestSerializer.py
@@ -88,8 +88,6 @@ class RequestSerializer(): | @@ -88,8 +88,6 @@ class RequestSerializer(): | ||
88 | sequence.jd1 = (time.time() + float(sequence.jd1)) / 86400 + TIMESTAMP_JD | 88 | sequence.jd1 = (time.time() + float(sequence.jd1)) / 86400 + TIMESTAMP_JD |
89 | sequence.jd2 = (time.time() + float(sequence.jd2)) / 86400 + TIMESTAMP_JD | 89 | sequence.jd2 = (time.time() + float(sequence.jd2)) / 86400 + TIMESTAMP_JD |
90 | sequence.request = self.request | 90 | sequence.request = self.request |
91 | - # TODO: REMOVE WHEN WE KNOW HOW TO DECIDE IF THE SEQUENCE IS OBSERVABLE | ||
92 | - sequence.status = Sequence.OBSERVABLE | ||
93 | sequence.save() | 91 | sequence.save() |
94 | for album, plans in albums: | 92 | for album, plans in albums: |
95 | album.sequence = sequence | 93 | album.sequence = sequence |
src/routine_manager/validators.py
1 | from common.models import Sequence | 1 | from common.models import Sequence |
2 | +from django.conf import settings | ||
2 | 3 | ||
3 | def check_plan_validity(plan): | 4 | def check_plan_validity(plan): |
4 | """ | 5 | """ |
@@ -52,7 +53,11 @@ def check_sequence_validity(seq): | @@ -52,7 +53,11 @@ def check_sequence_validity(seq): | ||
52 | if seq.albums.filter(complete=False).count() != 0 or seq.albums.count() == 0: | 53 | if seq.albums.filter(complete=False).count() != 0 or seq.albums.count() == 0: |
53 | seq.status = Sequence.INCOMPLETE | 54 | seq.status = Sequence.INCOMPLETE |
54 | else: | 55 | else: |
55 | - seq.status = Sequence.COMPLETE | 56 | + #TODO CHANGE WHEN WE KNOW HOW TO DECIDE IF THE SEQUENCE IS OBSERVABLE |
57 | + if settings.SIMULATOR: | ||
58 | + seq.status = Sequence.TOBEPLANNED | ||
59 | + else: | ||
60 | + seq.status = Sequence.COMPLETE | ||
56 | seq.save() | 61 | seq.save() |
57 | return check_request_validity(seq.request) | 62 | return check_request_validity(seq.request) |
58 | 63 |
src/routine_manager/views.py
@@ -428,7 +428,7 @@ def submit_request(request, req_id, redir): | @@ -428,7 +428,7 @@ def submit_request(request, req_id, redir): | ||
428 | return redirect(action_request, req_id=req_id, action="view", status=-1, message=message) | 428 | return redirect(action_request, req_id=req_id, action="view", status=-1, message=message) |
429 | 429 | ||
430 | for seq in req.sequences.all(): | 430 | for seq in req.sequences.all(): |
431 | - seq.status = Sequence.OBSERVABLE # TODO: utiliser le monitoring (regarder les conditions d'obseration pour dire si on met TBP ou OBS) | 431 | + seq.status = Sequence.TOBEPLANNED |
432 | seq.save() | 432 | seq.save() |
433 | req.submitted = True | 433 | req.submitted = True |
434 | req.save() | 434 | req.save() |
@@ -460,7 +460,7 @@ def unsubmit_request(request, req_id): | @@ -460,7 +460,7 @@ def unsubmit_request(request, req_id): | ||
460 | 460 | ||
461 | req.submitted = False | 461 | req.submitted = False |
462 | req.save() | 462 | req.save() |
463 | - sequences = req.sequences.filter(Q(status=Sequence.TOBEPLANNED) | Q(status=Sequence.OBSERVABLE) | | 463 | + sequences = req.sequences.filter(Q(status=Sequence.TOBEPLANNED) | Q(status=Sequence.PLANNED) | |
464 | Q(status=Sequence.INVALID) | Q(status=Sequence.UNPLANNABLE)) | 464 | Q(status=Sequence.INVALID) | Q(status=Sequence.UNPLANNABLE)) |
465 | for seq in sequences: | 465 | for seq in sequences: |
466 | seq.status = Sequence.COMPLETE | 466 | seq.status = Sequence.COMPLETE |
src/scheduler/Scheduler.py
1 | from operator import attrgetter | 1 | from operator import attrgetter |
2 | from .UserManager import UserManager | 2 | from .UserManager import UserManager |
3 | from .Interval import * | 3 | from .Interval import * |
4 | +from django.db.models import Q | ||
4 | 5 | ||
5 | SIMULATION = False | 6 | SIMULATION = False |
6 | - | 7 | +DEBUG_FILE = False |
7 | 8 | ||
8 | class Scheduler(IntervalManagement): | 9 | class Scheduler(IntervalManagement): |
9 | REJECTED_ROOM = "Insufficient room for this sequence" | 10 | REJECTED_ROOM = "Insufficient room for this sequence" |
@@ -29,27 +30,43 @@ class Scheduler(IntervalManagement): | @@ -29,27 +30,43 @@ class Scheduler(IntervalManagement): | ||
29 | def isFirstSchedule(self) -> bool: | 30 | def isFirstSchedule(self) -> bool: |
30 | return False | 31 | return False |
31 | 32 | ||
33 | + def determinePlanStart(self, previous_sched): | ||
34 | + start = secondsToPreciseJulianDate(getPreciseCurrentTime()) | ||
35 | + if start > previous_sched.plan_start + self.max_overhead: | ||
36 | + return start + self.max_overhead | ||
37 | + return previous_sched.plan_start | ||
38 | + | ||
32 | def copyFromPrevious(self) -> int: | 39 | def copyFromPrevious(self) -> int: |
33 | if len(Schedule.objects.all()) == 1: | 40 | if len(Schedule.objects.all()) == 1: |
34 | self.schedule.plan_night_start = self.schedule.plan_start | 41 | self.schedule.plan_night_start = self.schedule.plan_start |
35 | - self.log("No schedule found") | 42 | + if DEBUG_FILE: |
43 | + self.log("No schedule found") | ||
36 | return 1 | 44 | return 1 |
37 | try: | 45 | try: |
38 | previous_sched = Schedule.objects.order_by('-created')[1] | 46 | previous_sched = Schedule.objects.order_by('-created')[1] |
39 | - previous_exc_seq = previous_sched.sequences.filter(status=Sequence.EXECUTED) | 47 | + previous_exc_seq = previous_sched.sequences.filter(Q(status=Sequence.EXECUTED) | |
48 | + Q(status=Sequence.EXECUTING)) | ||
40 | except: | 49 | except: |
41 | self.schedule.plan_night_start = self.schedule.plan_start | 50 | self.schedule.plan_night_start = self.schedule.plan_start |
42 | - self.debug("Scheduler could not get information from previous schedule") | 51 | + if DEBUG_FILE: |
52 | + self.debug("Scheduler could not get information from previous schedule") | ||
43 | return 1 | 53 | return 1 |
44 | for seq in previous_exc_seq: | 54 | for seq in previous_exc_seq: |
45 | - shs = seq.shs | 55 | + shs = seq.shs.latest("schedule__created") |
46 | shs.pk = None | 56 | shs.pk = None |
47 | shs.schedule = self.schedule | 57 | shs.schedule = self.schedule |
48 | shs.save() | 58 | shs.save() |
59 | + adder = 0 | ||
60 | + try: | ||
61 | + executing = Sequence.objects.filter(status=Sequence.EXECUTING) | ||
62 | + if executing: | ||
63 | + s = Sequence.shs.latest("schedule__created") | ||
64 | + adder = s.tsp - secondsToPreciseJulianDate(getPreciseCurrentTime()) | ||
65 | + except: | ||
66 | + pass | ||
49 | self.schedule.plan_night_start = previous_sched.plan_night_start | 67 | self.schedule.plan_night_start = previous_sched.plan_night_start |
50 | self.schedule.plan_end = previous_sched.plan_end | 68 | self.schedule.plan_end = previous_sched.plan_end |
51 | - start = Decimal(secondsToJulianDate(getCurrentTime())) + self.max_overhead | ||
52 | - self.schedule.plan_start = (start if start > previous_sched.plan_start else previous_sched.plan_start) | 69 | + self.schedule.plan_start = self.determinePlanStart(previous_sched) + adder |
53 | return 0 | 70 | return 0 |
54 | 71 | ||
55 | def simulateSchedule(self, sequences) -> tuple: | 72 | def simulateSchedule(self, sequences) -> tuple: |
@@ -68,7 +85,8 @@ class Scheduler(IntervalManagement): | @@ -68,7 +85,8 @@ class Scheduler(IntervalManagement): | ||
68 | def computeSchedule(self) -> int: | 85 | def computeSchedule(self) -> int: |
69 | interval = Interval(self.schedule.plan_start, self.schedule.plan_end) | 86 | interval = Interval(self.schedule.plan_start, self.schedule.plan_end) |
70 | self.intervals.append(interval) | 87 | self.intervals.append(interval) |
71 | - self.log("Interval created : " + str(interval.__dict__)) | 88 | + if DEBUG_FILE: |
89 | + self.log("Interval created : " + str(interval.__dict__)) | ||
72 | self.removeInvalidSequences() | 90 | self.removeInvalidSequences() |
73 | self.determinePriorities() | 91 | self.determinePriorities() |
74 | self.removeNonEligible() | 92 | self.removeNonEligible() |
@@ -86,21 +104,27 @@ class Scheduler(IntervalManagement): | @@ -86,21 +104,27 @@ class Scheduler(IntervalManagement): | ||
86 | if self.copyFromPrevious(): | 104 | if self.copyFromPrevious(): |
87 | self.schedule.plan_night_start = self.schedule.plan_start | 105 | self.schedule.plan_night_start = self.schedule.plan_start |
88 | 106 | ||
89 | - self.sequences = list(Sequence.objects.filter()) | 107 | + self.sequences = list(Sequence.objects.filter(Q(status=Sequence.PLANNED) | Q(status=Sequence.TOBEPLANNED) |
108 | + | Q(status=Sequence.PENDING))) | ||
90 | self.sequences = [(sequence, ScheduleHasSequences(sequence=sequence, schedule=self.schedule)) | 109 | self.sequences = [(sequence, ScheduleHasSequences(sequence=sequence, schedule=self.schedule)) |
91 | for sequence in self.sequences] | 110 | for sequence in self.sequences] |
92 | - self.log(str(len(self.sequences)) + " sequences found") | 111 | + if DEBUG_FILE: |
112 | + self.log(str(len(self.sequences)) + " sequences found") | ||
93 | self.computeSchedule() | 113 | self.computeSchedule() |
94 | self.saveSchedule() | 114 | self.saveSchedule() |
95 | - self.log("Saving schedule with " + str(len(self.schedule.sequences.all())) + " sequences") | 115 | + if DEBUG_FILE: |
116 | + self.log("Saving schedule with " + str(len(self.schedule.sequences.all())) + " sequences") | ||
96 | return self.schedule | 117 | return self.schedule |
97 | 118 | ||
98 | def saveSchedule(self) -> int: | 119 | def saveSchedule(self) -> int: |
99 | self.schedule.save() | 120 | self.schedule.save() |
100 | - for _, shs in self.sequences: | 121 | + for sequence, shs in self.sequences: |
122 | + sequence.status = Sequence.PLANNED | ||
101 | shs.schedule = self.schedule | 123 | shs.schedule = self.schedule |
124 | + sequence.save() | ||
102 | shs.save() | 125 | shs.save() |
103 | - self.logSchedule() | 126 | + if DEBUG_FILE: |
127 | + self.logSchedule() | ||
104 | return 0 | 128 | return 0 |
105 | 129 | ||
106 | 130 | ||
@@ -116,7 +140,8 @@ class Scheduler(IntervalManagement): | @@ -116,7 +140,8 @@ class Scheduler(IntervalManagement): | ||
116 | if not SIMULATION: | 140 | if not SIMULATION: |
117 | sequence.save() | 141 | sequence.save() |
118 | self.sequences.remove((sequence, shs)) | 142 | self.sequences.remove((sequence, shs)) |
119 | - self.log("Removing non eligible sequence") | 143 | + if DEBUG_FILE: |
144 | + self.log("Removing non eligible sequence") | ||
120 | return 0 | 145 | return 0 |
121 | 146 | ||
122 | def removeInvalidSequences(self): | 147 | def removeInvalidSequences(self): |
@@ -124,7 +149,8 @@ class Scheduler(IntervalManagement): | @@ -124,7 +149,8 @@ class Scheduler(IntervalManagement): | ||
124 | if (sequence.jd1 < 0 or sequence.jd2 < 0 or | 149 | if (sequence.jd1 < 0 or sequence.jd2 < 0 or |
125 | is_nearby_less_or_equal(sequence.duration, Decimal(0)) or | 150 | is_nearby_less_or_equal(sequence.duration, Decimal(0)) or |
126 | sequence.jd2 - sequence.jd1 < sequence.duration): | 151 | sequence.jd2 - sequence.jd1 < sequence.duration): |
127 | - self.log("Removing sequence in removeInvalidSequences") | 152 | + if DEBUG_FILE: |
153 | + self.log("Removing sequence in removeInvalidSequences") | ||
128 | self.sequences.remove((sequence, shs)) | 154 | self.sequences.remove((sequence, shs)) |
129 | sequence.status = Sequence.INVALID | 155 | sequence.status = Sequence.INVALID |
130 | if not SIMULATION: | 156 | if not SIMULATION: |
@@ -160,7 +186,8 @@ class Scheduler(IntervalManagement): | @@ -160,7 +186,8 @@ class Scheduler(IntervalManagement): | ||
160 | shs.status = Sequence.PENDING | 186 | shs.status = Sequence.PENDING |
161 | self.decreaseQuota(sequence, sequence.duration) | 187 | self.decreaseQuota(sequence, sequence.duration) |
162 | else: | 188 | else: |
163 | - self.log("Removing sequence in place_sequences") | 189 | + if DEBUG_FILE: |
190 | + self.log("Removing sequence in place_sequences") | ||
164 | shs.status = Sequence.REJECTED | 191 | shs.status = Sequence.REJECTED |
165 | shs.desc = self.REJECTED_ROOM | 192 | shs.desc = self.REJECTED_ROOM |
166 | return 0 | 193 | return 0 |
src/scheduler/simulator.py
@@ -76,7 +76,7 @@ class Simulator(): | @@ -76,7 +76,7 @@ class Simulator(): | ||
76 | jd1 = Decimal("%.8f" % float(sequence_array[5])) | 76 | jd1 = Decimal("%.8f" % float(sequence_array[5])) |
77 | jd2 = Decimal("%.8f" % float(sequence_array[6])) | 77 | jd2 = Decimal("%.8f" % float(sequence_array[6])) |
78 | 78 | ||
79 | - sequence = Sequence(request=req, status=Sequence.OBSERVABLE, | 79 | + sequence = Sequence(request=req, status=Sequence.PLANNED, |
80 | name="sequence", id=id_seq, priority=priority, duration=duration, jd1=jd1, jd2=jd2, t_prefered=-1) | 80 | name="sequence", id=id_seq, priority=priority, duration=duration, jd1=jd1, jd2=jd2, t_prefered=-1) |
81 | sequences.append(sequence) | 81 | sequences.append(sequence) |
82 | 82 |
src/scheduler/tasks.py
@@ -11,9 +11,7 @@ class scheduling(Task): | @@ -11,9 +11,7 @@ class scheduling(Task): | ||
11 | def run(self, first_schedule=False, alert=False): | 11 | def run(self, first_schedule=False, alert=False): |
12 | 12 | ||
13 | Log.objects.create(agent='Scheduler', message='Start schedule : ' + str(datetime.datetime.now())) | 13 | Log.objects.create(agent='Scheduler', message='Start schedule : ' + str(datetime.datetime.now())) |
14 | - log.info("Scheduling start") | ||
15 | self.scheduler = Scheduler() | 14 | self.scheduler = Scheduler() |
16 | self.scheduler.setNightLimits(secondsToJulianDate(getNightStart()), secondsToJulianDate(getNightEnd())) | 15 | self.scheduler.setNightLimits(secondsToJulianDate(getNightStart()), secondsToJulianDate(getNightEnd())) |
17 | self.scheduler.makeSchedule() | 16 | self.scheduler.makeSchedule() |
18 | - log.info("Scheduling done") | ||
19 | Log.objects.create(agent='Scheduler', message='Scheduling finished : ' + str(datetime.datetime.now())) | 17 | Log.objects.create(agent='Scheduler', message='Scheduling finished : ' + str(datetime.datetime.now())) |
20 | \ No newline at end of file | 18 | \ No newline at end of file |
src/scheduler/templates/scheduler/retrieve_schedule.html
@@ -63,12 +63,16 @@ | @@ -63,12 +63,16 @@ | ||
63 | {% for sequence in sequences %} | 63 | {% for sequence in sequences %} |
64 | <tr> | 64 | <tr> |
65 | <td> | 65 | <td> |
66 | - {% if sequence.processing == 1 %} | ||
67 | - <img src="{% static "media/arrow_green.png" %}" alt="html5" height="30" width="30" style="margin-left:25%"/> | ||
68 | - {% elif sequence.processing == 0 and sequence.status == "EXECUTED" %} | ||
69 | - <img src="{% static "media/validate.jpg" %}" alt="html5" height="30" width="30" style="margin-left:25%"/> | 66 | + {% if sequence.0.status == "EXING" == 1 %} |
67 | + <img src="{% static "media/arrow_green.png" %}" alt="html5" height="30" width="30" style="margin-left:25%"/> | ||
68 | + {% elif sequence.0.status == "EXD" %} | ||
69 | + <img src="{% static "media/validate.jpg" %}" alt="html5" height="30" width="30" style="margin-left:25%"/> | ||
70 | + {% elif sequence.0.status == "PNDG" %} | ||
71 | + <img src="{% static "media/next.png" %}" alt="html5" height="30" width="30" style="margin-left:25%"/> | ||
72 | + {% elif sequence.0.status == "PLND" %} | ||
73 | + <img src="{% static "media/planned.png" %}" alt="html5" height="30" width="30" style="margin-left:25%"/> | ||
70 | {% else %} | 74 | {% else %} |
71 | - <img src="{% static "media/error.png" %}" alt="{{sequence.processing}}" height="30" width="30" style="margin-left:25%"/> | 75 | + <img src="{% static "media/error.png" %}" alt="html5" height="30" width="30" style="margin-left:25%"/> |
72 | {% endif %} | 76 | {% endif %} |
73 | </td> | 77 | </td> |
74 | <td>{{ sequence.0.id }}</td> | 78 | <td>{{ sequence.0.id }}</td> |
@@ -79,7 +83,7 @@ | @@ -79,7 +83,7 @@ | ||
79 | <td>{{ sequence.0.jd2|jdtodate }}</td> | 83 | <td>{{ sequence.0.jd2|jdtodate }}</td> |
80 | <td>{{ sequence.0.duration|jdtoduration }}</td> | 84 | <td>{{ sequence.0.duration|jdtoduration }}</td> |
81 | <td>{{ sequence.0.priority }}</td> | 85 | <td>{{ sequence.0.priority }}</td> |
82 | - <td>{{ sequence.1.status }}</td> | 86 | + <td>{{ sequence.0.status }}</td> |
83 | </tr> | 87 | </tr> |
84 | {% endfor %} | 88 | {% endfor %} |
85 | </tbody> | 89 | </tbody> |
src/scheduler/views.py
@@ -10,7 +10,7 @@ SIMULATION_FILE = 'file:./scheduler/sequences_cador.html' | @@ -10,7 +10,7 @@ SIMULATION_FILE = 'file:./scheduler/sequences_cador.html' | ||
10 | def retrieve_schedule(request): | 10 | def retrieve_schedule(request): |
11 | if (len(Schedule.objects.all()) > 0): # checking if the schedule is empty | 11 | if (len(Schedule.objects.all()) > 0): # checking if the schedule is empty |
12 | schedule = Schedule.objects.order_by("-created")[0] # Sorting Schedule | 12 | schedule = Schedule.objects.order_by("-created")[0] # Sorting Schedule |
13 | - shs_list = schedule.shs.all() # getting all the schedule has sequences references | 13 | + shs_list = schedule.shs.order_by("tsp") # getting all the schedule has sequences references |
14 | sequences = [(shs.sequence, shs) for shs in shs_list] # getting all sequences | 14 | sequences = [(shs.sequence, shs) for shs in shs_list] # getting all sequences |
15 | 15 | ||
16 | nb_scheduled_sequences = len(shs_list) | 16 | nb_scheduled_sequences = len(shs_list) |
@@ -33,7 +33,7 @@ def schedule_simulation(request): | @@ -33,7 +33,7 @@ def schedule_simulation(request): | ||
33 | simulator = Simulator() | 33 | simulator = Simulator() |
34 | schedule, sequences = simulator.simulate(SIMULATION_FILE) | 34 | schedule, sequences = simulator.simulate(SIMULATION_FILE) |
35 | 35 | ||
36 | - nb_scheduled_sequences = len([sequence for sequence in sequences if sequence[1].status != Sequence.OBSERVABLE]) | 36 | + nb_scheduled_sequences = len([sequence for sequence in sequences if sequence[1].status != Sequence.PLANNED]) |
37 | executed_sequences = len([sequence for sequence in sequences if sequence[1].status == Sequence.EXECUTED]) | 37 | executed_sequences = len([sequence for sequence in sequences if sequence[1].status == Sequence.EXECUTED]) |
38 | 38 | ||
39 | 39 |
src/utils/JDManipulator.py
1 | +from django.conf import settings | ||
1 | import datetime | 2 | import datetime |
2 | import time | 3 | import time |
3 | from decimal import * | 4 | from decimal import * |
@@ -5,9 +6,23 @@ from decimal import * | @@ -5,9 +6,23 @@ from decimal import * | ||
5 | JD_VALUE = 86400 | 6 | JD_VALUE = 86400 |
6 | TIMESTAMP_JD = 2440587.500000 | 7 | TIMESTAMP_JD = 2440587.500000 |
7 | DAILY_SECOND = 1 / 86400 | 8 | DAILY_SECOND = 1 / 86400 |
9 | +SECOND_DIV = 86400 | ||
10 | + | ||
11 | +def getSimTime(): | ||
12 | + current_time = datetime.datetime.now() | ||
13 | + if current_time.minute == 59: | ||
14 | + current_time = current_time.replace(hour=(current_time.hour + 1), minute=0, second=10) | ||
15 | + else: | ||
16 | + if current_time.second >= 50: | ||
17 | + current_time = current_time.replace(minute=current_time.minute + 1, second=10) | ||
18 | + else: | ||
19 | + current_time = current_time.replace(second=(current_time.second + 10)) | ||
20 | + return (time.mktime(current_time.timetuple())) | ||
21 | + | ||
22 | +SIM_TIME_START = getSimTime() | ||
8 | 23 | ||
9 | def JulianSeconds(value): | 24 | def JulianSeconds(value): |
10 | - return (Decimal(value * DAILY_SECOND)) | 25 | + return (Decimal(value) / SECOND_DIV) |
11 | 26 | ||
12 | def getPreciseCurrentTime(): | 27 | def getPreciseCurrentTime(): |
13 | return (Decimal(getCurrentTime())) | 28 | return (Decimal(getCurrentTime())) |
@@ -21,6 +36,9 @@ def getPreciseNightEnd(): | @@ -21,6 +36,9 @@ def getPreciseNightEnd(): | ||
21 | def secondsToJulianDate(time_seconds): | 36 | def secondsToJulianDate(time_seconds): |
22 | return (time_seconds / 86400 + TIMESTAMP_JD) | 37 | return (time_seconds / 86400 + TIMESTAMP_JD) |
23 | 38 | ||
39 | +def secondsToPreciseJulianDate(time_seconds): | ||
40 | + return (Decimal(time_seconds) / 86400 + Decimal(TIMESTAMP_JD)) | ||
41 | + | ||
24 | def julianDateToSeconds(time_julian): | 42 | def julianDateToSeconds(time_julian): |
25 | return ((time_julian - TIMESTAMP_JD) * 86400) | 43 | return ((time_julian - TIMESTAMP_JD) * 86400) |
26 | 44 | ||
@@ -46,7 +64,18 @@ def getNextDefaultNightEnd(): | @@ -46,7 +64,18 @@ def getNextDefaultNightEnd(): | ||
46 | 64 | ||
47 | def getDefaultNightStart(): | 65 | def getDefaultNightStart(): |
48 | current_time = datetime.datetime.now() | 66 | current_time = datetime.datetime.now() |
49 | - current_time = current_time.replace(hour=18, minute=0, second=0, microsecond=0) | 67 | + if settings.SIMULATOR: |
68 | + if settings.SIMULATOR: | ||
69 | + return SIM_TIME_START | ||
70 | + if current_time.minute == 59: | ||
71 | + current_time = current_time.replace(hour=(current_time.hour + 1), minute=0, second=10) | ||
72 | + else: | ||
73 | + if current_time.second > 50: | ||
74 | + current_time = current_time.replace(minute=current_time.minute + 1, second=10) | ||
75 | + else: | ||
76 | + current_time = current_time.replace(second=(current_time.second + 10)) | ||
77 | + else: | ||
78 | + current_time = current_time.replace(hour=18, minute=0, second=0, microsecond=0) | ||
50 | return (time.mktime(current_time.timetuple())) | 79 | return (time.mktime(current_time.timetuple())) |
51 | 80 | ||
52 | def getDefaultNightEnd(): | 81 | def getDefaultNightEnd(): |