core/homeassistant/components/sensor/forecast.py

267 lines
9.1 KiB
Python
Raw Normal View History

2015-06-17 19:59:38 +00:00
"""
homeassistant.components.sensor.forecast
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Forecast.io weather service.
2015-06-17 19:59:38 +00:00
Configuration:
To use the Forecast sensor you will need to add something like the
following to your configuration.yaml file.
2015-06-17 19:59:38 +00:00
sensor:
platform: forecast
api_key: YOUR_APP_KEY
monitored_conditions:
- summary
- icon
- nearest_storm_distance
- nearest_storm_bearing
2015-06-17 19:59:38 +00:00
- precip_type
- precip_intensity
- precip_probability
2015-06-17 19:59:38 +00:00
- temperature
- apparent_temperature
2015-06-17 19:59:38 +00:00
- dew_point
- wind_speed
- wind_bearing
- cloud_cover
- humidity
- pressure
- visibility
- ozone
# Optional: specify which unit system to use.
units: si, us, ca, uk2 or auto
2015-06-17 19:59:38 +00:00
Variables:
api_key
*Required
To retrieve this value log into your account at http://forecast.io/. You can
make 1000 requests per day. This means that you could create every 1.4 minute
one.
monitored_conditions
2015-06-17 19:59:38 +00:00
*Required
Conditions to monitor. See the configuration example above for a
2015-06-17 19:59:38 +00:00
list of all available conditions to monitor.
units
*Optional
Specify the unit system. Default to 'si' or 'us' based on the temperature
preference in Home Assistant. Other options are auto, us, si, ca, and uk2.
'auto' will let forecast.io decide the unit system based on location.
For more information see the API url below.
2015-06-17 19:59:38 +00:00
Details for the API : https://developer.forecast.io/docs/v2
"""
import logging
from datetime import timedelta
REQUIREMENTS = ['python-forecastio==1.3.3']
2015-08-06 20:28:46 +00:00
2015-07-07 07:01:46 +00:00
try:
import forecastio
except ImportError:
forecastio = None
2015-06-17 19:59:38 +00:00
from homeassistant.util import Throttle
from homeassistant.const import (CONF_API_KEY, TEMP_CELCIUS)
2015-06-17 19:59:38 +00:00
from homeassistant.helpers.entity import Entity
_LOGGER = logging.getLogger(__name__)
# Sensor types are defined like so:
# Name, si unit, us unit, ca unit, uk unit, uk2 unit
2015-06-17 19:59:38 +00:00
SENSOR_TYPES = {
'summary': ['Summary', '', '', '', '', ''],
'icon': ['Icon', '', '', '', '', ''],
'nearest_storm_distance': ['Nearest Storm Distance',
'km', 'm', 'km', 'km', 'm'],
'nearest_storm_bearing': ['Nearest Storm Bearing',
'°', '°', '°', '°', '°'],
'precip_type': ['Precip', '', '', '', '', ''],
'precip_intensity': ['Precip Intensity', 'mm', 'in', 'mm', 'mm', 'mm'],
'precip_probability': ['Precip Probability', '%', '%', '%', '%', '%'],
'temperature': ['Temperature', '°C', '°F', '°C', '°C', '°C'],
'apparent_temperature': ['Apparent Temperature',
'°C', '°F', '°C', '°C', '°C'],
'dew_point': ['Dew point', '°C', '°F', '°C', '°C', '°C'],
'wind_speed': ['Wind Speed', 'm/s', 'mph', 'km/h', 'mph', 'mph'],
'wind_bearing': ['Wind Bearing', '°', '°', '°', '°', '°'],
'cloud_cover': ['Cloud Coverage', '%', '%', '%', '%', '%'],
'humidity': ['Humidity', '%', '%', '%', '%', '%'],
'pressure': ['Pressure', 'mBar', 'mBar', 'mBar', 'mBar', 'mBar'],
'visibility': ['Visibility', 'km', 'm', 'km', 'km', 'm'],
'ozone': ['Ozone', 'DU', 'DU', 'DU', 'DU', 'DU'],
2015-06-17 19:59:38 +00:00
}
# Return cached results if last scan was less then this time ago
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=120)
def setup_platform(hass, config, add_devices, discovery_info=None):
""" Get the Forecast.io sensor. """
2015-07-07 07:01:46 +00:00
global forecastio # pylint: disable=invalid-name
if forecastio is None:
import forecastio as forecastio_
forecastio = forecastio_
2015-06-17 19:59:38 +00:00
if None in (hass.config.latitude, hass.config.longitude):
_LOGGER.error("Latitude or longitude not set in Home Assistant config")
return False
try:
forecast = forecastio.load_forecast(config.get(CONF_API_KEY, None),
hass.config.latitude,
hass.config.longitude)
forecast.currently()
except ValueError:
_LOGGER.error(
"Connection error "
"Please check your settings for Forecast.io.")
return False
if 'units' in config:
units = config['units']
elif hass.config.temperature_unit == TEMP_CELCIUS:
units = 'si'
else:
units = 'us'
2015-06-17 19:59:38 +00:00
data = ForeCastData(config.get(CONF_API_KEY, None),
hass.config.latitude,
hass.config.longitude,
units)
2015-06-17 19:59:38 +00:00
dev = []
for variable in config['monitored_conditions']:
if variable not in SENSOR_TYPES:
_LOGGER.error('Sensor type: "%s" does not exist', variable)
else:
dev.append(ForeCastSensor(data, variable))
2015-06-17 19:59:38 +00:00
add_devices(dev)
# pylint: disable=too-few-public-methods
class ForeCastSensor(Entity):
""" Implements an Forecast.io sensor. """
2015-06-17 19:59:38 +00:00
def __init__(self, weather_data, sensor_type):
self.client_name = 'Weather'
2015-06-17 19:59:38 +00:00
self._name = SENSOR_TYPES[sensor_type][0]
self.forecast_client = weather_data
self.type = sensor_type
self._state = None
self._unit_system = self.forecast_client.unit_system
if self._unit_system == 'si':
self._unit_of_measurement = SENSOR_TYPES[self.type][1]
elif self._unit_system == 'us':
self._unit_of_measurement = SENSOR_TYPES[self.type][2]
elif self._unit_system == 'ca':
self._unit_of_measurement = SENSOR_TYPES[self.type][3]
elif self._unit_system == 'uk':
self._unit_of_measurement = SENSOR_TYPES[self.type][4]
elif self._unit_system == 'uk2':
self._unit_of_measurement = SENSOR_TYPES[self.type][5]
2015-06-17 19:59:38 +00:00
self.update()
@property
def name(self):
return '{} {}'.format(self.client_name, self._name)
2015-06-17 19:59:38 +00:00
@property
def state(self):
""" Returns the state of the device. """
return self._state
@property
def unit_of_measurement(self):
""" Unit of measurement of this entity, if any. """
return self._unit_of_measurement
@property
def unit_system(self):
""" Unit system of this entity. """
return self._unit_system
2015-06-17 19:59:38 +00:00
# pylint: disable=too-many-branches
def update(self):
""" Gets the latest data from Forecast.io and updates the states. """
self.forecast_client.update()
data = self.forecast_client.data
try:
if self.type == 'summary':
self._state = data.summary
elif self.type == 'icon':
self._state = data.icon
elif self.type == 'nearest_storm_distance':
self._state = data.nearestStormDistance
elif self.type == 'nearest_storm_bearing':
self._state = data.nearestStormBearing
2015-06-17 19:59:38 +00:00
elif self.type == 'precip_intensity':
self._state = data.precipIntensity
2015-06-17 19:59:38 +00:00
if data.precipIntensity == 0:
self._state = 'None'
self._unit_of_measurement = ''
else:
self._state = data.precipIntensity
elif self.type == 'precip_type':
if data.precipType is None:
self._state = 'None'
self._unit_of_measurement = ''
else:
self._state = data.precipType
elif self.type == 'precip_probability':
self._state = round(data.precipProbability * 100, 1)
2015-06-17 19:59:38 +00:00
elif self.type == 'dew_point':
self._state = round(data.dewPoint, 1)
2015-06-17 19:59:38 +00:00
elif self.type == 'temperature':
self._state = round(data.temperature, 1)
elif self.type == 'apparent_temperature':
self._state = round(data.apparentTemperature, 1)
2015-06-17 19:59:38 +00:00
elif self.type == 'wind_speed':
self._state = data.windSpeed
elif self.type == 'wind_bearing':
self._state = data.windBearing
elif self.type == 'cloud_cover':
self._state = round(data.cloudCover * 100, 1)
elif self.type == 'humidity':
self._state = round(data.humidity * 100, 1)
elif self.type == 'pressure':
self._state = round(data.pressure, 1)
elif self.type == 'visibility':
self._state = data.visibility
elif self.type == 'ozone':
self._state = round(data.ozone, 1)
2015-06-17 19:59:38 +00:00
except forecastio.utils.PropertyUnavailable:
pass
class ForeCastData(object):
""" Gets the latest data from Forecast.io. """
def __init__(self, api_key, latitude, longitude, units):
2015-06-17 19:59:38 +00:00
self._api_key = api_key
self.latitude = latitude
self.longitude = longitude
self.data = None
self.unit_system = None
self.units = units
self.update()
2015-06-17 19:59:38 +00:00
@Throttle(MIN_TIME_BETWEEN_UPDATES)
def update(self):
""" Gets the latest data from Forecast.io. """
forecast = forecastio.load_forecast(self._api_key,
self.latitude,
self.longitude,
units=self.units)
2015-06-17 19:59:38 +00:00
self.data = forecast.currently()
self.unit_system = forecast.json['flags']['units']