Skip to content

Commit 534516a

Browse files
authored
Merge pull request #2 from pyobs/develop
v1.1
2 parents 0a89ae4 + c5201c2 commit 534516a

File tree

15 files changed

+265
-15
lines changed

15 files changed

+265
-15
lines changed

README.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,4 +130,16 @@ Probably you want to exclude the actual sensor readings and only backup the conf
130130

131131
In a fresh setup, you can restore the data via the 'loaddata' command:
132132

133-
./manage.py loaddata weather.json
133+
./manage.py loaddata weather.json
134+
135+
136+
## Changelog
137+
138+
#### version 1.0 (2020-11-23)
139+
- Initial release
140+
141+
#### version 1.1 (2020-11-24)
142+
- Added footer to page
143+
- Exclude average station from status evaluation
144+
- Logging current good/bad weather status
145+
- Added plot for solar elevation and good weather for last 24h

pyobs_weather/api/urls.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
path('stations/<str:station_code>/', views.station_detail, name='station_detail'),
1111
path('stations/<str:station_code>/<str:sensor_code>/', views.sensor_detail, name='sensor_detail'),
1212
path('history/', views.history_types, name='history_types'),
13+
path('history/goodweather/', views.good_weather, name='good_weather'),
1314
path('history/<str:sensor_type>/', views.history, name='history'),
1415
path('sensors/', views.sensors, name='sensor_status'),
1516
path('timeline/', views.timeline, name='timeline'),

pyobs_weather/api/views.py

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@
22
import dateutil.parser
33
from astroplan import Observer
44
from astropy.coordinates import EarthLocation
5-
from astropy.time import Time
5+
from astropy.time import Time, TimeDelta
66
import astropy.units as u
77
from django.conf import settings
88
from django.db.models import F
99
from django.http import JsonResponse, HttpResponseNotFound
10+
import numpy as np
1011

1112
from pyobs_weather.weather import evaluators
12-
from pyobs_weather.weather.models import Station, Sensor, Value, SensorType
13+
from pyobs_weather.weather.models import Station, Sensor, Value, SensorType, GoodWeather
1314
from pyobs_weather.weather.tasks import create_evaluator
1415

1516

@@ -232,3 +233,25 @@ def timeline(request):
232233

233234
# return all
234235
return JsonResponse({'time': now.isot, 'events': events})
236+
237+
238+
def good_weather(request):
239+
# get changes in status from last 24 hours
240+
changes = [{'time': g.time, 'good': g.good}
241+
for g in GoodWeather.objects.filter(time__gt=datetime.utcnow() - timedelta(days=1)).all()]
242+
243+
# get location
244+
location = EarthLocation(lon=settings.OBSERVER_LOCATION['longitude'] * u.deg,
245+
lat=settings.OBSERVER_LOCATION['latitude'] * u.deg,
246+
height=settings.OBSERVER_LOCATION['elevation'] * u.m)
247+
248+
# get observer and now
249+
now = Time.now()
250+
observer = Observer(location=location)
251+
252+
# get solar elevation for last 12 hours
253+
times = [now - TimeDelta((1. - x) * u.day) for x in np.linspace(0, 1, 100)]
254+
sun = [s.alt.degree for s in observer.sun_altaz(times)]
255+
256+
# return all
257+
return JsonResponse({'changes': changes, 'sun': {'time': [t.isot for t in times], 'alt': sun}})

pyobs_weather/frontend/static/frontend/css/styles.css

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,14 @@ table#current td {
5252
padding: 0;
5353
}
5454

55+
#wrap {
56+
min-height: 100%;
57+
}
58+
5559
#main {
60+
overflow: auto;
5661
margin-top: 70px;
62+
padding-bottom: 50px; /* this needs to be bigger than footer height*/
5763
}
5864

5965
#header {
@@ -96,4 +102,15 @@ p.sensorUnit {
96102
#timeline_plot {
97103
border: 1px solid black;
98104
display: block;
105+
}
106+
107+
footer {
108+
background-color: black;
109+
color: grey;
110+
text-align: center;
111+
position: relative;
112+
margin-top: -40px; /* negative value of footer height */
113+
height: 40px;
114+
clear: both;
115+
padding-top: 0.5em
99116
}

