2019-02-14 15:42:03 +00:00
|
|
|
"""Weather component that handles meteorological data for your location."""
|
2018-12-11 13:12:27 +00:00
|
|
|
from datetime import timedelta
|
2016-10-25 04:53:03 +00:00
|
|
|
import logging
|
|
|
|
|
2019-02-14 15:42:03 +00:00
|
|
|
from homeassistant.const import PRECISION_TENTHS, PRECISION_WHOLE, TEMP_CELSIUS
|
2019-02-05 05:52:19 +00:00
|
|
|
from homeassistant.helpers.config_validation import ( # noqa
|
2019-07-31 19:25:30 +00:00
|
|
|
PLATFORM_SCHEMA,
|
|
|
|
PLATFORM_SCHEMA_BASE,
|
|
|
|
)
|
2016-10-25 04:53:03 +00:00
|
|
|
from homeassistant.helpers.entity import Entity
|
2019-02-14 15:42:03 +00:00
|
|
|
from homeassistant.helpers.entity_component import EntityComponent
|
|
|
|
from homeassistant.helpers.temperature import display_temp as show_temp
|
2016-10-25 04:53:03 +00:00
|
|
|
|
2019-08-12 03:38:18 +00:00
|
|
|
|
|
|
|
# mypy: allow-untyped-defs, no-check-untyped-defs
|
|
|
|
|
2016-10-25 04:53:03 +00:00
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
|
2019-07-31 19:25:30 +00:00
|
|
|
ATTR_CONDITION_CLASS = "condition_class"
|
|
|
|
ATTR_FORECAST = "forecast"
|
|
|
|
ATTR_FORECAST_CONDITION = "condition"
|
|
|
|
ATTR_FORECAST_PRECIPITATION = "precipitation"
|
|
|
|
ATTR_FORECAST_TEMP = "temperature"
|
|
|
|
ATTR_FORECAST_TEMP_LOW = "templow"
|
|
|
|
ATTR_FORECAST_TIME = "datetime"
|
|
|
|
ATTR_FORECAST_WIND_BEARING = "wind_bearing"
|
|
|
|
ATTR_FORECAST_WIND_SPEED = "wind_speed"
|
|
|
|
ATTR_WEATHER_ATTRIBUTION = "attribution"
|
|
|
|
ATTR_WEATHER_HUMIDITY = "humidity"
|
|
|
|
ATTR_WEATHER_OZONE = "ozone"
|
|
|
|
ATTR_WEATHER_PRESSURE = "pressure"
|
|
|
|
ATTR_WEATHER_TEMPERATURE = "temperature"
|
|
|
|
ATTR_WEATHER_VISIBILITY = "visibility"
|
|
|
|
ATTR_WEATHER_WIND_BEARING = "wind_bearing"
|
|
|
|
ATTR_WEATHER_WIND_SPEED = "wind_speed"
|
|
|
|
|
|
|
|
DOMAIN = "weather"
|
|
|
|
|
|
|
|
ENTITY_ID_FORMAT = DOMAIN + ".{}"
|
2018-12-11 13:12:27 +00:00
|
|
|
|
|
|
|
SCAN_INTERVAL = timedelta(seconds=30)
|
|
|
|
|
2016-10-25 04:53:03 +00:00
|
|
|
|
2018-10-01 06:52:42 +00:00
|
|
|
async def async_setup(hass, config):
|
2017-05-02 16:18:47 +00:00
|
|
|
"""Set up the weather component."""
|
2018-12-11 13:12:27 +00:00
|
|
|
component = hass.data[DOMAIN] = EntityComponent(
|
2019-07-31 19:25:30 +00:00
|
|
|
_LOGGER, DOMAIN, hass, SCAN_INTERVAL
|
|
|
|
)
|
2018-10-01 06:52:42 +00:00
|
|
|
await component.async_setup(config)
|
2016-10-25 04:53:03 +00:00
|
|
|
return True
|
|
|
|
|
|
|
|
|
2018-10-08 21:54:55 +00:00
|
|
|
async def async_setup_entry(hass, entry):
|
|
|
|
"""Set up a config entry."""
|
|
|
|
return await hass.data[DOMAIN].async_setup_entry(entry)
|
|
|
|
|
|
|
|
|
|
|
|
async def async_unload_entry(hass, entry):
|
|
|
|
"""Unload a config entry."""
|
|
|
|
return await hass.data[DOMAIN].async_unload_entry(entry)
|
|
|
|
|
|
|
|
|
2016-10-25 04:53:03 +00:00
|
|
|
class WeatherEntity(Entity):
|
2017-06-07 08:49:54 +00:00
|
|
|
"""ABC for weather data."""
|
2016-10-25 04:53:03 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
def temperature(self):
|
|
|
|
"""Return the platform temperature."""
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
|
|
|
@property
|
|
|
|
def temperature_unit(self):
|
|
|
|
"""Return the unit of measurement."""
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
|
|
|
@property
|
|
|
|
def pressure(self):
|
|
|
|
"""Return the pressure."""
|
|
|
|
return None
|
|
|
|
|
|
|
|
@property
|
|
|
|
def humidity(self):
|
|
|
|
"""Return the humidity."""
|
|
|
|
raise NotImplementedError()
|
|
|
|
|
|
|
|
@property
|
|
|
|
def wind_speed(self):
|
|
|
|
"""Return the wind speed."""
|
|
|
|
return None
|
|
|
|
|
|
|
|
@property
|
|
|
|
def wind_bearing(self):
|
|
|
|
"""Return the wind bearing."""
|
|
|
|
return None
|
|
|
|
|
|
|
|
@property
|
|
|
|
def ozone(self):
|
|
|
|
"""Return the ozone level."""
|
|
|
|
return None
|
|
|
|
|
|
|
|
@property
|
|
|
|
def attribution(self):
|
|
|
|
"""Return the attribution."""
|
|
|
|
return None
|
|
|
|
|
2017-06-07 08:49:54 +00:00
|
|
|
@property
|
|
|
|
def visibility(self):
|
|
|
|
"""Return the visibility."""
|
|
|
|
return None
|
|
|
|
|
2017-02-20 00:42:12 +00:00
|
|
|
@property
|
|
|
|
def forecast(self):
|
|
|
|
"""Return the forecast."""
|
|
|
|
return None
|
|
|
|
|
2017-11-14 09:36:18 +00:00
|
|
|
@property
|
|
|
|
def precision(self):
|
|
|
|
"""Return the forecast."""
|
2019-07-31 19:25:30 +00:00
|
|
|
return (
|
|
|
|
PRECISION_TENTHS
|
|
|
|
if self.temperature_unit == TEMP_CELSIUS
|
2017-11-14 09:36:18 +00:00
|
|
|
else PRECISION_WHOLE
|
2019-07-31 19:25:30 +00:00
|
|
|
)
|
2017-11-14 09:36:18 +00:00
|
|
|
|
2016-10-25 04:53:03 +00:00
|
|
|
@property
|
|
|
|
def state_attributes(self):
|
|
|
|
"""Return the state attributes."""
|
2019-08-23 12:13:06 +00:00
|
|
|
data = {}
|
|
|
|
if self.temperature is not None:
|
|
|
|
data[ATTR_WEATHER_TEMPERATURE] = show_temp(
|
2019-07-31 19:25:30 +00:00
|
|
|
self.hass, self.temperature, self.temperature_unit, self.precision
|
|
|
|
)
|
2016-10-25 04:53:03 +00:00
|
|
|
|
2018-04-30 17:27:45 +00:00
|
|
|
humidity = self.humidity
|
|
|
|
if humidity is not None:
|
|
|
|
data[ATTR_WEATHER_HUMIDITY] = round(humidity)
|
|
|
|
|
2016-10-25 04:53:03 +00:00
|
|
|
ozone = self.ozone
|
|
|
|
if ozone is not None:
|
|
|
|
data[ATTR_WEATHER_OZONE] = ozone
|
|
|
|
|
|
|
|
pressure = self.pressure
|
|
|
|
if pressure is not None:
|
|
|
|
data[ATTR_WEATHER_PRESSURE] = pressure
|
|
|
|
|
|
|
|
wind_bearing = self.wind_bearing
|
|
|
|
if wind_bearing is not None:
|
|
|
|
data[ATTR_WEATHER_WIND_BEARING] = wind_bearing
|
|
|
|
|
|
|
|
wind_speed = self.wind_speed
|
|
|
|
if wind_speed is not None:
|
|
|
|
data[ATTR_WEATHER_WIND_SPEED] = wind_speed
|
|
|
|
|
2017-06-07 08:49:54 +00:00
|
|
|
visibility = self.visibility
|
|
|
|
if visibility is not None:
|
|
|
|
data[ATTR_WEATHER_VISIBILITY] = visibility
|
|
|
|
|
2016-10-25 04:53:03 +00:00
|
|
|
attribution = self.attribution
|
|
|
|
if attribution is not None:
|
|
|
|
data[ATTR_WEATHER_ATTRIBUTION] = attribution
|
|
|
|
|
2017-02-20 00:42:12 +00:00
|
|
|
if self.forecast is not None:
|
|
|
|
forecast = []
|
|
|
|
for forecast_entry in self.forecast:
|
|
|
|
forecast_entry = dict(forecast_entry)
|
2017-11-14 09:36:18 +00:00
|
|
|
forecast_entry[ATTR_FORECAST_TEMP] = show_temp(
|
2019-07-31 19:25:30 +00:00
|
|
|
self.hass,
|
|
|
|
forecast_entry[ATTR_FORECAST_TEMP],
|
|
|
|
self.temperature_unit,
|
|
|
|
self.precision,
|
|
|
|
)
|
2018-04-29 15:50:49 +00:00
|
|
|
if ATTR_FORECAST_TEMP_LOW in forecast_entry:
|
|
|
|
forecast_entry[ATTR_FORECAST_TEMP_LOW] = show_temp(
|
2019-07-31 19:25:30 +00:00
|
|
|
self.hass,
|
|
|
|
forecast_entry[ATTR_FORECAST_TEMP_LOW],
|
|
|
|
self.temperature_unit,
|
|
|
|
self.precision,
|
|
|
|
)
|
2017-02-20 00:42:12 +00:00
|
|
|
forecast.append(forecast_entry)
|
|
|
|
|
|
|
|
data[ATTR_FORECAST] = forecast
|
|
|
|
|
2016-10-25 04:53:03 +00:00
|
|
|
return data
|
|
|
|
|
|
|
|
@property
|
|
|
|
def state(self):
|
|
|
|
"""Return the current state."""
|
|
|
|
return self.condition
|
|
|
|
|
|
|
|
@property
|
|
|
|
def condition(self):
|
|
|
|
"""Return the current condition."""
|
|
|
|
raise NotImplementedError()
|