1 """Support for IPMA weather service."""
3 from __future__
import annotations
8 from typing
import Literal
10 from pyipma.api
import IPMA_API
11 from pyipma.forecast
import Forecast
as IPMAForecast
12 from pyipma.location
import Location
15 ATTR_FORECAST_CONDITION,
16 ATTR_FORECAST_NATIVE_TEMP,
17 ATTR_FORECAST_NATIVE_TEMP_LOW,
18 ATTR_FORECAST_NATIVE_WIND_SPEED,
19 ATTR_FORECAST_PRECIPITATION_PROBABILITY,
21 ATTR_FORECAST_WIND_BEARING,
44 MIN_TIME_BETWEEN_UPDATES,
46 from .entity
import IPMADevice
48 _LOGGER = logging.getLogger(__name__)
53 config_entry: ConfigEntry,
54 async_add_entities: AddEntitiesCallback,
56 """Add a weather entity from a config_entry."""
57 api = hass.data[DOMAIN][config_entry.entry_id][DATA_API]
58 location = hass.data[DOMAIN][config_entry.entry_id][DATA_LOCATION]
63 """Representation of a weather condition."""
65 _attr_attribution = ATTRIBUTION
67 _attr_native_pressure_unit = UnitOfPressure.HPA
68 _attr_native_temperature_unit = UnitOfTemperature.CELSIUS
69 _attr_native_wind_speed_unit = UnitOfSpeed.KILOMETERS_PER_HOUR
70 _attr_supported_features = (
71 WeatherEntityFeature.FORECAST_DAILY | WeatherEntityFeature.FORECAST_HOURLY
75 self, api: IPMA_API, location: Location, config_entry: ConfigEntry
77 """Initialise the platform with a data instance and station name."""
78 IPMADevice.__init__(self, api, location)
79 self.
_mode_mode = config_entry.data.get(CONF_MODE)
80 self.
_period_period = 1
if config_entry.data.get(CONF_MODE) ==
"hourly" else 24
83 self._hourly_forecast: list[IPMAForecast] |
None =
None
84 if self.
_mode_mode
is not None:
85 self.
_attr_unique_id_attr_unique_id = f
"{self._location.station_latitude}, {self._location.station_longitude}, {self._mode}"
88 f
"{self._location.station_latitude}, {self._location.station_longitude}"
91 @Throttle(MIN_TIME_BETWEEN_UPDATES)
93 """Update Condition and Forecast."""
94 async
with asyncio.timeout(10):
95 new_observation = await self.
_location_location.observation(self.
_api_api)
100 _LOGGER.warning(
"Could not update weather observation")
110 "Updated location %s based on %s, current observation %s",
118 forecast_type: Literal[
"daily",
"hourly"],
120 update_listeners: bool,
122 """Update weather forecast."""
123 new_forecast = await self.
_location_location.forecast(self.
_api_api, period)
125 setattr(self, f
"_{forecast_type}_forecast", new_forecast)
129 _LOGGER.warning(
"Could not update %s weather forecast", forecast_type)
132 """Convert from IPMA weather_type id to HA."""
133 if identifier == 1
and not is_up(self.
hasshass, forecast_dt):
134 identifier = -identifier
136 return CONDITION_MAP.get(identifier)
140 """Return the current condition which is only available on the hourly forecast data."""
141 forecast = self._hourly_forecast
150 """Return the current temperature."""
158 """Return the current pressure."""
166 """Return the name of the sensor."""
174 """Return the current windspeed."""
182 """Return the current wind bearing (degrees)."""
188 def _forecast(self, forecast: list[IPMAForecast] |
None) -> list[Forecast]:
189 """Return the forecast array."""
195 ATTR_FORECAST_TIME: data_in.forecast_date,
197 data_in.weather_type.id, data_in.forecast_date
199 ATTR_FORECAST_NATIVE_TEMP_LOW: data_in.min_temperature,
200 ATTR_FORECAST_NATIVE_TEMP: data_in.max_temperature,
201 ATTR_FORECAST_PRECIPITATION_PROBABILITY: data_in.precipitation_probability,
202 ATTR_FORECAST_NATIVE_WIND_SPEED: data_in.wind_strength,
203 ATTR_FORECAST_WIND_BEARING: data_in.wind_direction,
205 for data_in
in forecast
210 forecast_type: Literal[
"daily",
"hourly"],
213 """Try to update weather forecast."""
214 with contextlib.suppress(TimeoutError):
215 async
with asyncio.timeout(10):
219 """Return the daily forecast in native units."""
224 """Return the hourly forecast in native units."""
226 return self.
_forecast_forecast(self._hourly_forecast)
def native_pressure(self)
def native_temperature(self)
def native_wind_speed(self)
None _update_forecast(self, Literal["daily", "hourly"] forecast_type, int period, bool update_listeners)
None __init__(self, IPMA_API api, Location location, ConfigEntry config_entry)
list[Forecast] _forecast(self, list[IPMAForecast]|None forecast)
def _condition_conversion(self, identifier, forecast_dt)
None _try_update_forecast(self, Literal["daily", "hourly"] forecast_type, int period)
list[Forecast] async_forecast_daily(self)
list[Forecast] async_forecast_hourly(self)
None async_update_listeners(self, Iterable[Literal["daily", "hourly", "twice_daily"]]|None forecast_types)
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)