Merge pull request #539 from nkgilley/forecastio-units

Forecastio: Added support for specifying unit system in the configuration file.
This commit is contained in:
Paulus Schoutsen 2015-10-23 22:54:31 -07:00
commit 7a699fd819

View File

@ -13,9 +13,14 @@ sensor:
api_key: YOUR_APP_KEY api_key: YOUR_APP_KEY
monitored_conditions: monitored_conditions:
- summary - summary
- icon
- nearest_storm_distance
- nearest_storm_bearing
- precip_type - precip_type
- precip_intensity - precip_intensity
- precip_probability
- temperature - temperature
- apparent_temperature
- dew_point - dew_point
- wind_speed - wind_speed
- wind_bearing - wind_bearing
@ -24,6 +29,8 @@ sensor:
- pressure - pressure
- visibility - visibility
- ozone - ozone
# Optional: specify which unit system to use.
units: si, us, ca, uk2 or auto
Variables: Variables:
@ -33,15 +40,18 @@ 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 make 1000 requests per day. This means that you could create every 1.4 minute
one. one.
monitored_conditions
*Required
An array specifying the conditions to monitor.
monitored_conditions monitored_conditions
*Required *Required
Conditions to monitor. See the configuration example above for a Conditions to monitor. See the configuration example above for a
list of all available conditions to monitor. 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.
Details for the API : https://developer.forecast.io/docs/v2 Details for the API : https://developer.forecast.io/docs/v2
""" """
import logging import logging
@ -55,23 +65,34 @@ except ImportError:
forecastio = None forecastio = None
from homeassistant.util import Throttle from homeassistant.util import Throttle
from homeassistant.const import (CONF_API_KEY, TEMP_CELCIUS, TEMP_FAHRENHEIT) from homeassistant.const import (CONF_API_KEY, TEMP_CELCIUS)
from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity import Entity
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
# Sensor types are defined like so:
# Name, si unit, us unit, ca unit, uk unit, uk2 unit
SENSOR_TYPES = { SENSOR_TYPES = {
'summary': ['Summary', ''], 'summary': ['Summary', '', '', '', '', ''],
'precip_type': ['Precip', ''], 'icon': ['Icon', '', '', '', '', ''],
'precip_intensity': ['Precip intensity', 'mm'], 'nearest_storm_distance': ['Nearest Storm Distance',
'temperature': ['Temperature', ''], 'km', 'm', 'km', 'km', 'm'],
'dew_point': ['Dew point', '°C'], 'nearest_storm_bearing': ['Nearest Storm Bearing',
'wind_speed': ['Wind Speed', 'm/s'], '°', '°', '°', '°', '°'],
'wind_bearing': ['Wind Bearing', '°'], 'precip_type': ['Precip', '', '', '', '', ''],
'cloud_cover': ['Cloud coverage', '%'], 'precip_intensity': ['Precip Intensity', 'mm', 'in', 'mm', 'mm', 'mm'],
'humidity': ['Humidity', '%'], 'precip_probability': ['Precip Probability', '%', '%', '%', '%', '%'],
'pressure': ['Pressure', 'mBar'], 'temperature': ['Temperature', '°C', '°F', '°C', '°C', '°C'],
'visibility': ['Visibility', 'km'], 'apparent_temperature': ['Apparent Temperature',
'ozone': ['Ozone', 'DU'], '°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 # Return cached results if last scan was less then this time ago
@ -90,9 +111,6 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
_LOGGER.error("Latitude or longitude not set in Home Assistant config") _LOGGER.error("Latitude or longitude not set in Home Assistant config")
return False return False
SENSOR_TYPES['temperature'][1] = hass.config.temperature_unit
unit = hass.config.temperature_unit
try: try:
forecast = forecastio.load_forecast(config.get(CONF_API_KEY, None), forecast = forecastio.load_forecast(config.get(CONF_API_KEY, None),
hass.config.latitude, hass.config.latitude,
@ -104,16 +122,24 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
"Please check your settings for Forecast.io.") "Please check your settings for Forecast.io.")
return False return False
if 'units' in config:
units = config['units']
elif hass.config.temperature_unit == TEMP_CELCIUS:
units = 'si'
else:
units = 'us'
data = ForeCastData(config.get(CONF_API_KEY, None), data = ForeCastData(config.get(CONF_API_KEY, None),
hass.config.latitude, hass.config.latitude,
hass.config.longitude) hass.config.longitude,
units)
dev = [] dev = []
for variable in config['monitored_conditions']: for variable in config['monitored_conditions']:
if variable not in SENSOR_TYPES: if variable not in SENSOR_TYPES:
_LOGGER.error('Sensor type: "%s" does not exist', variable) _LOGGER.error('Sensor type: "%s" does not exist', variable)
else: else:
dev.append(ForeCastSensor(data, variable, unit)) dev.append(ForeCastSensor(data, variable))
add_devices(dev) add_devices(dev)
@ -122,14 +148,23 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
class ForeCastSensor(Entity): class ForeCastSensor(Entity):
""" Implements an Forecast.io sensor. """ """ Implements an Forecast.io sensor. """
def __init__(self, weather_data, sensor_type, unit): def __init__(self, weather_data, sensor_type):
self.client_name = 'Weather' self.client_name = 'Weather'
self._name = SENSOR_TYPES[sensor_type][0] self._name = SENSOR_TYPES[sensor_type][0]
self.forecast_client = weather_data self.forecast_client = weather_data
self._unit = unit
self.type = sensor_type self.type = sensor_type
self._state = None self._state = None
self._unit_of_measurement = SENSOR_TYPES[sensor_type][1] 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() self.update()
@property @property
@ -146,6 +181,11 @@ class ForeCastSensor(Entity):
""" Unit of measurement of this entity, if any. """ """ Unit of measurement of this entity, if any. """
return self._unit_of_measurement return self._unit_of_measurement
@property
def unit_system(self):
""" Unit system of this entity. """
return self._unit_system
# pylint: disable=too-many-branches # pylint: disable=too-many-branches
def update(self): def update(self):
""" Gets the latest data from Forecast.io and updates the states. """ """ Gets the latest data from Forecast.io and updates the states. """
@ -156,7 +196,14 @@ class ForeCastSensor(Entity):
try: try:
if self.type == 'summary': if self.type == 'summary':
self._state = data.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
elif self.type == 'precip_intensity': elif self.type == 'precip_intensity':
self._state = data.precipIntensity
if data.precipIntensity == 0: if data.precipIntensity == 0:
self._state = 'None' self._state = 'None'
self._unit_of_measurement = '' self._unit_of_measurement = ''
@ -168,20 +215,14 @@ class ForeCastSensor(Entity):
self._unit_of_measurement = '' self._unit_of_measurement = ''
else: else:
self._state = data.precipType self._state = data.precipType
elif self.type == 'precip_probability':
self._state = round(data.precipProbability * 100, 1)
elif self.type == 'dew_point': elif self.type == 'dew_point':
if self._unit == TEMP_CELCIUS: self._state = round(data.dewPoint, 1)
self._state = round(data.dewPoint, 1)
elif self._unit == TEMP_FAHRENHEIT:
self._state = round(data.dewPoint * 1.8 + 32.0, 1)
else:
self._state = round(data.dewPoint, 1)
elif self.type == 'temperature': elif self.type == 'temperature':
if self._unit == TEMP_CELCIUS: self._state = round(data.temperature, 1)
self._state = round(data.temperature, 1) elif self.type == 'apparent_temperature':
elif self._unit == TEMP_FAHRENHEIT: self._state = round(data.apparentTemperature, 1)
self._state = round(data.temperature * 1.8 + 32.0, 1)
else:
self._state = round(data.temperature, 1)
elif self.type == 'wind_speed': elif self.type == 'wind_speed':
self._state = data.windSpeed self._state = data.windSpeed
elif self.type == 'wind_bearing': elif self.type == 'wind_bearing':
@ -196,6 +237,7 @@ class ForeCastSensor(Entity):
self._state = data.visibility self._state = data.visibility
elif self.type == 'ozone': elif self.type == 'ozone':
self._state = round(data.ozone, 1) self._state = round(data.ozone, 1)
except forecastio.utils.PropertyUnavailable: except forecastio.utils.PropertyUnavailable:
pass pass
@ -203,11 +245,14 @@ class ForeCastSensor(Entity):
class ForeCastData(object): class ForeCastData(object):
""" Gets the latest data from Forecast.io. """ """ Gets the latest data from Forecast.io. """
def __init__(self, api_key, latitude, longitude): def __init__(self, api_key, latitude, longitude, units):
self._api_key = api_key self._api_key = api_key
self.latitude = latitude self.latitude = latitude
self.longitude = longitude self.longitude = longitude
self.data = None self.data = None
self.unit_system = None
self.units = units
self.update()
@Throttle(MIN_TIME_BETWEEN_UPDATES) @Throttle(MIN_TIME_BETWEEN_UPDATES)
def update(self): def update(self):
@ -216,5 +261,6 @@ class ForeCastData(object):
forecast = forecastio.load_forecast(self._api_key, forecast = forecastio.load_forecast(self._api_key,
self.latitude, self.latitude,
self.longitude, self.longitude,
units='si') units=self.units)
self.data = forecast.currently() self.data = forecast.currently()
self.unit_system = forecast.json['flags']['units']