pyobs_weather/frontend/static/frontend/js/app.js

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,9 @@ function plot(canvas) {
7676
},
7777
options: {
7878
scales: {
79+
bounds: 'ticks',
7980
xAxes: [{
81+
source: 'auto',
8082
type: 'time',
8183
time: {
8284
tooltipFormat: 'YYYY-MM-DD HH:mm.ss',
@@ -87,6 +89,10 @@ function plot(canvas) {
8789
hour: 'HH:mm'
8890
}
8991
},
92+
ticks: {
93+
min: moment.utc().subtract(1, 'days').format('YYYY-MM-DD HH:mm:ss'),
94+
max: moment.utc().format('YYYY-MM-DD HH:mm:ss')
95+
},
9096
distribution: 'linear',
9197
scaleLabel: {
9298
display: true,
@@ -97,6 +103,11 @@ function plot(canvas) {
97103
scaleLabel: {
98104
display: true,
99105
labelString: label
106+
},
107+
ticks: {
108+
callback: function (value) {
109+
return value.toFixed(1);
110+
}
100111
}
101112
}]
102113
},
@@ -250,11 +261,134 @@ function update_timeline() {
250261
setTimeout(update_timeline, 60000);
251262
}
252263

264+
function create_good_annotation(good) {
265+
return {
266+
type: 'box',
267+
display: true,
268+
xScaleID: 'x-axis-0',
269+
yScaleID: 'y-axis-0',
270+
drawTime: 'beforeDatasetsDraw',
271+
borderWidth: 0,
272+
backgroundColor: good ? 'rgba(0, 255, 0, 0.5)' : 'rgba(255, 0, 0, 0.5)'
273+
}
274+
}
275+
276+
function plot_good_history() {
277+
// do AJAX request
278+
$.ajax({
279+
url: rootURL + 'api/history/goodweather/',
280+
dataType: 'json',
281+
}).done(function (results) {
282+
// format data
283+
let data = [];
284+
results.sun.time.forEach(function (value, index) {
285+
data.push({t: new moment.utc(value).format('YYYY-MM-DD HH:mm:ss'), y: results.sun.alt[index]})
286+
});
287+
288+
// annotations
289+
let annotations = [];
290+
for (let i = 0; i < results.changes.length; i++) {
291+
// get change
292+
let change = results.changes[i];
293+
294+
// first one needs an additional annotation
295+
if (i === 0) {
296+
let ann = create_good_annotation(!change.good);
297+
ann.xMax = moment.utc(change.time).format('YYYY-MM-DD HH:mm:ss');
298+
annotations.push(ann);
299+
}
300+
301+
// min/max depends on first/last
302+
let ann = create_good_annotation(change.good);
303+
ann.xMin = moment.utc(change.time).format('YYYY-MM-DD HH:mm:ss');
304+
if (results.changes.length > i + 1) {
305+
ann.xMax = moment.utc(results.changes[i + 1].time).format('YYYY-MM-DD HH:mm:ss');
306+
}
307+
annotations.push(ann);
308+
}
309+
310+
// add annotation for line at 0
311+
annotations.push({
312+
type: 'line',
313+
mode: 'horizontal',
314+
scaleID: 'y-axis-0',
315+
value: 0,
316+
borderColor: 'rgb(0, 0, 0, 0.5)',
317+
borderWidth: 1
318+
})
319+
320+
// create plot
321+
new Chart($('#goodhistory')[0].getContext('2d'), {
322+
type: 'line',
323+
data: {
324+
datasets: [{
325+
label: undefined,
326+
data: data,
327+
backgroundColor: 'rgb(255, 255, 100, 0.5)',
328+
borderColor: 'rgb(255, 255, 100, 1)',
329+
pointRadius: 0,
330+
fill: false,
331+
lineTension: 0.2
332+
}]
333+
},
334+
options: {
335+
animation: {
336+
duration: 0
337+
},
338+
legend: {
339+
display: false
340+
},
341+
scales: {
342+
bounds: 'ticks',
343+
xAxes: [{
344+
type: 'time',
345+
source: 'auto',
346+
distribution: 'linear',
347+
time: {
348+
tooltipFormat: 'YYYY-MM-DD HH:mm.ss',
349+
displayFormats: {
350+
millisecond: 'HH:mm',
351+
second: 'HH:mm',
352+
minute: 'HH:mm',
353+
hour: 'HH:mm'
354+
}
355+
},
356+
ticks: {
357+
min: moment.utc().subtract(1, 'days').format('YYYY-MM-DD HH:mm:ss'),
358+
max: moment.utc().format('YYYY-MM-DD HH:mm:ss')
359+
},
360+
scaleLabel: {
361+
display: true,
362+
labelString: 'Time [UT]',
363+
}
364+
}],
365+
yAxes: [{
366+
scaleLabel: {
367+
display: true,
368+
labelString: 'Sun/good'
369+
},
370+
}]
371+
},
372+
annotation: {
373+
annotations: annotations
374+
}
375+
}
376+
});
377+
378+
});
379+
}
380+
381+
function update_good_history() {
382+
plot_good_history();
383+
setTimeout(update_good_history, 60000);
384+
}
385+
253386
$(function () {
254387
Chart.defaults.global.defaultFontFamily = 'Alegreya';
255388

256389
$(window).on('resize', draw_timeline);
257390
update_timeline();
258391
update_plots();
392+
update_good_history();
259393
update_values();
260394
});

pyobs_weather/frontend/static/frontend/js/vendor/Chart.min.js

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyobs_weather/frontend/templates/base.html

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!doctype html>
2-
{% load static %}
2+
{% load static version %}
33
<html>
44
<head>
55
<title>{{ title }}</title>
@@ -8,7 +8,7 @@
88
<link rel="stylesheet" href="{% static "frontend/css/vendor/bootstrap.min.css" %}">
99
<link rel="stylesheet" href="{% static "frontend/css/vendor/Chart.min.css" %}">
1010
<link rel="stylesheet" href="{% static "frontend/css/styles.css" %}">
11-
<script>let rootURL='{{ root_url|safe }}';</script>
11+
<script>let rootURL = '{{ root_url|safe }}';</script>
1212
</head>
1313
<body>
1414

@@ -52,12 +52,19 @@
5252
</div>
5353
</nav>
5454

55-
<div id="main" class="container">
56-
<div id="alert-error"></div>
57-
{% block content %}
58-
{% endblock %}
55+
<div id="wrap">
56+
<div id="main" class="container">
57+
<div id="alert-error"></div>
58+
{% block content %}
59+
{% endblock %}
60+
</div>
5961
</div>
6062

63+
<footer>
64+
pyobs-weather v{% version %} (<a href="https://github.com/pyobs/pyobs-weather">GitHub</a>)
65+
by <a href="mailto:[email protected]">Tim-Oliver Husser</a>
66+
</footer>
67+
6168
<script src="{% static "frontend/js/vendor/jquery.min.js" %}"></script>
6269
<script src="{% static "frontend/js/vendor/moment.min.js" %}"></script>
6370
<script src="{% static "frontend/js/app.js" %}"></script>

pyobs_weather/frontend/templates/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ <h2>{{ site }}</h2>
4141
</div>
4242

4343
<h3>Plots for last 24h</h3>
44+
<canvas id="goodhistory" width="600" height="100"></canvas>
4445
{% for type in plot_types %}
4546
<canvas data-sensor-type="{{ type.code }}" data-sensor-label="{{ type.name }}"
4647
class="plot" width="600" height="150"></canvas>

pyobs_weather/frontend/templatetags/__init__.py

Whitespace-only changes.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from django import template
2+
from pyobs_weather.version import VERSION
3+
4+
register = template.Library()
5+
6+
7+
@register.simple_tag
8+
def version():
9+
return VERSION

0 commit comments

Comments
 (0)