2017-06-07 08:49:54 +00:00
|
|
|
"""
|
|
|
|
Support for the Yahoo! Weather service.
|
|
|
|
|
|
|
|
For more details about this platform, please refer to the documentation at
|
|
|
|
https://home-assistant.io/components/weather.yweather/
|
|
|
|
"""
|
|
|
|
import logging
|
|
|
|
from datetime import timedelta
|
|
|
|
|
|
|
|
import voluptuous as vol
|
|
|
|
|
|
|
|
import homeassistant.helpers.config_validation as cv
|
|
|
|
from homeassistant.components.weather import (
|
2017-07-26 14:46:21 +00:00
|
|
|
WeatherEntity, PLATFORM_SCHEMA,
|
|
|
|
ATTR_FORECAST_TEMP, ATTR_FORECAST_TIME)
|
2017-06-07 08:49:54 +00:00
|
|
|
from homeassistant.const import (TEMP_CELSIUS, CONF_NAME, STATE_UNKNOWN)
|
|
|
|
|
|
|
|
REQUIREMENTS = ["yahooweather==0.8"]
|
|
|
|
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
|
2017-07-26 14:46:21 +00:00
|
|
|
DATA_CONDITION = 'yahoo_condition'
|
|
|
|
|
2017-06-07 08:49:54 +00:00
|
|
|
ATTR_FORECAST_CONDITION = 'condition'
|
|
|
|
ATTRIBUTION = "Weather details provided by Yahoo! Inc."
|
|
|
|
|
2017-07-26 14:46:21 +00:00
|
|
|
ATTR_FORECAST_TEMP_LOW = 'templow'
|
|
|
|
|
2017-06-07 08:49:54 +00:00
|
|
|
CONF_WOEID = 'woeid'
|
|
|
|
|
|
|
|
DEFAULT_NAME = 'Yweather'
|
|
|
|
|
|
|
|
SCAN_INTERVAL = timedelta(minutes=10)
|
|
|
|
|
|
|
|
CONDITION_CLASSES = {
|
|
|
|
'cloudy': [26, 27, 28, 29, 30],
|
|
|
|
'fog': [19, 20, 21, 22, 23],
|
|
|
|
'hail': [17, 18, 35],
|
|
|
|
'lightning': [37],
|
2017-07-26 14:46:21 +00:00
|
|
|
'lightning-rainy': [38, 39, 47],
|
2017-06-07 08:49:54 +00:00
|
|
|
'partlycloudy': [44],
|
|
|
|
'pouring': [40, 45],
|
|
|
|
'rainy': [9, 11, 12],
|
|
|
|
'snowy': [8, 13, 14, 15, 16, 41, 42, 43],
|
2017-07-26 14:46:21 +00:00
|
|
|
'snowy-rainy': [5, 6, 7, 10, 46],
|
|
|
|
'sunny': [32, 33, 34],
|
2017-06-07 08:49:54 +00:00
|
|
|
'windy': [24],
|
|
|
|
'windy-variant': [],
|
|
|
|
'exceptional': [0, 1, 2, 3, 4, 25, 36],
|
|
|
|
}
|
|
|
|
|
2017-07-26 14:46:21 +00:00
|
|
|
|
2017-06-07 08:49:54 +00:00
|
|
|
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
|
|
|
vol.Optional(CONF_WOEID, default=None): cv.string,
|
|
|
|
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
def setup_platform(hass, config, add_devices, discovery_info=None):
|
|
|
|
"""Setup the Yahoo! weather platform."""
|
|
|
|
from yahooweather import get_woeid, UNIT_C, UNIT_F
|
|
|
|
|
|
|
|
unit = hass.config.units.temperature_unit
|
|
|
|
woeid = config.get(CONF_WOEID)
|
|
|
|
name = config.get(CONF_NAME)
|
|
|
|
|
|
|
|
yunit = UNIT_C if unit == TEMP_CELSIUS else UNIT_F
|
|
|
|
|
|
|
|
# If not exists a customer WOEID/calculation from Home Assistant
|
|
|
|
if woeid is None:
|
|
|
|
woeid = get_woeid(hass.config.latitude, hass.config.longitude)
|
|
|
|
if woeid is None:
|
|
|
|
_LOGGER.warning("Can't retrieve WOEID from Yahoo!")
|
|
|
|
return False
|
|
|
|
|
|
|
|
yahoo_api = YahooWeatherData(woeid, yunit)
|
|
|
|
|
|
|
|
if not yahoo_api.update():
|
|
|
|
_LOGGER.critical("Can't retrieve weather data from Yahoo!")
|
|
|
|
return False
|
|
|
|
|
2017-07-26 14:46:21 +00:00
|
|
|
# create condition helper
|
|
|
|
if DATA_CONDITION not in hass.data:
|
|
|
|
hass.data[DATA_CONDITION] = [str(x) for x in range(0, 50)]
|
|
|
|
for cond, condlst in CONDITION_CLASSES.items():
|
|
|
|
for condi in condlst:
|
|
|
|
hass.data[DATA_CONDITION][condi] = cond
|
2017-06-07 08:49:54 +00:00
|
|
|
|
2017-07-26 14:46:21 +00:00
|
|
|
add_devices([YahooWeatherWeather(yahoo_api, name)], True)
|
2017-06-07 08:49:54 +00:00
|
|
|
|
|
|
|
|
|
|
|
class YahooWeatherWeather(WeatherEntity):
|
|
|
|
"""Representation of Yahoo! weather data."""
|
|
|
|
|
2017-07-26 14:46:21 +00:00
|
|
|
def __init__(self, weather_data, name):
|
2017-06-07 08:49:54 +00:00
|
|
|
"""Initialize the sensor."""
|
|
|
|
self._name = name
|
|
|
|
self._data = weather_data
|
|
|
|
|
|
|
|
@property
|
|
|
|
def name(self):
|
|
|
|
"""Return the name of the sensor."""
|
|
|
|
return self._name
|
|
|
|
|
|
|
|
@property
|
|
|
|
def condition(self):
|
|
|
|
"""Return the current condition."""
|
|
|
|
try:
|
2017-07-26 14:46:21 +00:00
|
|
|
return self.hass.data[DATA_CONDITION][int(
|
|
|
|
self._data.yahoo.Now['code'])]
|
|
|
|
except (ValueError, IndexError):
|
2017-06-07 08:49:54 +00:00
|
|
|
return STATE_UNKNOWN
|
|
|
|
|
|
|
|
@property
|
|
|
|
def temperature(self):
|
|
|
|
"""Return the temperature."""
|
|
|
|
return self._data.yahoo.Now['temp']
|
|
|
|
|
|
|
|
@property
|
|
|
|
def temperature_unit(self):
|
|
|
|
"""Return the unit of measurement."""
|
|
|
|
return TEMP_CELSIUS
|
|
|
|
|
|
|
|
@property
|
|
|
|
def pressure(self):
|
|
|
|
"""Return the pressure."""
|
|
|
|
return self._data.yahoo.Atmosphere['pressure']
|
|
|
|
|
|
|
|
@property
|
|
|
|
def humidity(self):
|
|
|
|
"""Return the humidity."""
|
|
|
|
return self._data.yahoo.Atmosphere['humidity']
|
|
|
|
|
|
|
|
@property
|
|
|
|
def visibility(self):
|
|
|
|
"""Return the visibility."""
|
|
|
|
return self._data.yahoo.Atmosphere['visibility']
|
|
|
|
|
|
|
|
@property
|
|
|
|
def wind_speed(self):
|
|
|
|
"""Return the wind speed."""
|
|
|
|
return self._data.yahoo.Wind['speed']
|
|
|
|
|
2017-07-26 14:46:21 +00:00
|
|
|
@property
|
|
|
|
def wind_bearing(self):
|
|
|
|
"""Return the wind direction."""
|
|
|
|
return self._data.yahoo.Wind['direction']
|
|
|
|
|
2017-06-07 08:49:54 +00:00
|
|
|
@property
|
|
|
|
def attribution(self):
|
|
|
|
"""Return the attribution."""
|
|
|
|
return ATTRIBUTION
|
|
|
|
|
|
|
|
@property
|
|
|
|
def forecast(self):
|
|
|
|
"""Return the forecast array."""
|
|
|
|
try:
|
2017-07-26 14:46:21 +00:00
|
|
|
return [
|
|
|
|
{
|
|
|
|
ATTR_FORECAST_TIME: v['date'],
|
|
|
|
ATTR_FORECAST_TEMP:int(v['high']),
|
|
|
|
ATTR_FORECAST_TEMP_LOW: int(v['low']),
|
|
|
|
ATTR_FORECAST_CONDITION:
|
|
|
|
self.hass.data[DATA_CONDITION][int(v['code'])]
|
|
|
|
} for v in self._data.yahoo.Forecast]
|
|
|
|
except (ValueError, IndexError):
|
2017-06-07 08:49:54 +00:00
|
|
|
return STATE_UNKNOWN
|
|
|
|
|
|
|
|
def update(self):
|
|
|
|
"""Get the latest data from Yahoo! and updates the states."""
|
|
|
|
self._data.update()
|
|
|
|
if not self._data.yahoo.RawData:
|
|
|
|
_LOGGER.info("Don't receive weather data from Yahoo!")
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
class YahooWeatherData(object):
|
|
|
|
"""Handle the Yahoo! API object and limit updates."""
|
|
|
|
|
|
|
|
def __init__(self, woeid, temp_unit):
|
|
|
|
"""Initialize the data object."""
|
|
|
|
from yahooweather import YahooWeather
|
|
|
|
self._yahoo = YahooWeather(woeid, temp_unit)
|
|
|
|
|
|
|
|
@property
|
|
|
|
def yahoo(self):
|
|
|
|
"""Return Yahoo! API object."""
|
|
|
|
return self._yahoo
|
|
|
|
|
|
|
|
def update(self):
|
|
|
|
"""Get the latest data from Yahoo!."""
|
|
|
|
return self._yahoo.updateWeather()
|