mirror of
https://github.com/jlu5/SupyPlugins.git
synced 2025-05-05 09:50:54 -05:00
NuWeather: switch to OneCall API for OpenWeatherMap
This API is more complete and includes things like daily forecasts.
This commit is contained in:
parent
47b7b422e4
commit
1eb83ea9df
@ -1,6 +1,6 @@
|
||||
###
|
||||
# Copyright (c) 2011-2014, Valentin Lorentz
|
||||
# Copyright (c) 2018-2019, James Lu <james@overdrivenetworks.com>
|
||||
# Copyright (c) 2018-2020, James Lu <james@overdrivenetworks.com>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
@ -180,6 +180,8 @@ class NuWeather(callbacks.Plugin):
|
||||
|
||||
@staticmethod
|
||||
def _format_uv(uv):
|
||||
if uv is None:
|
||||
return _('N/A')
|
||||
# From https://en.wikipedia.org/wiki/Ultraviolet_index#Index_usage 2018-12-30
|
||||
uv = float(uv)
|
||||
if uv <= 2.9:
|
||||
@ -503,71 +505,56 @@ class NuWeather(callbacks.Plugin):
|
||||
if not latlon:
|
||||
raise callbacks.Error("Unknown location %s." % location)
|
||||
|
||||
lat, lon, __, ___, geocode_backend = latlon
|
||||
url = 'https://api.openweathermap.org/data/2.5/weather?' + utils.web.urlencode({
|
||||
lat, lon, display_name, _geocode_id, geocode_backend = latlon
|
||||
url = 'https://api.openweathermap.org/data/2.5/onecall?' + utils.web.urlencode({
|
||||
'appid': apikey,
|
||||
'lat': lat,
|
||||
'lon': lon,
|
||||
'units': 'imperial',
|
||||
})
|
||||
self.log.debug('NuWeather: using url %s (current data)', url)
|
||||
self.log.debug('NuWeather: using url %s', url)
|
||||
|
||||
f = utils.web.getUrl(url, headers=HEADERS).decode('utf-8')
|
||||
data = json.loads(f, strict=False)
|
||||
|
||||
currentdata = data['current']
|
||||
|
||||
# XXX: are the units for this consistent across APIs?
|
||||
if currentdata.get('snow'):
|
||||
precip = self._format_precip(mm=currentdata['snow']['1h'] * 10)
|
||||
elif currentdata.get('rain'):
|
||||
precip = self._format_precip(mm=currentdata['rain']['1h'])
|
||||
else:
|
||||
precip = 'N/A'
|
||||
|
||||
output = {
|
||||
'location': '%s, %s' % (data['name'], data['sys']['country']),
|
||||
'location': display_name,
|
||||
'poweredby': 'OpenWeatherMap+' + geocode_backend,
|
||||
'url': 'https://openweathermap.org/weathermap?' + utils.web.urlencode({
|
||||
'lat': lat,
|
||||
'lon': lon,
|
||||
'zoom': 12
|
||||
}),
|
||||
# Unfortunately not all of the fields we use are available
|
||||
'current': {
|
||||
'condition': data['weather'][0]['description'],
|
||||
'temperature': self._format_temp(f=data['main']['temp']),
|
||||
'feels_like': 'N/A',
|
||||
'humidity': self._format_percentage(data['main']['humidity']),
|
||||
'precip': 'N/A',
|
||||
'wind': self._format_distance(mi=data['wind']['speed'], speed=True),
|
||||
'wind_gust': 'N/A',
|
||||
'wind_dir': self._wind_direction(data['wind']['deg']),
|
||||
'uv': 'N/A', # Requires a separate API call
|
||||
'visibility': self._format_distance(km=data['visibility']/1000),
|
||||
'condition': currentdata['weather'][0]['description'],
|
||||
'temperature': self._format_temp(f=currentdata['temp']),
|
||||
'feels_like': self._format_temp(f=currentdata['feels_like']),
|
||||
'humidity': self._format_percentage(currentdata['humidity']),
|
||||
'precip': precip,
|
||||
'wind': self._format_distance(mi=currentdata['wind_speed'], speed=True),
|
||||
'wind_dir': self._wind_direction(currentdata['wind_deg']),
|
||||
'wind_gust': self._format_distance(mi=currentdata.get('wind_gust'), speed=True),
|
||||
'uv': self._format_uv(currentdata.get('uvi')),
|
||||
'visibility': self._format_distance(km=currentdata['visibility']/1000),
|
||||
}
|
||||
}
|
||||
tzoffset = data['timezone']
|
||||
|
||||
# Get extended forecast (a separate API call)
|
||||
url = 'https://api.openweathermap.org/data/2.5/forecast?' + utils.web.urlencode({
|
||||
'appid': apikey,
|
||||
'lat': lat,
|
||||
'lon': lon,
|
||||
'units': 'imperial',
|
||||
})
|
||||
self.log.debug('NuWeather: using url %s (extended forecast)', url)
|
||||
|
||||
f = utils.web.getUrl(url, headers=HEADERS).decode('utf-8')
|
||||
data = json.loads(f, strict=False)
|
||||
def _owm_make_dayname(utcts):
|
||||
# OWM gives timestamps in UTC, but the /weather endpoint provides a timezone
|
||||
# offset in seconds. Use this data with pendulum to generate a human readable time.
|
||||
ts = utcts + tzoffset
|
||||
|
||||
if pendulum:
|
||||
dt = pendulum.from_timestamp(ts)
|
||||
return dt.format('dddd hA') # Return strings like "Sunday 8PM"
|
||||
return ts # fallback
|
||||
|
||||
# OWM's 5 day forecast gives data by 3 hour intervals. The actual daily forecast
|
||||
# requires a subscription.
|
||||
output['forecast'] = [
|
||||
{'dayname': _owm_make_dayname(forecast['dt']),
|
||||
'max': self._format_temp(f=forecast['main']['temp_max']),
|
||||
'min': self._format_temp(f=forecast['main']['temp_min']),
|
||||
{'dayname': self._get_dayname(forecast['dt'], idx, tz=data['timezone']),
|
||||
'max': self._format_temp(f=forecast['temp']['max']),
|
||||
'min': self._format_temp(f=forecast['temp']['min']),
|
||||
'summary': forecast['weather'][0]['description']}
|
||||
for forecast in data['list'][1::2] # grab data every 6 hours, excluding first pocket
|
||||
for idx, forecast in enumerate(data['daily'])
|
||||
]
|
||||
return output
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user