From 293ed275ab4a659248dbf0e70d5ee5c674a45757 Mon Sep 17 00:00:00 2001 From: Nolan Gilley Date: Tue, 20 Oct 2015 14:29:22 -0400 Subject: [PATCH 1/2] Added support for specifying units in the configuration file. If no units are specified in the config file it will use location to determine the units. --- homeassistant/components/sensor/forecast.py | 94 ++++++++++++--------- 1 file changed, 55 insertions(+), 39 deletions(-) diff --git a/homeassistant/components/sensor/forecast.py b/homeassistant/components/sensor/forecast.py index 2c966530967..8fe39c67114 100644 --- a/homeassistant/components/sensor/forecast.py +++ b/homeassistant/components/sensor/forecast.py @@ -24,6 +24,7 @@ sensor: - pressure - visibility - ozone + units: si, us, ca, uk, uk2 or auto(default) Variables: @@ -33,15 +34,16 @@ 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 -An array specifying the conditions to monitor. - 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 @@ -55,23 +57,26 @@ except ImportError: forecastio = None from homeassistant.util import Throttle -from homeassistant.const import (CONF_API_KEY, TEMP_CELCIUS, TEMP_FAHRENHEIT) +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'], - 'temperature': ['Temperature', ''], - 'dew_point': ['Dew point', '°C'], - 'wind_speed': ['Wind Speed', 'm/s'], - 'wind_bearing': ['Wind Bearing', '°'], - 'cloud_cover': ['Cloud coverage', '%'], - 'humidity': ['Humidity', '%'], - 'pressure': ['Pressure', 'mBar'], - 'visibility': ['Visibility', 'km'], - 'ozone': ['Ozone', 'DU'], + '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 @@ -90,9 +95,6 @@ def setup_platform(hass, config, add_devices, discovery_info=None): _LOGGER.error("Latitude or longitude not set in Home Assistant config") return False - SENSOR_TYPES['temperature'][1] = hass.config.temperature_unit - unit = hass.config.temperature_unit - try: forecast = forecastio.load_forecast(config.get(CONF_API_KEY, None), hass.config.latitude, @@ -104,16 +106,21 @@ def setup_platform(hass, config, add_devices, discovery_info=None): "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) + 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, unit)) + dev.append(ForeCastSensor(data, variable)) add_devices(dev) @@ -122,14 +129,23 @@ def setup_platform(hass, config, add_devices, discovery_info=None): class ForeCastSensor(Entity): """ 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._name = SENSOR_TYPES[sensor_type][0] self.forecast_client = weather_data - self._unit = unit self.type = sensor_type 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() @property @@ -146,6 +162,11 @@ class ForeCastSensor(Entity): """ 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. """ @@ -169,19 +190,9 @@ class ForeCastSensor(Entity): else: self._state = data.precipType elif self.type == 'dew_point': - if self._unit == TEMP_CELCIUS: - 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) + self._state = round(data.dewPoint, 1) elif self.type == 'temperature': - if self._unit == TEMP_CELCIUS: - self._state = round(data.temperature, 1) - elif self._unit == TEMP_FAHRENHEIT: - self._state = round(data.temperature * 1.8 + 32.0, 1) - else: - self._state = round(data.temperature, 1) + self._state = round(data.temperature, 1) elif self.type == 'wind_speed': self._state = data.windSpeed elif self.type == 'wind_bearing': @@ -196,6 +207,7 @@ class ForeCastSensor(Entity): self._state = data.visibility elif self.type == 'ozone': self._state = round(data.ozone, 1) + except forecastio.utils.PropertyUnavailable: pass @@ -203,11 +215,14 @@ class ForeCastSensor(Entity): class ForeCastData(object): """ 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.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): @@ -216,5 +231,6 @@ class ForeCastData(object): forecast = forecastio.load_forecast(self._api_key, self.latitude, self.longitude, - units='si') + units=self.units) self.data = forecast.currently() + self.unit_system = forecast.json['flags']['units'] From dd787ea5cede20fa51fc0a291fb7db51e9f37e22 Mon Sep 17 00:00:00 2001 From: Nolan Gilley Date: Fri, 23 Oct 2015 10:10:44 -0400 Subject: [PATCH 2/2] remove suggestion for uk unit system. change default to use si or us based on default temperature. added more sensor types. --- homeassistant/components/sensor/forecast.py | 48 +++++++++++++++++---- 1 file changed, 39 insertions(+), 9 deletions(-) diff --git a/homeassistant/components/sensor/forecast.py b/homeassistant/components/sensor/forecast.py index 8fe39c67114..0cbafe53d97 100644 --- a/homeassistant/components/sensor/forecast.py +++ b/homeassistant/components/sensor/forecast.py @@ -13,9 +13,14 @@ sensor: api_key: YOUR_APP_KEY monitored_conditions: - summary + - icon + - nearest_storm_distance + - nearest_storm_bearing - precip_type - precip_intensity + - precip_probability - temperature + - apparent_temperature - dew_point - wind_speed - wind_bearing @@ -24,7 +29,8 @@ sensor: - pressure - visibility - ozone - units: si, us, ca, uk, uk2 or auto(default) + # Optional: specify which unit system to use. + units: si, us, ca, uk2 or auto Variables: @@ -41,8 +47,10 @@ 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. +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 """ @@ -57,7 +65,7 @@ except ImportError: forecastio = None from homeassistant.util import Throttle -from homeassistant.const import (CONF_API_KEY) +from homeassistant.const import (CONF_API_KEY, TEMP_CELCIUS) from homeassistant.helpers.entity import Entity _LOGGER = logging.getLogger(__name__) @@ -66,13 +74,21 @@ _LOGGER = logging.getLogger(__name__) # Name, si unit, us unit, ca unit, uk unit, uk2 unit 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_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', '%', '%', '%', '%', '%'], + 'cloud_cover': ['Cloud Coverage', '%', '%', '%', '%', '%'], 'humidity': ['Humidity', '%', '%', '%', '%', '%'], 'pressure': ['Pressure', 'mBar', 'mBar', 'mBar', 'mBar', 'mBar'], 'visibility': ['Visibility', 'km', 'm', 'km', 'km', 'm'], @@ -106,9 +122,12 @@ def setup_platform(hass, config, add_devices, discovery_info=None): "Please check your settings for Forecast.io.") return False - units = config.get('units') - if units is None: - units = 'auto' + 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), hass.config.latitude, @@ -177,7 +196,14 @@ class ForeCastSensor(Entity): 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 elif self.type == 'precip_intensity': + self._state = data.precipIntensity if data.precipIntensity == 0: self._state = 'None' self._unit_of_measurement = '' @@ -189,10 +215,14 @@ class ForeCastSensor(Entity): self._unit_of_measurement = '' else: self._state = data.precipType + elif self.type == 'precip_probability': + self._state = round(data.precipProbability * 100, 1) elif self.type == 'dew_point': self._state = round(data.dewPoint, 1) elif self.type == 'temperature': self._state = round(data.temperature, 1) + elif self.type == 'apparent_temperature': + self._state = round(data.apparentTemperature, 1) elif self.type == 'wind_speed': self._state = data.windSpeed elif self.type == 'wind_bearing':