from __future__ import absolute_import from django.conf import settings from common.models import * from celery.task import Task import scheduler.tasks import alert_manager.tasks import observation_manager.tasks import time from devices.Telescope import TelescopeController from devices.CameraVIS import VISCameraController from devices.CameraNIR import NIRCameraController from devices.PLC import PLCController import time TIMER_CHECK = 10 # in seconds class monitoring(Task): ''' Infinite task created at the program's start. It initilize all the external connections, and starts the alert_listener. This is the place to put the starting configurations. Once the starting configurations are done, it becomes a loop that checks the PLC and instruments status. It also handles the beginning and the end of the night, recalculating them at each end of night. ''' def run(self): self.configure_instruments() self.update_software_versions() self.get_night_start_end() self.wait_devices_ready() # TODO: décommenter pour lancer un scheduling # scheduler.tasks.scheduling(first_schedule=True, alert=False, night_start=self.night_start, night_end=self.night_end) alert_manager.tasks.alert_listener.delay() self.timers_loop() def configure_instruments(self): ''' Creates the communication objects for each instrument, and give them the basic configurations. ''' self.tel = TelescopeController() self.vis_camera = VISCameraController() self.nir_camera = NIRCameraController() self.plc = PLCController() self.vis_camera.do("COOLER", 1.0, -150.0) self.nir_camera.do("COOLER", 1.0, -150.0) self.tel.do("HOMING") self.tel.do("DOORS", True) # TODO: dire au plc d'ouvrir le dome def update_software_versions(self): ''' Reads the softwares versions in the settings.py, store them in the DB and send them to the IC. ''' 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) # TODO: envoyer les versions à l'IC def get_night_start_end(self): ''' Computes the beginning and the end of the following (or current) night ''' # TODO: utiliser un logiciel by AK pour stocker en local le début et la fin de la nuit (on est peut-être dedans) self.night_start = time.time() + 180 / 86400 self.night_end = time.time() + 360 / 86400 pass def wait_devices_ready(self): ''' Loop to wait for the device to be idle avec the starting configurations. ''' nir_st = "" vis_st = "" tel_st = "" while nir_st != "IDLE" or vis_st != "IDLE" and tel_st != "IDLE": nir_st = self.nir_camera.get("STATUS") vis_st = self.vis_camera.get("STATUS") tel_st = self.tel.get("STATUS") # TODO: rajouter le fait que le dome doit être ouvert (PLC) print("Devices ready !") def timers_loop(self): ''' Infinite loop for the different timers : - Every TIMER_CHECK seconds, check PLC and instruments status (+ analyse them and send them to the IC) - 2 minutes before the night start, make a scheduling - At the end of the night, do calibration files and computes the next night limits + make a scheduling with the new schedule ''' timer_status = TIMER_CHECK ''' Set night start timer to 1 day, then compute the real ones if the current time isn't during the night ''' timer_night_start = 86400 night_start_seconds = self.night_start * 3600 * 24 night_end_seconds = self.night_end * 3600 * 24 if night_start_seconds - 120 > time.time(): timer_night_start = night_start_seconds - 120 - time.time() timer_night_end = night_end_seconds - time.time() timers = {"status": timer_status, "night_start": timer_night_start, "night_end": timer_night_end} while True: minimal_timer = min(timers, key=timers.get) ''' Wait for the nearest timer ''' time.sleep(timers[minimal_timer]) ''' Update the timers ''' timers = {key: value - timers[minimal_timer] for key, value in timers.items()} ''' Then check what timers are <= 0 ''' for timer_name, timer_value in timers.items(): if timer_value <= 0: if timer_name == "status": status_tel = self.tel.get("STATUS") status_nir = self.nir_camera.get("STATUS") status_vis = self.vis_camera.get("STATUS") status_plc = self.plc.get("STATUS") # TODO: stocker les statuts & les envoyer à l'IC timers["status"] = TIMER_CHECK self.analyze_plc_status() elif timer_name == "night_start": scheduler.tasks.scheduling.delay(first_schedule=False, alert=False) timers["night_start"] = 86400 elif timer_name == "night_end": # TODO: faire un majordome.system_pause (fin de nuit) observation_manager.tasks.create_calibrations.delay() self.get_night_start_end() scheduler.tasks.scheduling(first_schedule=True, alert=False, night_start=self.night_start, night_end=self.night_end) timers["night_start"] = self.night_start * 3600 * 24 - time.time() - 120 timers["night_end"] = self.night_end * 3600 * 24 - time.time() def analyze_plc_status(self): ''' Reads the status in DB, and fill missing fields (maybe ?) Determines the obs conditions and compare them with the previous ones to know if they changed Create a task to stop the system if there is a security problem ''' pass # TODO: toute la fct # On calcule le nouveau seeing, et si il y a eu du changement, on crée une tâche de majordome.change_obs_conditions