Blame view

src/majordome/tasks.py 35.7 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 *
6aec6155   theopuhl   Majordome algorit...
15
16
17
from dashboard.views import get_sunelev
from devices.TelescopeRemoteControlDefault import TelescopeRemoteControlDefault
from django.shortcuts import get_object_or_404
65149de7   Jeremy   Update
18
from devices.CameraNIR import NIRCameraController
ce470283   Jeremy   Plc simulator fin...
19
from devices.CameraVIS import VISCameraController
cfc9d09c   Jeremy   Added dome simula...
20
from devices.Dome import DomeController
65149de7   Jeremy   Update
21
from devices.PLC import PLCController
ce470283   Jeremy   Plc simulator fin...
22
23
from devices.Telescope import TelescopeController
from majordome.MajordomeDecorators import *
65149de7   Jeremy   Update
24
from utils.JDManipulator import *
6aec6155   theopuhl   Majordome algorit...
25
import time
cfc9d09c   Jeremy   Added dome simula...
26

ff448d43   Jeremy   Update
27
DEBUG_FILE = False
65149de7   Jeremy   Update
28
log = L.setupLogger("MajordomeTaskLogger", "Majordome")
5b5566ab   haribo   added celery
29

65149de7   Jeremy   Update
30
'''
05038bc8   Jeremy   Majordome logic i...
31
    Task to handle the execution of the program
65149de7   Jeremy   Update
32

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

    # New variables from TP:
d0b663be   Etienne Pallier   refactorized majo...
57
    
6aec6155   theopuhl   Majordome algorit...
58
    config = None
468a79dc   Etienne Pallier   added comments
59
    plc_status = None
6aec6155   theopuhl   Majordome algorit...
60
    current_state = "Passive"
d0b663be   Etienne Pallier   refactorized majo...
61
62
63
64
    
    # OCS-RESTART, OCS-SHUTDOWN, or NONE (default)
    closing_mode = "NONE"
    
6aec6155   theopuhl   Majordome algorit...
65
    '''
0997e1c3   Etienne Pallier   moved main run() ...
66
67
68
69
70
71
72
73
74
75
        OLD //// Function called by celery task
        Behavior:
            Init telescope / cameras
            set night limits
            check the software version
            launch the majordome loop ///// OLD

        Main loop of Majordome
        startup everything if needed
        Loop over Majordome state
d0b663be   Etienne Pallier   refactorized majo...
76
        Change behavior with the pyros states
0997e1c3   Etienne Pallier   moved main run() ...
77
78
79
80
81
82
83
84
85
86
87
        Take suitable decision thanks to states in database
    '''
    def run(self):
        #self.createTask()
        #self.updateSoftware()
        #self.setContext()
        #self.setTime()                     /// OLD Majordome
        #self.setTasks()
        #self.loop()


d0b663be   Etienne Pallier   refactorized majo...
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
        RESTART = True
        while RESTART:
            
            # SETUP
            try : 
                self.config = get_object_or_404(Config, id=1)
            except Config.ObjectDoesNotExist:
                return -1
            
            self.config.ntc = False
            
            # Set STATE to STARTING
            self.changeState("STARTING")
            
            '''
            if not self.config.majordome_restarted:
                #in order to start other agents etc....
                self.setup()
            
            # Set STATE to PASSIVE (NO PLC)
            self.changeState("Passive No PLC")
            print("Waiting for PLC connection")
            # Wait until PCL is connected
            while not self.plc_is_connected():                  
                pass           
            print("PLC is connected")
                    
            # Set STATE to PASSIVE (with PLC)
            self.changeState("Passive")
            self.config.majordome_state = "RUNNING"
    
            # MAIN LOOP: iterate on current state
            #while self.plc_is_connected() != False and self.closing_mode == "RUNNING" :          
            while self.plc_is_connected() and not self.is_closing_or_restarting():          
                # Call behavior for the current state and set new current state (can stay the same if no state change)
                #self.behavior[self.current_state](self)
                self.current_state = self.behavior[self.current_state](self)
                time.sleep(2)
            '''              
            while True:
                if self.is_closing_or_restarting(): break
                if self.current_state not in ['STARTING', 'PASSIVE_NO_PLC']:
                    if not self.plc_is_connected():
                        self.changeState("PASSIVE")        
                self.current_state = self.do_behavior_for_state(self.current_state)
                             
                      
            # EXIT      
            # Shutdown options change by the main program
            if self.closing_mode == "OCS-SHUTDOWN":          
                #self.closeBehaviour(self)
                self.behavior_closing()
                #TODO: self.kill_all_agents()
                RESTART = False
            
            elif self.closing_mode == "OCS-RESTART":
                self.config.majordome_restarted = True
                self.config.save()
                #TODO: self.kill_all_agents()
                self.send_alarm_if_not_closed()
                #self.run()
    
            #TODO: rester dans la main loop ???
            #elif self.closing_mode == "RUNNING" and self.plc_is_connected() == False:
            elif not self.plc_is_connected():
                #self.config.majordome_restarted = True
                #self.config.save()
                self.changeState("Passive No PLC")
                self.send_alarm_if_not_closed()
                #self.run()
0997e1c3   Etienne Pallier   moved main run() ...
158
 
d0b663be   Etienne Pallier   refactorized majo...
159
160
161
162
 
    def is_closing_or_restarting(self):
        return self.closing_mode != "NONE"
    
0997e1c3   Etienne Pallier   moved main run() ...
163
164

    '''
