diff --git a/NuWeather/plugin.py b/NuWeather/plugin.py index e692997..93aaa4d 100644 --- a/NuWeather/plugin.py +++ b/NuWeather/plugin.py @@ -1,6 +1,6 @@ ### # Copyright (c) 2011-2014, Valentin Lorentz -# Copyright (c) 2018-2019, James Lu +# Copyright (c) 2018-2020, James Lu # 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