Blame view

src/majordome/tasks.py 23 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
    def createTask(self):
        try:
1a2dc19f   Etienne Pallier   nombreux bugfixes...
71
72
73
            # (EP) NO find() method available from Django ORM !!!! 
            #TaskId.objects.find(task="majordome").delete()
            TaskId.objects.filter(task="majordome").delete()
c72eb17a   Jeremy   Update celery task
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
        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
89
90
91
92
93
94
95
96
97
    '''
        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
98
        self.createTask()
65149de7   Jeremy   Update
99
        self.updateSoftware()
65149de7   Jeremy   Update
100
        self.setContext()
4cb0ff36   Jeremy   Update
101
        self.setTime()
c72eb17a   Jeremy   Update celery task
102
        self.setTasks()
65149de7   Jeremy   Update
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
        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...
119
        Loop to wait for the device to be idle with the starting configurations.
65149de7   Jeremy   Update
120
121
    '''
    def waitDevices(self):
ce470283   Jeremy   Plc simulator fin...
122
123
124
125
126
        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
127
128
129
130
        return (0)

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

        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
150
151
        if (getCurrentTime() > self.night_start):
            self.adaptTimers()
65149de7   Jeremy   Update
152
153

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

257abe9b   Jeremy   Added comments
176
177
178
    '''
        Function called by the main loop to handle the task event (check monitoring and alert_manager)
    '''
c72eb17a   Jeremy   Update celery task
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
    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
198
199
200
    def adaptTimers(self):
        pass

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

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

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

257abe9b   Jeremy   Added comments
234
235
236
    '''
        Function called by the main loop to handle the devices status
    '''
4cb0ff36   Jeremy   Update
237
238
    def handleStatusTimer(self):
        self.timers["status"] = self.timer_status
ce470283   Jeremy   Plc simulator fin...
239
240
241
242
        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
243
        self.handleStatus()
c72eb17a   Jeremy   Update celery task
244
        return 0
4cb0ff36   Jeremy   Update
245

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

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

257abe9b   Jeremy   Added comments
288
    '''
1aed430d   jeremy   Alert handled + k...
289
290
291
292
293
294
295
296
297
298
299
300
301
302
        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
303
304
        Function called by the main loop to handle the end of a night
    '''
4cb0ff36   Jeremy   Update
305
    def handleNightEndTimer(self):
ce470283   Jeremy   Plc simulator fin...
306
        self.timers["night_end"] = getNightEnd()
4cb0ff36   Jeremy   Update
307
        if (self.isValidStatus(self.status_tel)):
c72eb17a   Jeremy   Update celery task
308
            observation_manager.tasks.night_calibrations.apply_async()
4cb0ff36   Jeremy   Update
309
310
311
312
        else:
            self.notifyTelescopeStatus("night_end")
        return (0)

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

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

05038bc8   Jeremy   Majordome logic i...
328
    def notifyDeviceStatus(self, device_name, timer_name, status):
ef60c3ec   Jeremy   Majordome and mon...
329
330
        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...
331
        # TODO MAYBE reset some variables and do a scheduling
65149de7   Jeremy   Update
332
333
334
        return (0)

    '''
257abe9b   Jeremy   Added comments
335
        Execute a schedule
65149de7   Jeremy   Update
336
337
    '''
    def executeSchedule(self, shs_list):
c72eb17a   Jeremy   Update celery task
338
        for shs in shs_list:  # shs_list is sorted by tsp
c53a13e0   Jeremy   Updating a lot of...
339
340
341
            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...
342
                if self.isExecutable() and self.executing_sequence is None:
c53a13e0   Jeremy   Updating a lot of...
343
344
345
346
347
                    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
348
                        else:
c53a13e0   Jeremy   Updating a lot of...
349
                            self.next_sequence = None
ff448d43   Jeremy   Update
350
351
                    else:
                        return 0
bca9a283   Jeremy   Reworked the sche...
352
            else:
ff448d43   Jeremy   Update
353
                if (settings.DEBUG and DEBUG_FILE):
bca9a283   Jeremy   Reworked the sche...
354
                    log.info("Sequence cannot be executed : Not observable")
ff448d43   Jeremy   Update
355
356
                self.logDB("Sequence "+shs.sequence.name+" cannot be executed : Not observable")
        return 0
05038bc8   Jeremy   Majordome logic i...
357

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

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

257abe9b   Jeremy   Added comments
368
369
370
    '''
        Kill the executing sequence and set its state to cancelled
    '''
678838ed   Jeremy   Weather ans insid...
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
    @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
390
            scheduler.tasks.scheduling.delay((False, False))
678838ed   Jeremy   Weather ans insid...
391
        elif type == "INSIDE":
c72eb17a   Jeremy   Update celery task
392
            scheduler.tasks.scheduling.delay((False, False))
678838ed   Jeremy   Weather ans insid...
393

257abe9b   Jeremy   Added comments
394
395
396
    '''
        Handle a new alarm (called by isInsideOk or isWeatherOk)
    '''
