Added daily and hourly modes to Openweathermap (#14875)
* Added daily and hourly modes Added wind speed and bearing to forecast * Fix mixed spaces and tabs * Fix lint * Fix pylint * Revert one attribution, order alphabeticallypull/17847/head
parent
7d9ef97bda
commit
716ab0433f
|
@ -11,10 +11,10 @@ import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components.weather import (
|
from homeassistant.components.weather import (
|
||||||
ATTR_FORECAST_CONDITION, ATTR_FORECAST_PRECIPITATION, ATTR_FORECAST_TEMP,
|
ATTR_FORECAST_CONDITION, ATTR_FORECAST_PRECIPITATION, ATTR_FORECAST_TEMP,
|
||||||
ATTR_FORECAST_TIME, PLATFORM_SCHEMA, WeatherEntity)
|
ATTR_FORECAST_TEMP_LOW, ATTR_FORECAST_TIME, PLATFORM_SCHEMA, WeatherEntity)
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
CONF_API_KEY, CONF_LATITUDE, CONF_LONGITUDE, CONF_NAME, STATE_UNKNOWN,
|
CONF_API_KEY, TEMP_CELSIUS, CONF_LATITUDE, CONF_LONGITUDE, CONF_MODE,
|
||||||
TEMP_CELSIUS)
|
CONF_NAME, STATE_UNKNOWN)
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.util import Throttle
|
from homeassistant.util import Throttle
|
||||||
|
|
||||||
|
@ -22,20 +22,25 @@ REQUIREMENTS = ['pyowm==2.8.0']
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
ATTR_FORECAST_WIND_SPEED = 'wind_speed'
|
||||||
|
ATTR_FORECAST_WIND_BEARING = 'wind_bearing'
|
||||||
|
|
||||||
ATTRIBUTION = 'Data provided by OpenWeatherMap'
|
ATTRIBUTION = 'Data provided by OpenWeatherMap'
|
||||||
|
|
||||||
|
FORECAST_MODE = ['hourly', 'daily']
|
||||||
|
|
||||||
DEFAULT_NAME = 'OpenWeatherMap'
|
DEFAULT_NAME = 'OpenWeatherMap'
|
||||||
|
|
||||||
MIN_TIME_BETWEEN_FORECAST_UPDATES = timedelta(minutes=30)
|
MIN_TIME_BETWEEN_FORECAST_UPDATES = timedelta(minutes=30)
|
||||||
MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=10)
|
MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=10)
|
||||||
|
|
||||||
CONDITION_CLASSES = {
|
CONDITION_CLASSES = {
|
||||||
'cloudy': [804],
|
'cloudy': [803, 804],
|
||||||
'fog': [701, 741],
|
'fog': [701, 741],
|
||||||
'hail': [906],
|
'hail': [906],
|
||||||
'lightning': [210, 211, 212, 221],
|
'lightning': [210, 211, 212, 221],
|
||||||
'lightning-rainy': [200, 201, 202, 230, 231, 232],
|
'lightning-rainy': [200, 201, 202, 230, 231, 232],
|
||||||
'partlycloudy': [801, 802, 803],
|
'partlycloudy': [801, 802],
|
||||||
'pouring': [504, 314, 502, 503, 522],
|
'pouring': [504, 314, 502, 503, 522],
|
||||||
'rainy': [300, 301, 302, 310, 311, 312, 313, 500, 501, 520, 521],
|
'rainy': [300, 301, 302, 310, 311, 312, 313, 500, 501, 520, 521],
|
||||||
'snowy': [600, 601, 602, 611, 612, 620, 621, 622],
|
'snowy': [600, 601, 602, 611, 612, 620, 621, 622],
|
||||||
|
@ -51,6 +56,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||||
vol.Required(CONF_API_KEY): cv.string,
|
vol.Required(CONF_API_KEY): cv.string,
|
||||||
vol.Optional(CONF_LATITUDE): cv.latitude,
|
vol.Optional(CONF_LATITUDE): cv.latitude,
|
||||||
vol.Optional(CONF_LONGITUDE): cv.longitude,
|
vol.Optional(CONF_LONGITUDE): cv.longitude,
|
||||||
|
vol.Optional(CONF_MODE, default='hourly'): vol.In(FORECAST_MODE),
|
||||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -62,6 +68,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||||
longitude = config.get(CONF_LONGITUDE, round(hass.config.longitude, 5))
|
longitude = config.get(CONF_LONGITUDE, round(hass.config.longitude, 5))
|
||||||
latitude = config.get(CONF_LATITUDE, round(hass.config.latitude, 5))
|
latitude = config.get(CONF_LATITUDE, round(hass.config.latitude, 5))
|
||||||
name = config.get(CONF_NAME)
|
name = config.get(CONF_NAME)
|
||||||
|
mode = config.get(CONF_MODE)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
owm = pyowm.OWM(config.get(CONF_API_KEY))
|
owm = pyowm.OWM(config.get(CONF_API_KEY))
|
||||||
|
@ -69,20 +76,21 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||||
_LOGGER.error("Error while connecting to OpenWeatherMap")
|
_LOGGER.error("Error while connecting to OpenWeatherMap")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
data = WeatherData(owm, latitude, longitude)
|
data = WeatherData(owm, latitude, longitude, mode)
|
||||||
|
|
||||||
add_devices([OpenWeatherMapWeather(
|
add_devices([OpenWeatherMapWeather(
|
||||||
name, data, hass.config.units.temperature_unit)], True)
|
name, data, hass.config.units.temperature_unit, mode)], True)
|
||||||
|
|
||||||
|
|
||||||
class OpenWeatherMapWeather(WeatherEntity):
|
class OpenWeatherMapWeather(WeatherEntity):
|
||||||
"""Implementation of an OpenWeatherMap sensor."""
|
"""Implementation of an OpenWeatherMap sensor."""
|
||||||
|
|
||||||
def __init__(self, name, owm, temperature_unit):
|
def __init__(self, name, owm, temperature_unit, mode):
|
||||||
"""Initialize the sensor."""
|
"""Initialize the sensor."""
|
||||||
self._name = name
|
self._name = name
|
||||||
self._owm = owm
|
self._owm = owm
|
||||||
self._temperature_unit = temperature_unit
|
self._temperature_unit = temperature_unit
|
||||||
|
self._mode = mode
|
||||||
self.data = None
|
self.data = None
|
||||||
self.forecast_data = None
|
self.forecast_data = None
|
||||||
|
|
||||||
|
@ -140,11 +148,30 @@ class OpenWeatherMapWeather(WeatherEntity):
|
||||||
"""Return the forecast array."""
|
"""Return the forecast array."""
|
||||||
data = []
|
data = []
|
||||||
for entry in self.forecast_data.get_weathers():
|
for entry in self.forecast_data.get_weathers():
|
||||||
|
if self._mode == 'daily':
|
||||||
data.append({
|
data.append({
|
||||||
ATTR_FORECAST_TIME: entry.get_reference_time('unix') * 1000,
|
ATTR_FORECAST_TIME:
|
||||||
|
entry.get_reference_time('unix') * 1000,
|
||||||
|
ATTR_FORECAST_TEMP:
|
||||||
|
entry.get_temperature('celsius').get('day'),
|
||||||
|
ATTR_FORECAST_TEMP_LOW:
|
||||||
|
entry.get_temperature('celsius').get('night'),
|
||||||
|
ATTR_FORECAST_WIND_SPEED:
|
||||||
|
entry.get_wind().get('speed'),
|
||||||
|
ATTR_FORECAST_WIND_BEARING:
|
||||||
|
entry.get_wind().get('deg'),
|
||||||
|
ATTR_FORECAST_CONDITION:
|
||||||
|
[k for k, v in CONDITION_CLASSES.items()
|
||||||
|
if entry.get_weather_code() in v][0]
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
data.append({
|
||||||
|
ATTR_FORECAST_TIME:
|
||||||
|
entry.get_reference_time('unix') * 1000,
|
||||||
ATTR_FORECAST_TEMP:
|
ATTR_FORECAST_TEMP:
|
||||||
entry.get_temperature('celsius').get('temp'),
|
entry.get_temperature('celsius').get('temp'),
|
||||||
ATTR_FORECAST_PRECIPITATION: entry.get_rain().get('3h'),
|
ATTR_FORECAST_PRECIPITATION:
|
||||||
|
entry.get_rain().get('3h'),
|
||||||
ATTR_FORECAST_CONDITION:
|
ATTR_FORECAST_CONDITION:
|
||||||
[k for k, v in CONDITION_CLASSES.items()
|
[k for k, v in CONDITION_CLASSES.items()
|
||||||
if entry.get_weather_code() in v][0]
|
if entry.get_weather_code() in v][0]
|
||||||
|
@ -169,8 +196,9 @@ class OpenWeatherMapWeather(WeatherEntity):
|
||||||
class WeatherData(object):
|
class WeatherData(object):
|
||||||
"""Get the latest data from OpenWeatherMap."""
|
"""Get the latest data from OpenWeatherMap."""
|
||||||
|
|
||||||
def __init__(self, owm, latitude, longitude):
|
def __init__(self, owm, latitude, longitude, mode):
|
||||||
"""Initialize the data object."""
|
"""Initialize the data object."""
|
||||||
|
self._mode = mode
|
||||||
self.owm = owm
|
self.owm = owm
|
||||||
self.latitude = latitude
|
self.latitude = latitude
|
||||||
self.longitude = longitude
|
self.longitude = longitude
|
||||||
|
@ -193,8 +221,14 @@ class WeatherData(object):
|
||||||
from pyowm.exceptions.api_call_error import APICallError
|
from pyowm.exceptions.api_call_error import APICallError
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
if self._mode == 'daily':
|
||||||
|
fcd = self.owm.daily_forecast_at_coords(
|
||||||
|
self.latitude, self.longitude, 15
|
||||||
|
)
|
||||||
|
else:
|
||||||
fcd = self.owm.three_hours_forecast_at_coords(
|
fcd = self.owm.three_hours_forecast_at_coords(
|
||||||
self.latitude, self.longitude)
|
self.latitude, self.longitude
|
||||||
|
)
|
||||||
except APICallError:
|
except APICallError:
|
||||||
_LOGGER.error("Exception when calling OWM web API "
|
_LOGGER.error("Exception when calling OWM web API "
|
||||||
"to update forecast")
|
"to update forecast")
|
||||||
|
|
Loading…
Reference in New Issue