Blame view

src/majordome/tasks.py 22.8 KB
5b5566ab   haribo   added celery
1
from __future__ import absolute_import
ce470283   Jeremy   Plc simulator fin...
2

5b5566ab   haribo   added celery
3
from celery.task import Task
ce470283   Jeremy   Plc simulator fin...
4
5
6
from django.core.exceptions import ObjectDoesNotExist
from django.db.models import Q

9774228b   haribo   Date: 22/06/2016
7
import observation_manager
abfb02e2   Jeremy   Device Model is n...
8
import observation_manager.tasks
ce470283   Jeremy   Plc simulator fin...
9
10
11
import scheduler
import scheduler.tasks as sched_task
import utils.Logger as L
c72eb17a   Jeremy   Update celery task
12
13
import monitoring.tasks
import alert_manager.tasks
ce470283   Jeremy   Plc simulator fin...
14
from common.models import *
65149de7   Jeremy   Update
15
from devices.CameraNIR import NIRCameraController
ce470283   Jeremy   Plc simulator fin...
16
from devices.CameraVIS import VISCameraController
cfc9d09c   Jeremy   Added dome simula...
17
from devices.Dome import DomeController
65149de7   Jeremy   Update
18
from devices.PLC import PLCController
ce470283   Jeremy   Plc simulator fin...
19
20
from devices.Telescope import TelescopeController
from majordome.MajordomeDecorators import *
65149de7   Jeremy   Update
21
from utils.JDManipulator import *
cfc9d09c   Jeremy   Added dome simula...
22

ff448d43   Jeremy   Update
23
DEBUG_FILE = False
65149de7   Jeremy   Update
24
log = L.setupLogger("MajordomeTaskLogger", "Majordome")
5b5566ab   haribo   added celery
25

65149de7   Jeremy   Update
26
'''
05038bc8   Jeremy   Majordome logic i...
27
    Task to handle the execution of the program
65149de7   Jeremy   Update
28

4cb0ff36   Jeremy   Update
29
    check the environment status in database
05038bc8   Jeremy   Majordome logic i...
30
31
32
    check the devices status (telescope / cameras)
    check if the last schedule made has to be planned
    launch schedule's sequences
65149de7   Jeremy   Update
33
34
35
36
'''
class Majordome(Task):
    loop_speed = 1
    julian_div = 86400
05038bc8   Jeremy   Majordome logic i...
37
38
39
40
41
    executing_sequence = None
    next_sequence = None
    status_tel = ""
    status_nir = ""
    status_vis = ""
cfc9d09c   Jeremy   Added dome simula...
42
    status_dom = ""
ce470283   Jeremy   Plc simulator fin...
43
44
    site_status = "OK"
    weather_status = "OK"
ef60c3ec   Jeremy   Majordome and mon...
45
46
47
    timers = {}
    functions = {}
    schedule = None
c53a13e0   Jeremy   Updating a lot of...
48
    available_status = []
ce470283   Jeremy   Plc simulator fin...
49
    current_status = "RUNNING"
678838ed   Jeremy   Weather ans insid...
50
    alarm_list = []
65149de7   Jeremy   Update
51

e8e6f017   Jeremy   Reworked devices ...
52
53
54
55
56
57
58
59
    '''
        Check if the instrument status is valid
    '''
    def isValidStatus(self, status):
        # TODO REMOVE COMMENT AND CHANGE WHEN DEFINED
        # if (status == "" or status == "ERROR" or status == "FAILED" or status == "NOT_SET"):
        #     return (False)
        return (True)
65149de7   Jeremy   Update
60
61
62
63
64
65

    def setContext(self):
        self.tel = TelescopeController()
        self.vis_camera = VISCameraController()
        self.nir_camera = NIRCameraController()
        self.plc = PLCController()
cfc9d09c   Jeremy   Added dome simula...
66
        self.dom = DomeController()
65149de7   Jeremy   Update
67
        return (0)
65149de7   Jeremy   Update
68

c72eb17a   Jeremy   Update celery task
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
    def createTask(self):
        try:
            TaskId.objects.find(task="majordome").delete()
        except Exception as e:
            log.info(str(e))
            return 1
        TaskId.objects.create(task_id=self.request.id, task="majordome")
        return 0

    def setTasks(self):
        try:
            self.monitoring_task = TaskId.objects.get(task="monitoring")
            self.alert_task = TaskId.objects.get(task="alert_manager")
        except Exception as e:
            self.monitoring_task = None
            self.alert_task = None
        return 0

65149de7   Jeremy   Update
87
88
89
90
91
92
93
94
95
    '''
        Function called by celery task
        Behavior:
            Init telescope / cameras
            set night limits
            check the software version
            launch the majordome loop
    '''
    def run(self):
c72eb17a   Jeremy   Update celery task
96
        self.createTask()
65149de7   Jeremy   Update
97
        self.updateSoftware()
65149de7   Jeremy   Update
98
        self.setContext()
4cb0ff36   Jeremy   Update
99
        self.setTime()
c72eb17a   Jeremy   Update celery task
100
        self.setTasks()
65149de7   Jeremy   Update
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
        self.loop()

    '''
        Reads the softwares versions in the settings.py, store them in the DB and send them to the IC.
    '''
    def updateSoftware(self):
        versions = settings.MODULES_VERSIONS
        for module, version in versions.items():
            same_module_versions = Version.objects.filter(module_name=module)
            if same_module_versions.count() == 0:
                Version.objects.create(module_name=module, version=version)
            elif same_module_versions.order_by("-created")[0].version != version:
                Version.objects.create(module_name=module, version=version)
        return (0)

    '''
ce470283   Jeremy   Plc simulator fin...
117
        Loop to wait for the device to be idle with the starting configurations.
65149de7   Jeremy   Update
118
119
    '''
    def waitDevices(self):
ce470283   Jeremy   Plc simulator fin...
120
121
122
123
124
        while self.status_vis == "" and self.status_tel == "" and self.status_nir == "" and self.status_dom == "":
            self.status_vis = self.vis_camera.getStatus()
            self.status_nir = self.nir_camera.getStatus()
            self.status_tel = self.tel.getStatus()
            self.status_dom = self.dom.getStatus()
65149de7   Jeremy   Update
125
126
127
128
        return (0)

    '''
        Computes the beginning and the end of the following (or current) night
257abe9b   Jeremy   Added comments
129
        set the timers -> maybe put timers in a config file ?
65149de7   Jeremy   Update
130
131
132
133
134
135
    '''
    def setTime(self):
        self.night_start = getNightStart()
        self.night_end = getNightEnd()
        self.night_start_jd = secondsToJulianDate(getNightStart())
        self.night_end_jd = secondsToJulianDate(getNightEnd())
ef60c3ec   Jeremy   Majordome and mon...
136
137
        self.timer_night_start = self.night_start - getCurrentTime()
        self.timer_night_end = self.night_end - getCurrentTime()
65149de7   Jeremy   Update
138
        self.timer_status = 5
c72eb17a   Jeremy   Update celery task
139
        self.tasks_timer = 5
65149de7   Jeremy   Update
140
        self.timer_plc = 2
1aed430d   jeremy   Alert handled + k...
141
        self.alert_timer = 1
65149de7   Jeremy   Update
142
        self.timer_schedule = 1
05038bc8   Jeremy   Majordome logic i...
143
        self.timer_sequence = 1
65149de7   Jeremy   Update
144
145
146
147

        if (self.night_start - 120 > getCurrentTime()):
            self.timer_night_start = self.night_start - 120 - getCurrentTime()
        self.timer_night_end = self.night_end - getCurrentTime()
4cb0ff36   Jeremy   Update
148
149
        if (getCurrentTime() > self.night_start):
            self.adaptTimers()
65149de7   Jeremy   Update
150
151

        self.timers = {
4cb0ff36   Jeremy   Update
152
153
154
155
156
            "status": self.timer_status,
            "environment": self.timer_plc,
            "night_start": self.timer_night_start,
            "night_end": self.timer_night_end,
            "schedule": self.timer_schedule,
c72eb17a   Jeremy   Update celery task
157
158
            "sequence": self.timer_sequence,
            "tasks": self.tasks_timer
4cb0ff36   Jeremy   Update
159
        }
ff448d43   Jeremy   Update
160
        if (settings.DEBUG and DEBUG_FILE):
e8e6f017   Jeremy   Reworked devices ...
161
162
            log.info("Majordome started with timers : " + str(self.timers))
        # Functions called during the loop
4cb0ff36   Jeremy   Update
163
164
165
166
167
168
        self.functions = {
            "status": self.handleStatusTimer,
            "environment": self.handleEnvironmentTimer,
            "night_start": self.handleNightStartTimer,
            "night_end": self.handleNightEndTimer,
            "schedule": self.handleScheduleTimer,
c72eb17a   Jeremy   Update celery task
169
170
            "sequence": self.handleSequenceTimer,
            "tasks": self.handleTasks
65149de7   Jeremy   Update
171
        }
65149de7   Jeremy   Update
172
173
        return (0)

257abe9b   Jeremy   Added comments
174
175
176
    '''
        Function called by the main loop to handle the task event (check monitoring and alert_manager)
    '''
c72eb17a   Jeremy   Update celery task
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
    def handleTasks(self):
        self.timers["tasks"] = self.tasks_timer
        if self.monitoring_task is None:
            try:
                self.monitoring_task = TaskId.objects.get(task="monitoring")
            except Exception as e:
                monitoring.tasks.Monitoring.apply_async()
                if settings.DEBUG and DEBUG_FILE:
                    log.info(str(e))
        if self.alert_task is None:
            try:
                self.alert_task = TaskId.objects.get(task="alert_manager")
            except Exception as e:
                alert_manager.tasks.AlertListener.apply_async()
                if settings.DEBUG and DEBUG_FILE:
                    log.info(str(e))
        return 0

    # TODO adapt timers if the majordome is started during the night or not ?
4cb0ff36   Jeremy   Update
196
197
198
    def adaptTimers(self):
        pass

bca9a283   Jeremy   Reworked the sche...
199
200
201
    def logDB(self, message: str):
        Log.objects.create(agent="Majordome", message=message)

65149de7   Jeremy   Update
202
203
    '''
        Infinite loop according to the majordome behavior
65149de7   Jeremy   Update
204
205
    '''
    def loop(self):
c53a13e0   Jeremy   Updating a lot of...
206
        while (self.current_status != "SHUTDOWN"):
65149de7   Jeremy   Update
207
208
209
210
            minimal_timer = min(self.timers, key=self.timers.get)
            if (self.timers[minimal_timer] > 0):
                time.sleep(self.timers[minimal_timer])
                self.timers = {key: value - self.timers[minimal_timer] for key, value in self.timers.items()}
65149de7   Jeremy   Update
211
212
            for timer_name, timer_value in self.timers.items():
                if (timer_value <= 0):
4cb0ff36   Jeremy   Update
213
                    if timer_name in self.functions:
bca9a283   Jeremy   Reworked the sche...
214
                        self.logDB("Executing timer " + str(timer_name))
4cb0ff36   Jeremy   Update
215
                        self.functions[timer_name]()
65149de7   Jeremy   Update
216
                    else:
ff448d43   Jeremy   Update
217
                        if (settings.DEBUG and DEBUG_FILE):
4cb0ff36   Jeremy   Update
218
                            log.info("Timer : " + str(timer_name) + "is not known by the Majordome")
bca9a283   Jeremy   Reworked the sche...
219
                        self.logDB("Timer " + str(timer_name) + " unknown")
ff448d43   Jeremy   Update
220
                    if (settings.DEBUG and DEBUG_FILE):
e8e6f017   Jeremy   Reworked devices ...
221
                        log.info("Timer : " + str(timer_name) + " executed")
05038bc8   Jeremy   Majordome logic i...
222
223
        return (0)

257abe9b   Jeremy   Added comments
224
225
226
    '''
        Function called by the main loop to handle environment event (PLC info)
    '''
4cb0ff36   Jeremy   Update
227
228
    def handleEnvironmentTimer(self):
        self.timers["environment"] = self.timer_plc
ce470283   Jeremy   Plc simulator fin...
229
        self.handlePLC()
4cb0ff36   Jeremy   Update
230
231
        return (0)

257abe9b   Jeremy   Added comments
232
233
234
    '''
        Function called by the main loop to handle the devices status
    '''
4cb0ff36   Jeremy   Update
235
236
    def handleStatusTimer(self):
        self.timers["status"] = self.timer_status
ce470283   Jeremy   Plc simulator fin...
237
238
239
240
        self.status_tel = self.tel.getStatus()
        self.status_nir = self.nir_camera.getStatus()
        self.status_vis = self.vis_camera.getStatus()
        self.status_dom = self.dom.getStatus()
4cb0ff36   Jeremy   Update
241
        self.handleStatus()
c72eb17a   Jeremy   Update celery task
242
        return 0
4cb0ff36   Jeremy   Update
243

257abe9b   Jeremy   Added comments
244
245
246
    '''
        Function called by the main loop to check if the executing sequence is finished
    '''
4cb0ff36   Jeremy   Update
247
248
    def handleSequenceTimer(self):
        self.timers["sequence"] = self.timer_sequence
ff448d43   Jeremy   Update
249
250
251
        if (self.executing_sequence):
            self.handleSequence(self.executing_sequence[0],
                                self.executing_sequence[1], self.executing_sequence[2])
4cb0ff36   Jeremy   Update
252
253
        return (0)

257abe9b   Jeremy   Added comments
254
255
256
    '''
        Function called by the main loop to check if there is a new schedule and to execute its sequences
    '''
4cb0ff36   Jeremy   Update
257
    def handleScheduleTimer(self):
ef60c3ec   Jeremy   Majordome and mon...
258
        self.timers["schedule"] = self.timer_schedule
4cb0ff36   Jeremy   Update
259
        if (self.isValidStatus(self.status_tel)):
ff448d43   Jeremy   Update
260
            if (self.schedule is None):
ef60c3ec   Jeremy   Majordome and mon...
261
262
263
                try:
                    self.schedule = Schedule.objects.latest('created')
                except ObjectDoesNotExist:
ff448d43   Jeremy   Update
264
                    if (settings.DEBUG and DEBUG_FILE):
ef60c3ec   Jeremy   Majordome and mon...
265
266
                        log.info("No schedule found in database")
                    return (1)
4cb0ff36   Jeremy   Update
267
            else:
ef60c3ec   Jeremy   Majordome and mon...
268
269
270
                try:
                    schedule = Schedule.objects.latest('created')
                except ObjectDoesNotExist:
ff448d43   Jeremy   Update
271
                    if (settings.DEBUG and DEBUG_FILE):
ef60c3ec   Jeremy   Majordome and mon...
272
273
                        log.info("No schedule found in database")
                    return (1)
4cb0ff36   Jeremy   Update
274
275
276
                if (schedule.created != self.schedule.created):
                    self.next_sequence = None
                    self.schedule = schedule
1aed430d   jeremy   Alert handled + k...
277
                    self.firstSequenceIsAlert()
4cb0ff36   Jeremy   Update
278
            if (self.schedule):
c53a13e0   Jeremy   Updating a lot of...
279
280
                shs_list = self.schedule.shs.filter(Q(status=Sequence.PLANNED) |
                                                    Q(status=Sequence.PENDING)).order_by('tsp')
4cb0ff36   Jeremy   Update
281
282
283
284
285
                self.executeSchedule(shs_list)
        else:
            self.notifyTelescopeStatus("scheduler")
        return (0)

257abe9b   Jeremy   Added comments
286
    '''
1aed430d   jeremy   Alert handled + k...
287
288
289
290
291
292
293
294
295
296
297
298
299
300
        Function called by handleScheduleTimer, the purpose is to kill the executing sequence if the
        first sequence in the new planning is from an alert
    '''
    @executingSequenceExist
    def firstSequenceIsAlert(self):
        shs_list = self.schedule.shs.filter(Q(status=Sequence.PLANNED) |
                                            Q(status=Sequence.PENDING)).order_by('tsp')
        if shs_list and shs_list[0].sequence.is_alert:
            if shs_list[0].sequence.created.date() >= (datetime.datetime.now() - datetime.timedelta(seconds=10)).date():
                self.killExecutingSequence()
                return 1
        return 0

    '''
257abe9b   Jeremy   Added comments
301
302
        Function called by the main loop to handle the end of a night
    '''
4cb0ff36   Jeremy   Update
303
    def handleNightEndTimer(self):
ce470283   Jeremy   Plc simulator fin...
304
        self.timers["night_end"] = getNightEnd()
4cb0ff36   Jeremy   Update
305
        if (self.isValidStatus(self.status_tel)):
c72eb17a   Jeremy   Update celery task
306
            observation_manager.tasks.night_calibrations.apply_async()
4cb0ff36   Jeremy   Update
307
308
309
310
        else:
            self.notifyTelescopeStatus("night_end")
        return (0)

257abe9b   Jeremy   Added comments
311
    '''
ed1bf194   Etienne Pallier   bugfix task major...
312
        Function called by the main loop to handle the beginning of a night
257abe9b   Jeremy   Added comments
313
    '''
4cb0ff36   Jeremy   Update
314
315
    def handleNightStartTimer(self):
        self.timers["night_start"] = getNextNightStart()
