Commit 800f4279a1300456162ad3f8db703bc69292ff7f

Authored by Alexis Koralewski
1 parent e5f122b6
Exists in dev

Updating WeatherWatchHistory models attributes, adding view for WeatherWatchHist…

…ory, improving plotting UI
CHANGELOG
  1 +28-04-2022 (AKo): v0.4.6.0
  2 + - Adding weather history view
  3 + - time every new entry of weather history is added and last x minutes to plot are set up from config_pyros
  4 + - adding env monitoring to config_pyros, update schema accordingly
  5 + - update WeatherWatchHistory models attributes to match those with WeatherWatch
  6 + - WeatherWatchHistory entry makes a copy of WeatherWatch data
  7 +
1 8 27-04-2022 (AKo): v0.4.5.0
2 9 - Adding unsubmit button for sequences
3 10 - Re-enabling cancel button for sequence (cancel = delete)
4 11 - Fixing bug where "show more informations" button on plan view page was submitting form
  12 + - Fixing issue with saveWeather for agentM
5 13  
6 14 26-04-2022 (AKo): v0.4.4.1
7 15 - Adding 3 full sequences to debris scientific program in initial fixture
... ...
VERSION
1   -0.4.5.0
2 1 \ No newline at end of file
  2 +0.4.6.0
3 3 \ No newline at end of file
... ...
src/core/pyros_django/common/models.py
... ... @@ -2179,6 +2179,12 @@ class WeatherWatchHistory(models.Model):
2179 2179 rain = models.CharField(max_length=45, blank=True, null=True)
2180 2180 dwn = models.CharField(max_length=45, blank=True, null=True)
2181 2181  
  2182 + humidity = models.FloatField(blank=True, null=True)
  2183 + wind = models.FloatField(blank=True, null=True)
  2184 + wind_dir = models.CharField(max_length=45, blank=True, null=True)
  2185 + temperature = models.FloatField(blank=True, null=True)
  2186 + cloud = models.FloatField(blank=True, null=True)
  2187 +
