Added routes for ogn-live (#24)

pull/78/head
Konstantin Gründger 2019-05-04 21:32:43 +02:00
rodzic b9eca062b5
commit bfb9ebc08a
4 zmienionych plików z 187 dodań i 101 usunięć

Wyświetl plik

@ -1,10 +1,9 @@
from datetime import datetime, timedelta, timezone, date
from sqlalchemy import func, and_, between, case
from ogn_python.model import AircraftBeacon, Device, Receiver
from ogn_python import db
from ogn_python.model.receiver_beacon import ReceiverBeacon
def utc_to_local(utc_dt):
@ -20,19 +19,24 @@ def decode(code):
def rec():
last_10_minutes = datetime.utcnow() - timedelta(minutes=10)
receiver_query = db.session.query(Receiver,
case([(Receiver.lastseen > last_10_minutes, True)],
else_=False).label('is_online')) \
.order_by(Receiver.name)
min_online_timestamp = datetime.utcnow() - timedelta(minutes=10)
lines = list()
timestamp_range_filter = [db.between(ReceiverBeacon.timestamp, datetime(2018, 7, 31, 11, 55, 0), datetime(2018, 7, 31, 12, 5, 0))]
last_seen_query = db.session.query(ReceiverBeacon) \
.filter(*timestamp_range_filter) \
.order_by(ReceiverBeacon.receiver_id, ReceiverBeacon.timestamp) \
.distinct(ReceiverBeacon.receiver_id)
lines = []
lines.append('<?xml version="1.0" encoding="UTF-8"?>')
lines.append('<markers>')
lines.append('<m e="0"/>')
for [receiver, is_online] in receiver_query.all():
for receiver_beacon in last_seen_query:
if receiver_beacon.location == None or receiver_beacon.name.startswith('FNB'):
continue
lines.append('<m a="{0}" b="{1:.7f}" c="{2:.7f}" d="{3:1d}"/>'
.format(receiver.name, receiver.location.latitude, receiver.location.longitude, is_online))
.format(receiver_beacon.name, receiver_beacon.location.latitude, receiver_beacon.location.longitude, receiver_beacon.timestamp < min_online_timestamp))
lines.append('</markers>')
xml = '\n'.join(lines)
@ -42,24 +46,20 @@ def rec():
def lxml(show_offline=False, lat_max=90, lat_min=-90, lon_max=180, lon_min=-180):
if show_offline:
observation_start = date.today()
else:
observation_start = datetime.utcnow() - timedelta(minutes=5)
timestamp_range_filter = [db.between(AircraftBeacon.timestamp, datetime(2018, 7, 31, 11, 55, 0), datetime(2018, 7, 31, 12, 5, 0))]
position_query = db.session.query(AircraftBeacon, Device) \
.filter(and_(between(func.ST_Y(AircraftBeacon.location_wkt), lat_min, lat_max),
between(func.ST_X(AircraftBeacon.location_wkt), lon_min, lon_max))) \
.filter(Device.lastseen > observation_start) \
.filter(Device.lastseen == AircraftBeacon.timestamp) \
.filter(Device.id == AircraftBeacon.device_id) \
.order_by(AircraftBeacon.timestamp)
last_seen_query = db.session.query(AircraftBeacon) \
.filter(*timestamp_range_filter) \
.order_by(AircraftBeacon.device_id, AircraftBeacon.timestamp) \
.distinct(AircraftBeacon.device_id) \
lines = list()
lines.append('<?xml version="1.0" encoding="UTF-8"?>')
lines.append('<markers>')
for [aircraft_beacon, device] in position_query.all():
for aircraft_beacon in last_seen_query:
device = aircraft_beacon.device
code = encode(device.address)
if device.info:
@ -105,4 +105,4 @@ def lxml(show_offline=False, lat_max=90, lat_min=-90, lon_max=180, lon_min=-180)
lines.append('</markers>')
xml = '\n'.join(lines)
return xml
return xml

Wyświetl plik