c72eb17a   Jeremy   Update celery task
316
317
318
319
        if self.isOutsideOk():
            self.dom.open()
            self.vis_camera.open_shutter()
            self.nir_camera.open_shutter()
ce470283   Jeremy   Plc simulator fin...
320
        scheduler.tasks.scheduling.apply_async((False, False))
4cb0ff36   Jeremy   Update
321
322
        return (0)

ef60c3ec   Jeremy   Majordome and mon...
323
324
325
    def notifyTelescopeStatus(self, timer_name):
        return (self.notifyDeviceStatus("telescope", timer_name, self.status_tel))

05038bc8   Jeremy   Majordome logic i...
326
    def notifyDeviceStatus(self, device_name, timer_name, status):
ef60c3ec   Jeremy   Majordome and mon...
327
328
        Log.objects.create(agent=device_name, created=datetime.datetime.now(),
                           message="The action : " + str(timer_name) + " has been canceled : Telescope status : " + str(status))
ce470283   Jeremy   Plc simulator fin...
329
        # TODO MAYBE reset some variables and do a scheduling
65149de7   Jeremy   Update
330
331
332
        return (0)

    '''
257abe9b   Jeremy   Added comments
333
        Execute a schedule
65149de7   Jeremy   Update
334
335
    '''
    def executeSchedule(self, shs_list):
c72eb17a   Jeremy   Update celery task
336
        for shs in shs_list:  # shs_list is sorted by tsp
c53a13e0   Jeremy   Updating a lot of...
337
338
339
            if (self.executableSequence(shs.sequence.status) and self.observable(shs.sequence)):
                if self.next_sequence is None:
                    self.setNextSequence(shs, shs.sequence)
678838ed   Jeremy   Weather ans insid...
340
                if self.isExecutable() and self.executing_sequence is None:
c53a13e0   Jeremy   Updating a lot of...
341
342
343
344
345
                    if self.isValidTimer(self.next_sequence[0]):
                        if self.executeSequence(self.next_sequence[0], self.next_sequence[1]) == -1:
                            return -1
                        if self.next_sequence[0] != shs and self.next_sequence[1] != shs.sequence:
                            self.setNextSequence(shs, shs.sequence)
ff448d43   Jeremy   Update
346
                        else:
c53a13e0   Jeremy   Updating a lot of...
347
                            self.next_sequence = None
ff448d43   Jeremy   Update
348
349
                    else:
                        return 0
bca9a283   Jeremy   Reworked the sche...
350
            else:
ff448d43   Jeremy   Update
351
                if (settings.DEBUG and DEBUG_FILE):
bca9a283   Jeremy   Reworked the sche...
352
                    log.info("Sequence cannot be executed : Not observable")
ff448d43   Jeremy   Update
353
354
                self.logDB("Sequence "+shs.sequence.name+" cannot be executed : Not observable")
        return 0
05038bc8   Jeremy   Majordome logic i...
355

4cb0ff36   Jeremy   Update
356
    def observable(self, sequence):
ff448d43   Jeremy   Update
357
358
359
        if (sequence.jd2 - sequence.duration - secondsToPreciseJulianDate(getPreciseCurrentTime()) <= 0):
            return 0
        return 1
4cb0ff36   Jeremy   Update
360

c53a13e0   Jeremy   Updating a lot of...
361
362
363
364
365
    def executableSequence(self, status):
        if status == Sequence.PLANNED or status == Sequence.PENDING:
            return 1
        return 0

257abe9b   Jeremy   Added comments
366
367
368
    '''
        Kill the executing sequence and set its state to cancelled
    '''
678838ed   Jeremy   Weather ans insid...
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
    @executingSequenceExist
    def killExecutingSequence(self):
        shs = self.executing_sequence[0]
        sequence = self.executing_sequence[1]
        executing_plans = self.executing_sequence[2]

        shs.status = Sequence.CANCELLED
        sequence.status = Sequence.CANCELLED
        shs.save()
        sequence.save()
        for rev in executing_plans:
            if (not rev.failed() and not rev.successful()):
                rev.revoke(terminate=True)
        self.executing_sequence = None
        return 0

    def reset(self, type):
        if type == "WEATHER":
            self.dom.open()
c72eb17a   Jeremy   Update celery task
388
            scheduler.tasks.scheduling.delay((False, False))
678838ed   Jeremy   Weather ans insid...
389
        elif type == "INSIDE":
c72eb17a   Jeremy   Update celery task
390
            scheduler.tasks.scheduling.delay((False, False))
678838ed   Jeremy   Weather ans insid...
391

257abe9b   Jeremy   Added comments
392
393
394
    '''
        Handle a new alarm (called by isInsideOk or isWeatherOk)
    '''
678838ed   Jeremy   Weather ans insid...
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
    @SameAlarmCheck
    def handleAlarm(self, type, pos=-1):
        if type == "WEATHER":
            #TODO send email
            self.dom.close()
            self.killExecutingSequence()
            self.vis_camera.park()
            self.nir_camera.park()
        elif type == "INSIDE":
            #TODO send email
            self.killExecutingSequence()
            self.vis_camera.park()
            self.nir_camera.park()
        elif type == "ENDED":
            if len(self.alarm_list) > 0 and pos != -1:
                ended = self.alarm_list[pos]
                del self.alarm_list[pos]
                self.reset(ended)
            return 0
        else:
            return 1
        self.alarm_list.append(type)
        return 0

    '''
        for now weather_status and site_status contains something different than OK if the status is critical
        Later we may have other states to handle
    '''
ce470283   Jeremy   Plc simulator fin...
423
424
425
    def isOutsideOk(self) -> bool:
        self.handlePLC()
        if self.weather_status == "OK":
678838ed   Jeremy   Weather ans insid...
426
427
            if "WEATHER" in self.alarm_list:
                self.handleAlarm("ENDED", self.alarm_list.index("WEATHER"))
ce470283   Jeremy   Plc simulator fin...
428
            return True
678838ed   Jeremy   Weather ans insid...
429
        self.handleAlarm("WEATHER")
ce470283   Jeremy   Plc simulator fin...
430
431
        return False

257abe9b   Jeremy   Added comments
432
433
434
    '''
        Check the telescope inside status
    '''
ce470283   Jeremy   Plc simulator fin...
435
436
437
    def isInsideOk(self) -> bool:
        self.handlePLC()
        if self.site_status == "OK":
678838ed   Jeremy   Weather ans insid...
438
439
            if "INSIDE" in self.alarm_list:
                self.handleAlarm("ENDED", self.alarm_list.index("INSIDE"))
ce470283   Jeremy   Plc simulator fin...
440
            return True
678838ed   Jeremy   Weather ans insid...
441
        self.handleAlarm("INSIDE")
ce470283   Jeremy   Plc simulator fin...
442
443
444
445
446
447
448
449
450
451
452
453
454
455
        return False

    def isDevicesOk(self) -> bool:
        if self.isValidStatus(self.status_tel) and self.isValidStatus(self.status_dom)\
            and self.isValidStatus(self.status_vis) and self.isValidStatus(self.status_nir):
            return True
        return False

    def isExecutable(self) -> bool:
        if self.isValidStatus(self.status_tel) and self.isValidStatus(self.status_dom)\
                and self.isOutsideOk() and self.isInsideOk():
            return True
        return False

257abe9b   Jeremy   Added comments
456
457
458
    '''
        check if the sequence timer is valid for execution, also check if there is a scheduling task running
    '''
ce470283   Jeremy   Plc simulator fin...
459
    def isValidTimer(self, shs) -> bool:
c53a13e0   Jeremy   Updating a lot of...
460
461
        current_countdown = self.getCountdown(shs)
        if (current_countdown <= JulianSeconds(5)):
c53a13e0   Jeremy   Updating a lot of...
462
463
464
            try:
                task = TaskId.objects.filter(task="scheduling")
                if not task:
ce470283   Jeremy   Plc simulator fin...
465
466
                    return True
                return False
c53a13e0   Jeremy   Updating a lot of...
467
            except:
ce470283   Jeremy   Plc simulator fin...
468
469
                return True
        return False
c53a13e0   Jeremy   Updating a lot of...
470

05038bc8   Jeremy   Majordome logic i...
471
    '''
257abe9b   Jeremy   Added comments
472
        Launch the observation tasks NIR and VIS associated to a sequence
05038bc8   Jeremy   Majordome logic i...
473
    '''
c53a13e0   Jeremy   Updating a lot of...
474
    def executeSequence(self, shs, sequence):
3224f14a   Jeremy   Fixed some simula...
475
476
477
478
        shs.status = Sequence.EXECUTING
        sequence.status = Sequence.EXECUTING
        shs.save()
        sequence.save()
c53a13e0   Jeremy   Updating a lot of...
479
        log.info("Executing sequence id = " + str(sequence.pk))
bca9a283   Jeremy   Reworked the sche...
480
        self.logDB("Executing sequence")
05038bc8   Jeremy   Majordome logic i...
481
        plans_results = []
05038bc8   Jeremy   Majordome logic i...
482
483
484
        if sequence.albums.filter(detector__name="Cagire").exists():
            if (self.isValidStatus(self.status_nir)):
                for plan in sequence.albums.get(detector__name="Cagire").plans.all():
c53a13e0   Jeremy   Updating a lot of...
485
486
487
488
                    res = observation_manager.tasks.execute_plan_nir.apply_async(
                        (plan.id, float(self.getCountdown(shs))))
                    # JB TODO : is it still usefull ?
                    # TaskId.objects.create(task_id=res.id, task="execute_plan")
05038bc8   Jeremy   Majordome logic i...
489
                    plans_results.append(res)
ff448d43   Jeremy   Update
490
491
            else:
                self.notifyDeviceStatus("Cagire", "Sequence execution", self.status_nir)
c53a13e0   Jeremy   Updating a lot of...
492
493
494
                sequence.status = Sequence.CANCELLED
                shs.status = Sequence.CANCELLED
                shs.save()
ff448d43   Jeremy   Update
495
496
                sequence.save()
                return (1)
05038bc8   Jeremy   Majordome logic i...
497
498
499
        if sequence.albums.filter(detector__name="Visible camera").exists():
            if (self.isValidStatus(self.status_vis)):
                for plan in sequence.albums.get(detector__name="Visible camera").plans.all():
c53a13e0   Jeremy   Updating a lot of...
500
501
                    res = observation_manager.tasks.execute_plan_vis.apply_async(
                        (plan.id, float(self.getCountdown(shs))))
05038bc8   Jeremy   Majordome logic i...
502
503
504
                    plans_results.append(res)
            else:
                self.notifyDeviceStatus("Camera visible", "Sequence execution", self.status_vis)
c53a13e0   Jeremy   Updating a lot of...
505
506
507
                sequence.status = Sequence.CANCELLED
                shs.status = Sequence.CANCELLED
                shs.save()
05038bc8   Jeremy   Majordome logic i...
508
509
                sequence.save()
                return (1)
05038bc8   Jeremy   Majordome logic i...
510
        self.executing_sequence = [shs, sequence, plans_results]
05038bc8   Jeremy   Majordome logic i...
511
512
513
514
515
        return (0)

    '''
        Set the next sequence
    '''
c53a13e0   Jeremy   Updating a lot of...
516
    def setNextSequence(self, shs, sequence):
ff448d43   Jeremy   Update
517
        sequence.status = Sequence.PENDING
c53a13e0   Jeremy   Updating a lot of...
518
519
        shs.status = Sequence.PENDING
        self.next_sequence = [shs, sequence]
ff448d43   Jeremy   Update
520
        sequence.save()
c53a13e0   Jeremy   Updating a lot of...
521
        shs.save()
05038bc8   Jeremy   Majordome logic i...
522
523
524
525
526
527
        return (0)

    '''
        Check if the current sequence is finished
    '''
    def handleSequence(self, shs, sequence, executing_plans):
c53a13e0   Jeremy   Updating a lot of...
528
        count = 0
c53a13e0   Jeremy   Updating a lot of...
529
        for res in executing_plans:
05038bc8   Jeremy   Majordome logic i...
530
            try:
c53a13e0   Jeremy   Updating a lot of...
531
532
                if res.successful() or res.failed():
                    count += 1
05038bc8   Jeremy   Majordome logic i...
533
            except Exception as e:
678838ed   Jeremy   Weather ans insid...
534
535
                if DEBUG_FILE and settings.DEBUG:
                    log.info(str(e))
05038bc8   Jeremy   Majordome logic i...
536
537
538
539
540
                shs.status = Sequence.CANCELLED
                sequence.status = Sequence.CANCELLED
                shs.save()
                sequence.save()
                for rev in executing_plans:
c53a13e0   Jeremy   Updating a lot of...
541
542
543
                    if (not rev.failed() and not rev.successful()):
                        rev.revoke(terminate=True)
                self.executing_sequence = None
05038bc8   Jeremy   Majordome logic i...
544
                return (-1)
