2015-11-11 07:03:42 +00:00
|
|
|
import csv
|
2017-10-03 11:31:24 +00:00
|
|
|
import gzip
|
2015-11-11 07:03:42 +00:00
|
|
|
from io import StringIO
|
2015-11-06 21:34:19 +00:00
|
|
|
|
2016-04-22 08:44:39 +00:00
|
|
|
from aerofiles.seeyou import Reader
|
2017-10-03 11:31:24 +00:00
|
|
|
from geopy.exc import GeopyError
|
|
|
|
from geopy.geocoders import Nominatim
|
2018-09-03 17:58:35 +00:00
|
|
|
from ogn.parser.utils import FEETS_TO_METER
|
2017-10-03 11:31:24 +00:00
|
|
|
import requests
|
|
|
|
|
2017-12-02 12:08:44 +00:00
|
|
|
from .model import DeviceInfoOrigin, DeviceInfo, Airport, Location
|
2016-04-22 08:44:39 +00:00
|
|
|
|
2017-06-04 09:52:48 +00:00
|
|
|
|
2016-05-31 18:56:09 +00:00
|
|
|
DDB_URL = "http://ddb.glidernet.org/download/?t=1"
|
2015-11-06 21:34:19 +00:00
|
|
|
|
2015-11-15 07:51:40 +00:00
|
|
|
|
2016-01-05 23:23:45 +00:00
|
|
|
address_prefixes = {'F': 'FLR',
|
|
|
|
'O': 'OGN',
|
|
|
|
'I': 'ICA'}
|
2015-12-01 18:11:31 +00:00
|
|
|
|
2016-04-22 08:44:39 +00:00
|
|
|
nm2m = 1852
|
|
|
|
mi2m = 1609.34
|
|
|
|
|
2015-11-06 21:34:19 +00:00
|
|
|
|
2017-12-08 18:24:33 +00:00
|
|
|
def get_ddb(csvfile=None, address_origin=DeviceInfoOrigin.unknown):
|
2015-11-11 07:03:42 +00:00
|
|
|
if csvfile is None:
|
|
|
|
r = requests.get(DDB_URL)
|
|
|
|
rows = '\n'.join(i for i in r.text.splitlines() if i[0] != '#')
|
|
|
|
else:
|
|
|
|
r = open(csvfile, 'r')
|
|
|
|
rows = ''.join(i for i in r.readlines() if i[0] != '#')
|
|
|
|
|
|
|
|
data = csv.reader(StringIO(rows), quotechar="'", quoting=csv.QUOTE_ALL)
|
2015-11-06 21:34:19 +00:00
|
|
|
|
2016-06-21 17:34:05 +00:00
|
|
|
device_infos = list()
|
2015-11-11 07:03:42 +00:00
|
|
|
for row in data:
|
2016-06-21 17:34:05 +00:00
|
|
|
device_info = DeviceInfo()
|
|
|
|
device_info.address_type = row[0]
|
|
|
|
device_info.address = row[1]
|
|
|
|
device_info.aircraft = row[2]
|
|
|
|
device_info.registration = row[3]
|
|
|
|
device_info.competition = row[4]
|
|
|
|
device_info.tracked = row[5] == 'Y'
|
|
|
|
device_info.identified = row[6] == 'Y'
|
|
|
|
device_info.aircraft_type = int(row[7])
|
2017-12-08 18:24:33 +00:00
|
|
|
device_info.address_origin = address_origin
|
2016-06-21 17:34:05 +00:00
|
|
|
|
|
|
|
device_infos.append(device_info)
|
|
|
|
|
|
|
|
return device_infos
|
2015-11-06 21:34:19 +00:00
|
|
|
|
|
|
|
|
2015-12-01 18:11:31 +00:00
|
|
|
def get_trackable(ddb):
|
2016-01-05 23:23:45 +00:00
|
|
|
l = []
|
|
|
|
for i in ddb:
|
|
|
|
if i.tracked and i.address_type in address_prefixes:
|
2016-02-03 22:19:25 +00:00
|
|
|
l.append("{}{}".format(address_prefixes[i.address_type], i.address))
|
2016-01-05 23:23:45 +00:00
|
|
|
return l
|
2015-12-01 18:11:31 +00:00
|
|
|
|
|
|
|
|
2015-11-06 21:34:19 +00:00
|
|
|
def get_country_code(latitude, longitude):
|
|
|
|
geolocator = Nominatim()
|
2015-11-12 07:38:43 +00:00
|
|
|
try:
|
2016-02-03 22:19:25 +00:00
|
|
|
location = geolocator.reverse("{}, {}".format(latitude, longitude))
|
|
|
|
country_code = location.raw['address']['country_code']
|
2015-11-12 07:38:43 +00:00
|
|
|
except KeyError:
|
|
|
|
country_code = None
|
2016-02-03 22:09:11 +00:00
|
|
|
except GeopyError:
|
|
|
|
country_code = None
|
2015-11-06 21:34:19 +00:00
|
|
|
return country_code
|
2016-01-28 19:29:08 +00:00
|
|
|
|
|
|
|
|
2016-04-22 08:44:39 +00:00
|
|
|
def get_airports(cupfile):
|
|
|
|
airports = list()
|
|
|
|
with open(cupfile) as f:
|
|
|
|
for line in f:
|
|
|
|
try:
|
|
|
|
for waypoint in Reader([line]):
|
2016-05-22 05:26:02 +00:00
|
|
|
if waypoint['style'] > 5: # reject unlandable places
|
|
|
|
continue
|
|
|
|
|
2016-04-22 08:44:39 +00:00
|
|
|
airport = Airport()
|
|
|
|
airport.name = waypoint['name']
|
|
|
|
airport.code = waypoint['code']
|
|
|
|
airport.country_code = waypoint['country']
|
|
|
|
airport.style = waypoint['style']
|
|
|
|
airport.description = waypoint['description']
|
2016-04-24 17:34:25 +00:00
|
|
|
location = Location(waypoint['longitude'], waypoint['latitude'])
|
|
|
|
airport.location_wkt = location.to_wkt()
|
2016-04-22 08:44:39 +00:00
|
|
|
airport.altitude = waypoint['elevation']['value']
|
|
|
|
if (waypoint['elevation']['unit'] == 'ft'):
|
2018-09-03 17:58:35 +00:00
|
|
|
airport.altitude = airport.altitude * FEETS_TO_METER
|
2016-04-22 08:44:39 +00:00
|
|
|
airport.runway_direction = waypoint['runway_direction']
|
|
|
|
airport.runway_length = waypoint['runway_length']['value']
|
|
|
|
if (waypoint['runway_length']['unit'] == 'nm'):
|
2016-04-24 17:34:25 +00:00
|
|
|
airport.altitude = airport.altitude * nm2m
|
2016-04-22 08:44:39 +00:00
|
|
|
elif (waypoint['runway_length']['unit'] == 'ml'):
|
2016-04-24 17:34:25 +00:00
|
|
|
airport.altitude = airport.altitude * mi2m
|
2016-04-22 08:44:39 +00:00
|
|
|
airport.frequency = waypoint['frequency']
|
|
|
|
|
|
|
|
airports.append(airport)
|
2016-04-24 17:34:25 +00:00
|
|
|
except AttributeError as e:
|
|
|
|
print('Failed to parse line: {} {}'.format(line, e))
|
2016-04-22 08:44:39 +00:00
|
|
|
|
|
|
|
return airports
|
2017-06-04 09:52:48 +00:00
|
|
|
|
|
|
|
|
|
|
|
def open_file(filename):
|
|
|
|
"""Opens a regular or unzipped textfile for reading."""
|
2017-10-03 11:31:24 +00:00
|
|
|
f = open(filename, 'rb')
|
2017-06-04 09:52:48 +00:00
|
|
|
a = f.read(2)
|
|
|
|
f.close()
|
|
|
|
if (a == b'\x1f\x8b'):
|
|
|
|
f = gzip.open(filename, 'rt')
|
|
|
|
return f
|
|
|
|
else:
|
|
|
|
f = open(filename, 'rt')
|
|
|
|
return f
|
2018-09-03 17:58:35 +00:00
|
|
|
|
|
|
|
from math import radians, cos, sin, asin, sqrt, atan2, degrees
|
|
|
|
|
|
|
|
def haversine(lat1, lon1, lat2, lon2):
|
|
|
|
"""
|
|
|
|
Calculate the great circle distance between two points
|
|
|
|
on the earth (specified in decimal degrees)
|
|
|
|
"""
|
|
|
|
# convert decimal degrees to radians
|
|
|
|
lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])
|
|
|
|
|
|
|
|
# haversine formula
|
|
|
|
dlon = lon2 - lon1
|
|
|
|
dlat = lat2 - lat1
|
|
|
|
a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
|
|
|
|
c = 2 * asin(sqrt(a))
|
|
|
|
r = 6371000.785 # Radius of earth in meters
|
|
|
|
d = c * r
|
|
|
|
|
|
|
|
# calculate bearing
|
|
|
|
bearing = atan2(sin(dlon)*cos(lat2), cos(lat1)*sin(lat2)-sin(lat1)*cos(lat2)*cos(dlon))
|
|
|
|
bearing = (degrees(bearing) + 360) % 360
|
|
|
|
|
|
|
|
return d,bearing
|