1
0
mirror of https://github.com/home-assistant/core.git synced 2025-12-24 12:59:34 +00:00
Files
core/homeassistant/components/sensor/forecast.py

237 lines
7.7 KiB
Python

"""
homeassistant.components.sensor.forecast
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Forecast.io weather service.
Configuration:
To use the Forecast sensor you will need to add something like the
following to your configuration.yaml file.
sensor:
platform: forecast
api_key: YOUR_APP_KEY
monitored_conditions:
- summary
- precip_type
- precip_intensity
- temperature
- dew_point
- wind_speed
- wind_bearing
- cloud_cover
- humidity
- pressure
- visibility
- ozone
units: si, us, ca, uk, uk2 or auto(default)
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
*Required
Conditions to monitor. See the configuration example above for a
list of all available conditions to monitor.
units
*Optional
Specify the unit system. Default to 'auto' which is based on location.
Other options are us, si, ca, uk, and uk2. For more info see API link below.
Details for the API : https://developer.forecast.io/docs/v2
"""
import logging
from datetime import timedelta
REQUIREMENTS = ['python-forecastio==1.3.3']
try:
import forecastio
except ImportError:
forecastio = None
from homeassistant.util import Throttle
from homeassistant.const import (CONF_API_KEY)
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
SENSOR_TYPES = {
'summary': ['Summary', '', '', '', '', ''],
'precip_type': ['Precip', '', '', '', '', ''],
'precip_intensity': ['Precip intensity', 'mm', 'in', 'mm', 'mm', 'mm'],
'temperature': ['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'],
}
# 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. """
global forecastio # pylint: disable=invalid-name
if forecastio is None:
import forecastio as forecastio_
forecastio = forecastio_
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
units = config.get('units')
if units is None:
units = 'auto'
data = ForeCastData(config.get(CONF_API_KEY, None),
hass.config.latitude,
hass.config.longitude,
units)
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))
add_devices(dev)
# pylint: disable=too-few-public-methods
class ForeCastSensor(Entity):
""" Implements an Forecast.io sensor. """
def __init__(self, weather_data, sensor_type):
self.client_name = 'Weather'
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]
self.update()
@property
def name(self):
return '{} {}'.format(self.client_name, self._name)
@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
# 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 == 'precip_intensity':
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 == 'dew_point':
self._state = round(data.dewPoint, 1)
elif self.type == 'temperature':
self._state = round(data.temperature, 1)
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)
except forecastio.utils.PropertyUnavailable:
pass
class ForeCastData(object):
""" Gets the latest data from Forecast.io. """
def __init__(self, api_key, latitude, longitude, units):
self._api_key = api_key
self.latitude = latitude
self.longitude = longitude
self.data = None
self.unit_system = None
self.units = units
self.update()
@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)
self.data = forecast.currently()
self.unit_system = forecast.json['flags']['units']