6aec6155   theopuhl   Majordome algorit...
165
166
167
        Function called to change and save current state of pyros.
    '''
    def changeState(self, state):
468a79dc   Etienne Pallier   added comments
168
        # (local variable) idem self.config.pyros_state
6aec6155   theopuhl   Majordome algorit...
169
        self.current_state = state
468a79dc   Etienne Pallier   added comments
170
171

        # (in DB) PASSIVE, STANDBY, REMOTE, OPERATING
6aec6155   theopuhl   Majordome algorit...
172
173
        self.config.pyros_state = state
        self.config.save()
d0b663be   Etienne Pallier   refactorized majo...
174
175
        
        
6aec6155   theopuhl   Majordome algorit...
176
    '''
d0b663be   Etienne Pallier   refactorized majo...
177
178
        Each function with behavior describes the behavior of a state,
        they are all contained in a dictionary called in run()
6aec6155   theopuhl   Majordome algorit...
179
    '''
d0b663be   Etienne Pallier   refactorized majo...
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
    def behavior_starting(self):
        #print("STARTING")
        #if self.is_closing_or_restarting(): return
        if not self.config.majordome_restarted:
            #TODO: Do setup things... (start agents...)
            time.sleep(2)
        '''
        Cette variable sert à indiquer l'état du majordome dans la DB.
        Elle va aussi être changée par le panneau Simulator pour passer à l'état SHUTDOWN ou RESTART.
        Elle est récupérée à chaque itération par la fonction plcConnection()
        '''
        self.config.majordome_state = "RUNNING"
        #self.config.majordome_state = "NONE"

        self.changeState("PASSIVE_NO_PLC")
        #return self.current_state

    def behavior_passive_no_plc(self):
        #print("PASSIVE_NO_PLC")
        #if self.is_closing_or_restarting(): return
        #self.changeState("Passive No PLC")
        print("Waiting for PLC connection")
        # Wait until PCL is connected
        while not self.plc_is_connected():
            if self.is_closing_or_restarting(): return
        print("PLC is connected")
        # Set STATE to PASSIVE (with PLC)
        self.changeState("Passive")
        #return self.current_state
        
    def behavior_passive(self):
        #print("Passive")
        #if self.is_closing_or_restarting(): return
6aec6155   theopuhl   Majordome algorit...
213
        if self.plc_status.plc_mode == "AUTO":
d0b663be   Etienne Pallier   refactorized majo...
214
            if not self.config.majordome_restarted: self.config.ntc = True
6aec6155   theopuhl   Majordome algorit...
215
            self.changeState("Standby")
d0b663be   Etienne Pallier   refactorized majo...
216
        #return self.current_state
6aec6155   theopuhl   Majordome algorit...
217
            
d0b663be   Etienne Pallier   refactorized majo...
218
219
    def behavior_standby(self):
        #print("Standby")
6aec6155   theopuhl   Majordome algorit...
220
221
        if self.config.ntc:
            self.changeState("Closing")
d0b663be   Etienne Pallier   refactorized majo...
222
        elif self.plc_status.plc_mode != "AUTO" or self.is_closing_or_restarting(): 
6aec6155   theopuhl   Majordome algorit...
223
224
225
226
227
            self.changeState("Passive")
        elif self.config.global_mode == False and self.config.lock == False:
            self.changeState("Remote")
        elif get_sunelev() < -10 and self.plc_status.is_safe == True and self.config.ack == True and self.config.lock == False :
            self.changeState("Startup")
d0b663be   Etienne Pallier   refactorized majo...
228
        #return self.current_state
6aec6155   theopuhl   Majordome algorit...
229

d0b663be   Etienne Pallier   refactorized majo...
230
231
    def behavior_remote(self):
        #print("Remote")
6aec6155   theopuhl   Majordome algorit...
232
233
234
235
236
237
238
239
240
241
242
243
        if self.config.global_mode:
            self.changeState("Standby")
        elif self.config.lock:
            self.config.ntc == True
            self.changeState("Standby")
        #TODO: get shutter from db status (then while until close/open)
        #elif not self.plc_status.is_safe:
        #    response = TelescopeRemoteControlDefault("DOME SHUTTER CLOSE", expert_mode=True).exec_command()
        #elif self.plc_status.is_safe == True:
        #    response = TelescopeRemoteControlDefault("DOME SHUTTER OPEN", expert_mode=True).exec_command()
        elif self.plc_status.plc_mode != "AUTO":
            self.changeState("Passive")
d0b663be   Etienne Pallier   refactorized majo...
244
        #return self.current_state
6aec6155   theopuhl   Majordome algorit...
245

d0b663be   Etienne Pallier   refactorized majo...
246
    def behavior_startup(self):
6aec6155   theopuhl   Majordome algorit...
247
248
249
250
        #TODO: get shutter and telescope from db status
        #if dome_shutter == Open and telescope == Ready
            #TelescopeRemoteControlDefault("DO DOME SHUTTER OPEN", expert_mode=True).exec_command()
            #TelescopeRemoteControlDefault("DO START", expert_mode=True).exec_command()
d0b663be   Etienne Pallier   refactorized majo...
251
        #print("Startup")
6aec6155   theopuhl   Majordome algorit...
252
        if self.config.lock:
d0b663be   Etienne Pallier   refactorized majo...
253
            self.config.ntc = True
6aec6155   theopuhl   Majordome algorit...
254
255
256
            self.changeState("Standby")
        else:
            self.changeState("Scheduler")
d0b663be   Etienne Pallier   refactorized majo...
257
        #return self.current_state
6aec6155   theopuhl   Majordome algorit...
258
259
        

d0b663be   Etienne Pallier   refactorized majo...
260
261
    def behavior_scheduler(self):
        #print("Scheduler")
6aec6155   theopuhl   Majordome algorit...
262
263
264
265
266
        if get_sunelev() > -10 or self.plc_status.is_safe is False or self.config.lock is True :
            self.config.ntc = True
            self.changeState("Standby")
        elif self.config.global_mode == False or self.plc_status.plc_mode != "AUTO":
            self.changeState("Standby")
d0b663be   Etienne Pallier   refactorized majo...
267
        #return self.current_state
6aec6155   theopuhl   Majordome algorit...
268

d0b663be   Etienne Pallier   refactorized majo...
269
270
    def behavior_closing(self):
        #print("Closing")
6aec6155   theopuhl   Majordome algorit...
271
272
273
274
275
276
277
278
279
280
        self.config.ntc = False
        self.config.save()
        response = TelescopeRemoteControlDefault("DO DOME SHUTTER CLOSE", expert_mode=True).exec_command()
        response = TelescopeRemoteControlDefault("DO DOME PARK", expert_mode=True).exec_command()
        response = TelescopeRemoteControlDefault("DO TELESCOPE PARK", expert_mode=True).exec_command()
        if self.plc_status.plc_mode != "AUTO":
            self.changeState("Standby")
        self.changeState("Standby")
        # TODO: elif dome == Parked and dome_shutter == Close and telescospe == Parked 
            #self.changeState("Standby")
d0b663be   Etienne Pallier   refactorized majo...
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
        #return self.current_state

    behavior = {
        "STARTING": behavior_starting,
        "PASSIVE_NO_PLC": behavior_passive_no_plc,
        "Passive": behavior_passive,
        "Standby": behavior_standby,
        "Remote": behavior_remote,
        "Startup": behavior_startup,
        "Scheduler": behavior_scheduler,
        "Closing": behavior_closing,
    }
    def do_behavior_for_state(self, current_state:str) -> str:
        print("CURRENT OCS (MAJORDOME) STATE: "+current_state)
        # EXIT if PLC not connected
        #if not self.plc_is_connected(): return                  
        # EXIT if closing or restarting
        #if self.is_closing_or_restarting(): return
        # run behavior for this state
        #self.behavior[current_state](self)
        self.behavior[current_state](self)
        return self.current_state        
468a79dc   Etienne Pallier   added comments
303

0997e1c3   Etienne Pallier   moved main run() ...
304
           
6aec6155   theopuhl   Majordome algorit...
305
    '''
