Commit 1832e49b authored by Baptiste Jonglez's avatar Baptiste Jonglez

Allow to use several altitude providers

Two altitude providers are now used by default:

- a very accurate provider, but limited to France
- as a fallback, a less accurate provider, but with a global coverage
parent 028abfd9
from __future__ import unicode_literals, division, print_function
import requests
import logging
import re
logger = logging.getLogger(__name__)
class AltitudeProvider(object):
url_template = "http://example.com/{lon}/{lat}"
def parse_answer(self, req):
"""[req] is a Request instances from requests. Should return a float."""
try:
return float(req.text)
except ValueError:
raise
class GeonamesProvider(AltitudeProvider):
url_template = "http://api.geonames.org/astergdem?lat={lat}&lng={lon}&username=celutz&style=full"
class GeoportailProvider(AltitudeProvider):
url_template = "https://wxs.ign.fr/an7nvfzojv5wa96dsga5nk8w/alti/rest/elevation.xml?lon={lon}&lat={lat}&indent=false&crs=%27CRS:84%27&zonly=true"
def parse_answer(self, req):
m = re.search(r'<z>(.*)</z>', req.text)
if m == None:
raise ValueError
return float(m.group(1))
# Main function
def get_altitude(providers, timeout, latitude, longitude):
"""Given a list of altitude provider classes, and a timeout for each
provider, try them all in order until we obtain a reasonable altitude
for the given coordinates.
If all providers fail, returns None.
"""
# Try all providers in order
for Provider in providers:
name = Provider.__name__
logger.info("Trying {}…".format(name))
provider = Provider()
url = provider.url_template.format(lat=latitude, lon=longitude)
try:
r = requests.get(url, timeout=timeout)
except requests.exceptions.ReadTimeout:
logger.warning("{} timeout out after {} seconds".format(name, timeout))
continue
if r.status_code != 200:
continue
try:
alt = provider.parse_answer(r)
logger.info("Got {}m".format(alt))
if alt < 0:
continue
return alt
except ValueError:
continue
# If all providers failed, return nothing
from django.conf.urls import url
from django.views.decorators.cache import cache_page
from altitude.views import geonames_altitude
from altitude.views import get_altitude
urlpatterns = [
url(r'^(?P<lat>-?\d+(?:\.\d+)?)/(?P<lon>-?\d+(?:\.\d+)?)/$', cache_page(7*24*60*60)(geonames_altitude)),
url(r'^(?P<lat>-?\d+(?:\.\d+)?)/(?P<lon>-?\d+(?:\.\d+)?)/$', cache_page(7*24*60*60)(get_altitude)),
]
import requests
import logging
from django.http import HttpResponse, HttpResponseServerError
from django.conf import settings
logger = logging.getLogger(__name__)
import altitude.providers
def geonames_altitude(request, lat, lon):
def get_altitude(request, lat, lon):
lat = float(lat)
lon = float(lon)
url = settings.GEONAMES_ASTERGDEM.format(lat=lat, lon=lon)
r = requests.get(url)
if r.status_code != 200:
return HttpResponseServerError()
# The API sometimes returns an error but still sends a 200 code,
# so we validate the answer just to make sure...
try:
return HttpResponse(float(r.text))
except ValueError:
logger.warning("api.geonames.org error: {}".format(r.text))
alt = altitude.providers.get_altitude(settings.ALTITUDE_PROVIDERS,
settings.ALTITUDE_PROVIDER_TIMEOUT,
lat, lon)
if alt == None:
return HttpResponseServerError()
else:
return HttpResponse(alt)
......@@ -12,6 +12,7 @@ https://docs.djangoproject.com/en/1.7/ref/settings/
import os
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
import altitude.providers
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.7/howto/deployment/checklist/
......@@ -119,8 +120,11 @@ STATIC_URL = '/static/'
# Is it required to login to use celutz?
LOGIN_REQUIRED = False
GEONAMES_ASTERGDEM = "http://api.geonames.org/astergdem?lat={lat}&lng={lon}&username=celutz&style=full"
# Altitude providers are tried in order until obtaining a result.
ALTITUDE_PROVIDERS = [altitude.providers.GeoportailProvider,
altitude.providers.GeonamesProvider]
# Connection timeout for each provider, in seconds
ALTITUDE_PROVIDER_TIMEOUT = 3.
# For uploaded panorama
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment