1 """Weather component that handles meteorological data for your location."""
3 from __future__
import annotations
5 from datetime
import datetime
7 from pytomorrowio.const
import DAILY, FORECASTS, HOURLY, NOWCAST, WeatherCode
10 ATTR_FORECAST_CONDITION,
11 ATTR_FORECAST_HUMIDITY,
12 ATTR_FORECAST_NATIVE_DEW_POINT,
13 ATTR_FORECAST_NATIVE_PRECIPITATION,
14 ATTR_FORECAST_NATIVE_TEMP,
15 ATTR_FORECAST_NATIVE_TEMP_LOW,
16 ATTR_FORECAST_NATIVE_WIND_SPEED,
17 ATTR_FORECAST_PRECIPITATION_PROBABILITY,
19 ATTR_FORECAST_WIND_BEARING,
20 DOMAIN
as WEATHER_DOMAIN,
22 SingleCoordinatorWeatherEntity,
29 UnitOfPrecipitationDepth,
44 DEFAULT_FORECAST_TYPE,
51 TMRW_ATTR_PRECIPITATION,
52 TMRW_ATTR_PRECIPITATION_PROBABILITY,
54 TMRW_ATTR_TEMPERATURE,
55 TMRW_ATTR_TEMPERATURE_HIGH,
56 TMRW_ATTR_TEMPERATURE_LOW,
59 TMRW_ATTR_WIND_DIRECTION,
62 from .coordinator
import TomorrowioDataUpdateCoordinator
63 from .entity
import TomorrowioEntity
68 config_entry: ConfigEntry,
69 async_add_entities: AddEntitiesCallback,
71 """Set up a config entry."""
72 coordinator = hass.data[DOMAIN][config_entry.data[CONF_API_KEY]]
73 entity_registry = er.async_get(hass)
78 for forecast_type
in (HOURLY, NOWCAST):
79 if not entity_registry.async_get_entity_id(
93 """Calculate unique ID."""
94 return f
"{config_entry_unique_id}_{forecast_type}"
98 """Entity that talks to Tomorrow.io v4 API to retrieve weather data."""
100 _attr_native_precipitation_unit = UnitOfPrecipitationDepth.MILLIMETERS
101 _attr_native_pressure_unit = UnitOfPressure.HPA
102 _attr_native_temperature_unit = UnitOfTemperature.CELSIUS
103 _attr_native_visibility_unit = UnitOfLength.KILOMETERS
104 _attr_native_wind_speed_unit = UnitOfSpeed.METERS_PER_SECOND
105 _attr_supported_features = (
106 WeatherEntityFeature.FORECAST_DAILY | WeatherEntityFeature.FORECAST_HOURLY
111 config_entry: ConfigEntry,
112 coordinator: TomorrowioDataUpdateCoordinator,
116 """Initialize Tomorrow.io Weather Entity."""
117 super().
__init__(config_entry, coordinator, api_version)
120 forecast_type == DEFAULT_FORECAST_TYPE
124 config_entry.unique_id, forecast_type
129 forecast_dt: datetime,
132 precipitation: float |
None,
133 precipitation_probability: int |
None,
135 temp_low: float |
None,
136 humidity: float |
None,
137 dew_point: float |
None,
138 wind_direction: float |
None,
139 wind_speed: float |
None,
141 """Return formatted Forecast dict from Tomorrow.io forecast data."""
150 ATTR_FORECAST_TIME: forecast_dt.isoformat(),
151 ATTR_FORECAST_CONDITION: translated_condition,
152 ATTR_FORECAST_NATIVE_PRECIPITATION: precipitation,
153 ATTR_FORECAST_PRECIPITATION_PROBABILITY: precipitation_probability,
154 ATTR_FORECAST_NATIVE_TEMP: temp,
155 ATTR_FORECAST_NATIVE_TEMP_LOW: temp_low,
156 ATTR_FORECAST_HUMIDITY: humidity,
157 ATTR_FORECAST_NATIVE_DEW_POINT: dew_point,
158 ATTR_FORECAST_WIND_BEARING: wind_direction,
159 ATTR_FORECAST_NATIVE_WIND_SPEED: wind_speed,
164 condition: int |
None, sun_is_up: bool =
True
166 """Translate Tomorrow.io condition into an HA condition."""
167 if condition
is None:
170 condition = WeatherCode(condition)
171 if condition
in (WeatherCode.CLEAR, WeatherCode.MOSTLY_CLEAR):
173 return CLEAR_CONDITIONS[
"day"]
174 return CLEAR_CONDITIONS[
"night"]
175 return CONDITIONS[condition]
179 """Return the platform temperature."""
184 """Return the raw pressure."""
189 """Return the humidity."""
194 """Return the raw wind speed."""
199 """Return the wind bearing."""
204 """Return the O3 (ozone) level."""
209 """Return the condition."""
217 """Return the raw visibility."""
220 def _forecast(self, forecast_type: str) -> list[Forecast] |
None:
221 """Return the forecast."""
224 self.coordinator.data.get(self.
_config_entry_config_entry.entry_id, {})
228 if not raw_forecasts:
231 forecasts: list[Forecast] = []
232 max_forecasts = MAX_FORECASTS[forecast_type]
236 today = dt_util.as_local(dt_util.utcnow()).
date()
240 for forecast
in raw_forecasts:
241 forecast_dt = dt_util.parse_datetime(forecast[TMRW_ATTR_TIMESTAMP])
244 if forecast_dt
is None or dt_util.as_local(forecast_dt).
date() < today:
247 values = forecast[
"values"]
250 condition = values.get(TMRW_ATTR_CONDITION)
251 precipitation = values.get(TMRW_ATTR_PRECIPITATION)
252 precipitation_probability = values.get(TMRW_ATTR_PRECIPITATION_PROBABILITY)
255 precipitation_probability = round(precipitation_probability)
257 precipitation_probability =
None
259 temp = values.get(TMRW_ATTR_TEMPERATURE_HIGH)
261 dew_point = values.get(TMRW_ATTR_DEW_POINT)
262 humidity = values.get(TMRW_ATTR_HUMIDITY)
264 wind_direction = values.get(TMRW_ATTR_WIND_DIRECTION)
265 wind_speed = values.get(TMRW_ATTR_WIND_SPEED)
267 if forecast_type == DAILY:
269 temp_low = values.get(TMRW_ATTR_TEMPERATURE_LOW)
271 precipitation = precipitation * 24
272 elif forecast_type == NOWCAST:
277 precipitation / 60 * self.
_config_entry_config_entry.options[CONF_TIMESTEP]
286 precipitation_probability,
297 if forecast_count == max_forecasts:
304 """Return the daily forecast in native units."""
309 """Return the hourly forecast in native units."""
int|str|float|None _get_current_property(self, str property_name)
list[Forecast]|None _async_forecast_daily(self)
def native_visibility(self)
list[Forecast]|None _async_forecast_hourly(self)
str|None _translate_condition(int|None condition, bool sun_is_up=True)
def native_wind_speed(self)
_attr_entity_registry_enabled_default
list[Forecast]|None _forecast(self, str forecast_type)
None __init__(self, ConfigEntry config_entry, TomorrowioDataUpdateCoordinator coordinator, int api_version, str forecast_type)
def native_pressure(self)
Forecast _forecast_dict(self, datetime forecast_dt, bool use_datetime, int condition, float|None precipitation, int|None precipitation_probability, float|None temp, float|None temp_low, float|None humidity, float|None dew_point, float|None wind_direction, float|None wind_speed)
def native_temperature(self)
web.Response get(self, web.Request request, str config_key)
str _calculate_unique_id(str|None config_entry_unique_id, str forecast_type)
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)
bool is_up(HomeAssistant hass, datetime.datetime|None utc_point_in_time=None)