678838ed   Jeremy   Weather ans insid...
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
423
424
    @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...
425
426
427
    def isOutsideOk(self) -> bool:
        self.handlePLC()
        if self.weather_status == "OK":
678838ed   Jeremy   Weather ans insid...
428
429
            if "WEATHER" in self.alarm_list:
                self.handleAlarm("ENDED", self.alarm_list.index("WEATHER"))
ce470283   Jeremy   Plc simulator fin...
430
            return True
678838ed   Jeremy   Weather ans insid...
431
        self.handleAlarm("WEATHER")
ce470283   Jeremy   Plc simulator fin...
432
433
        return False

257abe9b   Jeremy   Added comments
434
435
436
    '''
        Check the telescope inside status
    '''
ce470283   Jeremy   Plc simulator fin...
437
438
439
    def isInsideOk(self) -> bool:
        self.handlePLC()
        if self.site_status == "OK":
678838ed   Jeremy   Weather ans insid...
440
441
            if "INSIDE" in self.alarm_list:
                self.handleAlarm("ENDED", self.alarm_list.index("INSIDE"))
ce470283   Jeremy   Plc simulator fin...
442
            return True
678838ed   Jeremy   Weather ans insid...
443
        self.handleAlarm("INSIDE")
ce470283   Jeremy   Plc simulator fin...
444
445
446
447
448
449
450
451
452
453
454
455
456
457
        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
458
459
460
    '''
        check if the sequence timer is valid for execution, also check if there is a scheduling task running
    '''
ce470283   Jeremy   Plc simulator fin...
461
    def isValidTimer(self, shs) -> bool:
c53a13e0   Jeremy   Updating a lot of...
462
463
        current_countdown = self.getCountdown(shs)
        if (current_countdown <= JulianSeconds(5)):
c53a13e0   Jeremy   Updating a lot of...
464
465
466
            try:
                task = TaskId.objects.filter(task="scheduling")
                if not task:
ce470283   Jeremy   Plc simulator fin...
467
468
                    return True
                return False
c53a13e0   Jeremy   Updating a lot of...
469
            except:
ce470283   Jeremy   Plc simulator fin...
470
471
                return True
        return False
c53a13e0   Jeremy   Updating a lot of...
472

05038bc8   Jeremy   Majordome logic i...
473
    '''
257abe9b   Jeremy   Added comments
474
        Launch the observation tasks NIR and VIS associated to a sequence
05038bc8   Jeremy   Majordome logic i...
475
    '''
c53a13e0   Jeremy   Updating a lot of...
476
    def executeSequence(self, shs, sequence):
3224f14a   Jeremy   Fixed some simula...
477
478
479
480
        shs.status = Sequence.EXECUTING
        sequence.status = Sequence.EXECUTING
        shs.save()
        sequence.save()
c53a13e0   Jeremy   Updating a lot of...
481
        log.info("Executing sequence id = " + str(sequence.pk))
bca9a283   Jeremy   Reworked the sche...
482
        self.logDB("Executing sequence")
05038bc8   Jeremy   Majordome logic i...
483
        plans_results = []
05038bc8   Jeremy   Majordome logic i...
484
485
486
        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...
487
488
489
490
                    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...
491
                    plans_results.append(res)
ff448d43   Jeremy   Update
492
493
            else:
                self.notifyDeviceStatus("Cagire", "Sequence execution", self.status_nir)
c53a13e0   Jeremy   Updating a lot of...
494
495
496
                sequence.status = Sequence.CANCELLED
                shs.status = Sequence.CANCELLED
                shs.save()
ff448d43   Jeremy   Update
497
498
                sequence.save()
                return (1)
05038bc8   Jeremy   Majordome logic i...
499
500
501
        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...
502
503
                    res = observation_manager.tasks.execute_plan_vis.apply_async(
                        (plan.id, float(self.getCountdown(shs))))
05038bc8   Jeremy   Majordome logic i...
504
505
506
                    plans_results.append(res)
            else:
                self.notifyDeviceStatus("Camera visible", "Sequence execution", self.status_vis)
c53a13e0   Jeremy   Updating a lot of...
507
508
509
                sequence.status = Sequence.CANCELLED
                shs.status = Sequence.CANCELLED
                shs.save()
05038bc8   Jeremy   Majordome logic i...
510
511
                sequence.save()
                return (1)
05038bc8   Jeremy   Majordome logic i...
512
        self.executing_sequence = [shs, sequence, plans_results]
05038bc8   Jeremy   Majordome logic i...
513
514
515
516
517
        return (0)

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

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

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

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

        dome.save()
        telescope.save()
        camera_nir.save()
        camera_vis.save()
bca9a283   Jeremy   Reworked the sche...
575
576
        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
577
578
579
        return (0)

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

    '''
65149de7   Jeremy   Update
591
592
        Function called to do an action with the site status and the wheather status
    '''
ce470283   Jeremy   Plc simulator fin...
593
594
595
596
597
598
599
600
601
602
603
    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...
604
        return 0
5b5566ab   haribo   added celery
605

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

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