2182 2188 class Meta:
2183 2189 managed = True
2184 2190 db_table = 'weatherwatchhistory'
... ...
src/core/pyros_django/misc/static/js/plotter.js
... ... @@ -48,7 +48,7 @@ function PlotterClas(hkname, plotdiv, HKRange) {
48 48 width: 400,
49 49 height: 200,
50 50 margin: {
51   - l: 20,
  51 + l: 50,
52 52 r: 10,
53 53 b: 50,
54 54 t: 50,
... ... @@ -81,7 +81,11 @@ PlotterClas.prototype = {
81 81 methode: function() {
82 82 alert("Attributs: " + this.hkname + ", " + this.plotdiv);
83 83 },
84   -
  84 + clear: function(){
  85 + this.HKQueue.x = [];
  86 + this.HKQueue.y = [];
  87 +
  88 + },
85 89 refresh_list: function(data) {
86 90  
87 91 var x = this.HKQueue.x.push(data[0]);
... ... @@ -101,7 +105,7 @@ PlotterClas.prototype = {
101 105 // this.maxQueue.y.shift();
102 106 // }
103 107 var config = {responsive: true};
104   - Plotly.newPlot(this.plotdiv, this.dataPlot, this.layout, this.config);
  108 + Plotly.newPlot(this.plotdiv, this.dataPlot, this.layout, config);
105 109  
106 110 }
107 111  
... ...
src/core/pyros_django/monitoring/templates/monitoring/monitoring_index.html
... ... @@ -90,6 +90,15 @@
90 90 </div></a>
91 91 </div>
92 92 </li>
  93 + <li>
  94 + <div class="all-box all-img-weather">
  95 + <a href="{% url "weather_history" %}">
  96 + <div class="all-info">
  97 + <h3>Weather history</h3>
  98 + <img id="weather_big_img" src="{% static "media/weather.png" %}" alt="html5" />
  99 + </div></a>
  100 + </div>
  101 + </li>
93 102 {# TBD #}
94 103 {% if USER_LEVEL|ifinlist:"Admin,Operator,Unit-PI,Management board member,Observer,TAC" %}
95 104 <li>
... ...
src/core/pyros_django/monitoring/templates/monitoring/weather_history.html 0 → 100644
... ... @@ -0,0 +1,123 @@
  1 +{% extends 'base.html' %}
  2 +{% load static %}
  3 +{% block head %}
  4 +<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
  5 +<script src="{% static "js/plotly-2.11.1.min.js" %}"></script>
  6 +<script src="{% static "js/plotter.js" %}"></script>
  7 +<script src="{% static "js/weather.js" %}"></script>
  8 +<script src="{% static "js/vue.min.js" %}"></script>
  9 +<script>
  10 +var myHeaders = new Headers();
  11 +
  12 +var myInit = { method: 'GET',
  13 + headers: myHeaders,
  14 + mode: 'cors',
  15 + cache: 'default' };
  16 +
  17 +$(document).ready(function () {
  18 + $("#loader").hide();
  19 + $("#div_plots").hide();
  20 + var weather_plots = {
  21 + humidity_plot : new PlotterClas("humidity", "humidity_plot", [0,80]),
  22 + pressure_plot : new PlotterClas("pressure", "pressure_plot", []),
  23 + rain_plot : new PlotterClas("rain", "rain_plot", []),
  24 + temperature_plot : new PlotterClas("temperature", "temperature_plot", []),
  25 + wind_plot : new PlotterClas("wind", "wind_plot", [0,80]),
  26 + wind_dir_plot : new PlotterClas("wind_dir", "wind_dir_plot", []),
  27 + }
  28 + $("#weather_history_form").submit(function(event){
  29 + event.preventDefault();
  30 + var start_datetime = $("#start_datetime").val()
  31 + var end_datetime = $("#end_datetime").val()
  32 + $("#loader").show();
  33 + // Clear plots, can't iterate on weather_plots
  34 + weather_plots.humidity_plot.clear();
  35 + weather_plots.pressure_plot.clear();
  36 + weather_plots.rain_plot.clear();
  37 + weather_plots.temperature_plot.clear();
  38 + weather_plots.wind_plot.clear();
  39 + weather_plots.wind_dir_plot.clear();
  40 + $.get("weather_history",{start_datetime: start_datetime,end_datetime:end_datetime},function(data){
  41 +
  42 + for(var entry of data){
  43 + weather_plots.humidity_plot.refresh_list([entry.fields.datetime , entry.fields.humidity]);
  44 + weather_plots.pressure_plot.refresh_list([entry.fields.datetime , entry.fields.pressure]);
  45 + weather_plots.rain_plot.refresh_list([entry.fields.datetime , entry.fields.rain]);
  46 + weather_plots.temperature_plot.refresh_list([entry.fields.datetime , entry.fields.temperature]);
  47 + weather_plots.wind_plot.refresh_list([entry.fields.datetime , entry.fields.wind]);
  48 + weather_plots.wind_dir_plot.refresh_list([entry.fields.datetime , entry.fields.wind_dir]);
  49 +
  50 + }
  51 + $("#loader").hide();
  52 + $("#div_plots").show();
  53 + });
  54 + });
  55 +});
  56 +</script>
  57 + <style>
  58 + div.hbox {
  59 + float:left;
  60 + display:inline;
  61 + font-size: 11pt;
  62 + /*background:#e7e4e4;*/
  63 + border: 1px solid rgba(0, 0, 0, 0.125);
  64 + border-color: #2FA4E7;
  65 + border-radius: 0.25rem;
  66 + padding: 3px 5px 3px 3px;
  67 + margin: 1px 2px 1px 1px;
  68 + }
  69 + div.box {
  70 + /*float:left;*/
  71 + /*display:inline;*/
  72 + font-size: 11pt;
  73 + /*background:#e7e4e4;*/
  74 + border: 1px solid rgba(0, 0, 0, 0.125);
  75 + border-color: #2FA4E7;
  76 + border-radius: 0.25rem;
  77 + padding: 3px 5px 3px 3px;
  78 + margin: 1px 2px 1px 1px;
  79 + }
  80 +
  81 +
  82 + .loader {
  83 + border: 16px solid #f3f3f3; /* Light grey */
  84 + border-top: 16px solid #3498db; /* Blue */
  85 + border-radius: 50%;
  86 + width: 120px;
  87 + height: 120px;
  88 + animation: spin 2s linear infinite;
  89 + position: fixed;
  90 + left: 45%;
  91 + z-index: 1;
  92 + top: 45%;
  93 + }
  94 +
  95 + @keyframes spin {
  96 + 0% { transform: rotate(0deg); }
  97 + 100% { transform: rotate(360deg); }
  98 + }
  99 + </style>
  100 +
  101 +{% endblock %}
  102 +
  103 +{% block content %}
  104 +<div id="loader" class="loader" style="display: none;"></div>
  105 + <div class="row">
  106 + <div class="col-md-auto">
  107 + <form id="weather_history_form" action="">
  108 + <p>Start datetime (UTC): <input type="datetime" placeholder="dd/mm/yyyy H:m:s" id="start_datetime"></input></p>
  109 + <p>End datetime (UTC): <input type="datetime" id="end_datetime" value="{{ default_end_datetime }}"></input></p>
  110 + <button class="btn btn-success" type="submit"> Get data</button>
  111 + </form>
  112 + </div>
  113 + <h3>Weather history </h3>
  114 + <div class="col" id="div_plots">
  115 + <div id="humidity_plot" class="row hbox"></div>
  116 + <div id="pressure_plot" class="row hbox"></div>
  117 + <div id="rain_plot" class="row hbox"></div>
  118 + <div id="temperature_plot" class="row hbox"></div>
  119 + <div id="wind_plot" class="row hbox"></div>
  120 + <div id="wind_dir_plot" class="row hbox"></div>
  121 + </div>
  122 + </div>
  123 +{% endblock %}
0 124 \ No newline at end of file
... ...
src/core/pyros_django/monitoring/urls.py
... ... @@ -6,4 +6,5 @@ urlpatterns = [
6 6 path('index', views.index, name="monitoring_index"),
7 7 path('weather/config', views.weather_config, name="weather_config"),
8 8 path('weather/config/update', views.weather_config_update, name="weather_config_update"),
9   - ]
  9 + path('weather_history', views.weather_history, name="weather_history"),
  10 +]
... ...
src/core/pyros_django/monitoring/views.py
  1 +from datetime import datetime
1 2 from django.http import HttpResponse
2 3 from django.shortcuts import render
3   -from common.models import AgentCmd
  4 +from common.models import AgentCmd, WeatherWatchHistory
  5 +from django.http import Http404
  6 +import json
  7 +from django.db.models import Q
  8 +
  9 +from django.core import serializers
4 10  
5 11 # Create your views here.
6 12  
... ... @@ -13,6 +19,32 @@ def index(request):
13 19  
14 20  
15 21  
  22 +def get_weather_history_from_date(start_datetime:datetime, end_datetime:datetime):
  23 + if WeatherWatchHistory.objects.all().exists():
  24 + weather_history_queryset = WeatherWatchHistory.objects.filter(Q(datetime__gte=start_datetime) & Q(datetime__lte=end_datetime)).order_by("datetime")
  25 + weather = serializers.serialize('json', weather_history_queryset)
  26 + return weather
  27 +
  28 +def weather_history(request):
  29 + if request.GET:
  30 + start_datetime = request.GET.get("start_datetime")
  31 + end_datetime = request.GET.get("end_datetime")
  32 + if start_datetime and end_datetime:
  33 + start_datetime = datetime.strptime(start_datetime, "%d/%m/%Y %H:%M:%S")
  34 + end_datetime = datetime.strptime(end_datetime, "%d/%m/%Y %H:%M:%S")
  35 + try:
  36 + weather_history = get_weather_history_from_date(start_datetime, end_datetime)
  37 + #return HttpResponse(json.dumps(weather), content_type="application/json")
  38 + return HttpResponse(weather_history, content_type="application/json")
  39 + except WeatherWatchHistory.DoesNotExist:
  40 + raise Http404("No WeatherWatchHistory matches the given query.")
  41 + else:
  42 + return HttpResponse(json.dumps({"result":"No required start and end datetime found in query"}), content_type="application/json")
  43 + end_datetime =datetime.utcnow().strftime("%d/%m/%Y %H:%M:%S")
  44 + return render(request,"monitoring/weather_history.html",{
  45 + "default_end_datetime" : end_datetime
  46 + })
  47 +
16 48 def weather_config(request):
17 49 """ PM 20180926 prototype without database
18 50 http://127.0.0.1:8000/dashboard/weather/config
... ...
src/core/pyros_django/pyros/settings.py
... ... @@ -439,7 +439,7 @@ EMAIL_BACKEND = &#39;django.core.mail.backends.console.EmailBackend&#39;
439 439  
440 440 python_version = subprocess.run( "python --version | cut -d ' ' -f 2 | cut -d '.' -f 1,2",shell=True,stdout=subprocess.PIPE,universal_newlines=True)
441 441 python_version = python_version.stdout
442   -day = "2022-04-27"
  442 +day = "2022-04-28"
443 443 django_version_major,django_version_minor = django.VERSION[:2][0],django.VERSION[:2][1]
444 444 pyros_version = read_version_number_from_file(f"{BASE_DIR}/../../../VERSION")
445 445  
... ...