Black
This commit is contained in:
parent
da05dfe708
commit
4de97abc3a
2676 changed files with 163166 additions and 140084 deletions
|
@ -5,51 +5,68 @@ import logging
|
|||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.weather import (
|
||||
ATTR_FORECAST_CONDITION, ATTR_FORECAST_PRECIPITATION, ATTR_FORECAST_TEMP,
|
||||
ATTR_FORECAST_TEMP_LOW, ATTR_FORECAST_TIME, ATTR_FORECAST_WIND_BEARING,
|
||||
ATTR_FORECAST_WIND_SPEED, PLATFORM_SCHEMA, WeatherEntity)
|
||||
ATTR_FORECAST_CONDITION,
|
||||
ATTR_FORECAST_PRECIPITATION,
|
||||
ATTR_FORECAST_TEMP,
|
||||
ATTR_FORECAST_TEMP_LOW,
|
||||
ATTR_FORECAST_TIME,
|
||||
ATTR_FORECAST_WIND_BEARING,
|
||||
ATTR_FORECAST_WIND_SPEED,
|
||||
PLATFORM_SCHEMA,
|
||||
WeatherEntity,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
CONF_API_KEY, CONF_LATITUDE, CONF_LONGITUDE, CONF_MODE, CONF_NAME,
|
||||
PRESSURE_HPA, PRESSURE_INHG, STATE_UNKNOWN, TEMP_CELSIUS)
|
||||
CONF_API_KEY,
|
||||
CONF_LATITUDE,
|
||||
CONF_LONGITUDE,
|
||||
CONF_MODE,
|
||||
CONF_NAME,
|
||||
PRESSURE_HPA,
|
||||
PRESSURE_INHG,
|
||||
STATE_UNKNOWN,
|
||||
TEMP_CELSIUS,
|
||||
)
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.util import Throttle
|
||||
from homeassistant.util.pressure import convert as convert_pressure
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
ATTRIBUTION = 'Data provided by OpenWeatherMap'
|
||||
ATTRIBUTION = "Data provided by OpenWeatherMap"
|
||||
|
||||
FORECAST_MODE = ['hourly', 'daily', 'freedaily']
|
||||
FORECAST_MODE = ["hourly", "daily", "freedaily"]
|
||||
|
||||
DEFAULT_NAME = 'OpenWeatherMap'
|
||||
DEFAULT_NAME = "OpenWeatherMap"
|
||||
|
||||
MIN_TIME_BETWEEN_FORECAST_UPDATES = timedelta(minutes=30)
|
||||
MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=10)
|
||||
|
||||
CONDITION_CLASSES = {
|
||||
'cloudy': [803, 804],
|
||||
'fog': [701, 741],
|
||||
'hail': [906],
|
||||
'lightning': [210, 211, 212, 221],
|
||||
'lightning-rainy': [200, 201, 202, 230, 231, 232],
|
||||
'partlycloudy': [801, 802],
|
||||
'pouring': [504, 314, 502, 503, 522],
|
||||
'rainy': [300, 301, 302, 310, 311, 312, 313, 500, 501, 520, 521],
|
||||
'snowy': [600, 601, 602, 611, 612, 620, 621, 622],
|
||||
'snowy-rainy': [511, 615, 616],
|
||||
'sunny': [800],
|
||||
'windy': [905, 951, 952, 953, 954, 955, 956, 957],
|
||||
'windy-variant': [958, 959, 960, 961],
|
||||
'exceptional': [711, 721, 731, 751, 761, 762, 771, 900, 901, 962, 903,
|
||||
904],
|
||||
"cloudy": [803, 804],
|
||||
"fog": [701, 741],
|
||||
"hail": [906],
|
||||
"lightning": [210, 211, 212, 221],
|
||||
"lightning-rainy": [200, 201, 202, 230, 231, 232],
|
||||
"partlycloudy": [801, 802],
|
||||
"pouring": [504, 314, 502, 503, 522],
|
||||
"rainy": [300, 301, 302, 310, 311, 312, 313, 500, 501, 520, 521],
|
||||
"snowy": [600, 601, 602, 611, 612, 620, 621, 622],
|
||||
"snowy-rainy": [511, 615, 616],
|
||||
"sunny": [800],
|
||||
"windy": [905, 951, 952, 953, 954, 955, 956, 957],
|
||||
"windy-variant": [958, 959, 960, 961],
|
||||
"exceptional": [711, 721, 731, 751, 761, 762, 771, 900, 901, 962, 903, 904],
|
||||
}
|
||||
|
||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
vol.Required(CONF_API_KEY): cv.string,
|
||||
vol.Optional(CONF_LATITUDE): cv.latitude,
|
||||
vol.Optional(CONF_LONGITUDE): cv.longitude,
|
||||
vol.Optional(CONF_MODE, default='hourly'): vol.In(FORECAST_MODE),
|
||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
||||
})
|
||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
||||
{
|
||||
vol.Required(CONF_API_KEY): cv.string,
|
||||
vol.Optional(CONF_LATITUDE): cv.latitude,
|
||||
vol.Optional(CONF_LONGITUDE): cv.longitude,
|
||||
vol.Optional(CONF_MODE, default="hourly"): vol.In(FORECAST_MODE),
|
||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||
|
@ -69,8 +86,10 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
|
|||
|
||||
data = WeatherData(owm, latitude, longitude, mode)
|
||||
|
||||
add_entities([OpenWeatherMapWeather(
|
||||
name, data, hass.config.units.temperature_unit, mode)], True)
|
||||
add_entities(
|
||||
[OpenWeatherMapWeather(name, data, hass.config.units.temperature_unit, mode)],
|
||||
True,
|
||||
)
|
||||
|
||||
|
||||
class OpenWeatherMapWeather(WeatherEntity):
|
||||
|
@ -94,15 +113,18 @@ class OpenWeatherMapWeather(WeatherEntity):
|
|||
def condition(self):
|
||||
"""Return the current condition."""
|
||||
try:
|
||||
return [k for k, v in CONDITION_CLASSES.items() if
|
||||
self.data.get_weather_code() in v][0]
|
||||
return [
|
||||
k
|
||||
for k, v in CONDITION_CLASSES.items()
|
||||
if self.data.get_weather_code() in v
|
||||
][0]
|
||||
except IndexError:
|
||||
return STATE_UNKNOWN
|
||||
|
||||
@property
|
||||
def temperature(self):
|
||||
"""Return the temperature."""
|
||||
return self.data.get_temperature('celsius').get('temp')
|
||||
return self.data.get_temperature("celsius").get("temp")
|
||||
|
||||
@property
|
||||
def temperature_unit(self):
|
||||
|
@ -112,10 +134,9 @@ class OpenWeatherMapWeather(WeatherEntity):
|
|||
@property
|
||||
def pressure(self):
|
||||
"""Return the pressure."""
|
||||
pressure = self.data.get_pressure().get('press')
|
||||
if self.hass.config.units.name == 'imperial':
|
||||
return round(
|
||||
convert_pressure(pressure, PRESSURE_HPA, PRESSURE_INHG), 2)
|
||||
pressure = self.data.get_pressure().get("press")
|
||||
if self.hass.config.units.name == "imperial":
|
||||
return round(convert_pressure(pressure, PRESSURE_HPA, PRESSURE_INHG), 2)
|
||||
return pressure
|
||||
|
||||
@property
|
||||
|
@ -126,15 +147,15 @@ class OpenWeatherMapWeather(WeatherEntity):
|
|||
@property
|
||||
def wind_speed(self):
|
||||
"""Return the wind speed."""
|
||||
if self.hass.config.units.name == 'imperial':
|
||||
return round(self.data.get_wind().get('speed') * 2.24, 2)
|
||||
if self.hass.config.units.name == "imperial":
|
||||
return round(self.data.get_wind().get("speed") * 2.24, 2)
|
||||
|
||||
return round(self.data.get_wind().get('speed') * 3.6, 2)
|
||||
return round(self.data.get_wind().get("speed") * 3.6, 2)
|
||||
|
||||
@property
|
||||
def wind_bearing(self):
|
||||
"""Return the wind bearing."""
|
||||
return self.data.get_wind().get('deg')
|
||||
return self.data.get_wind().get("deg")
|
||||
|
||||
@property
|
||||
def attribution(self):
|
||||
|
@ -154,47 +175,52 @@ class OpenWeatherMapWeather(WeatherEntity):
|
|||
return None
|
||||
return round(rain_value + snow_value, 1)
|
||||
|
||||
if self._mode == 'freedaily':
|
||||
if self._mode == "freedaily":
|
||||
weather = self.forecast_data.get_weathers()[::8]
|
||||
else:
|
||||
weather = self.forecast_data.get_weathers()
|
||||
|
||||
for entry in weather:
|
||||
if self._mode == 'daily':
|
||||
data.append({
|
||||
ATTR_FORECAST_TIME:
|
||||
entry.get_reference_time('unix') * 1000,
|
||||
ATTR_FORECAST_TEMP:
|
||||
entry.get_temperature('celsius').get('day'),
|
||||
ATTR_FORECAST_TEMP_LOW:
|
||||
entry.get_temperature('celsius').get('night'),
|
||||
ATTR_FORECAST_PRECIPITATION:
|
||||
calc_precipitation(
|
||||
entry.get_rain().get('all'),
|
||||
entry.get_snow().get('all')),
|
||||
ATTR_FORECAST_WIND_SPEED:
|
||||
entry.get_wind().get('speed'),
|
||||
ATTR_FORECAST_WIND_BEARING:
|
||||
entry.get_wind().get('deg'),
|
||||
ATTR_FORECAST_CONDITION:
|
||||
[k for k, v in CONDITION_CLASSES.items()
|
||||
if entry.get_weather_code() in v][0]
|
||||
})
|
||||
if self._mode == "daily":
|
||||
data.append(
|
||||
{
|
||||
ATTR_FORECAST_TIME: entry.get_reference_time("unix") * 1000,
|
||||
ATTR_FORECAST_TEMP: entry.get_temperature("celsius").get("day"),
|
||||
ATTR_FORECAST_TEMP_LOW: entry.get_temperature("celsius").get(
|
||||
"night"
|
||||
),
|
||||
ATTR_FORECAST_PRECIPITATION: calc_precipitation(
|
||||
entry.get_rain().get("all"), entry.get_snow().get("all")
|
||||
),
|
||||
ATTR_FORECAST_WIND_SPEED: entry.get_wind().get("speed"),
|
||||
ATTR_FORECAST_WIND_BEARING: entry.get_wind().get("deg"),
|
||||
ATTR_FORECAST_CONDITION: [
|
||||
k
|
||||
for k, v in CONDITION_CLASSES.items()
|
||||
if entry.get_weather_code() in v
|
||||
][0],
|
||||
}
|
||||
)
|
||||
else:
|
||||
data.append({
|
||||
ATTR_FORECAST_TIME:
|
||||
entry.get_reference_time('unix') * 1000,
|
||||
ATTR_FORECAST_TEMP:
|
||||
entry.get_temperature('celsius').get('temp'),
|
||||
ATTR_FORECAST_PRECIPITATION:
|
||||
(round(entry.get_rain().get('3h'), 1)
|
||||
if entry.get_rain().get('3h') is not None
|
||||
and (round(entry.get_rain().get('3h'), 1) > 0)
|
||||
else None),
|
||||
ATTR_FORECAST_CONDITION:
|
||||
[k for k, v in CONDITION_CLASSES.items()
|
||||
if entry.get_weather_code() in v][0]
|
||||
})
|
||||
data.append(
|
||||
{
|
||||
ATTR_FORECAST_TIME: entry.get_reference_time("unix") * 1000,
|
||||
ATTR_FORECAST_TEMP: entry.get_temperature("celsius").get(
|
||||
"temp"
|
||||
),
|
||||
ATTR_FORECAST_PRECIPITATION: (
|
||||
round(entry.get_rain().get("3h"), 1)
|
||||
if entry.get_rain().get("3h") is not None
|
||||
and (round(entry.get_rain().get("3h"), 1) > 0)
|
||||
else None
|
||||
),
|
||||
ATTR_FORECAST_CONDITION: [
|
||||
k
|
||||
for k, v in CONDITION_CLASSES.items()
|
||||
if entry.get_weather_code() in v
|
||||
][0],
|
||||
}
|
||||
)
|
||||
return data
|
||||
|
||||
def update(self):
|
||||
|
@ -240,15 +266,16 @@ class WeatherData:
|
|||
from pyowm.exceptions.api_call_error import APICallError
|
||||
|
||||
try:
|
||||
if self._mode == 'daily':
|
||||
if self._mode == "daily":
|
||||
fcd = self.owm.daily_forecast_at_coords(
|
||||
self.latitude, self.longitude, 15)
|
||||
self.latitude, self.longitude, 15
|
||||
)
|
||||
else:
|
||||
fcd = self.owm.three_hours_forecast_at_coords(
|
||||
self.latitude, self.longitude)
|
||||
self.latitude, self.longitude
|
||||
)
|
||||
except APICallError:
|
||||
_LOGGER.error("Exception when calling OWM web API "
|
||||
"to update forecast")
|
||||
_LOGGER.error("Exception when calling OWM web API " "to update forecast")
|
||||
return
|
||||
|
||||
if fcd is None:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue