Implement Wind Gust speed in Weather entity component (#95065)

* Weather wind gust speed

* strings

* No compat
This commit is contained in:
G Johansson 2023-06-23 08:22:46 +02:00 committed by GitHub
parent d811fa0e74
commit 5d365ecb6b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 102 additions and 0 deletions

View File

@ -43,6 +43,7 @@ from .const import (
ATTR_WEATHER_VISIBILITY,
ATTR_WEATHER_VISIBILITY_UNIT,
ATTR_WEATHER_WIND_BEARING,
ATTR_WEATHER_WIND_GUST_SPEED,
ATTR_WEATHER_WIND_SPEED,
ATTR_WEATHER_WIND_SPEED_UNIT,
DOMAIN,
@ -85,6 +86,8 @@ ATTR_FORECAST_NATIVE_TEMP_LOW: Final = "native_templow"
ATTR_FORECAST_TEMP_LOW: Final = "templow"
ATTR_FORECAST_TIME: Final = "datetime"
ATTR_FORECAST_WIND_BEARING: Final = "wind_bearing"
ATTR_FORECAST_NATIVE_WIND_GUST_SPEED: Final = "native_wind_gust_speed"
ATTR_FORECAST_WIND_GUST_SPEED: Final = "wind_gust_speed"
ATTR_FORECAST_NATIVE_WIND_SPEED: Final = "native_wind_speed"
ATTR_FORECAST_WIND_SPEED: Final = "wind_speed"
ATTR_FORECAST_NATIVE_DEW_POINT: Final = "native_dew_point"
@ -138,6 +141,7 @@ class Forecast(TypedDict, total=False):
native_templow: float | None
templow: None
wind_bearing: float | str | None
native_wind_gust_speed: float | None
native_wind_speed: float | None
wind_speed: None
native_dew_point: float | None
@ -218,6 +222,7 @@ class WeatherEntity(Entity):
_attr_native_visibility: float | None = None
_attr_native_visibility_unit: str | None = None
_attr_native_precipitation_unit: str | None = None
_attr_native_wind_gust_speed: float | None = None
_attr_native_wind_speed: float | None = None
_attr_native_wind_speed_unit: str | None = None
_attr_native_dew_point: float | None = None
@ -418,6 +423,11 @@ class WeatherEntity(Entity):
"""Return the humidity in native units."""
return self._attr_humidity
@property
def native_wind_gust_speed(self) -> float | None:
"""Return the wind gust speed in native units."""
return self._attr_native_wind_gust_speed
@final
@property
def wind_speed(self) -> float | None:
@ -686,6 +696,20 @@ class WeatherEntity(Entity):
if (wind_bearing := self.wind_bearing) is not None:
data[ATTR_WEATHER_WIND_BEARING] = wind_bearing
if (wind_gust_speed := self.native_wind_gust_speed) is not None:
from_unit = self.native_wind_speed_unit or self._default_wind_speed_unit
to_unit = self._wind_speed_unit
try:
wind_gust_speed_f = float(wind_gust_speed)
value_wind_gust_speed = UNIT_CONVERSIONS[ATTR_WEATHER_WIND_SPEED_UNIT](
wind_gust_speed_f, from_unit, to_unit
)
data[ATTR_WEATHER_WIND_GUST_SPEED] = round(
value_wind_gust_speed, ROUNDING_PRECISION
)
except (TypeError, ValueError):
data[ATTR_WEATHER_WIND_GUST_SPEED] = wind_gust_speed
if (wind_speed := self.native_wind_speed) is not None:
from_unit = self.native_wind_speed_unit or self._default_wind_speed_unit
to_unit = self._wind_speed_unit
@ -828,6 +852,27 @@ class WeatherEntity(Entity):
ROUNDING_PRECISION,
)
if (
forecast_wind_gust_speed := forecast_entry.pop(
ATTR_FORECAST_NATIVE_WIND_GUST_SPEED,
None,
)
) is not None:
from_wind_speed_unit = (
self.native_wind_speed_unit or self._default_wind_speed_unit
)
to_wind_speed_unit = self._wind_speed_unit
with suppress(TypeError, ValueError):
forecast_wind_gust_speed_f = float(forecast_wind_gust_speed)
forecast_entry[ATTR_FORECAST_WIND_GUST_SPEED] = round(
UNIT_CONVERSIONS[ATTR_WEATHER_WIND_SPEED_UNIT](
forecast_wind_gust_speed_f,
from_wind_speed_unit,
to_wind_speed_unit,
),
ROUNDING_PRECISION,
)
if (
forecast_wind_speed := forecast_entry.pop(
ATTR_FORECAST_NATIVE_WIND_SPEED,

View File

@ -29,6 +29,7 @@ ATTR_WEATHER_TEMPERATURE_UNIT = "temperature_unit"
ATTR_WEATHER_VISIBILITY = "visibility"
ATTR_WEATHER_VISIBILITY_UNIT = "visibility_unit"
ATTR_WEATHER_WIND_BEARING = "wind_bearing"
ATTR_WEATHER_WIND_GUST_SPEED = "wind_gust_speed"
ATTR_WEATHER_WIND_SPEED = "wind_speed"
ATTR_WEATHER_WIND_SPEED_UNIT = "wind_speed_unit"
ATTR_WEATHER_PRECIPITATION_UNIT = "precipitation_unit"

View File

@ -63,6 +63,9 @@
"wind_bearing": {
"name": "Wind bearing"
},
"wind_gust_speed": {
"name": "Wind gust speed"
},
"wind_speed": {
"name": "Wind speed"
},

View File

@ -14,6 +14,7 @@ from homeassistant.components.weather import (
ATTR_FORECAST_TEMP,
ATTR_FORECAST_TEMP_LOW,
ATTR_FORECAST_WIND_BEARING,
ATTR_FORECAST_WIND_GUST_SPEED,
ATTR_FORECAST_WIND_SPEED,
ATTR_WEATHER_APPARENT_TEMPERATURE,
ATTR_WEATHER_OZONE,
@ -25,6 +26,7 @@ from homeassistant.components.weather import (
ATTR_WEATHER_VISIBILITY,
ATTR_WEATHER_VISIBILITY_UNIT,
ATTR_WEATHER_WIND_BEARING,
ATTR_WEATHER_WIND_GUST_SPEED,
ATTR_WEATHER_WIND_SPEED,
ATTR_WEATHER_WIND_SPEED_UNIT,
ROUNDING_PRECISION,
@ -77,6 +79,7 @@ class MockWeatherEntity(WeatherEntity):
self._attr_native_temperature_unit = UnitOfTemperature.CELSIUS
self._attr_native_visibility = 30
self._attr_native_visibility_unit = UnitOfLength.KILOMETERS
self._attr_native_wind_gust_speed = 10
self._attr_native_wind_speed = 3
self._attr_native_wind_speed_unit = UnitOfSpeed.METERS_PER_SECOND
self._attr_forecast = [
@ -373,6 +376,49 @@ async def test_wind_speed(
)
@pytest.mark.parametrize(
"native_unit",
(
UnitOfSpeed.MILES_PER_HOUR,
UnitOfSpeed.KILOMETERS_PER_HOUR,
UnitOfSpeed.METERS_PER_SECOND,
),
)
@pytest.mark.parametrize(
("state_unit", "unit_system"),
(
(UnitOfSpeed.KILOMETERS_PER_HOUR, METRIC_SYSTEM),
(UnitOfSpeed.MILES_PER_HOUR, US_CUSTOMARY_SYSTEM),
),
)
async def test_wind_gust_speed(
hass: HomeAssistant,
enable_custom_integrations: None,
native_unit: str,
state_unit: str,
unit_system,
) -> None:
"""Test wind speed."""
hass.config.units = unit_system
native_value = 10
state_value = SpeedConverter.convert(native_value, native_unit, state_unit)
entity0 = await create_entity(
hass, native_wind_gust_speed=native_value, native_wind_speed_unit=native_unit
)
state = hass.states.get(entity0.entity_id)
forecast = state.attributes[ATTR_FORECAST][0]
expected = state_value
assert float(state.attributes[ATTR_WEATHER_WIND_GUST_SPEED]) == pytest.approx(
expected, rel=1e-2
)
assert float(forecast[ATTR_FORECAST_WIND_GUST_SPEED]) == pytest.approx(
expected, rel=1e-2
)
@pytest.mark.parametrize("native_unit", (None,))
@pytest.mark.parametrize(
("state_unit", "unit_system"),

View File

@ -13,6 +13,7 @@ from homeassistant.components.weather import (
ATTR_FORECAST_NATIVE_PRESSURE,
ATTR_FORECAST_NATIVE_TEMP,
ATTR_FORECAST_NATIVE_TEMP_LOW,
ATTR_FORECAST_NATIVE_WIND_GUST_SPEED,
ATTR_FORECAST_NATIVE_WIND_SPEED,
ATTR_FORECAST_PRECIPITATION,
ATTR_FORECAST_PRESSURE,
@ -80,6 +81,11 @@ class MockWeather(MockEntity, WeatherEntity):
"""Return the humidity."""
return self._handle("humidity")
@property
def native_wind_gust_speed(self) -> float | None:
"""Return the wind speed."""
return self._handle("native_wind_gust_speed")
@property
def native_wind_speed(self) -> float | None:
"""Return the wind speed."""
@ -219,6 +225,7 @@ class MockWeatherMockForecast(MockWeather):
ATTR_FORECAST_NATIVE_DEW_POINT: self.native_dew_point,
ATTR_FORECAST_CLOUD_COVERAGE: self.cloud_coverage,
ATTR_FORECAST_NATIVE_PRESSURE: self.native_pressure,
ATTR_FORECAST_NATIVE_WIND_GUST_SPEED: self.native_wind_gust_speed,
ATTR_FORECAST_NATIVE_WIND_SPEED: self.native_wind_speed,
ATTR_FORECAST_WIND_BEARING: self.wind_bearing,
ATTR_FORECAST_NATIVE_PRECIPITATION: self._values.get(