@ -0,0 +1,90 @@
from flask import request, render_template, make_response, send_file
from flask_cors import cross_origin
from ogn_python.backend.liveglidernet import rec, lxml
from ogn_python import app
from ogn_python import db
from ogn_python import cache
@app.route('/live.html')
@cross_origin()
def live():
return render_template('ogn_live.html', host=request.host)
@app.route('/rec.php')
def rec_php():
a = request.args.get('a')
z = request.args.get('z')
xml = rec()
resp = app.make_response(xml)
resp.mimetype = "text/xml"
return resp
@app.route('/lxml.php')
def lxml_php():
a = request.args.get('a')
b = request.args.get('b')
c = request.args.get('c')
d = request.args.get('d')
e = request.args.get('e')
z = request.args.get('z')
xml = lxml()
resp = app.make_response(xml)
resp.mimetype = "text/xml"
return resp
@app.route('/pict/<filename>')
def pict(filename):
return app.send_static_file('ognlive/pict/' + filename)
@app.route('/favicon.gif')
def favicon_gif():
return app.send_static_file('ognlive/pict/favicon.gif')
@app.route('/horizZoomControl.js')
def horizZoomControl_js():
return app.send_static_file('ognlive/horizZoomControl.js')
@app.route('/barogram.js')
def barogram_js():
return app.send_static_file('ognlive/barogram.js')
@app.route('/util.js')
def util_js():
return app.send_static_file('ognlive/util.js')
@app.route('/ogn.js')
def ogn_js():
return app.send_static_file('ognlive/ogn.js')
@app.route('/ol.js')
def ol_js():
return app.send_static_file('ognlive/ol.js')
@app.route('/osm.js')
def osm_js():
return app.send_static_file('ognlive/osm.js')
@app.route('/ol.css')
def ol_css():
return app.send_static_file('ognlive/ol.css')
@app.route('/osm.css')
def osm_css():
return app.send_static_file('ognlive/osm.css')

Wyświetl plik

@ -1,7 +1,7 @@
import datetime
from flask import request, render_template
from sqlalchemy import func, and_, or_
from flask import request, render_template, send_file
from flask_cors import cross_origin
from ogn_python import app
from ogn_python import db
@ -24,6 +24,7 @@ def get_countries_in_receivers():
def get_countries_in_logbook():
query = db.session.query(Country.iso2) \
.filter(Country.iso2 == Airport.country_code) \
.filter(Logbook.takeoff_airport_id == Airport.id) \
.order_by(Country.iso2) \
.distinct(Country.iso2)
@ -43,11 +44,11 @@ def get_airports_in_country(sel_country):
@cache.memoize()
def get_dates_for_airport(sel_airport):
query = db.session.query(func.date(Logbook.reftime), func.count(Logbook.id).label('logbook_count')) \
query = db.session.query(db.func.date(Logbook.reftime), db.func.count(Logbook.id).label('logbook_count')) \
.filter(Airport.id == sel_airport) \
.filter(or_(Airport.id == Logbook.takeoff_airport_id, Airport.id == Logbook.landing_airport_id)) \
.group_by(func.date(Logbook.reftime)) \
.order_by(func.date(Logbook.reftime).desc())
.filter(db.or_(Airport.id == Logbook.takeoff_airport_id, Airport.id == Logbook.landing_airport_id)) \
.group_by(db.func.date(Logbook.reftime)) \
.order_by(db.func.date(Logbook.reftime).desc())
return [{'date': date, 'logbook_count': logbook_count} for (date, logbook_count) in query.all()]
@ -87,7 +88,7 @@ def receivers():
# Get receiver selection list
if sel_country:
receivers = db.session.query(Receiver) \
.filter(and_(Receiver.country_id == Country.gid, Country.iso2 == sel_country)) \
.filter(db.and_(Receiver.country_id == Country.gid, Country.iso2 == sel_country)) \
.order_by(Receiver.name)
else:
receivers = db.session.query(Receiver) \
@ -109,9 +110,9 @@ def receiver_detail():
.one()
airport = db.session.query(Airport) \
.filter(and_(Receiver.id == sel_receiver_id,
func.st_contains(func.st_buffer(Receiver.location_wkt, 0.5), Airport.location_wkt),
func.st_distance_sphere(Airport.location_wkt, Receiver.location_wkt) < 1000)) \
.filter(db.and_(Receiver.id == sel_receiver_id,
db.func.st_contains(db.func.st_buffer(Receiver.location_wkt, 0.5), Airport.location_wkt),
db.func.st_distance_sphere(Airport.location_wkt, Receiver.location_wkt) < 1000)) \
.filter(Airport.style.in_((2,4,5))) \
return render_template('receiver_detail.html',
@ -215,6 +216,18 @@ def logbook():
dates=dates,
logbook=logbook)
@app.route('/download.html')
def download_flight():
from io import StringIO
buffer = StringIO()
buffer.write('Moin moin\nAlter Verwalter')
buffer.seek(0)
return send_file(buffer,
as_attachment=True,
attachment_filename='wtf.igc',
mimetype = 'text/plain')
@app.route('/statistics.html')
def statistics():
@ -228,10 +241,3 @@ def statistics():
return render_template('statistics.html',
title='Receiver Statistics',
receiverstats=receiverstats)
# Backend routes for other sites
@app.route('/live.html')
def live():
return render_template('ogn_live.jinja')

Wyświetl plik

@ -1,22 +1,6 @@
<!DOCTYPE html>
<!--
ogn-live - Display glider traffic from OpenGliderNetwork
Copyright (C) 2015 Sebastien Chaumontet and others
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
____ _____ _ _ _ _ _ _ _
/ __ \ / ____| (_) | | | \ | | | | | |
| | | |_ __ ___ _ __ | | __| |_ __| | ___ _ __ | \| | ___| |___ _____ _ __| | __
@ -28,54 +12,60 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<title>Spot the gliders!</title>
<link href="cunimb.css" rel="stylesheet" type="text/css" />
<link rel="shortcut icon" href="favicon.gif"/>
<link rel="icon" type="image/gif" href="favicon.png"/>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<title>Spot the gliders!</title>
<link href="ol.css" rel="stylesheet" type="text/css" />
<link href="osm.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="ol.js"></script>
<script type="text/javascript" src="util.js"></script>
<script type="text/javascript">
var cxml = "lxml.php";
var cxml1 = "livexml1.php";
var dxml = "dataxml.php";
var rxml = "rec.php";
var tld = "http://{{ host }}";
var vlon = 5;
var vlat = 45;
var bound = false;
var boundc = '';
var amax = 85;
var amin = -85;
var omax = 180;
var omin = -180;
var recc = "";
var parc = "";
var tz;
try {
tz = new Date().getTimezoneOffset();
}
catch(e) {
tz = 0;
}
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?v=3&amp;libraries=geometry&amp;sensor=false"></script>
<script type="text/javascript" src="util.js"></script>
<script type="text/javascript">
var cxml = "lxml.php";
var cxml1 = "livexml1.php";
var dxml = "dataxml.php";
var rxml = "rec.php";
var tld = "http://{{ ip_address }}:{{ port }}";
var vlon = 11.0;
var vlat = 48.0;
var vlatmin = 40.0;
var vlonmin = 10.0;
var vlatmax = 60.0;
var vlonmax = 20.0;
var bound = false;
var boundc = '';
var amax = 85;
var amin = -85;
var omax = 180;
var omin = -180;
var recc = "";
var parc = "";
var tz;
try {
tz = new Date().getTimezoneOffset();
} catch (e) {
tz = 0;
}
</script>
<script type="text/javascript" src="cunimb.js"></script>
</script>
<script type="text/javascript" src="ogn.js"></script>
<script type="text/javascript" src="barogram.js"></script>
<script type="text/javascript" src="horizZoomControl.js"></script>
</head>
<body onload="initialize()">
<div id="popup" onclick="cp('popup');"></div>
<div id="map_canvas"></div>
<div id="ac" class="acright" onclick="this.style.display='none';"></div>
<div id="dlist" class="lright">
<DIV id="ett1"></DIV>
<DIV id="ett2"></DIV>
<DIV id="dtable"></DIV>
</div>
<div id="popup" onclick="cp('popup');"></div>
<div id="map_canvas"></div>
<div id="ac" class="acright" onclick="this.style.display='none';"></div>
<div id="lonlatoverlay" style="background-color: white; border-radius: 10px; border: 1px solid black; padding: 5px 10px; display: none;"></div>
<div id="dlist" class="lright">
<DIV id="ett1" ></DIV>
<DIV id="ett2" ></DIV>
<DIV id="dtable"></DIV>
</div>
<div id="dbaro" class="baroleft" style="display:block; visibility:hidden;">
<canvas id="div_baroScale" width="45" ></canvas>
<canvas id="div_baro" width="70"></canvas>
<canvas id="div_baroMark" width="30" ></canvas>
</div>
</body>
</html>