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 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'] = 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 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 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): 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}) 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') scheduler_logs = Log.objects.filter(agent='Scheduler') majordome_logs = Log.objects.filter(agent='Majordome') obs_logs = Log.objects.filter(agent='Observation manager') analyzer_logs = Log.objects.filter(agent='Analyzer') monitoring_logs = Log.objects.filter(agent='Monitoring') 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") if input_0: commands.append(input_0) if input_1: commands.append(input_1) if input_2: commands.append(input_2) 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_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") if input_0: commands.append(input_0) if input_1: commands.append(input_1) if input_2: commands.append(input_2) 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): #import os if request.method == 'POST': param = request.POST.get("commande_expert") if param: response = CameraVISRemoteControlDefault(param, expert_mode=True, chosen_camera="ddrago_b").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_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 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") if input_0: commands.append(input_0) if input_1: commands.append(input_1) if input_2: commands.append(input_2) 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(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')