Merge branch 'group-obs-fixes' into 'dev'
Fixes on Observations Group Scheduling See merge request librespacefoundation/satnogs/satnogs-network!493environments/stage/deployments/120
commit
609b8c30cf
|
@ -36,24 +36,29 @@ def calculate_polar_data(observer, satellite, start, end, points):
|
|||
|
||||
|
||||
def resolve_overlaps(station, gs_data, start, end):
|
||||
overlapped = False
|
||||
if gs_data:
|
||||
for datum in gs_data:
|
||||
if datum.is_past:
|
||||
continue
|
||||
if datum.start <= end and start <= datum.end:
|
||||
overlapped = True
|
||||
if datum.start <= start and datum.end >= end:
|
||||
return False
|
||||
return ()
|
||||
if start < datum.start and end > datum.end:
|
||||
start1 = start
|
||||
end1 = datum.start
|
||||
start2 = datum.end
|
||||
end1 = datum.start - timedelta(seconds=10)
|
||||
start2 = datum.end + timedelta(seconds=10)
|
||||
end2 = end
|
||||
return start1, end1, start2, end2
|
||||
if datum.start <= start:
|
||||
start = datum.end
|
||||
start = datum.end + timedelta(seconds=10)
|
||||
if datum.end >= end:
|
||||
end = datum.start
|
||||
return start, end
|
||||
end = datum.start - timedelta(seconds=10)
|
||||
if overlapped:
|
||||
return start, end, overlapped
|
||||
else:
|
||||
return start, end
|
||||
|
||||
|
||||
def cache_get_key(*args, **kwargs):
|
||||
|
|
|
@ -235,6 +235,33 @@ def observation_new(request):
|
|||
messages.error(request, 'Please schedule an observation that begins in the future')
|
||||
return redirect(reverse('base:observation_new'))
|
||||
|
||||
total = int(request.POST.get('total'))
|
||||
changed = 0
|
||||
for item in range(total):
|
||||
start = make_aware(datetime.strptime(
|
||||
request.POST.get('{0}-starting_time'.format(item)), '%Y-%m-%d %H:%M:%S.%f'
|
||||
))
|
||||
end = make_aware(datetime.strptime(
|
||||
request.POST.get('{}-ending_time'.format(item)), '%Y-%m-%d %H:%M:%S.%f'
|
||||
))
|
||||
station_id = request.POST.get('{}-station'.format(item))
|
||||
station = Station.objects.get(id=station_id)
|
||||
gs_data = Observation.objects.filter(ground_station=station)
|
||||
window = resolve_overlaps(station, gs_data, start, end)
|
||||
if (len(window) > 2 or len(window) == 0):
|
||||
changed += 1
|
||||
|
||||
if changed > 0:
|
||||
error_message = (
|
||||
str(changed) + " observations are already scheduled or overlap with others."
|
||||
" Please recalculate and try schedule them again."
|
||||
)
|
||||
if(changed == 1):
|
||||
error_message = (
|
||||
"The observation is already scheduled or overlaps with others."
|
||||
" Please recalculate and try schedule it again.")
|
||||
messages.error(request, error_message)
|
||||
return redirect(reverse('base:observation_new'))
|
||||
start = make_aware(start_time, utc)
|
||||
end = make_aware(end_time, utc)
|
||||
sat = Satellite.objects.get(norad_cat_id=sat_id)
|
||||
|
@ -247,8 +274,6 @@ def observation_new(request):
|
|||
observer = ephem.Observer()
|
||||
observer.date = str(start)
|
||||
|
||||
total = int(request.POST.get('total'))
|
||||
|
||||
scheduled = []
|
||||
|
||||
for item in range(total):
|
||||
|
@ -385,26 +410,26 @@ def prediction_windows(request, sat_id, transmitter, start_date, end_date,
|
|||
observer.elevation = station.alt
|
||||
observer.date = str(start_date)
|
||||
station_match = False
|
||||
keep_digging = True
|
||||
while keep_digging:
|
||||
while True:
|
||||
try:
|
||||
tr, azr, tt, altt, ts, azs = observer.next_pass(satellite)
|
||||
except ValueError:
|
||||
data = {
|
||||
'error': 'That satellite seems to stay always below your horizon.'
|
||||
}
|
||||
if len(stations) == 1:
|
||||
data = [{
|
||||
'error': 'That satellite seems to stay always below your horizon.'
|
||||
}]
|
||||
break
|
||||
|
||||
# no match if the sat will not rise above the configured min horizon
|
||||
elevation = format(math.degrees(altt), '.0f')
|
||||
if float(elevation) >= station.horizon:
|
||||
if ephem.Date(tr).datetime() < end_date:
|
||||
if ephem.Date(ts).datetime() > end_date:
|
||||
ts = end_date
|
||||
keep_digging = False
|
||||
else:
|
||||
time_start_new = ephem.Date(ts).datetime() + timedelta(minutes=1)
|
||||
observer.date = time_start_new.strftime("%Y-%m-%d %H:%M:%S.%f")
|
||||
if ephem.Date(tr).datetime() < end_date:
|
||||
if ephem.Date(ts).datetime() > end_date:
|
||||
break
|
||||
else:
|
||||
time_start_new = ephem.Date(ts).datetime() + timedelta(minutes=1)
|
||||
observer.date = time_start_new.strftime("%Y-%m-%d %H:%M:%S.%f")
|
||||
|
||||
if float(elevation) >= station.horizon:
|
||||
|
||||
# Adjust or discard window if overlaps exist
|
||||
window_start = make_aware(ephem.Date(tr).datetime(), utc)
|
||||
|
@ -413,40 +438,43 @@ def prediction_windows(request, sat_id, transmitter, start_date, end_date,
|
|||
# Check if overlaps with existing scheduled observations
|
||||
gs_data = Observation.objects.filter(ground_station=station)
|
||||
window = resolve_overlaps(station, gs_data, window_start, window_end)
|
||||
window_length = len(window)
|
||||
|
||||
if window:
|
||||
if window_length > 0:
|
||||
if not station_match:
|
||||
station_windows = {
|
||||
'id': station.id,
|
||||
'name': station.name,
|
||||
'status': station.status,
|
||||
'window': []
|
||||
}
|
||||
station_match = True
|
||||
|
||||
window_start = window[0]
|
||||
window_end = window[1]
|
||||
station_windows['window'].append(
|
||||
{
|
||||
'start': window_start.strftime("%Y-%m-%d %H:%M:%S.%f"),
|
||||
'end': window_end.strftime("%Y-%m-%d %H:%M:%S.%f"),
|
||||
'az_start': azr
|
||||
'az_start': azr,
|
||||
'overlapped': window_length != 2
|
||||
})
|
||||
# In case our window was split in two
|
||||
try:
|
||||
if window_length == 4:
|
||||
# In this case our window was split in two
|
||||
window_start = window[2]
|
||||
window_end = window[3]
|
||||
station_windows['window'].append(
|
||||
{
|
||||
'start': window_start.strftime("%Y-%m-%d %H:%M:%S.%f"),
|
||||
'end': window_end.strftime("%Y-%m-%d %H:%M:%S.%f"),
|
||||
'az_start': azr
|
||||
'az_start': azr,
|
||||
'overlapped': True
|
||||
})
|
||||
except IndexError:
|
||||
pass
|
||||
else:
|
||||
# window start outside of window bounds
|
||||
break
|
||||
# did not rise above user configured horizon
|
||||
continue
|
||||
else:
|
||||
# did not rise above user configured horizon
|
||||
# window start outside of window bounds
|
||||
break
|
||||
|
||||
if station_match:
|
||||
|
|
|
@ -312,9 +312,9 @@ OPBEAT = {
|
|||
# Observations settings
|
||||
# Datetimes in minutes for scheduling OPTIONS
|
||||
OBSERVATION_DATE_MIN_START = config('OBSERVATION_DATE_MIN_START', default=15, cast=int)
|
||||
OBSERVATION_DATE_MIN_END = config('OBSERVATION_DATE_MIN_START', default=75, cast=int)
|
||||
OBSERVATION_DATE_MIN_END = config('OBSERVATION_DATE_MIN_START', default=25, cast=int)
|
||||
# Deletion range in minutes
|
||||
OBSERVATION_DATE_MAX_RANGE = config('OBSERVATION_DATE_MAX_RANGE', default=480, cast=int)
|
||||
OBSERVATION_DATE_MAX_RANGE = config('OBSERVATION_DATE_MAX_RANGE', default=2880, cast=int)
|
||||
# Clean up threshold in days
|
||||
OBSERVATION_OLD_RANGE = config('OBSERVATION_OLD_RANGE', default=30, cast=int)
|
||||
|
||||
|
|
|
@ -22,18 +22,32 @@ $(document).ready( function(){
|
|||
}
|
||||
|
||||
if (!obs_filter_dates) {
|
||||
var minstart = $('#datetimepicker-start').data('date-minstart');
|
||||
var minend = $('#datetimepicker-end').data('date-minend');
|
||||
var maxrange = $('#datetimepicker-end').data('date-maxrange');
|
||||
$('#datetimepicker-start').datetimepicker();
|
||||
$('#datetimepicker-start').data('DateTimePicker').minDate(moment.utc().add(minstart, 'm'));
|
||||
$('#datetimepicker-end').datetimepicker();
|
||||
$('#datetimepicker-end').data('DateTimePicker').minDate(moment.utc().add(minend, 'm'));
|
||||
var minStart = $('#datetimepicker-start').data('date-minstart');
|
||||
var minEnd = $('#datetimepicker-end').data('date-minend');
|
||||
var maxRange = $('#datetimepicker-end').data('date-maxrange');
|
||||
var minRange = minEnd - minStart;
|
||||
var minStartDate = moment().utc().add(minStart, 'm').format('YYYY-MM-DD HH:mm');
|
||||
var maxStartDate = moment().utc().add(minStart + maxRange - minRange, 'm').format('YYYY-MM-DD HH:mm');
|
||||
var minEndDate = moment().utc().add(minEnd, 'm').format('YYYY-MM-DD HH:mm');
|
||||
var maxEndDate = moment().utc().add(minStart + maxRange, 'm').format('YYYY-MM-DD HH:mm');
|
||||
$('#datetimepicker-start').datetimepicker({
|
||||
useCurrent: false //https://github.com/Eonasdan/bootstrap-datetimepicker/issues/1075
|
||||
});
|
||||
$('#datetimepicker-start').data('DateTimePicker').date(minStartDate);
|
||||
$('#datetimepicker-start').data('DateTimePicker').minDate(minStartDate);
|
||||
$('#datetimepicker-start').data('DateTimePicker').maxDate(maxStartDate);
|
||||
$('#datetimepicker-end').datetimepicker({
|
||||
useCurrent: false //https://github.com/Eonasdan/bootstrap-datetimepicker/issues/1075
|
||||
});
|
||||
$('#datetimepicker-end').data('DateTimePicker').date(minEndDate);
|
||||
$('#datetimepicker-end').data('DateTimePicker').minDate(minEndDate);
|
||||
$('#datetimepicker-end').data('DateTimePicker').maxDate(maxEndDate);
|
||||
$('#datetimepicker-start').on('dp.change',function (e) {
|
||||
// Setting default, minimum and maximum for end
|
||||
$('#datetimepicker-end').data('DateTimePicker').defaultDate(moment.utc(e.date).add(60, 'm'));
|
||||
$('#datetimepicker-end').data('DateTimePicker').minDate(e.date);
|
||||
$('#datetimepicker-end').data('DateTimePicker').maxDate(moment.utc(e.date).add(maxrange, 'm'));
|
||||
var newMinEndDate = e.date.clone().add(minRange, 'm');
|
||||
if ($('#datetimepicker-end').data('DateTimePicker').date() < newMinEndDate) {
|
||||
$('#datetimepicker-end').data('DateTimePicker').date(newMinEndDate);
|
||||
}
|
||||
$('#datetimepicker-end').data('DateTimePicker').minDate(newMinEndDate);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -64,8 +78,8 @@ $(document).ready( function(){
|
|||
beforeSend: function() { $('#loading').show(); }
|
||||
}).done(function(data) {
|
||||
$('#loading').hide();
|
||||
if (data.error) {
|
||||
var error_msg = data.error;
|
||||
if (data.length == 1 && data[0].error) {
|
||||
var error_msg = data[0].error;
|
||||
$('#windows-data').html('<span class="text-danger">' + error_msg + '</span>');
|
||||
} else {
|
||||
var dc = 0; // Data counter
|
||||
|
@ -73,18 +87,24 @@ $(document).ready( function(){
|
|||
var label = '';
|
||||
$('#windows-data').empty();
|
||||
$.each(data, function(i, k){
|
||||
label = k.id + ' - ' + k.name;
|
||||
var times = [];
|
||||
$.each(k.window, function(m, n){
|
||||
var starting_time = moment.utc(n.start).valueOf();
|
||||
var ending_time = moment.utc(n.end).valueOf();
|
||||
$('#windows-data').append('<input type="hidden" name="' + dc + '-starting_time" value="' + n.start + '">');
|
||||
$('#windows-data').append('<input type="hidden" name="' + dc + '-ending_time" value="' + n.end + '">');
|
||||
$('#windows-data').append('<input type="hidden" name="' + dc + '-station" value="' + k.id + '">');
|
||||
times.push({starting_time: starting_time, ending_time: ending_time});
|
||||
dc = dc + 1;
|
||||
});
|
||||
suggested_data.push({label: label, times: times});
|
||||
if(k.status !== 1 || obs_filter_station){
|
||||
label = k.id + ' - ' + k.name;
|
||||
var times = [];
|
||||
$.each(k.window, function(m, n){
|
||||
if(!n.overlapped || obs_filter_station){
|
||||
var starting_time = moment.utc(n.start).valueOf();
|
||||
var ending_time = moment.utc(n.end).valueOf();
|
||||
$('#windows-data').append('<input type="hidden" name="' + dc + '-starting_time" value="' + n.start + '">');
|
||||
$('#windows-data').append('<input type="hidden" name="' + dc + '-ending_time" value="' + n.end + '">');
|
||||
$('#windows-data').append('<input type="hidden" name="' + dc + '-station" value="' + k.id + '">');
|
||||
times.push({starting_time: starting_time, ending_time: ending_time});
|
||||
dc = dc + 1;
|
||||
}
|
||||
});
|
||||
if(times.length > 0){
|
||||
suggested_data.push({label: label, times: times});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$('#windows-data').append('<input type="hidden" name="total" value="' + dc + '">');
|
||||
|
|
Loading…
Reference in New Issue