Skip to content

Instantly share code, notes, and snippets.

@tkardi
Last active May 20, 2022 11:51
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tkardi/f9cc6199713adf14f8525ec4494b6710 to your computer and use it in GitHub Desktop.
Save tkardi/f9cc6199713adf14f8525ec4494b6710 to your computer and use it in GitHub Desktop.
Code companion to 'Building a flightradar in Leaflet (pt I)'
# Flask app to run the `proxy.py` script.
# Run it on the path where both of the files are saved with
# (on Linux, for other systems plese see
# http://flask.pocoo.org/docs/1.0/quickstart/#a-minimal-application)
#
# $ export FLASK_APP=flaskapp.py
# $ flask run
#
# This will make the API available at http://127.0.0.1:5000/flightradar
#
# The following Python code is published under the Unlicense.
#
# SPDX-License-Identifier: Unlicense #
import json
from flask import Flask
from flask import Response
from proxy import get_flight_radar_data
app = Flask(__name__)
@app.route('/flightradar')
def flightradar():
return Response(
response=json.dumps(get_flight_radar_data()),
status=200,
mimetype='application/json'
)
<!DOCTYPE html>
<html>
<!-- The following HTML page together with the accompanying
javascript is published under the Unlicense.
SPDX-License-Identifier: Unlicense
-->
<head>
<meta charset="utf-8">
<title>Air traffic map</title>
<link
rel="stylesheet"
type="text/css"
href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.0.1/leaflet.css"/>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.0.1/leaflet.js"
type="text/javascript">
</script>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/leaflet-realtime/2.0.0/leaflet-realtime.min.js"
type="text/javascript">
</script>
<style>
#map {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
}
.aeroplane-visible {
background: #109856;
border: none;
opacity: 1.0;
}
</style>
</head>
<body>
<div id="map">
</div>
<script>
// set up map
var center = [58.65, 25.06];
var map = L.map('map').setView(center, 7);
// Stamen's Toner basemap
L.tileLayer(
'https://stamen-tiles-{s}.a.ssl.fastly.net/toner/{z}/{x}/{y}.png', {
attribution: 'Map tiles by <a href="http://stamen.com">' +
'Stamen Design</a>, under' +
'<a href="http://creativecommons.org/licenses/by/3.0">' +
'CC BY 3.0</a>. Data by <a href="http://openstreetmap.org">' +
'OpenStreetMap</a>, under' +
'<a href="http://www.openstreetmap.org/copyright">ODbL</a>.'
}).addTo(map);
// air traffic locations layer,
// should actually request when the "radar beam" is pointing N e.g
// but we'll go with L.Realtime for the moment.
var realtime = L.realtime('http://127.0.0.1:5000/flightradar', {
// interval of data refresh (in milliseconds)
interval: 10 * 1000,
getFeatureId: function(feature) {
// required for L.Realtime to track which feature is which
// over consecutive data requests.
return feature.id;
},
pointToLayer: function(feature, latlng) {
// style the aeroplane loction markers with L.DivIcons
var marker = L.marker(latlng, {
icon: L.divIcon({
className:'aeroplane-visible',
iconSize: [10,10]
}),
riseOnHover: true
}).bindTooltip(
// and as we're already here, bind a tooltip based on feature
// property values
'<b>{callsign}</b><br>Alt: {geo_altitude} m @ {velocity} m/s'.replace(
L.Util.templateRe, function (str, key) {
var value = feature.properties[key];
if (value === undefined || value == null) {
value = 'N/A';
}
return value;
}),
{
permanent: false, opacity: 0.7}
);
return marker;
}
}).addTo(map);
map.attributionControl.addAttribution(
'<br>Marker animation: <a href="https://github.com/perliedman/leaflet-realtime">Leaflet Realtime</a>'
);
map.attributionControl.addAttribution(
'<br>Air traffic location data from <a href="http://www.opensky-network.org">The OpenSky Network</a>\'s public <a href="https://opensky-network.org/apidoc/">API</a>'
);
</script>
</body>
</html>
# This is the proxy.py script for grabbing realtime aircraft locations
# from the OpenSky Network's (https://opensky-network.org/)
# public API (https://opensky-network.org/apidoc/) and
# reformatting the data as GeoJSON.
#
# Run it as a flask app in your localhost
#
# The following Python code is published under the Unlicense.
#
# SPDX-License-Identifier: Unlicense #
import requests
from collections import OrderedDict
# note the use of bounding box coords in the URL
# this is roughly the area for Latvia, Estonia and
# a small part of southern Finland
url = 'https://opensky-network.org/api/states/all?lamin=57.48&lomin=21.6&lamax=59.82&lomax=28.52'
keys = [
'icao24', 'callsign', 'origin_country', 'time_position', 'last_contact',
'longitude', 'latitude', 'baro_altitude', 'on_ground', 'velocity',
'true_track', 'vertical_rate', 'sensors', 'geo_altitude', 'squawk',
'spi', 'position_source'
]
def get_flight_radar_data():
r = requests.get(url)
r.raise_for_status()
return to_geojson(r.json())
def to_geojson(data):
f = [
OrderedDict(
type='Feature',
id=ac[0],
geometry=OrderedDict(type='Point', coordinates=[ac[5],ac[6]]),
properties=OrderedDict(zip(keys, ac))
) for ac in data.get('states', [])
]
return dict(
type='FeatureCollection',
features=f
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment