core/homeassistant/components/sensor/wunderground.py

168 lines
5.5 KiB
Python
Raw Normal View History

2016-08-17 21:25:42 +00:00
"""Support for Wunderground weather service."""
from datetime import timedelta
import logging
import requests
2016-08-18 04:18:37 +00:00
import voluptuous as vol
from homeassistant.helpers.entity import Entity
2016-08-18 04:18:37 +00:00
from homeassistant.helpers.config_validation import ensure_list
from homeassistant.util import Throttle
2016-08-18 04:18:37 +00:00
from homeassistant.const import (CONF_PLATFORM, CONF_MONITORED_CONDITIONS,
CONF_API_KEY, TEMP_FAHRENHEIT, TEMP_CELSIUS,
STATE_UNKNOWN)
CONF_PWS_ID = 'pws_id'
_URL_QUERY = '/conditions/q/'
_RESOURCE = 'http://api.wunderground.com/api/'
_LOGGER = logging.getLogger(__name__)
# Return cached results if last scan was less then this time ago.
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=300)
# Sensor types are defined like: Name, units
SENSOR_TYPES = {
'weather': ['Weather Summary', None],
'station_id': ['Station ID', None],
'feelslike_c': ['Feels Like (°C)', TEMP_CELSIUS],
'feelslike_f': ['Feels Like (°F)', TEMP_FAHRENHEIT],
'feelslike_string': ['Feels Like', None],
'heat_index_c': ['Dewpoint (°C)', TEMP_CELSIUS],
'heat_index_f': ['Dewpoint (°F)', TEMP_FAHRENHEIT],
'heat_index_string': ['Heat Index Summary', None],
'dewpoint_c': ['Dewpoint (°C)', TEMP_CELSIUS],
'dewpoint_f': ['Dewpoint (°F)', TEMP_FAHRENHEIT],
'dewpoint_string': ['Dewpoint Summary', None],
'wind_kph': ['Wind Speed', 'kpH'],
'wind_mph': ['Wind Speed', 'mpH'],
'UV': ['UV', None],
'pressure_in': ['Pressure', 'in'],
'pressure_mb': ['Pressure', 'mbar'],
'wind_dir': ['Wind Direction', None],
'wind_string': ['Wind Summary', None],
'temp_c': ['Temperature (°C)', TEMP_CELSIUS],
'temp_f': ['Temperature (°F)', TEMP_FAHRENHEIT],
'relative_humidity': ['Relative Humidity', '%'],
'visibility_mi': ['Visibility (miles)', 'mi'],
'visibility_km': ['Visibility (km)', 'km'],
'precip_today_in': ['Precipation Today', 'in'],
2016-08-17 20:50:32 +00:00
'precip_today_metric': ['Precipitation Today', 'mm'],
'precip_today_string': ['Precipitation today', None],
'solarradiation': ['Solar Radiation', None]
}
2016-08-18 04:19:13 +00:00
PLATFORM_SCHEMA = vol.Schema({
vol.Required(CONF_PLATFORM): "wunderground",
vol.Required(CONF_API_KEY): vol.Coerce(str),
CONF_PWS_ID: vol.Coerce(str),
vol.Required(CONF_MONITORED_CONDITIONS, default=[]): ensure_list,
})
def setup_platform(hass, config, add_devices, discovery_info=None):
2016-08-17 21:25:42 +00:00
"""Setup the Wunderground sensor."""
2016-08-18 04:28:18 +00:00
if not PLATFORM_SCHEMA(config):
return False
2016-08-18 04:29:00 +00:00
rest = WUndergroundData(hass,
config.get(CONF_API_KEY),
2016-08-18 04:29:00 +00:00
config.get(CONF_PWS_ID, None))
sensors = []
for variable in config['monitored_conditions']:
if variable in SENSOR_TYPES:
sensors.append(WUndergroundSensor(rest, variable))
else:
_LOGGER.error('Wunderground sensor: "%s" does not exist', variable)
try:
rest.update()
except ValueError as err:
_LOGGER.error("Received error from WUnderground: %s", err)
return False
add_devices(sensors)
return True
class WUndergroundSensor(Entity):
"""Implementing the Wunderground sensor."""
def __init__(self, rest, condition):
"""Initialize the sensor."""
self.rest = rest
self._condition = condition
self._unit_of_measurement = None
@property
def name(self):
"""Return the name of the sensor."""
2016-08-18 04:29:49 +00:00
return "PWS_" + self._condition
@property
def state(self):
"""Return the state of the sensor."""
2016-08-18 04:30:23 +00:00
if self.rest.data and self._condition in self.rest.data:
return self.rest.data[self._condition]
else:
return STATE_UNKNOWN
@property
def entity_picture(self):
"""Return the entity picture."""
2016-08-17 20:31:36 +00:00
value = self.rest.data
if self._condition == 'weather':
2016-08-17 20:31:36 +00:00
return value['icon_url']
@property
def unit_of_measurement(self):
"""Return the units of measurement."""
return SENSOR_TYPES[self._condition][1]
def update(self):
"""Update current conditions."""
self.rest.update()
self._state = self.rest.data
# pylint: disable=too-few-public-methods
class WUndergroundData(object):
2016-08-17 20:31:36 +00:00
"""Get data from Wundeground."""
2016-08-18 04:28:05 +00:00
def __init__(self, hass, api_key, pws_id=None):
"""Initialize the data object."""
2016-08-18 04:28:05 +00:00
self._hass = hass
self._api_key = api_key
self._pws_id = pws_id
2016-08-18 04:28:05 +00:00
self._latitude = hass.config.latitude
self._longitude = hass.config.longitude
self.data = None
2016-08-18 04:22:11 +00:00
def _build_url(self):
print(self._api_key)
url = _RESOURCE + self._api_key + _URL_QUERY
if self._pws_id:
url = url + 'pws:' + self._pws_id
else:
url = url + '{},{}'.format(self._latitude, self._longitude)
return url + '.json'
@Throttle(MIN_TIME_BETWEEN_UPDATES)
def update(self):
2016-08-17 21:48:37 +00:00
"""Get the latest data from wunderground."""
try:
result = requests.get(self._resource + self._api_key +
2016-08-17 20:31:36 +00:00
'/conditions/q/pws:' + self._pws_id +
2016-08-17 20:15:07 +00:00
'.json', timeout=10)
if "error" in result.json():
raise ValueError(result.json()["response"]["error"]
["description"])
else:
self.data = result.json()["current_observation"]
except ValueError as err:
_LOGGER.error("Check Wunderground API %s", err.args)
self.data = None