from ast import arguments
import re
import sys
from django.http import HttpResponse
from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
import datetime
from datetime import timezone
from django.core.paginator import Paginator
from common.models import Log, SP_Period_Guest, WeatherWatch, SiteWatch, ScientificProgram, Config, PyrosUser, PlcDeviceStatus, Telescope, TelescopeCommand, UserLevel, WeatherWatchHistory, Majordome, AgentSurvey, AgentCmd
from django.core import serializers
import utils.Logger as l
from django.forms import modelformset_factory
from django.http import HttpResponseRedirect
from dashboard.forms import ConfigForm, UserForm, MajordomeForm
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
from django.db.models.query import QuerySet
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 devices import PLC
import time,os
from src.core.pyros_django.obsconfig.obsconfig_class import OBSConfig
from django.conf import settings as pyros_settings
sys.path.append("../../..")
from config.pyros.config_pyros import ConfigPyros
#import utils.celme as celme
import vendor.guitastro.src.guitastro as guitastro
from django.contrib import messages
from django.http import JsonResponse
from collections import OrderedDict
SUN_ELEV_DAY_THRESHOLD = -10
MAX_LOGS_LINES = 100
log = l.setupLogger("dashboard", "dashboard")
def index(request):
config = OBSConfig(os.environ["PATH_TO_OBSCONF_FILE"],os.environ["unit_name"])
observatory_name = config.get_obs_name()
unit_name = config.unit_name
request.session["obsname"] = observatory_name+" "+unit_name
request.session["pyros_config"] = pyros_settings.CONFIG_PYROS
logo = pyros_settings.CONFIG_PYROS.get("general").get("logo")
request.session["logo"] = "media/"+logo
message = ""
if request.user.is_authenticated:
if SP_Period_Guest.objects.filter(email=request.user.email):
message = "You are requested to join the following proposals, click on the following link(s) to accept those invitations :
"
domain = pyros_settings.DEFAULT_DOMAIN
for sp_period_guest in SP_Period_Guest.objects.filter(email=request.user.email):
url = f"http://{domain}{reverse('sp_register',args=(sp_period_guest.SP_Period.scientific_program.id,sp_period_guest.SP_Period.period.id))}"
message+=f"- {url}
"
message+="
"
# return the initial view (the dashboard's one)
return render(request, 'dashboard/index.html', {'USER_LEVEL': request.user.get_priority(), 'base_template' : "base.html","message":message})
return render(request, 'dashboard/index.html', {"USER_LEVEL" : "Visitor", 'base_template' : "base.html"})
def observation_index(request):
if request.user.is_authenticated:
CAN_VIEW_SCIENCE_THEMES = request.session.get("role") in ("Admin","Unit-PI","Unit-board")
# return the initial view (the dashboard's one)
return render(request, 'dashboard/observation_index.html',{
"base_template":"base.html",
"CAN_VIEW_SCIENCE_THEMES": CAN_VIEW_SCIENCE_THEMES
})
return render(request, 'dashboard/observation_index.html', {'USER_LEVEL': "Visitor", 'base_template' : "base.html"})
def retrieve_env(request):
try:
#weather_status = WeatherWatch.objects.latest('updated')
weather_status = get_latest_from_db_or_empty(WeatherWatch)
#plc_device_status = PlcDeviceStatus.objects.exclude(plc_mode=None).latest('created')
plc_device_status = get_latest_plc_device_status_or_empty()
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 guitastro code to determine sun elevation, maybe it should be moved somewhere else ?
'''
def get_sunelev():
date = guitastro.dates.Date("now")
site = guitastro.siteobs.Siteobs("MPC 244.5367 0.85792 +0.51292") # coords of san pedro martir site
skyobj= {'planet':'Sun'}
outputs = ['name','ra','dec','elev']
target = guitastro.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):
'''
Function which get the last status of the plc in th db, the config info, the sunelev, put it in a json
and send it to the client.
This function is called every REFRESH_ICONS_FREQUENCE_MILLISECONDS in base.html
'''
try:
weather = get_weather_data()
return HttpResponse(json.dumps(weather), content_type="application/json")
except WeatherWatch.DoesNotExist:
raise Http404("No WeatherWatch matches the given query.")
'''
##if request.is_ajax():
try:
#weather_status = WeatherWatch.objects.latest('updated')
weather_status = WeatherWatch.objects.latest('updated') if WeatherWatch.objects.all().exists() else WeatherWatch()
#plc_device_status = PlcDeviceStatus.objects.exclude(plc_mode=None).latest('created')
#plc_device_status = PlcDeviceStatus.objects.exclude(plc_mode=None).latest('created') if PlcDeviceStatus.objects.all().exists() else PlcDeviceStatus()
if PlcDeviceStatus.objects.all().exists():
plc_device_status = PlcDeviceStatus.objects.exclude(plc_mode=None).latest('created')
else:
plc_device_status = PlcDeviceStatus()
#plc_device_status.created='2018-07-26 12:48:49.949228'
plc_device_status.created=datetime.datetime(2018, 6, 21, 9, 53, 30, 599462)
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
#if not PlcDeviceStatus.objects.all().exists() plc_device_status.created='2018-07-26 12:48:49.949228'
#timeout = (datetime.datetime.now() - LAST_PLC_ITEM_TIME).total_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
if SiteWatch.objects.all().exists():
sitewatch = SiteWatch.objects.latest('updated')
else:
sitewatch = SiteWatch()
#sitewatch.global_status='KO'
weather[0]["sitewatch_global_status"] = sitewatch.global_status
#weather[0]["sitewatch_global_status"] = SiteWatch.objects.latest('updated').global_status
#weather[0]["sitewatch_global_status"] = SiteWatch.objects.latest('updated').global_status if SiteWatch.objects.all().exists() else SiteWatch()
return HttpResponse(json.dumps(weather), content_type="application/json")
except WeatherWatch.DoesNotExist:
raise Http404("No WeatherWatch matches the given query.")
'''
@login_required
def settings(request):
'''
View called to see the settings (for the software, observatory, users...) page
'''
CAN_VIEW_PERIOD = request.session.get("role") in ("Admin", "Unit-PI", "Observer", "Unit-board")
CAN_CHANGE_SOFT_MODE = request.session.get("role") in ("Admin", "Unit-PI", "Operator")
CAN_VIEW_AGENTS_STATE = request.session.get("role") in ("Admin", "Unit-PI", "Operator")
return(render(request, "dashboard/settings.html", locals()))
def agent_detail(request, agent_name):
agent_log_path = os.path.join(os.environ.get("PROJECT_ROOT_PATH"),f"logs/{agent_name}/",f"{agent_name}.log")
try:
log = open(agent_log_path,"r")
log_content = log.readlines()
if len(log_content) > 30:
log_last_30_lines = log_content[-30:]
else:
log_last_30_lines = log_content
log.close()
except FileNotFoundError:
error_message = f"Cannot find agent logs. (Agent log path tried : {agent_log_path})"
specific_cmd_with_args = None
if AgentSurvey.objects.get(name=agent_name).status != "EXITING":
agent_specific_cmds = AgentCmd.send_cmd_from_to("System",agent_name,"get_specific_cmds")
wait_time = 0
max_wait_time = 10
while AgentCmd.objects.get(id=agent_specific_cmds.id).state != "CMD_EXECUTED":
time.sleep(0.5)
wait_time += 0.5
if AgentCmd.objects.get(id=agent_specific_cmds.id).state == "CMD_EXECUTED":
agent_specific_cmd_to_list = AgentCmd.objects.get(id=agent_specific_cmds.id).result.split(";")
specific_cmd_with_args = {}
for specific_cmd in agent_specific_cmd_to_list:
if "(" in specific_cmd:
cmd = specific_cmd.split("(")[0]
specific_cmd_with_args[cmd] = []
# get text between paretheses
args = re.findall(pattern="\(([^)]+)\)",string=specific_cmd)
for arg in args:
arguments = arg.split(",")
for arg in arguments:
#arg,arg_type = arg.split(":")
specific_cmd_with_args[cmd].append(arg.split(":"))
if request.GET.get("cmd"):
if request.GET.get("cmd") in list(specific_cmd_with_args.keys()):
return JsonResponse(specific_cmd_with_args.get(request.GET.get("cmd")),safe=False)
else:
return JsonResponse(None,safe=False)
else:
if request.GET.get("cmd"):
return JsonResponse(None,safe=False)
commands_sent_by_agent = AgentCmd.get_commands_sent_by_agent(agent_name)
commands_recivied_by_agent = AgentCmd.get_commands_sent_to_agent(agent_name)
commands_of_agent = commands_sent_by_agent | commands_recivied_by_agent
commands_of_agent = commands_of_agent.exclude(full_name="get_specific_cmds")
commands_of_agent = commands_of_agent.order_by("-s_deposit_time")
paginator = Paginator(commands_of_agent, pyros_settings.NB_ELEMENT_PER_PAGE)
page_number = request.GET.get("page",1)
agent_general_commands = AgentCmd._AGENT_GENERAL_COMMANDS
config = OBSConfig(os.environ["PATH_TO_OBSCONF_FILE"],os.environ["unit_name"])
managed_agents = None
status_of_agents = None
managed_by = None
if "AgentSST" in agent_name:
# get computer of agentSST
# get agents of this computer
# mettre des boutons d'actions pour arrêter ou démarrer ou redémarrer l'agent
computer_of_agent = config.get_agent_information(config.unit_name,agent_name).get("computer")
computer_hostname = config.get_computers().get(computer_of_agent).get("computer_config").get("hostname")
agents = config.get_agents_per_computer(config.unit_name).get(computer_hostname)
managed_agents = agents
status_of_agents = {}
for agent in managed_agents:
if "AgentSST" in agent:
managed_agents.remove(agent)
continue
try:
status_of_agents[agent] = AgentSurvey.objects.get(name=agent).status
except AgentSurvey.DoesNotExist:
status_of_agents[agent] = "None"
else:
managed_by = None
computer_of_agent = config.get_agent_information(config.unit_name,agent_name).get("computer")
computer_hostname = config.get_computers().get(computer_of_agent).get("computer_config").get("hostname")
agents = config.get_agents_per_computer(config.unit_name).get(computer_hostname)
for agent in agents:
if "AgentSST" in agent:
managed_by = agent
break
obj, created = Majordome.objects.get_or_create(id=1)
CAN_SEND_COMMAND = obj.soft_mode == Majordome.MANUAL_MODE
try:
commands = paginator.page(page_number)
except PageNotAnInteger:
commands = paginator.page(1)
except EmptyPage:
commands = paginator.page(paginator.num_pages)
return render(request, "dashboard/agent_detail.html", locals())
def agent_action(request):
if request.POST:
action = request.POST.get("action")
agentsst = request.POST.get("agentsst")
recipient = request.POST.get("recipient")
if action == "start":
new_cmd = AgentCmd.send_cmd_from_to(request.user,agentsst,"do_start_agent",recipient)
elif action == "restart":
new_cmd = AgentCmd.send_cmd_from_to(request.user,agentsst,"do_restart_agent",recipient)
elif action == "stop":
new_cmd = AgentCmd.send_cmd_from_to(request.user,agentsst,"do_kill_agent",recipient)
if new_cmd != None:
messages.add_message(request, messages.INFO, f"Command sent !")
else:
messages.add_message(request, messages.INFO, f"Error while creating command, please try again.")
return redirect(agent_detail,agent_name=agentsst)
def send_agent_cmd(request):
if request.POST:
# make a copy because request.POST is immutable
post_data = request.POST.copy()
reciever = post_data.get("agent_name")
cmd_name = post_data.get("cmd_name")
post_data.pop("agent_name")
post_data.pop("cmd_name")
post_data.pop("csrfmiddlewaretoken")
cmd_args = ""
for arg_name in post_data:
cmd_args += post_data.get(arg_name)+ " "
if len(cmd_args)>0:
cmd_args = cmd_args[:-1]
new_cmd = AgentCmd.send_cmd_from_to(request.user,reciever,cmd_name,cmd_args)
if new_cmd != None:
messages.add_message(request, messages.INFO, f"Command sent !")
else:
messages.add_message(request, messages.INFO, f"Error while creating command, please try again.")
return redirect(agent_detail,agent_name=reciever)
def retrieve_log_content(request):
if request.POST:
agent_name = request.POST.get("agent_name")
agent_log_path = os.path.join(os.environ.get("PROJECT_ROOT_PATH"),f"logs/{agent_name}/",f"{agent_name}.log")
try:
log = open(agent_log_path,"r")
log_content = log.readlines()
if len(log_content) > 30:
log_last_30_lines = log_content[-30:]
else:
log_last_30_lines = log_content
log.close()
return HttpResponse(log_last_30_lines)
except FileNotFoundError:
error_message = f"Cannot find agent logs. (Agent log path tried : {agent_log_path})"
return HttpResponse(error_message)
@login_required
@level_required("Admin", "Unit-PI", "Operator")
def soft_mode(request):
if request.POST:
form = MajordomeForm(request.POST)
if form.is_valid():
obj, created = Majordome.objects.get_or_create(id=1)
obj.soft_mode = form.cleaned_data["soft_mode"]
obj.save()
new_soft_mode = form.instance.soft_mode
messages.add_message(request, messages.INFO, f"Changed observatory mode to {new_soft_mode}")
obj, created = Majordome.objects.get_or_create(id=1)
form = MajordomeForm(instance=obj)
soft_mode = obj.soft_mode
is_auto = soft_mode == Majordome.AUTO_MODE
return render(request, "dashboard/soft_mode.html", locals())
def agents_state(request):
agents = AgentSurvey.objects.all()
datetime_now = datetime.datetime.utcnow()
if request.GET:
agent_name = request.GET["agent_name"]
try:
running_commands = AgentCmd.objects.get(state="CMD_RUNNING",sender=agent_name)
return HttpResponse(running_commands.full_name)
except AgentCmd.DoesNotExist:
return HttpResponse("None")
# running_command_per_agent = {}
# for cmd in running_commands:
# running_command_per_agent = running_commands[cmd.get("sender")] = cmd.get("full_name")
# return HttpResponse(running_command_per_agent)
soon_out_of_date_agents = []
for agent in agents:
datetime_now_minus_thirty_sec = datetime_now - datetime.timedelta(seconds=30)
datetime_now_minus_thirty_sec = datetime_now_minus_thirty_sec.replace(tzinfo=timezone.utc)
if datetime_now_minus_thirty_sec >= agent.updated:
soon_out_of_date_agents.append(agent.name)
return render(request, "dashboard/agents_state.html", locals())
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(2)
def routines(request):
url_ = reverse('admin:common_request_changelist')
return redirect(url_)
def get_lastest_and_last_x_minutes_before_latest_weather(x:float=0):
if WeatherWatch.objects.all().exists():
latest_entry = WeatherWatch.objects.latest('updated')
# Get datetime of last weather datetime entry minus x
time_start_range = latest_entry.updated - datetime.timedelta(minutes=x)
# If we have entries in WeatherWatchHistory
if WeatherWatchHistory.objects.all().exists():
# Get the first entry in history that is less or equal than time_start_range
first_weather_of_time_start = WeatherWatch.objects.filter(updated__lte=time_start_range).order_by("-updated").first()
if first_weather_of_time_start != None:
first_weather_of_time_start_id = first_weather_of_time_start.id
# get all id in history that are after the first_weather_of_time_start
list_id_weather_history = WeatherWatchHistory.objects.filter(weather__id__gte=first_weather_of_time_start_id).values_list("weather__id",flat=True)
list_id_weather_history = list(list_id_weather_history)
# add the last entry of weatherwatch at the end of the list
list_id_weather_history.append(latest_entry.id)
# Get all WeatherWatch instance that match those ids
weather_data = WeatherWatch.objects.filter(id__in=list_id_weather_history).order_by("updated")
if weather_data.count() > 0:
return weather_data
else:
# We don't have a matching history entry yet, return the last entry of WeatherWatch (plot with one dot)
return latest_entry
# We don't have an WeatherWatchHistory entry yet, return the last entry of WeatherWatch (plot with one dot)
return latest_entry
else:
# We don't have WeatherWatch data, return empty WeatherWatch (empty plot)
return WeatherWatch()
def get_latest_from_db_or_empty(db_model):
return db_model.objects.latest('updated') if db_model.objects.all().exists() else db_model()
def get_latest_plc_device_status_or_empty():
if PlcDeviceStatus.objects.all().exists() and PlcDeviceStatus.objects.exclude(plc_mode=None).exists():
plc_device_status = PlcDeviceStatus.objects.exclude(plc_mode=None).latest('created')
else:
# Create an empty object
plc_device_status = PlcDeviceStatus()
# Set a dummy date
#plc_device_status.created='2018-07-26 12:48:49.949228'
plc_device_status.created=datetime.datetime(2018, 6, 21, 9, 53, 30, 599462)
plc_device_status.is_safe = False
return plc_device_status
def get_weather_data():
#weather_status = WeatherWatch.objects.latest('updated') if WeatherWatch.objects.all().exists() else WeatherWatch()
#weather_status = get_latest_from_db_or_empty(WeatherWatch)
pyros_config_file = os.environ.get("pyros_config_file")
config_pyros = ConfigPyros(pyros_config_file).pyros_config
env_config = config_pyros.get("ENV")
last_x_minutes = 15
if env_config:
last_x_minutes = env_config.get("time_before_plot")
weather_history = get_lastest_and_last_x_minutes_before_latest_weather(last_x_minutes)
plc_device_status = get_latest_plc_device_status_or_empty()
plc_mode = plc_device_status.plc_mode
is_safe = plc_device_status.is_safe
if isinstance(weather_history,QuerySet):
# If we have weather history + last entry of weather
weather = serializers.serialize('json', weather_history)
else:
# We have only the last entry of weather
weather = serializers.serialize('json', [weather_history])
weather = json.loads(weather)
ack = Config.objects.get(id=1).ack
plc_timeout = Config.objects.get(pk=1).plc_timeout_seconds
#if not PlcDeviceStatus.objects.all().exists() plc_device_status.created='2018-07-26 12:48:49.949228'
#timeout = (datetime.datetime.now() - LAST_PLC_ITEM_TIME).total_seconds()
# PM 20190416 TODO: Check error
#timeout = (datetime.datetime.now() - plc_device_status.created).total_seconds()
timeout = 0
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
# only for retrieve_env_navbar:
sitewatch = get_latest_from_db_or_empty(SiteWatch)
'''
if SiteWatch.objects.all().exists():
sitewatch = SiteWatch.objects.latest('updated')
else:
sitewatch = SiteWatch()
#sitewatch.global_status='KO'
'''
weather[0]["sitewatch_global_status"] = sitewatch.global_status
#weather[0]["sitewatch_global_status"] = SiteWatch.objects.latest('updated').global_status
#weather[0]["sitewatch_global_status"] = SiteWatch.objects.latest('updated').global_status if SiteWatch.objects.all().exists() else SiteWatch()
return weather
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.html"})
def weather_current(request):
# PM 20180718
#if request.is_ajax():
try:
weather = get_weather_data()
return HttpResponse(json.dumps(weather), content_type="application/json")
except WeatherWatch.DoesNotExist:
raise Http404("No WeatherWatch matches the given query.")
'''
try:
#weather_status = WeatherWatch.objects.latest('updated')
#weather_status = WeatherWatch.objects.latest('updated') if WeatherWatch.objects.all().exists() else WeatherWatch()
EMPTY_TABLE = WeatherWatch.objects.all().exists()
weather_status = WeatherWatch.objects.latest('updated') if not EMPTY_TABLE else WeatherWatch()
#plc_device_status = PlcDeviceStatus.objects.exclude(plc_mode=None).latest('created')
plc_device_status = PlcDeviceStatus.objects.exclude(plc_mode=None).latest('created') if PlcDeviceStatus.objects.all().exists() else PlcDeviceStatus()
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()
LAST_PLC_ITEM_TIME = plc_device_status.created if not EMPTY_TABLE else '2018-07-26 12:48:49.949228'
timeout = (datetime.datetime.now() - LAST_PLC_ITEM_TIME).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_config(request):
""" PM 20180926 prototype without database
http://127.0.0.1:8000/dashboard/weather/config
Moved to monitoring
http://127.0.0.1:8000/monitoring/weather/config
"""
try:
# Import PLC status sensor parser
from monitoring.plc_checker import PlcChecker
# Parse PLC status in colibri-new-fixed-2.json
#colibri_json = open("../simulators/plc/colibri-new-fixed-2.json")
#colibri_struct = json.load(colibri_json)
#plc_status = colibri_struct["statuses"][1]["entities"][0]
plc_checker = PlcChecker()
_struct = {"origin":plc_checker.origin, "sensors_table":plc_checker.sensors_table}
# Return template with sensors list
return render(request, 'dashboard/config_weather.html', {'weather_config' : _struct, 'base_template' : "base.html"})
except Config.DoesNotExist:
return render(request, 'dashboard/config_weather.html', {'weather_info' : None})
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' : site_current, '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.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):
if SiteWatch.objects.all().exists():
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("Admin")
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 reverse('settings')
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")[:MAX_LOGS_LINES]
scheduler_logs = Log.objects.filter(agent='Scheduler').order_by("-created")[:MAX_LOGS_LINES]
majordome_logs = Log.objects.filter(agent='Majordome').order_by("-created")[:MAX_LOGS_LINES]
obs_logs = Log.objects.filter(agent='Observation manager').order_by("-created")[:MAX_LOGS_LINES]
analyzer_logs = Log.objects.filter(agent='Analyzer').order_by("-created")[:MAX_LOGS_LINES]
monitoring_logs = Log.objects.filter(agent='Monitoring').order_by("-created")[:MAX_LOGS_LINES]
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')
plc_device_status = get_latest_plc_device_status_or_empty()
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')
plc_device_status = get_latest_plc_device_status_or_empty()
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')
plc_device_status = get_latest_plc_device_status_or_empty()
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(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):
'''
function called when a command it submitted for the cameraVIS_1 in the remote control page
(called in the corresponding control_command file)
'''
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):
'''
function called when a command it submitted in expert mode for the cameraVIS_1 in the remote control page
(called in the corresponding control_command file)
'''
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):
'''
function called when a command it submitted for the cameraNIR in the remote control page
(called in the corresponding control_command file)
'''
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):
'''
function called when a command it submitted in expert mode for the cameraNIR in the remote control page
(called in the corresponding control_command file)
'''
if request.method == 'POST':
param = request.POST.get("commande_expert")
if param:
response = CameraNIRRemoteControlDefault(param, expert_mode=True).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_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):
'''
function called when a command it submitted for the cameraVIS_2 in the remote control page
(called in the corresponding control_command file)
'''
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):
'''
function called when a command it submitted in expert mode for the cameraVIS_2 in the remote control page
(called in the corresponding control_command file)
'''
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):
'''
function called when a command it submitted for the Telescope in the remote control page
(called in control_command.js)
'''
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
request = ' '.join(commands)
NEW_MODE = True
if NEW_MODE:
TelescopeCommand.objects.create(request=request)
else:
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):
'''
function called when a command it submitted in expert mode for the Telescope in the remote control page
(called in control_command.js)
'''
if request.method == 'POST':
param = request.POST.get("commande_expert")
if param:
request = TelescopeCommand.objects.create(request=param)
time.sleep(1)
response = TelescopeCommand.objects.get(pk=request.id).answer
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):
if request.method == 'POST':
param = request.POST.get("commande_expert")
if param:
plc_controller = PLC.PLCController()
response = "Unrecognized command"
if param.startswith("GET STATUS ") or param =="GET STATUS": #pas beau a revoir (classe dédiée ?)
response = plc_controller.getStatus(param)
elif param.startswith("SWITCH LIGHTS"):
response = plc_controller.switch_lights(param)
elif param.endswith(" SHUTTERS"):
response = plc_controller.manage_shutters(param)
return HttpResponse(json.dumps({'message': "Command send OK", 'response': response}))
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(3)
def operator_state(request):
instance = get_object_or_404(Config, id=1)
#plc_device_status = PlcDeviceStatus.objects.exclude(plc_mode=None).latest('created')
plc_device_status = get_latest_plc_device_status_or_empty()
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')
plc_status = get_latest_plc_device_status_or_empty()
return(render(request, 'dashboard/simulator.html', locals()))
except Config.DoesNotExist:
return redirect('simulator')
@login_required
@level_required("Admin")
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')
# if safe => switch to unsafe
# if unsafe => switch to safe
@login_required
@level_required("Admin")
def simulator_switch_safe(request):
try :
#plc_device_status = PlcDeviceStatus.objects.exclude(plc_mode=None).latest('created')
plc_device_status = get_latest_plc_device_status_or_empty()
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("Admin")
def simulator_give_auto(request):
try :
#plc_device_status = PlcDeviceStatus.objects.exclude(plc_mode=None).latest('created')
plc_device_status = get_latest_plc_device_status_or_empty()
plc_device_status.plc_mode = "AUTO"
plc_device_status.save()
return redirect('simulator')
except Config.DoesNotExist:
return redirect('simulator')
@login_required
@level_required("Admin")
def simulator_give_manu(request):
try :
#plc_device_status = PlcDeviceStatus.objects.exclude(plc_mode=None).latest('created')
plc_device_status = get_latest_plc_device_status_or_empty()
plc_device_status.plc_mode = "MANU"
plc_device_status.save()
return redirect('simulator')
except Config.DoesNotExist:
return redirect('simulator')
@login_required
@level_required("Admin")
def simulator_give_ko(request):
try :
#plc_device_status = PlcDeviceStatus.objects.exclude(plc_mode=None).latest('created')
plc_device_status = get_latest_plc_device_status_or_empty()
plc_device_status.plc_mode = "OFF"
plc_device_status.save()
return redirect('simulator')
except Config.DoesNotExist:
return redirect('simulator')
@login_required
@level_required("Admin")
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("Admin")
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("Admin")
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("Admin")
def simulator_majordome_restart(request):
try :
config = get_object_or_404(Config, id=1)
config.majordome_state = "OCS-RESTART"
config.save()
return redirect('simulator')
except Config.DoesNotExist:
return redirect('simulator')
@login_required
@level_required("Admin")
def simulator_majordome_shutdown(request):
try :
config = get_object_or_404(Config, id=1)
config.majordome_state = "OCS-SHUTDOWN"
config.save()
return redirect('simulator')
except Config.DoesNotExist:
return redirect('simulator')