6aec6155   theopuhl   Majordome algorit...
306
307
        Function called to send alarms is the site isn't closed (Empty for the moment)
    '''
d0b663be   Etienne Pallier   refactorized majo...
308
    def send_alarm_if_not_closed(self):
6aec6155   theopuhl   Majordome algorit...
309
310
        pass

0997e1c3   Etienne Pallier   moved main run() ...
311

6aec6155   theopuhl   Majordome algorit...
312
313
314
315
    '''
        Function called by run to wait for PLC connection before and during the loop
        (also gathering needed info)
    '''
d0b663be   Etienne Pallier   refactorized majo...
316
    def plc_is_connected(self):
6aec6155   theopuhl   Majordome algorit...
317
318
319
        try :
            self.config = Config.objects.get(pk=1)
            self.plc_status = PlcDeviceStatus.objects.exclude(plc_mode=None).latest('created')
6aec6155   theopuhl   Majordome algorit...
320
            timeout = (datetime.datetime.now() - self.plc_status.created).total_seconds()
d0b663be   Etienne Pallier   refactorized majo...
321
            if timeout >= self.config.plc_timeout_seconds:
6aec6155   theopuhl   Majordome algorit...
322
323
                return (False)
            return (True)
d0b663be   Etienne Pallier   refactorized majo...
324
        
6aec6155   theopuhl   Majordome algorit...
325
326
327
328
329
330
        except Config.DoesNotExist or PlcDeviceStatus.DoesNotExist:
            return (False)




e8e6f017   Jeremy   Reworked devices ...
331
332
333
334
335
336
337
338
    '''
        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
339
340
341
342
343
344

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

c72eb17a   Jeremy   Update celery task
348
349
    def createTask(self):
        try:
1a2dc19f   Etienne Pallier   nombreux bugfixes...
350
351
352
            # (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
353
354
355
356
357
358
359
360
361
362
363
364
365
366
        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
