Initial IBM-based weather proxy. No auth yet.

This commit is contained in:
Katharine Berry 2018-06-29 05:17:35 -07:00
parent 1ba8570cf7
commit 9cfed171b6
2 changed files with 105 additions and 0 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
.pyenv
.idea

103
weather/__init__.py Normal file
View file

@ -0,0 +1,103 @@
import datetime
import os
import time
import requests
from flask import Flask, request, jsonify
from werkzeug.routing import FloatConverter
app = Flask(__name__)
ibm_root = os.environ['IBM_API_ROOT']
# For some reason, the standard float converter rejects negative numbers
# (and also integers without a decimal point).
class SignedFloatConverter(FloatConverter):
regex = r'-?\d+(\.\d+)?'
app.url_map.converters['float'] = SignedFloatConverter
def format_date(date):
return date.strftime("%Y-%m-%dT%H:%M:%S")
@app.route('/api/v1/geocode/<float:latitude>/<float:longitude>/')
def geocode(latitude, longitude):
units = request.args.get('units', 'h')
language = request.args.get('language', 'en-US')
forecast_req = requests.get(f"{ibm_root}/geocode/{latitude}/{longitude}/forecast/daily/7day.json?language={language}&units={units}")
forecast_req.raise_for_status()
forecast = forecast_req.json()
current_req = requests.get(f"{ibm_root}/geocode/{latitude}/{longitude}/observations.json?language={language}&units={units}")
current_req.raise_for_status()
current = current_req.json()
observation = current['observation']
old_style_conditions = {
'metadata': current['metadata'],
'observation': {
'class': observation['class'],
'expire_time_gmt': observation['expire_time_gmt'],
'obs_time': observation['valid_time_gmt'],
# 'obs_time_local': we don't know.
'wdir': observation['wdir'],
'icon_code': observation['wx_icon'],
'icon_extd': observation['icon_extd'],
# sunrise: we don't know these, but we could yank them out of the forecast for today.
# sunset
'day_ind': observation['day_ind'],
'uv_index': observation['uv_index'],
# uv_warning: I don't even know what this is. Apparently numeric.
# wxman: ???
'obs_qualifier_code': observation['qualifier'],
'ptend_code': observation['pressure_tend'],
'dow': datetime.datetime.utcfromtimestamp(observation['expire_time_gmt']).strftime('%A'),
'wdir_cardinal': observation['wdir_cardinal'], # sometimes this is "CALM", don't know if that's okay
'uv_desc': observation['uv_desc'],
# I'm just guessing at how the three phrases map.
'phrase_12char': observation['blunt_phrase'] or observation['wx_phrase'],
'phrase_22char': observation['terse_phrase'] or observation['wx_phrase'],
'phrase_32char': observation['wx_phrase'],
'ptend_desc': observation['pressure_desc'],
# sky_cover: we don't seem to get a description of this?
'clds': observation['clds'],
'obs_qualifier_severity': observation['qualifier_svrty'],
# vocal_key: we don't get one of these
{'e': 'imperial', 'm': 'metric', 'h': 'uk_hybrid'}[units]: {
'wspd': observation['wspd'],
'gust': observation['gust'],
'vis': observation['vis'],
# mslp: don't know what this is but it doesn't map to anything
'altimeter': observation['pressure'],
'temp': observation['temp'],
'dewpt': observation['dewPt'],
'rh': observation['rh'],
'wc': observation['wc'],
'hi': observation['heat_index'],
'feels_like': observation['feels_like'],
# temp_change_24hour, temp_max_24hour, temp_min_24hour, pchange: don't get any of these
# {snow,precip}_{{1,6,24}hour,mtd,season,{2,3,7}day}: don't get these either
# ceiling, obs_qualifier_{100,50,32}char: or these.
# these are all now in their own request that you can pay extra to retrieve.
},
}
}
return jsonify(
fcstdaily7={
'errors': False,
'data': forecast,
},
conditions={
'errors': False,
'data': old_style_conditions,
},
metadata={
'version': 2,
'transaction_id': str(int(time.time())),
},
)