from django.http import HttpResponse from django.shortcuts import render, redirect from django.contrib.auth.decorators import login_required import datetime from common.models import Log, WeatherWatch, SiteWatch, ScientificProgram, Config, PyrosUser, PlcDeviceStatus from django.core import serializers import utils.Logger as l from django.forms import modelformset_factory from dashboard.forms import ConfigForm, UserForm from dashboard.decorator import level_required from django.views.generic.edit import UpdateView from django.shortcuts import get_object_or_404 from django.utils.decorators import method_decorator from django.urls import reverse_lazy, reverse from django.http import Http404 import json from random import randint from devices.Telescope import TelescopeController from devices.TelescopeRemoteControlDefault import TelescopeRemoteControlDefault from devices.CameraVISRemoteControlDefault import CameraVISRemoteControlDefault from devices.CameraNIRRemoteControlDefault import CameraNIRRemoteControlDefault from django.core.mail import send_mail import time import utils.celme as celme from collections import OrderedDict SUN_ELEV_DAY_THRESHOLD = -10 log = l.setupLogger("dashboard", "dashboard") def index(request): if request.user.is_authenticated: return render(request, 'dashboard/index.html', {'USER_LEVEL': request.user.user_level.priority, 'base_template' : "base.html"}) # return the initial view (the dashboard's one) return render(request, 'dashboard/index.html', {'USER_LEVEL': 0, 'base_template' : "base_unlogged.html"}) # return the initial view (the dashboard's one) def retrieve_env(request): try: weather_status = WeatherWatch.objects.latest('updated') plc_device_status = PlcDeviceStatus.objects.exclude(plc_mode=None).latest('created') plc_timeout = Config.objects.get(pk=1).plc_timeout_seconds timeout = (datetime.datetime.now() - plc_device_status.created).total_seconds() timeout_affichage = datetime.datetime.now() - datetime.timedelta(seconds=timeout) sunelev = get_sunelev() t = datetime.datetime.now() + datetime.timedelta(hours=-7) isDay = False if sunelev >= SUN_ELEV_DAY_THRESHOLD: isDay = True return render(request, 'dashboard/observation_status_env.html', locals()) except WeatherWatch.DoesNotExist: raise Http404("No WeatherWatch matches the given query.") ''' Function that call celme code to determine sun elevation, maybe it should be moved somewhere else ? ''' def get_sunelev(): date = celme.dates.Date("now") site = celme.Site("MPC 244.5367 0.85792 +0.51292") # coords of san pedro martir site skyobj= {'planet':'Sun'} outputs = ['name','ra','dec','elev'] target = celme.Target() target.define(skyobj) output0s = ['ra','dec'] results = target.ephem(date,site,output0s) ra = results['RA'] dec = results['DEC'] skyobj= {'RA':ra , 'DEC':dec } target.define(skyobj) results = target.ephem(date,site,outputs) elev = round(results['ELEV'],2) return elev def retrieve_env_navbar(request): if request.is_ajax(): try: weather_status = WeatherWatch.objects.latest('updated') plc_device_status = PlcDeviceStatus.objects.exclude(plc_mode=None).latest('created') plc_mode = plc_device_status.plc_mode is_safe = plc_device_status.is_safe weather = serializers.serialize('json', [weather_status]) weather = json.loads(weather) ack = Config.objects.get(id=1).ack plc_timeout = Config.objects.get(pk=1).plc_timeout_seconds timeout = (datetime.datetime.now() - plc_device_status.created).total_seconds() weather[0]['max_sunelev'] = SUN_ELEV_DAY_THRESHOLD #weather[0]['sunelev'] = 10 weather[0]['sunelev'] = get_sunelev() weather[0]["plc_mode"] = plc_mode weather[0]["is_safe"] = is_safe weather[0]["ACK"] = ack weather[0]["plc_timeout"] = timeout weather[0]["max_plc_timeout"] = plc_timeout weather[0]["pyros_mode"] = Config.objects.get(id=1).pyros_state weather[0]["sitewatch_global_status"] = SiteWatch.objects.latest('updated').global_status return HttpResponse(json.dumps(weather), content_type="application/json") except WeatherWatch.DoesNotExist: raise Http404("No WeatherWatch matches the given query.") def retrieve_main_icon(request): if request.is_ajax(): try: weather_status = WeatherWatch.objects.latest('updated') plc_mode = PlcDeviceStatus.objects.exclude(plc_mode=None).latest('created').plc_mode weather = serializers.serialize('json', [weather_status]) weather = json.loads(weather) weather[0]["plc_mode"] = plc_mode weather[0]["sitewatch_global_status"] = SiteWatch.objects.latest('updated').global_status return HttpResponse(json.dumps(weather), content_type="application/json") except WeatherWatch.DoesNotExist: raise Http404("No WeatherWatch matches the given query.") @login_required @level_required(6) def users(request): instance = PyrosUser.objects.order_by("-id") return render(request, 'dashboard/users_management.html', {'instance': instance}) # return the initial view (the users management's one) @login_required @level_required(2) def routines(request): url_ = reverse('admin:common_request_changelist') return redirect(url_) def weather(request): if request.user.is_authenticated: return render(request, 'dashboard/reload_weather.html', {'base_template' : "base.html"}) # return the needed html file return render(request, 'dashboard/reload_weather.html', {'base_template' : "base_unlogged.html"}) def weather_current(request): # PM 20180718 if request.is_ajax(): try: weather_status = WeatherWatch.objects.latest('updated') plc_device_status = PlcDeviceStatus.objects.exclude(plc_mode=None).latest('created') plc_mode = plc_device_status.plc_mode is_safe = plc_device_status.is_safe weather = serializers.serialize('json', [weather_status]) weather = json.loads(weather) ack = Config.objects.get(id=1).ack plc_timeout = Config.objects.get(pk=1).plc_timeout_seconds timeout = (datetime.datetime.now() - plc_device_status.created).total_seconds() weather[0]['max_sunelev'] = SUN_ELEV_DAY_THRESHOLD weather[0]['sunelev'] = get_sunelev() weather[0]["plc_mode"] = plc_mode weather[0]["is_safe"] = is_safe weather[0]["ACK"] = ack weather[0]["plc_timeout"] = timeout weather[0]["max_plc_timeout"] = plc_timeout weather[0]["pyros_mode"] = Config.objects.get(id=1).pyros_state return HttpResponse(json.dumps(weather), content_type="application/json") except WeatherWatch.DoesNotExist: raise Http404("No WeatherWatch matches the given query.") def weather_current_old(request): try: if (len(Config.objects.all()) == 1): monitoring = int(int(Config.objects.get(id=1).row_data_save_frequency) / 5) else: monitoring = 60 if (len(WeatherWatch.objects.all()) > 0): weather_info = WeatherWatch.objects.order_by("-id")[:monitoring] # Use 300 seconds by default with an iteration every 5 seconds # Get the number of data available else: weather_info = None return render(request, 'dashboard/current_weather.html', {'weather_info' : weather_info, 'iteration' : monitoring}) except Config.DoesNotExist: return render(request, 'dashboard/current_weather.html', {'weather_info' : None, 'iteration' : 60}) def site(request): if request.user.is_authenticated: return render(request, 'dashboard/reload_site.html', {'base_template' : "base.html"}) # return the needed html file return render(request, 'dashboard/reload_site.html', {'base_template' : "base_unlogged.html"}) # return the needed html file def site_current(request): try: if (len(Config.objects.all()) == 1): monitoring = int(int(Config.objects.get(id=1).row_data_save_frequency) / 5) else: monitoring = 60 if (len(SiteWatch.objects.all()) > 0): site_info = SiteWatch.objects.order_by("-id")[:monitoring] else: site_info = None return render(request, 'dashboard/current_site.html', {'site_info' : site_info, 'iteration' : monitoring, 'global_mode' : Config.objects.get(id=1).global_mode}) except Config.DoesNotExist: return render(request, 'dashboard/current_site.html', {'site_info' : None, 'iteration' : 60}) @login_required @level_required(2) def proposal(request): if (len(ScientificProgram.objects.all()) > 0): # checking if the observatory table is empty proposal_info = ScientificProgram.objects.order_by("-id")[:100] # Sorting Weather table nb_info_proposal = len(proposal_info) # Get the number of data available else: # if empty set everything to 0 / None (variables are checked in src/templates/scheduler/current_weather.html) proposal_info = None nb_info_proposal = 0 return render(request, 'dashboard/proposal.html', {'proposal_info' : proposal_info, 'nb_info_proposal' : nb_info_proposal}) @login_required @level_required(5) def configUpdate(request): instance = get_object_or_404(Config, id=1) form = ConfigForm(request.POST or None, instance=instance) if form.is_valid(): form.save() return redirect('../user_manager/profile') return render(request, 'dashboard/configuration.html', {'form': form}) @login_required def devices(request): url_ = reverse('admin:common_device_changelist') return redirect(url_) @login_required def system(request): return render(request, 'dashboard/system.html') @login_required def system_retrieve_logs(request): ''' Called by the dashboard system page with ajax request every seconds, to get the logs and print them ''' if request.is_ajax(): alert_logs = Log.objects.filter(agent='Alert manager').order_by("-created") scheduler_logs = Log.objects.filter(agent='Scheduler').order_by("-created") majordome_logs = Log.objects.filter(agent='Majordome').order_by("-created") obs_logs = Log.objects.filter(agent='Observation manager').order_by("-created") analyzer_logs = Log.objects.filter(agent='Analyzer').order_by("-created") monitoring_logs = Log.objects.filter(agent='Monitoring').order_by("-created") return render(request, 'dashboard/system_logs.html', locals()) def schedule(request): url_ = reverse('admin:common_schedule_changelist') return redirect(url_) @login_required @level_required(6) def quotas(request): url_ = reverse('admin:common_pyrosuser_changelist') return redirect(url_) @login_required @level_required(3) def change_globalMode(request): try : config = get_object_or_404(Config, id=1) plc_device_status = PlcDeviceStatus.objects.exclude(plc_mode=None).latest('created') if config.global_mode == False and plc_device_status.is_safe == False: return redirect('states') config.global_mode = not config.global_mode config.save() return redirect('states') except Config.DoesNotExist: return redirect('states') @login_required @level_required(4) def change_bypass(request): try : config = get_object_or_404(Config, id=1) plc_device_status = PlcDeviceStatus.objects.exclude(plc_mode=None).latest('created') if plc_device_status.is_safe == True: return redirect('states') config.bypass = not config.bypass config.save() return redirect('states') except Config.DoesNotExist: return redirect('states') @login_required @level_required(3) def change_lock(request): try : config = get_object_or_404(Config, id=1) plc_device_status = PlcDeviceStatus.objects.exclude(plc_mode=None).latest('created') if config.lock == False and plc_device_status.is_safe == False: return redirect('states') config.lock = not config.lock if (config.lock == True): config.ntc = not config.ntc config.save() return redirect('states') except Config.DoesNotExist: return redirect('states') @login_required @level_required(6) def change_activate(request, pk): try : user = get_object_or_404(PyrosUser, pk=pk) user.is_active = not user.is_active text_mail = "" text_object = "" if (user.first_time == False and user.is_active == True): user.first_time = True text_mail = "Hi,\n\nCongratulations, your registration has been approuved by the PI. Welcome to the Colibri Control Center.\n\nCordialy,\n\nColibri Control Center" text_object = "[COLIBRI CC] Welcome" elif (user.is_active == True): text_mail = "Hi,\n\nYour account on the Colibri Control Center have been re-activated.\n\nCordialy,\n\nColibri Control Center" text_object = "[COLIBRI CC] Re-activation" else : text_mail = "Hi,\n\nYour account on the Colibri Control Center have benn desactivated. Please contact the PI for futher information.\n\nCordialy,\n\nColibri Control Center" text_object = "[COLIBRI CC] Desactivation" user.save() send_mail(text_object, text_mail, '', [user.email], fail_silently=False,) return redirect('user-detail', pk=pk) except PyrosUser.DoesNotExist: return redirect('user-detail', pk=pk) @login_required @level_required(3) def send_command_to_cameraVIS_1(request): data = "" with open('../simulators/config/grammar.json') as f: data = json.load(f, object_pairs_hook=OrderedDict) json_str = json.dumps(data) return render(request, "dashboard/send_command_cameraVIS_1.html", locals()) @login_required @level_required(3) def submit_command_to_cameraVIS_1(request): if request.method == 'POST': commands = [request.POST.get("first_command"), request.POST.get("first_param")] try: #TODO faire un truc plus joli pour gérer les params queqlue soit leur nombre input_0 = request.POST.get("input_number_0") input_1 = request.POST.get("input_number_1") input_2 = request.POST.get("input_number_2") input_3 = request.POST.get("input_number_3") if input_0: commands.append(input_0) if input_1: commands.append(input_1) if input_2: commands.append(input_2) if input_3: commands.append(input_3) except Exception: pass response = CameraVISRemoteControlDefault(commands, expert_mode=False, chosen_camera="ddrago_r").exec_command() #TODO passer en JS pour send les réponses en AJAX return redirect('send_command_to_cameraVIS_1') @login_required @level_required(3) def submit_command_to_cameraVIS_1_expert(request): #import os if request.method == 'POST': param = request.POST.get("commande_expert") if param: response = CameraVISRemoteControlDefault(param, expert_mode=True, chosen_camera="ddrago_r").exec_command() #os.system("echo \"status :" + response + "\" >> /home/portos/IRAP/pyros/src/status") return HttpResponse(json.dumps({'message': "Command send OK", 'response': response})) return HttpResponse(json.dumps({'message': "Missing command data"})) return redirect('submit_command_to_telescope') @login_required @level_required(3) def send_command_to_cameraNIR(request): data = "" with open('../simulators/config/grammar.json') as f: data = json.load(f, object_pairs_hook=OrderedDict) json_str = json.dumps(data) return render(request, "dashboard/send_command_cameraNIR.html", locals()) @login_required @level_required(3) def submit_command_to_cameraNIR(request): if request.method == 'POST': commands = [request.POST.get("first_command"), request.POST.get("first_param")] try: #TODO faire un truc plus joli pour gérer les params queqlue soit leur nombre input_0 = request.POST.get("input_number_0") input_1 = request.POST.get("input_number_1") input_2 = request.POST.get("input_number_2") input_3 = request.POST.get("input_number_3") if input_0: commands.append(input_0) if input_1: commands.append(input_1) if input_2: commands.append(input_2) if input_3: commands.append(input_3) except Exception: pass response = CameraNIRRemoteControlDefault(commands, expert_mode=False).exec_command() #TODO passer en JS pour send les réponses en AJAX return redirect('send_command_to_cameraNIR') @login_required @level_required(3) def submit_command_to_cameraNIR_expert(request): #import os if request.method == 'POST': param = request.POST.get("commande_expert") if param: response = CameraNIRRemoteControlDefault(param, expert_mode=True).exec_command() #os.system("echo \"status :" + response + "\" >> /home/portos/IRAP/pyros/src/status") return HttpResponse(json.dumps({'message': "Command send OK", 'response': response})) return HttpResponse(json.dumps({'message': "Missing command data"})) return redirect('submit_command_to_cameraNIR') @login_required @level_required(3) def send_command_to_cameraVIS_2(request): data = "" with open('../simulators/config/grammar.json') as f: data = json.load(f, object_pairs_hook=OrderedDict) json_str = json.dumps(data) return render(request, "dashboard/send_command_cameraVIS_2.html", locals()) @login_required @level_required(3) def submit_command_to_cameraVIS_2(request): if request.method == 'POST': commands = [request.POST.get("first_command"), request.POST.get("first_param")] try: #TODO faire un truc plus joli pour gérer les params queqlue soit leur nombre input_0 = request.POST.get("input_number_0") input_1 = request.POST.get("input_number_1") input_2 = request.POST.get("input_number_2") input_3 = request.POST.get("input_number_3") if input_0: commands.append(input_0) if input_1: commands.append(input_1) if input_2: commands.append(input_2) if input_3: commands.append(input_3) except Exception: pass response = CameraVISRemoteControlDefault(commands, expert_mode=False, chosen_camera="ddrago_b").exec_command() #TODO passer en JS pour send les réponses en AJAX return redirect('send_command_to_cameraVIS_2') @login_required @level_required(3) def submit_command_to_cameraVIS_2_expert(request): if request.method == 'POST': param = request.POST.get("commande_expert") if param: response = CameraVISRemoteControlDefault(param, expert_mode=True, chosen_camera="ddrago_b").exec_command() return HttpResponse(json.dumps({'message': "Command send OK", 'response': response})) return HttpResponse(json.dumps({'message': "Missing command data"})) return redirect('submit_command_to_cameraVIS_2') @login_required @level_required(3) def send_command_to_telescope(request): data = "" with open('../simulators/config/grammar.json') as f: data = json.load(f, object_pairs_hook=OrderedDict) json_str = json.dumps(data) return render(request, "dashboard/send_command_telescope.html", locals()) @login_required @level_required(3) def submit_command_to_telescope(request): if request.method == 'POST': commands = [request.POST.get("first_command"), request.POST.get("first_param")] try: #TODO faire un truc plus joli pour gérer les params quelque soit leur nombre la c'est du rapide super moche et max 4 input input_0 = request.POST.get("input_number_0") input_1 = request.POST.get("input_number_1") input_2 = request.POST.get("input_number_2") input_3 = request.POST.get("input_number_3") if input_0: commands.append(input_0) if input_1: commands.append(input_1) if input_2: commands.append(input_2) if input_3: commands.append(input_3) except Exception: pass response = TelescopeRemoteControlDefault(commands, False).exec_command() #TODO passer en JS pour send les réponses en AJAX return redirect('send_command_to_telescope') @login_required @level_required(3) def submit_command_to_telescope_expert(request): #import os if request.method == 'POST': param = request.POST.get("commande_expert") if param: response = TelescopeRemoteControlDefault(param, expert_mode=True).exec_command() #os.system("echo \"status :" + response + "\" >> /home/portos/IRAP/pyros/src/status") return HttpResponse(json.dumps({'message': "Command send OK", 'response': response})) return HttpResponse(json.dumps({'message': "Missing command data"})) return redirect('submit_command_to_telescope') @login_required @level_required(3) def submit_command_to_plc(request): #import os if request.method == 'POST': param = request.POST.get("commande_expert") if param: #response = TelescopeRemoteControlDefault(param, expert_mode=True).exec_command() #os.system("echo \"status :" + response + "\" >> /home/portos/IRAP/pyros/src/status") return HttpResponse(json.dumps({'message': "Command send OK", 'response': "ceci est un test"})) return HttpResponse(json.dumps({'message': "Missing command data"})) return redirect('submit_command_to_plc') @login_required @level_required(3) def send_command_to_plc(request): return render(request, 'dashboard/send_command_to_plc.html') @login_required @level_required(2) def user_detail_view(request,pk): try: user_id=PyrosUser.objects.get(pk=pk) current_user = request.user except PyrosUser.DoesNotExist: raise Http404("User does not exist") return render(request, 'dashboard/user_detail.html', context={'user' : user_id, 'current_user' : current_user, 'USER_LEVEL': request.user.user_level.priority}) @login_required @level_required(6) def user_detail_edit(request,pk): edit = get_object_or_404(PyrosUser, pk=pk) form = UserForm(request.POST or None, instance=edit) if form.is_valid(): form.save() return redirect('user-detail', pk=pk) return render(request, 'dashboard/user_detail_edit.html', {'form': form}) @login_required @level_required(3) def operator_state(request): instance = get_object_or_404(Config, id=1) plc_device_status = PlcDeviceStatus.objects.exclude(plc_mode=None).latest('created') return render(request, 'dashboard/operator_state.html', {'config' : instance, 'is_safe' : plc_device_status.is_safe}) @login_required @level_required(3) def simulator(request): try : config = get_object_or_404(Config, id=1) plc_status = PlcDeviceStatus.objects.exclude(plc_mode=None).latest('created') return(render(request, 'dashboard/simulator.html', locals())) except Config.DoesNotExist: return redirect('simulator') @login_required @level_required(7) def simulator_switch_ack(request): try : config = get_object_or_404(Config, id=1) config.ack = not config.ack config.save() return redirect('simulator') except Config.DoesNotExist: return redirect('simulator') @login_required @level_required(7) def simulator_switch_safe(request): try : plc_device_status = PlcDeviceStatus.objects.exclude(plc_mode=None).latest('created') plc_device_status.is_safe = not plc_device_status.is_safe plc_device_status.save() return redirect('simulator') except Config.DoesNotExist: return redirect('simulator') @login_required @level_required(7) def simulator_give_auto(request): try : plc_device_status = PlcDeviceStatus.objects.exclude(plc_mode=None).latest('created') plc_device_status.plc_mode = "AUTO" plc_device_status.save() return redirect('simulator') except Config.DoesNotExist: return redirect('simulator') @login_required @level_required(7) def simulator_give_manu(request): try : plc_device_status = PlcDeviceStatus.objects.exclude(plc_mode=None).latest('created') plc_device_status.plc_mode = "MANU" plc_device_status.save() return redirect('simulator') except Config.DoesNotExist: return redirect('simulator') @login_required @level_required(7) def simulator_give_ko(request): try : plc_device_status = PlcDeviceStatus.objects.exclude(plc_mode=None).latest('created') plc_device_status.plc_mode = "OFF" plc_device_status.save() return redirect('simulator') except Config.DoesNotExist: return redirect('simulator') @login_required @level_required(7) def simulator_switch_bypass(request): try : config = get_object_or_404(Config, id=1) config.bypass = not config.bypass config.save() return redirect('simulator') except Config.DoesNotExist: return redirect('simulator') @login_required @level_required(7) def simulator_switch_lock(request): try : config = get_object_or_404(Config, id=1) config.lock = not config.lock config.save() return redirect('simulator') except Config.DoesNotExist: return redirect('simulator') @login_required @level_required(7) def simulator_switch_globalMode(request): try : config = get_object_or_404(Config, id=1) config.global_mode = not config.global_mode config.save() return redirect('simulator') except Config.DoesNotExist: return redirect('simulator') @login_required @level_required(7) def simulator_majordome_restart(request): try : config = get_object_or_404(Config, id=1) config.majordome_state = "RESTART" config.save() return redirect('simulator') except Config.DoesNotExist: return redirect('simulator') @login_required @level_required(7) def simulator_majordome_shutdown(request): try : config = get_object_or_404(Config, id=1) config.majordome_state = "SHUTDOWN" config.save() return redirect('simulator') except Config.DoesNotExist: return redirect('simulator')