mirror of
https://github.com/home-assistant/core.git
synced 2025-07-17 10:17:09 +00:00
Add twice_daily forecast to SMHI
This commit is contained in:
parent
cd94685b7d
commit
918e5430a3
@ -24,6 +24,7 @@ class SMHIForecastData:
|
||||
|
||||
daily: list[SMHIForecast]
|
||||
hourly: list[SMHIForecast]
|
||||
twice_daily: list[SMHIForecast]
|
||||
|
||||
|
||||
class SMHIDataUpdateCoordinator(DataUpdateCoordinator[SMHIForecastData]):
|
||||
@ -52,6 +53,9 @@ class SMHIDataUpdateCoordinator(DataUpdateCoordinator[SMHIForecastData]):
|
||||
async with asyncio.timeout(TIMEOUT):
|
||||
_forecast_daily = await self._smhi_api.async_get_daily_forecast()
|
||||
_forecast_hourly = await self._smhi_api.async_get_hourly_forecast()
|
||||
_forecast_twice_daily = (
|
||||
await self._smhi_api.async_get_twice_daily_forecast()
|
||||
)
|
||||
except SmhiForecastException as ex:
|
||||
raise UpdateFailed(
|
||||
"Failed to retrieve the forecast from the SMHI API"
|
||||
@ -60,4 +64,5 @@ class SMHIDataUpdateCoordinator(DataUpdateCoordinator[SMHIForecastData]):
|
||||
return SMHIForecastData(
|
||||
daily=_forecast_daily,
|
||||
hourly=_forecast_hourly,
|
||||
twice_daily=_forecast_twice_daily,
|
||||
)
|
||||
|
@ -26,6 +26,7 @@ from homeassistant.components.weather import (
|
||||
ATTR_FORECAST_CLOUD_COVERAGE,
|
||||
ATTR_FORECAST_CONDITION,
|
||||
ATTR_FORECAST_HUMIDITY,
|
||||
ATTR_FORECAST_IS_DAYTIME,
|
||||
ATTR_FORECAST_NATIVE_PRECIPITATION,
|
||||
ATTR_FORECAST_NATIVE_PRESSURE,
|
||||
ATTR_FORECAST_NATIVE_TEMP,
|
||||
@ -109,7 +110,9 @@ class SmhiWeather(SmhiWeatherBaseEntity, SingleCoordinatorWeatherEntity):
|
||||
_attr_native_wind_speed_unit = UnitOfSpeed.METERS_PER_SECOND
|
||||
_attr_native_pressure_unit = UnitOfPressure.HPA
|
||||
_attr_supported_features = (
|
||||
WeatherEntityFeature.FORECAST_DAILY | WeatherEntityFeature.FORECAST_HOURLY
|
||||
WeatherEntityFeature.FORECAST_DAILY
|
||||
| WeatherEntityFeature.FORECAST_HOURLY
|
||||
| WeatherEntityFeature.FORECAST_TWICE_DAILY
|
||||
)
|
||||
|
||||
def update_entity_data(self) -> None:
|
||||
@ -145,7 +148,7 @@ class SmhiWeather(SmhiWeatherBaseEntity, SingleCoordinatorWeatherEntity):
|
||||
super()._handle_coordinator_update()
|
||||
|
||||
def _get_forecast_data(
|
||||
self, forecast_data: list[SMHIForecast] | None
|
||||
self, forecast_data: list[SMHIForecast] | None, forecast_type: str
|
||||
) -> list[Forecast] | None:
|
||||
"""Get forecast data."""
|
||||
if forecast_data is None or len(forecast_data) < 3:
|
||||
@ -160,7 +163,7 @@ class SmhiWeather(SmhiWeatherBaseEntity, SingleCoordinatorWeatherEntity):
|
||||
):
|
||||
condition = ATTR_CONDITION_CLEAR_NIGHT
|
||||
|
||||
data.append(
|
||||
new_forecast = Forecast(
|
||||
{
|
||||
ATTR_FORECAST_TIME: forecast["valid_time"].isoformat(),
|
||||
ATTR_FORECAST_NATIVE_TEMP: forecast["temperature_max"],
|
||||
@ -178,13 +181,23 @@ class SmhiWeather(SmhiWeatherBaseEntity, SingleCoordinatorWeatherEntity):
|
||||
ATTR_FORECAST_CLOUD_COVERAGE: forecast["total_cloud"],
|
||||
}
|
||||
)
|
||||
if forecast_type == "twice_daily":
|
||||
new_forecast[ATTR_FORECAST_IS_DAYTIME] = False
|
||||
if forecast["valid_time"].hour == 12:
|
||||
new_forecast[ATTR_FORECAST_IS_DAYTIME] = True
|
||||
|
||||
data.append(new_forecast)
|
||||
|
||||
return data
|
||||
|
||||
def _async_forecast_daily(self) -> list[Forecast] | None:
|
||||
"""Service to retrieve the daily forecast."""
|
||||
return self._get_forecast_data(self.coordinator.data.daily)
|
||||
return self._get_forecast_data(self.coordinator.data.daily, "daily")
|
||||
|
||||
def _async_forecast_hourly(self) -> list[Forecast] | None:
|
||||
"""Service to retrieve the hourly forecast."""
|
||||
return self._get_forecast_data(self.coordinator.data.hourly)
|
||||
return self._get_forecast_data(self.coordinator.data.hourly, "hourly")
|
||||
|
||||
def _async_forecast_twice_daily(self) -> list[Forecast] | None:
|
||||
"""Service to retrieve the twice daily forecast."""
|
||||
return self._get_forecast_data(self.coordinator.data.twice_daily, "twice_daily")
|
||||
|
@ -68,7 +68,7 @@
|
||||
'precipitation_unit': <UnitOfPrecipitationDepth.MILLIMETERS: 'mm'>,
|
||||
'pressure': 992.4,
|
||||
'pressure_unit': <UnitOfPressure.HPA: 'hPa'>,
|
||||
'supported_features': <WeatherEntityFeature: 3>,
|
||||
'supported_features': <WeatherEntityFeature: 7>,
|
||||
'temperature': 18.4,
|
||||
'temperature_unit': <UnitOfTemperature.CELSIUS: '°C'>,
|
||||
'thunder_probability': 37,
|
||||
@ -287,7 +287,7 @@
|
||||
'precipitation_unit': <UnitOfPrecipitationDepth.MILLIMETERS: 'mm'>,
|
||||
'pressure': 992.4,
|
||||
'pressure_unit': <UnitOfPressure.HPA: 'hPa'>,
|
||||
'supported_features': <WeatherEntityFeature: 3>,
|
||||
'supported_features': <WeatherEntityFeature: 7>,
|
||||
'temperature': 18.4,
|
||||
'temperature_unit': <UnitOfTemperature.CELSIUS: '°C'>,
|
||||
'thunder_probability': 37,
|
||||
@ -299,3 +299,291 @@
|
||||
'wind_speed_unit': <UnitOfSpeed.KILOMETERS_PER_HOUR: 'km/h'>,
|
||||
})
|
||||
# ---
|
||||
# name: test_twice_daily_forecast_service[load_platforms0]
|
||||
dict({
|
||||
'weather.smhi_test': dict({
|
||||
'forecast': list([
|
||||
dict({
|
||||
'cloud_coverage': 100,
|
||||
'condition': 'fog',
|
||||
'datetime': '2023-08-07T08:00:00+00:00',
|
||||
'humidity': 100,
|
||||
'is_daytime': False,
|
||||
'precipitation': 0.0,
|
||||
'pressure': 992.4,
|
||||
'temperature': 18.4,
|
||||
'templow': 18.4,
|
||||
'wind_bearing': 93,
|
||||
'wind_gust_speed': 22.32,
|
||||
'wind_speed': 9.0,
|
||||
}),
|
||||
dict({
|
||||
'cloud_coverage': 100,
|
||||
'condition': 'cloudy',
|
||||
'datetime': '2023-08-07T12:00:00+00:00',
|
||||
'humidity': 96,
|
||||
'is_daytime': True,
|
||||
'precipitation': 0.0,
|
||||
'pressure': 991.7,
|
||||
'temperature': 18.4,
|
||||
'templow': 17.1,
|
||||
'wind_bearing': 114,
|
||||
'wind_gust_speed': 32.76,
|
||||
'wind_speed': 10.08,
|
||||
}),
|
||||
dict({
|
||||
'cloud_coverage': 100,
|
||||
'condition': 'cloudy',
|
||||
'datetime': '2023-08-08T00:00:00+00:00',
|
||||
'humidity': 99,
|
||||
'is_daytime': False,
|
||||
'precipitation': 0.1,
|
||||
'pressure': 987.5,
|
||||
'temperature': 18.4,
|
||||
'templow': 14.8,
|
||||
'wind_bearing': 357,
|
||||
'wind_gust_speed': 10.44,
|
||||
'wind_speed': 3.96,
|
||||
}),
|
||||
dict({
|
||||
'cloud_coverage': 100,
|
||||
'condition': 'rainy',
|
||||
'datetime': '2023-08-08T12:00:00+00:00',
|
||||
'humidity': 97,
|
||||
'is_daytime': True,
|
||||
'precipitation': 0.3,
|
||||
'pressure': 984.1,
|
||||
'temperature': 18.4,
|
||||
'templow': 12.8,
|
||||
'wind_bearing': 183,
|
||||
'wind_gust_speed': 27.36,
|
||||
'wind_speed': 11.16,
|
||||
}),
|
||||
dict({
|
||||
'cloud_coverage': 100,
|
||||
'condition': 'cloudy',
|
||||
'datetime': '2023-08-09T00:00:00+00:00',
|
||||
'humidity': 85,
|
||||
'is_daytime': False,
|
||||
'precipitation': 0.1,
|
||||
'pressure': 995.6,
|
||||
'temperature': 18.4,
|
||||
'templow': 11.2,
|
||||
'wind_bearing': 193,
|
||||
'wind_gust_speed': 48.6,
|
||||
'wind_speed': 19.8,
|
||||
}),
|
||||
dict({
|
||||
'cloud_coverage': 100,
|
||||
'condition': 'rainy',
|
||||
'datetime': '2023-08-09T12:00:00+00:00',
|
||||
'humidity': 95,
|
||||
'is_daytime': True,
|
||||
'precipitation': 1.1,
|
||||
'pressure': 1001.4,
|
||||
'temperature': 18.4,
|
||||
'templow': 11.1,
|
||||
'wind_bearing': 166,
|
||||
'wind_gust_speed': 48.24,
|
||||
'wind_speed': 18.0,
|
||||
}),
|
||||
dict({
|
||||
'cloud_coverage': 100,
|
||||
'condition': 'rainy',
|
||||
'datetime': '2023-08-10T00:00:00+00:00',
|
||||
'humidity': 99,
|
||||
'is_daytime': False,
|
||||
'precipitation': 3.6,
|
||||
'pressure': 1007.8,
|
||||
'temperature': 18.4,
|
||||
'templow': 10.4,
|
||||
'wind_bearing': 200,
|
||||
'wind_gust_speed': 28.08,
|
||||
'wind_speed': 14.4,
|
||||
}),
|
||||
dict({
|
||||
'cloud_coverage': 100,
|
||||
'condition': 'cloudy',
|
||||
'datetime': '2023-08-10T12:00:00+00:00',
|
||||
'humidity': 75,
|
||||
'is_daytime': True,
|
||||
'precipitation': 0.0,
|
||||
'pressure': 1011.1,
|
||||
'temperature': 18.4,
|
||||
'templow': 13.9,
|
||||
'wind_bearing': 174,
|
||||
'wind_gust_speed': 29.16,
|
||||
'wind_speed': 11.16,
|
||||
}),
|
||||
dict({
|
||||
'cloud_coverage': 100,
|
||||
'condition': 'cloudy',
|
||||
'datetime': '2023-08-11T00:00:00+00:00',
|
||||
'humidity': 98,
|
||||
'is_daytime': False,
|
||||
'precipitation': 0.0,
|
||||
'pressure': 1012.3,
|
||||
'temperature': 18.4,
|
||||
'templow': 11.7,
|
||||
'wind_bearing': 169,
|
||||
'wind_gust_speed': 16.56,
|
||||
'wind_speed': 7.56,
|
||||
}),
|
||||
dict({
|
||||
'cloud_coverage': 100,
|
||||
'condition': 'cloudy',
|
||||
'datetime': '2023-08-11T12:00:00+00:00',
|
||||
'humidity': 69,
|
||||
'is_daytime': True,
|
||||
'precipitation': 0.0,
|
||||
'pressure': 1015.3,
|
||||
'temperature': 18.4,
|
||||
'templow': 17.6,
|
||||
'wind_bearing': 197,
|
||||
'wind_gust_speed': 27.36,
|
||||
'wind_speed': 10.08,
|
||||
}),
|
||||
dict({
|
||||
'cloud_coverage': 0,
|
||||
'condition': 'clear-night',
|
||||
'datetime': '2023-08-12T00:00:00+00:00',
|
||||
'humidity': 97,
|
||||
'is_daytime': False,
|
||||
'precipitation': 0.0,
|
||||
'pressure': 1015.8,
|
||||
'temperature': 18.4,
|
||||
'templow': 12.3,
|
||||
'wind_bearing': 191,
|
||||
'wind_gust_speed': 18.0,
|
||||
'wind_speed': 8.64,
|
||||
}),
|
||||
dict({
|
||||
'cloud_coverage': 100,
|
||||
'condition': 'cloudy',
|
||||
'datetime': '2023-08-12T12:00:00+00:00',
|
||||
'humidity': 82,
|
||||
'is_daytime': True,
|
||||
'precipitation': 0.0,
|
||||
'pressure': 1014.0,
|
||||
'temperature': 18.4,
|
||||
'templow': 17.0,
|
||||
'wind_bearing': 225,
|
||||
'wind_gust_speed': 28.08,
|
||||
'wind_speed': 8.64,
|
||||
}),
|
||||
dict({
|
||||
'cloud_coverage': 12,
|
||||
'condition': 'clear-night',
|
||||
'datetime': '2023-08-13T00:00:00+00:00',
|
||||
'humidity': 92,
|
||||
'is_daytime': False,
|
||||
'precipitation': 0.0,
|
||||
'pressure': 1013.9,
|
||||
'temperature': 18.4,
|
||||
'templow': 13.6,
|
||||
'wind_bearing': 233,
|
||||
'wind_gust_speed': 20.16,
|
||||
'wind_speed': 10.08,
|
||||
}),
|
||||
dict({
|
||||
'cloud_coverage': 75,
|
||||
'condition': 'partlycloudy',
|
||||
'datetime': '2023-08-13T12:00:00+00:00',
|
||||
'humidity': 59,
|
||||
'is_daytime': True,
|
||||
'precipitation': 0.0,
|
||||
'pressure': 1013.6,
|
||||
'temperature': 20.0,
|
||||
'templow': 18.4,
|
||||
'wind_bearing': 234,
|
||||
'wind_gust_speed': 35.64,
|
||||
'wind_speed': 14.76,
|
||||
}),
|
||||
dict({
|
||||
'cloud_coverage': 50,
|
||||
'condition': 'partlycloudy',
|
||||
'datetime': '2023-08-14T00:00:00+00:00',
|
||||
'humidity': 91,
|
||||
'is_daytime': False,
|
||||
'precipitation': 0.0,
|
||||
'pressure': 1015.2,
|
||||
'temperature': 18.4,
|
||||
'templow': 13.5,
|
||||
'wind_bearing': 227,
|
||||
'wind_gust_speed': 23.4,
|
||||
'wind_speed': 10.8,
|
||||
}),
|
||||
dict({
|
||||
'cloud_coverage': 100,
|
||||
'condition': 'partlycloudy',
|
||||
'datetime': '2023-08-14T12:00:00+00:00',
|
||||
'humidity': 56,
|
||||
'is_daytime': True,
|
||||
'precipitation': 0.0,
|
||||
'pressure': 1015.3,
|
||||
'temperature': 20.8,
|
||||
'templow': 18.4,
|
||||
'wind_bearing': 216,
|
||||
'wind_gust_speed': 33.12,
|
||||
'wind_speed': 13.68,
|
||||
}),
|
||||
dict({
|
||||
'cloud_coverage': 100,
|
||||
'condition': 'cloudy',
|
||||
'datetime': '2023-08-15T00:00:00+00:00',
|
||||
'humidity': 93,
|
||||
'is_daytime': False,
|
||||
'precipitation': 1.2,
|
||||
'pressure': 1014.9,
|
||||
'temperature': 18.4,
|
||||
'templow': 14.3,
|
||||
'wind_bearing': 196,
|
||||
'wind_gust_speed': 22.32,
|
||||
'wind_speed': 10.08,
|
||||
}),
|
||||
dict({
|
||||
'cloud_coverage': 88,
|
||||
'condition': 'partlycloudy',
|
||||
'datetime': '2023-08-15T12:00:00+00:00',
|
||||
'humidity': 64,
|
||||
'is_daytime': True,
|
||||
'precipitation': 2.4,
|
||||
'pressure': 1014.3,
|
||||
'temperature': 20.4,
|
||||
'templow': 18.4,
|
||||
'wind_bearing': 226,
|
||||
'wind_gust_speed': 33.12,
|
||||
'wind_speed': 13.68,
|
||||
}),
|
||||
dict({
|
||||
'cloud_coverage': 38,
|
||||
'condition': 'clear-night',
|
||||
'datetime': '2023-08-16T00:00:00+00:00',
|
||||
'humidity': 93,
|
||||
'is_daytime': False,
|
||||
'precipitation': 1.2,
|
||||
'pressure': 1014.9,
|
||||
'temperature': 18.4,
|
||||
'templow': 13.8,
|
||||
'wind_bearing': 228,
|
||||
'wind_gust_speed': 21.24,
|
||||
'wind_speed': 10.08,
|
||||
}),
|
||||
dict({
|
||||
'cloud_coverage': 75,
|
||||
'condition': 'partlycloudy',
|
||||
'datetime': '2023-08-16T12:00:00+00:00',
|
||||
'humidity': 61,
|
||||
'is_daytime': True,
|
||||
'precipitation': 1.2,
|
||||
'pressure': 1014.0,
|
||||
'temperature': 20.2,
|
||||
'templow': 18.4,
|
||||
'wind_bearing': 233,
|
||||
'wind_gust_speed': 33.48,
|
||||
'wind_speed': 14.04,
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
})
|
||||
# ---
|
||||
|
@ -473,3 +473,23 @@ async def test_forecast_service(
|
||||
return_response=True,
|
||||
)
|
||||
assert response == snapshot
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"load_platforms",
|
||||
[[Platform.WEATHER]],
|
||||
)
|
||||
async def test_twice_daily_forecast_service(
|
||||
hass: HomeAssistant,
|
||||
load_int: MockConfigEntry,
|
||||
snapshot: SnapshotAssertion,
|
||||
) -> None:
|
||||
"""Test forecast service."""
|
||||
response = await hass.services.async_call(
|
||||
WEATHER_DOMAIN,
|
||||
SERVICE_GET_FORECASTS,
|
||||
{"entity_id": ENTITY_ID, "type": "twice_daily"},
|
||||
blocking=True,
|
||||
return_response=True,
|
||||
)
|
||||
assert response == snapshot
|
||||
|
Loading…
x
Reference in New Issue
Block a user