Yahoo! weather support (#2457)
* initial import yahoo weather * fix temperature in HA style * add suggestion from @fabaff * change with suggestion from @balloob
This commit is contained in:
parent
5d6c13c12c
commit
2ab2f68318
3 changed files with 193 additions and 0 deletions
|
@ -211,6 +211,7 @@ omit =
|
|||
homeassistant/components/sensor/twitch.py
|
||||
homeassistant/components/sensor/uber.py
|
||||
homeassistant/components/sensor/worldclock.py
|
||||
homeassistant/components/sensor/yweather.py
|
||||
homeassistant/components/switch/acer_projector.py
|
||||
homeassistant/components/switch/arest.py
|
||||
homeassistant/components/switch/dlink.py
|
||||
|
|
189
homeassistant/components/sensor/yweather.py
Normal file
189
homeassistant/components/sensor/yweather.py
Normal file
|
@ -0,0 +1,189 @@
|
|||
"""
|
||||
Support for the Yahoo! Weather service.
|
||||
|
||||
For more details about this platform, please refer to the documentation at
|
||||
https://home-assistant.io/components/sensor.yweather/
|
||||
"""
|
||||
import logging
|
||||
from datetime import timedelta
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.const import (CONF_PLATFORM, TEMP_CELSIUS,
|
||||
CONF_MONITORED_CONDITIONS, STATE_UNKNOWN)
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.util import Throttle
|
||||
|
||||
REQUIREMENTS = ["yahooweather==0.4"]
|
||||
|
||||
SENSOR_TYPES = {
|
||||
'weather_current': ['Current', None],
|
||||
'weather': ['Condition', None],
|
||||
'temperature': ['Temperature', "temperature"],
|
||||
'temp_min': ['Temperature', "temperature"],
|
||||
'temp_max': ['Temperature', "temperature"],
|
||||
'wind_speed': ['Wind speed', "speed"],
|
||||
'humidity': ['Humidity', "%"],
|
||||
'pressure': ['Pressure', "pressure"],
|
||||
'visibility': ['Visibility', "distance"],
|
||||
}
|
||||
|
||||
PLATFORM_SCHEMA = vol.Schema({
|
||||
vol.Required(CONF_PLATFORM): "yweather",
|
||||
vol.Optional("woeid"): vol.Coerce(str),
|
||||
vol.Optional("forecast"): vol.Coerce(int),
|
||||
vol.Required(CONF_MONITORED_CONDITIONS, default=[]):
|
||||
[vol.In(SENSOR_TYPES.keys())],
|
||||
})
|
||||
|
||||
# Return cached results if last scan was less then this time ago.
|
||||
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=120)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
"""Setup the Yahoo! weather sensor."""
|
||||
from yahooweather import get_woeid, UNIT_C, UNIT_F
|
||||
|
||||
unit = hass.config.temperature_unit
|
||||
woeid = config.get("woeid", None)
|
||||
forecast = config.get("forecast", 0)
|
||||
|
||||
# convert unit
|
||||
yunit = UNIT_C if unit == TEMP_CELSIUS else UNIT_F
|
||||
|
||||
# for print HA style temp
|
||||
SENSOR_TYPES["temperature"][1] = unit
|
||||
SENSOR_TYPES["temp_min"][1] = unit
|
||||
SENSOR_TYPES["temp_max"][1] = unit
|
||||
|
||||
# if not exists a customer woeid / calc from HA
|
||||
if woeid is None:
|
||||
woeid = get_woeid(hass.config.latitude, hass.config.longitude)
|
||||
# receive a error?
|
||||
if woeid is None:
|
||||
_LOGGER.critical("Can't retrieve WOEID from yahoo!")
|
||||
return False
|
||||
|
||||
# create api object
|
||||
yahoo_api = YahooWeatherData(woeid, yunit)
|
||||
|
||||
# if update is false, it will never work...
|
||||
if not yahoo_api.update():
|
||||
_LOGGER.critical("Can't retrieve weather data from yahoo!")
|
||||
return False
|
||||
|
||||
# check if forecast support by API
|
||||
if forecast >= len(yahoo_api.yahoo.Forecast):
|
||||
_LOGGER.error("Yahoo! only support %d days forcast!",
|
||||
len(yahoo_api.yahoo.Forecast))
|
||||
return False
|
||||
|
||||
dev = []
|
||||
for variable in config[CONF_MONITORED_CONDITIONS]:
|
||||
dev.append(YahooWeatherSensor(yahoo_api, forecast, variable))
|
||||
|
||||
add_devices(dev)
|
||||
|
||||
|
||||
# pylint: disable=too-many-instance-attributes
|
||||
class YahooWeatherSensor(Entity):
|
||||
"""Implementation of an Yahoo! weather sensor."""
|
||||
|
||||
def __init__(self, weather_data, forecast, sensor_type):
|
||||
"""Initialize the sensor."""
|
||||
self._client = 'Weather'
|
||||
self._name = SENSOR_TYPES[sensor_type][0]
|
||||
self._type = sensor_type
|
||||
self._state = STATE_UNKNOWN
|
||||
self._unit = SENSOR_TYPES[sensor_type][1]
|
||||
self._data = weather_data
|
||||
self._forecast = forecast
|
||||
self._code = None
|
||||
|
||||
# update data
|
||||
self.update()
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name of the sensor."""
|
||||
return '{} {}'.format(self._client, self._name)
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
"""Return the state of the device."""
|
||||
return self._state
|
||||
|
||||
@property
|
||||
def unit_of_measurement(self):
|
||||
"""Return the unit of measurement of this entity, if any."""
|
||||
return self._data.yahoo.Units.get(self._unit, self._unit)
|
||||
|
||||
@property
|
||||
def entity_picture(self):
|
||||
"""Return the entity picture to use in the frontend, if any."""
|
||||
if self._code is None or "weather" not in self._type:
|
||||
return None
|
||||
|
||||
return self._data.yahoo.getWeatherImage(self._code)
|
||||
|
||||
@property
|
||||
def device_state_attributes(self):
|
||||
"""Return the state attributes."""
|
||||
return {
|
||||
'about': "Weather forecast delivered by Yahoo! Inc. are provided"
|
||||
" free of charge for use by individuals and non-profit"
|
||||
" organizations for personal, non-commercial uses."
|
||||
}
|
||||
|
||||
def update(self):
|
||||
"""Get the latest data from Yahoo! and updates the states."""
|
||||
self._data.update()
|
||||
|
||||
# default code for weather image
|
||||
self._code = self._data.yahoo.Now["code"]
|
||||
|
||||
# read data
|
||||
if self._type == "weather_current":
|
||||
self._state = self._data.yahoo.Now["text"]
|
||||
elif self._type == "weather":
|
||||
self._code = self._data.yahoo.Forecast[self._forecast]["code"]
|
||||
self._state = self._data.yahoo.Forecast[self._forecast]["text"]
|
||||
elif self._type == "temperature":
|
||||
self._state = self._data.yahoo.Now["temp"]
|
||||
elif self._type == "temp_min":
|
||||
self._code = self._data.yahoo.Forecast[self._forecast]["code"]
|
||||
self._state = self._data.yahoo.Forecast[self._forecast]["low"]
|
||||
elif self._type == "temp_max":
|
||||
self._code = self._data.yahoo.Forecast[self._forecast]["code"]
|
||||
self._state = self._data.yahoo.Forecast[self._forecast]["high"]
|
||||
elif self._type == "wind_speed":
|
||||
self._state = self._data.yahoo.Wind["speed"]
|
||||
elif self._type == "humidity":
|
||||
self._state = self._data.yahoo.Atmosphere["humidity"]
|
||||
elif self._type == "pressure":
|
||||
self._state = self._data.yahoo.Atmosphere["pressure"]
|
||||
elif self._type == "visibility":
|
||||
self._state = self._data.yahoo.Atmosphere["visibility"]
|
||||
|
||||
|
||||
# pylint: disable=too-few-public-methods
|
||||
class YahooWeatherData(object):
|
||||
"""Handle yahoo api object and limit updates."""
|
||||
|
||||
def __init__(self, woeid, temp_unit):
|
||||
"""Initialize the data object."""
|
||||
from yahooweather import YahooWeather
|
||||
|
||||
# init yahoo api object
|
||||
self._yahoo = YahooWeather(woeid, temp_unit)
|
||||
|
||||
@property
|
||||
def yahoo(self):
|
||||
"""Return yahoo api object."""
|
||||
return self._yahoo
|
||||
|
||||
@Throttle(MIN_TIME_BETWEEN_UPDATES)
|
||||
def update(self):
|
||||
"""Get the latest data from yahoo. True is success."""
|
||||
return self._yahoo.updateWeather()
|
|
@ -433,5 +433,8 @@ xbee-helper==0.0.7
|
|||
# homeassistant.components.sensor.yr
|
||||
xmltodict
|
||||
|
||||
# homeassistant.components.sensor.yweather
|
||||
yahooweather==0.4
|
||||
|
||||
# homeassistant.components.zeroconf
|
||||
zeroconf==0.17.5
|
||||
|
|
Loading…
Add table
Reference in a new issue