367
368
369
370
371
372
373
374
375
376
377
378
379
380
    '''
        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...
381
        Loop to wait for the device to be idle with the starting configurations.
65149de7   Jeremy   Update
382
383
    '''
    def waitDevices(self):
ce470283   Jeremy   Plc simulator fin...
384
385
386
387
388
        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
389
390
391
392
        return (0)

    '''
        Computes the beginning and the end of the following (or current) night
257abe9b   Jeremy   Added comments
393
        set the timers -> maybe put timers in a config file ?
65149de7   Jeremy   Update
394
395
396
397
398
399
    '''
    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...
400
401
        self.timer_night_start = self.night_start - getCurrentTime()
        self.timer_night_end = self.night_end - getCurrentTime()
65149de7   Jeremy   Update
402
        self.timer_status = 5
c72eb17a   Jeremy   Update celery task
403
        self.tasks_timer = 5
65149de7   Jeremy   Update
404
        self.timer_plc = 2
1aed430d   jeremy   Alert handled + k...
405
        self.alert_timer = 1
65149de7   Jeremy   Update
406
        self.timer_schedule = 1
05038bc8   Jeremy   Majordome logic i...
407
        self.timer_sequence = 1
65149de7   Jeremy   Update
408
409
410
411

        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
412
413
        if (getCurrentTime() > self.night_start):
            self.adaptTimers()
65149de7   Jeremy   Update
414
415

        self.timers = {
4cb0ff36   Jeremy   Update
416
417
418
419
420
            "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
421
422
            "sequence": self.timer_sequence,
            "tasks": self.tasks_timer
4cb0ff36   Jeremy   Update
423
        }
ff448d43   Jeremy   Update
424
        if (settings.DEBUG and DEBUG_FILE):
e8e6f017   Jeremy   Reworked devices ...
425
426
            log.info("Majordome started with timers : " + str(self.timers))
        # Functions called during the loop
4cb0ff36   Jeremy   Update
427
428
429
430
431
432
        self.functions = {
            "status": self.handleStatusTimer,
            "environment": self.handleEnvironmentTimer,
            "night_start": self.handleNightStartTimer,
            "night_end": self.handleNightEndTimer,
            "schedule": self.handleScheduleTimer,
c72eb17a   Jeremy   Update celery task
433
434
            "sequence": self.handleSequenceTimer,
            "tasks": self.handleTasks
65149de7   Jeremy   Update
435
        }
65149de7   Jeremy   Update
436
437
        return (0)

257abe9b   Jeremy   Added comments
438
439
440
    '''
        Function called by the main loop to handle the task event (check monitoring and alert_manager)
    '''
c72eb17a   Jeremy   Update celery task
441
    def handleTasks(self):