c53a13e0   Jeremy   Updating a lot of...
545
        if count >= len(executing_plans):
05038bc8   Jeremy   Majordome logic i...
546
547
548
549
550
            sequence.status = Sequence.EXECUTED
            shs.status = Sequence.EXECUTED
            sequence.save()
            shs.save()
            message = "Finished sequence " + str(sequence.pk) + " execution"
05038bc8   Jeremy   Majordome logic i...
551
            Log.objects.create(agent="Majordome", message=message)
c53a13e0   Jeremy   Updating a lot of...
552
            self.executing_sequence = None
05038bc8   Jeremy   Majordome logic i...
553
        return (0)
65149de7   Jeremy   Update
554
555
556
557

    '''
        Function called to do an action with the devices status
    '''
05038bc8   Jeremy   Majordome logic i...
558
    def handleStatus(self):
05038bc8   Jeremy   Majordome logic i...
559
560
561
        telescope = Telescope.objects.first()
        camera_nir = Detector.objects.get(name="Cagire")
        camera_vis = Detector.objects.get(name="Visible camera")
ce470283   Jeremy   Plc simulator fin...
562
563
564
        dome = Dome.objects.get(name="Dome")

        dome.status = self.status_dom
05038bc8   Jeremy   Majordome logic i...
565
566
567
        telescope.status = self.status_tel
        camera_nir.status = self.status_nir
        camera_vis.status = self.status_vis
ce470283   Jeremy   Plc simulator fin...
568
569
570
571
572

        dome.save()
        telescope.save()
        camera_nir.save()
        camera_vis.save()
bca9a283   Jeremy   Reworked the sche...
573
574
        self.logDB("Instrument status : dome  = " + str(self.status_dom) + ", telescope = " + str(self.status_tel)
                   + ", camera_nir = " + str(self.status_nir) + ", camera_vis" + str(self.status_vis))
65149de7   Jeremy   Update
575
576
577
        return (0)

    '''
3224f14a   Jeremy   Fixed some simula...
578
        Put the majordome in pause
4cb0ff36   Jeremy   Update
579
    '''
4cb0ff36   Jeremy   Update
580
    def systemPause(self, duration, cause: str):
bca9a283   Jeremy   Reworked the sche...
581
        self.logDB("System in pause for " + str(duration))
4cb0ff36   Jeremy   Update
582
        time.sleep(duration)
c72eb17a   Jeremy   Update celery task
583
        scheduler.tasks.scheduling.apply_async(first_schedule=False, alert=False)
4cb0ff36   Jeremy   Update
584
585
586
587
588
        self.setTime()
        print("system has been paused. Cause : " + cause)
        return (0)

    '''
65149de7   Jeremy   Update
589
590
        Function called to do an action with the site status and the wheather status
    '''
ce470283   Jeremy   Plc simulator fin...
591
592
593
594
595
596
597
598
599
600
601
    def handlePLC(self):
        try:
            site_status = SiteWatch.objects.latest('updated')
            weather_status = WeatherWatch.objects.latest('updated')
            self.weather_status = weather_status.global_status
            self.site_status = site_status.global_status
        except ObjectDoesNotExist as e:
            if (settings.DEBUG and DEBUG_FILE):
                log.info("No site_status or weather_status found in database : " + str(e))
            # TODO shutdown everything
            return 1
3224f14a   Jeremy   Fixed some simula...
602
        return 0
5b5566ab   haribo   added celery
603

4cb0ff36   Jeremy   Update
604
    '''
05038bc8   Jeremy   Majordome logic i...
605
        Gets the time before the expected start of the execution.
4cb0ff36   Jeremy   Update
606
    '''
05038bc8   Jeremy   Majordome logic i...
607
608
    def getCountdown(self, shs):
        # TODO start sequence as soon as possible (a lot of verifications must be done there)
ff448d43   Jeremy   Update
609
        current_time = secondsToPreciseJulianDate(getPreciseCurrentTime())
05038bc8   Jeremy   Majordome logic i...
610
        countdown = shs.tsp - current_time
9774228b   haribo   Date: 22/06/2016
611
        return countdown
7a79e25b   haribo   Date: 19/05/2016
612

4cb0ff36   Jeremy   Update
613
614
615
616
    '''
        Change observation conditions
    '''
    def changeObsConditions(self):
5b5566ab   haribo   added celery
617
        print("change_obs_conditions")
4cb0ff36   Jeremy   Update
618
        pass