05bdcc44   Etienne Pallier   BIG DEMO tests (s...
442
443
        if not settings.USE_CELERY: return 0

c72eb17a   Jeremy   Update celery task
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
        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
462
463
464
    def adaptTimers(self):
        pass

bca9a283   Jeremy   Reworked the sche...
465
466
467
    def logDB(self, message: str):
        Log.objects.create(agent="Majordome", message=message)

65149de7   Jeremy   Update
468
469
    '''
        Infinite loop according to the majordome behavior
65149de7   Jeremy   Update
470
471
    '''
    def loop(self):
d0b663be   Etienne Pallier   refactorized majo...
472
        while (self.closing_mode != "OCS-SHUTDOWN"):
b4e8963c   Etienne Pallier   Each agent (envmo...
473
            print("(MAJOR): start new iteration")
65149de7   Jeremy   Update
474
475
476
477
            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
478
479
            for timer_name, timer_value in self.timers.items():
                if (timer_value <= 0):
4cb0ff36   Jeremy   Update
480
                    if timer_name in self.functions:
bca9a283   Jeremy   Reworked the sche...
481
                        self.logDB("Executing timer " + str(timer_name))
4cb0ff36   Jeremy   Update
482
                        self.functions[timer_name]()
65149de7   Jeremy   Update
483
                    else:
ff448d43   Jeremy   Update
484
                        if (settings.DEBUG and DEBUG_FILE):
4cb0ff36   Jeremy   Update
485
                            log.info("Timer : " + str(timer_name) + "is not known by the Majordome")
bca9a283   Jeremy   Reworked the sche...
486
                        self.logDB("Timer " + str(timer_name) + " unknown")
ff448d43   Jeremy   Update
487
                    if (settings.DEBUG and DEBUG_FILE):
e8e6f017   Jeremy   Reworked devices ...
488
                        log.info("Timer : " + str(timer_name) + " executed")
075082e1   Etienne Pallier   added start of ag...
489
490
            # EP added because loop is too quick (without CELERY)
            if not settings.USE_CELERY: time.sleep(2)
05038bc8   Jeremy   Majordome logic i...
491
492
        return (0)

257abe9b   Jeremy   Added comments
493
494
495
    '''
        Function called by the main loop to handle environment event (PLC info)
    '''
4cb0ff36   Jeremy   Update
496
497
    def handleEnvironmentTimer(self):
        self.timers["environment"] = self.timer_plc
ce470283   Jeremy   Plc simulator fin...
498
        self.handlePLC()
4cb0ff36   Jeremy   Update
499
500
        return (0)

257abe9b   Jeremy   Added comments
501
502
503
    '''
        Function called by the main loop to handle the devices status
    '''
4cb0ff36   Jeremy   Update
504
505
    def handleStatusTimer(self):
        self.timers["status"] = self.timer_status
ce470283   Jeremy   Plc simulator fin...
506
507
508
509
        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
510
        self.handleStatus()
c72eb17a   Jeremy   Update celery task
511
        return 0
4cb0ff36   Jeremy   Update
512

257abe9b   Jeremy   Added comments
513
514
515
    '''
        Function called by the main loop to check if the executing sequence is finished
    '''
4cb0ff36   Jeremy   Update
516
517
    def handleSequenceTimer(self):
        self.timers["sequence"] = self.timer_sequence
ff448d43   Jeremy   Update
518
519
520
        if (self.executing_sequence):
            self.handleSequence(self.executing_sequence[0],
                                self.executing_sequence[1], self.executing_sequence[2])
4cb0ff36   Jeremy   Update
521
522
        return (0)

257abe9b   Jeremy   Added comments
523
524
525
    '''
        Function called by the main loop to check if there is a new schedule and to execute its sequences
    '''
4cb0ff36   Jeremy   Update
526
    def handleScheduleTimer(self):
ef60c3ec   Jeremy   Majordome and mon...
527
        self.timers["schedule"] = self.timer_schedule
4cb0ff36   Jeremy   Update
528
        if (self.isValidStatus(self.status_tel)):
ff448d43   Jeremy   Update
529
            if (self.schedule is None):
ef60c3ec   Jeremy   Majordome and mon...
530
531
532
                try:
                    self.schedule = Schedule.objects.latest('created')
                except ObjectDoesNotExist:
ff448d43   Jeremy   Update
533
                    if (settings.DEBUG and DEBUG_FILE):
ef60c3ec   Jeremy   Majordome and mon...
534
535
                        log.info("No schedule found in database")
                    return (1)
4cb0ff36   Jeremy   Update
536
            else:
ef60c3ec   Jeremy   Majordome and mon...
537
538
539
                try:
                    schedule = Schedule.objects.latest('created')
                except ObjectDoesNotExist:
ff448d43   Jeremy   Update
540
                    if (settings.DEBUG and DEBUG_FILE):
ef60c3ec   Jeremy   Majordome and mon...
541
542
                        log.info("No schedule found in database")
                    return (1)
4cb0ff36   Jeremy   Update
543
544
545
                if (schedule.created != self.schedule.created):
                    self.next_sequence = None
                    self.schedule = schedule
1aed430d   jeremy   Alert handled + k...
546
                    self.firstSequenceIsAlert()
4cb0ff36   Jeremy   Update
547
            if (self.schedule):
c53a13e0   Jeremy   Updating a lot of...
548
549
                shs_list = self.schedule.shs.filter(Q(status=Sequence.PLANNED) |
                                                    Q(status=Sequence.PENDING)).order_by('tsp')
4cb0ff36   Jeremy   Update
550
551
552
553
554
                self.executeSchedule(shs_list)
        else:
            self.notifyTelescopeStatus("scheduler")
        return (0)

257abe9b   Jeremy   Added comments
555
    '''
1aed430d   jeremy   Alert handled + k...
556
557
558
559
560
561
562
563
564
565
566
567
568
569
        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
570
571
        Function called by the main loop to handle the end of a night
    '''
4cb0ff36   Jeremy   Update
572
    def handleNightEndTimer(self):
ce470283   Jeremy   Plc simulator fin...
573
        self.timers["night_end"] = getNightEnd()
4cb0ff36   Jeremy   Update
574
        if (self.isValidStatus(self.status_tel)):
05bdcc44   Etienne Pallier   BIG DEMO tests (s...
575
576
577
578
579
580
581
582
            #observation_manager.tasks.night_calibrations.apply_async()
            if settings.USE_CELERY:
                print("MJ: call observation_manager WITH CELERY")
                observation_manager.tasks.night_calibrations.apply_async()
            else:
                print("MJ: call observation_manager WITHOUT CELERY")
                observation_manager.tasks.night_calibrations().run()

4cb0ff36   Jeremy   Update
583
584
585
586
        else:
            self.notifyTelescopeStatus("night_end")
        return (0)

257abe9b   Jeremy   Added comments
587
    '''
ed1bf194   Etienne Pallier   bugfix task major...
588
        Function called by the main loop to handle the beginning of a night
257abe9b   Jeremy   Added comments
589
    '''
4cb0ff36   Jeremy   Update
590
591
    def handleNightStartTimer(self):
        self.timers["night_start"] = getNextNightStart()
c72eb17a   Jeremy   Update celery task
592
593
594
595
        if self.isOutsideOk():
            self.dom.open()
            self.vis_camera.open_shutter()
            self.nir_camera.open_shutter()
05bdcc44   Etienne Pallier   BIG DEMO tests (s...
596
597
598
599
600
601
602
603
        #scheduler.tasks.scheduling.apply_async((False, False))
        if settings.USE_CELERY:
            print("MJ: call schedule WITH CELERY")
            scheduler.tasks.scheduling.apply_async((False, False))
        else:
            print("MJ: call schedule WITHOUT CELERY")
            scheduler.tasks.scheduling().run((False, False))

4cb0ff36   Jeremy   Update
604
605
        return (0)

ef60c3ec   Jeremy   Majordome and mon...
606
607
608
    def notifyTelescopeStatus(self, timer_name):
        return (self.notifyDeviceStatus("telescope", timer_name, self.status_tel))

05038bc8   Jeremy   Majordome logic i...
609
    def notifyDeviceStatus(self, device_name, timer_name, status):
ef60c3ec   Jeremy   Majordome and mon...
610
611
        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...
612
        # TODO MAYBE reset some variables and do a scheduling
65149de7   Jeremy   Update
613
614
615
        return (0)

    '''
257abe9b   Jeremy   Added comments
616
        Execute a schedule
65149de7   Jeremy   Update
617
618
    '''
    def executeSchedule(self, shs_list):
c72eb17a   Jeremy   Update celery task
619
        for shs in shs_list:  # shs_list is sorted by tsp
c53a13e0   Jeremy   Updating a lot of...
620
621
622
            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...
623
                if self.isExecutable() and self.executing_sequence is None:
c53a13e0   Jeremy   Updating a lot of...
624
625
626
627
628
                    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
629
                        else:
c53a13e0   Jeremy   Updating a lot of...
630
                            self.next_sequence = None
ff448d43   Jeremy   Update
631
632
                    else:
                        return 0
bca9a283   Jeremy   Reworked the sche...
633
            else:
ff448d43   Jeremy   Update
634
                if (settings.DEBUG and DEBUG_FILE):
bca9a283   Jeremy   Reworked the sche...
635
                    log.info("Sequence cannot be executed : Not observable")
ff448d43   Jeremy   Update
636
637
                self.logDB("Sequence "+shs.sequence.name+" cannot be executed : Not observable")
        return 0
05038bc8   Jeremy   Majordome logic i...
638

4cb0ff36   Jeremy   Update
639
    def observable(self, sequence):
ff448d43   Jeremy   Update
640
641
642
        if (sequence.jd2 - sequence.duration - secondsToPreciseJulianDate(getPreciseCurrentTime()) <= 0):
            return 0
        return 1
4cb0ff36   Jeremy   Update
643

c53a13e0   Jeremy   Updating a lot of...
644
645
646
647
648
    def executableSequence(self, status):
        if status == Sequence.PLANNED or status == Sequence.PENDING:
            return 1
        return 0

257abe9b   Jeremy   Added comments
649
650
651
    '''
        Kill the executing sequence and set its state to cancelled
    '''
678838ed   Jeremy   Weather ans insid...
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
    @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()
05bdcc44   Etienne Pallier   BIG DEMO tests (s...
671
672
673
674
675
676
677
678
            #scheduler.tasks.scheduling.delay((False, False))
            if settings.USE_CELERY:
                print("MJ: call schedule WITH CELERY")
                scheduler.tasks.scheduling.delay((False, False))
            else:
                print("MJ: call schedule WITHOUT CELERY")
                scheduler.tasks.scheduling().run((False, False))

678838ed   Jeremy   Weather ans insid...
679
        elif type == "INSIDE":
05bdcc44   Etienne Pallier   BIG DEMO tests (s...
680
681
682
683
684
685
686
            #scheduler.tasks.scheduling.delay((False, False))
            if settings.USE_CELERY:
                print("MJ: call schedule WITH CELERY")
                scheduler.tasks.scheduling.delay((False, False))
            else:
                print("MJ: call schedule WITHOUT CELERY")
                scheduler.tasks.scheduling().run((False, False))
678838ed   Jeremy   Weather ans insid...
687

257abe9b   Jeremy   Added comments
688
689
690
    '''
        Handle a new alarm (called by isInsideOk or isWeatherOk)
    '''
678838ed   Jeremy   Weather ans insid...
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
    @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...
719
720
721
    def isOutsideOk(self) -> bool:
        self.handlePLC()
        if self.weather_status == "OK":
678838ed   Jeremy   Weather ans insid...
722
723
            if "WEATHER" in self.alarm_list:
                self.handleAlarm("ENDED", self.alarm_list.index("WEATHER"))
ce470283   Jeremy   Plc simulator fin...
724
            return True
678838ed   Jeremy   Weather ans insid...
725
        self.handleAlarm("WEATHER")
ce470283   Jeremy   Plc simulator fin...
726
727
        return False

257abe9b   Jeremy   Added comments
728
729
730
    '''
        Check the telescope inside status
    '''
ce470283   Jeremy   Plc simulator fin...
731
732
733
    def isInsideOk(self) -> bool:
        self.handlePLC()
        if self.site_status == "OK":
678838ed   Jeremy   Weather ans insid...
734
735
            if "INSIDE" in self.alarm_list:
                self.handleAlarm("ENDED", self.alarm_list.index("INSIDE"))
ce470283   Jeremy   Plc simulator fin...
736
            return True
678838ed   Jeremy   Weather ans insid...
737
        self.handleAlarm("INSIDE")
ce470283   Jeremy   Plc simulator fin...
738
739
740
741
742
743
744
745
746
747
748
749
750
751
        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
752
753
754
    '''
        check if the sequence timer is valid for execution, also check if there is a scheduling task running
    '''
ce470283   Jeremy   Plc simulator fin...
755
    def isValidTimer(self, shs) -> bool:
c53a13e0   Jeremy   Updating a lot of...
756
757
        current_countdown = self.getCountdown(shs)
        if (current_countdown <= JulianSeconds(5)):
c53a13e0   Jeremy   Updating a lot of...
758
759
760
            try:
                task = TaskId.objects.filter(task="scheduling")
                if not task:
ce470283   Jeremy   Plc simulator fin...
761
762
                    return True
                return False
c53a13e0   Jeremy   Updating a lot of...
763
            except:
ce470283   Jeremy   Plc simulator fin...
764
765
                return True
        return False
c53a13e0   Jeremy   Updating a lot of...
766

05038bc8   Jeremy   Majordome logic i...
767
    '''
257abe9b   Jeremy   Added comments
768
        Launch the observation tasks NIR and VIS associated to a sequence
05038bc8   Jeremy   Majordome logic i...
769
    '''
c53a13e0   Jeremy   Updating a lot of...
770
    def executeSequence(self, shs, sequence):
3224f14a   Jeremy   Fixed some simula...
771
772
773
774
        shs.status = Sequence.EXECUTING
        sequence.status = Sequence.EXECUTING
        shs.save()
        sequence.save()
c53a13e0   Jeremy   Updating a lot of...
775
        log.info("Executing sequence id = " + str(sequence.pk))
bca9a283   Jeremy   Reworked the sche...
776
        self.logDB("Executing sequence")
05038bc8   Jeremy   Majordome logic i...
777
        plans_results = []
05038bc8   Jeremy   Majordome logic i...
778
779
780
        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():
05bdcc44   Etienne Pallier   BIG DEMO tests (s...
781
782
783
784
785
786
787
788
789
790
                    #res = observation_manager.tasks.execute_plan_nir.apply_async((plan.id, float(self.getCountdown(shs))))
                    if settings.USE_CELERY:
                        print("MJ: call observation_manager WITH CELERY")
                        res = observation_manager.tasks.execute_plan_nir.apply_async(
                            (plan.id, float(self.getCountdown(shs))))
                    else:
                        print("MJ: call observation_manager WITHOUT CELERY")
                        res = observation_manager.tasks.execute_plan_nir().run(
                            (plan.id, float(self.getCountdown(shs))))

c53a13e0   Jeremy   Updating a lot of...
791
792
                    # JB TODO : is it still usefull ?
                    # TaskId.objects.create(task_id=res.id, task="execute_plan")
05038bc8   Jeremy   Majordome logic i...
793
                    plans_results.append(res)
ff448d43   Jeremy   Update
794
795
            else:
                self.notifyDeviceStatus("Cagire", "Sequence execution", self.status_nir)
c53a13e0   Jeremy   Updating a lot of...
796
797
798
                sequence.status = Sequence.CANCELLED
                shs.status = Sequence.CANCELLED
                shs.save()
ff448d43   Jeremy   Update
799
800
                sequence.save()
                return (1)
05038bc8   Jeremy   Majordome logic i...
801
802
803
        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():
05bdcc44   Etienne Pallier   BIG DEMO tests (s...
804
805
806
807
808
809
810
811
                    #res = observation_manager.tasks.execute_plan_vis.apply_async((plan.id, float(self.getCountdown(shs))))
                    if settings.USE_CELERY:
                        print("MJ: call observation_manager WITH CELERY")
                        res = observation_manager.tasks.execute_plan_vis.apply_async((plan.id, float(self.getCountdown(shs))))
                    else:
                        print("MJ: call observation_manager WITHOUT CELERY")
                        res = observation_manager.tasks.execute_plan_vis().run((plan.id, float(self.getCountdown(shs))))

05038bc8   Jeremy   Majordome logic i...
812
813
814
                    plans_results.append(res)
            else:
                self.notifyDeviceStatus("Camera visible", "Sequence execution", self.status_vis)
c53a13e0   Jeremy   Updating a lot of...
815
816
817
                sequence.status = Sequence.CANCELLED
                shs.status = Sequence.CANCELLED
                shs.save()
05038bc8   Jeremy   Majordome logic i...
818
819
                sequence.save()
                return (1)
05038bc8   Jeremy   Majordome logic i...
820
        self.executing_sequence = [shs, sequence, plans_results]
05038bc8   Jeremy   Majordome logic i...
821
822
823
824
825
        return (0)

    '''
        Set the next sequence
    '''
c53a13e0   Jeremy   Updating a lot of...
826
    def setNextSequence(self, shs, sequence):
ff448d43   Jeremy   Update
827
        sequence.status = Sequence.PENDING
c53a13e0   Jeremy   Updating a lot of...
828
829
        shs.status = Sequence.PENDING
        self.next_sequence = [shs, sequence]
ff448d43   Jeremy   Update
830
        sequence.save()
c53a13e0   Jeremy   Updating a lot of...
831
        shs.save()
05038bc8   Jeremy   Majordome logic i...
832
833
834
835
836
837
        return (0)

    '''
        Check if the current sequence is finished
    '''
    def handleSequence(self, shs, sequence, executing_plans):
c53a13e0   Jeremy   Updating a lot of...
838
        count = 0
c53a13e0   Jeremy   Updating a lot of...
839
        for res in executing_plans:
05038bc8   Jeremy   Majordome logic i...
840
            try:
c53a13e0   Jeremy   Updating a lot of...
841
842
                if res.successful() or res.failed():
                    count += 1
05038bc8   Jeremy   Majordome logic i...
843
            except Exception as e:
678838ed   Jeremy   Weather ans insid...
844
845
                if DEBUG_FILE and settings.DEBUG:
                    log.info(str(e))
05038bc8   Jeremy   Majordome logic i...
846
847
848
849
850
                shs.status = Sequence.CANCELLED
                sequence.status = Sequence.CANCELLED
                shs.save()
                sequence.save()
                for rev in executing_plans:
c53a13e0   Jeremy   Updating a lot of...
851
852
853
                    if (not rev.failed() and not rev.successful()):
                        rev.revoke(terminate=True)
                self.executing_sequence = None
05038bc8   Jeremy   Majordome logic i...
854
                return (-1)
c53a13e0   Jeremy   Updating a lot of...
855
        if count >= len(executing_plans):
05038bc8   Jeremy   Majordome logic i...
856
857
858
859
860
            sequence.status = Sequence.EXECUTED
            shs.status = Sequence.EXECUTED
            sequence.save()
            shs.save()
            message = "Finished sequence " + str(sequence.pk) + " execution"
05038bc8   Jeremy   Majordome logic i...
861
            Log.objects.create(agent="Majordome", message=message)
c53a13e0   Jeremy   Updating a lot of...
862
            self.executing_sequence = None
05038bc8   Jeremy   Majordome logic i...
863
        return (0)
65149de7   Jeremy   Update
864
865
866
867

    '''
        Function called to do an action with the devices status
    '''
05038bc8   Jeremy   Majordome logic i...
868
    def handleStatus(self):
05038bc8   Jeremy   Majordome logic i...
869
870
871
        telescope = Telescope.objects.first()
        camera_nir = Detector.objects.get(name="Cagire")
        camera_vis = Detector.objects.get(name="Visible camera")
ce470283   Jeremy   Plc simulator fin...
872
873
874
        dome = Dome.objects.get(name="Dome")

        dome.status = self.status_dom
05038bc8   Jeremy   Majordome logic i...
875
876
877
        telescope.status = self.status_tel
        camera_nir.status = self.status_nir
        camera_vis.status = self.status_vis
ce470283   Jeremy   Plc simulator fin...
878
879
880
881
882

        dome.save()
        telescope.save()
        camera_nir.save()
        camera_vis.save()
bca9a283   Jeremy   Reworked the sche...
883
884
        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
885
886
887
        return (0)

    '''
3224f14a   Jeremy   Fixed some simula...
888
        Put the majordome in pause
4cb0ff36   Jeremy   Update
889
    '''
4cb0ff36   Jeremy   Update
890
    def systemPause(self, duration, cause: str):
bca9a283   Jeremy   Reworked the sche...
891
        self.logDB("System in pause for " + str(duration))
4cb0ff36   Jeremy   Update
892
        time.sleep(duration)
05bdcc44   Etienne Pallier   BIG DEMO tests (s...
893
894
895
896
897
898
899
900
        #scheduler.tasks.scheduling.apply_async(first_schedule=False, alert=False)
        if settings.USE_CELERY:
            print("MJ: call schedule WITH CELERY")
            scheduler.tasks.scheduling.apply_async(first_schedule=False, alert=False)
        else:
            print("MJ: call schedule WITHOUT CELERY")
            scheduler.tasks.scheduling().run(first_schedule=False, alert=False)

4cb0ff36   Jeremy   Update
901
902
903
904
905
        self.setTime()
        print("system has been paused. Cause : " + cause)
        return (0)

    '''
65149de7   Jeremy   Update
906
907
        Function called to do an action with the site status and the wheather status
    '''
ce470283   Jeremy   Plc simulator fin...
908
909
910
911
912
913
914
915
916
917
918
    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...
919
        return 0
5b5566ab   haribo   added celery
920

4cb0ff36   Jeremy   Update
921
    '''
05038bc8   Jeremy   Majordome logic i...
922
        Gets the time before the expected start of the execution.
4cb0ff36   Jeremy   Update
923
    '''
05038bc8   Jeremy   Majordome logic i...
924
925
    def getCountdown(self, shs):
        # TODO start sequence as soon as possible (a lot of verifications must be done there)
ff448d43   Jeremy   Update
926
        current_time = secondsToPreciseJulianDate(getPreciseCurrentTime())
05038bc8   Jeremy   Majordome logic i...
927
        countdown = shs.tsp - current_time
9774228b   haribo   Date: 22/06/2016
928
        return countdown
7a79e25b   haribo   Date: 19/05/2016
929

4cb0ff36   Jeremy   Update
930
931
932
933
    '''
        Change observation conditions
    '''
    def changeObsConditions(self):
5b5566ab   haribo   added celery
934
        print("change_obs_conditions")
6aec6155   theopuhl   Majordome algorit...
935
        pass