mirror of
https://github.com/home-assistant/core.git
synced 2025-07-16 17:57:11 +00:00
Implement Wind Gust speed in Weather entity component (#95065)
* Weather wind gust speed * strings * No compat
This commit is contained in:
parent
d811fa0e74
commit
5d365ecb6b
@ -43,6 +43,7 @@ from .const import (
|
|||||||
ATTR_WEATHER_VISIBILITY,
|
ATTR_WEATHER_VISIBILITY,
|
||||||
ATTR_WEATHER_VISIBILITY_UNIT,
|
ATTR_WEATHER_VISIBILITY_UNIT,
|
||||||
ATTR_WEATHER_WIND_BEARING,
|
ATTR_WEATHER_WIND_BEARING,
|
||||||
|
ATTR_WEATHER_WIND_GUST_SPEED,
|
||||||
ATTR_WEATHER_WIND_SPEED,
|
ATTR_WEATHER_WIND_SPEED,
|
||||||
ATTR_WEATHER_WIND_SPEED_UNIT,
|
ATTR_WEATHER_WIND_SPEED_UNIT,
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
@ -85,6 +86,8 @@ ATTR_FORECAST_NATIVE_TEMP_LOW: Final = "native_templow"
|
|||||||
ATTR_FORECAST_TEMP_LOW: Final = "templow"
|
ATTR_FORECAST_TEMP_LOW: Final = "templow"
|
||||||
ATTR_FORECAST_TIME: Final = "datetime"
|
ATTR_FORECAST_TIME: Final = "datetime"
|
||||||
ATTR_FORECAST_WIND_BEARING: Final = "wind_bearing"
|
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_NATIVE_WIND_SPEED: Final = "native_wind_speed"
|
||||||
ATTR_FORECAST_WIND_SPEED: Final = "wind_speed"
|
ATTR_FORECAST_WIND_SPEED: Final = "wind_speed"
|
||||||
ATTR_FORECAST_NATIVE_DEW_POINT: Final = "native_dew_point"
|
ATTR_FORECAST_NATIVE_DEW_POINT: Final = "native_dew_point"
|
||||||
@ -138,6 +141,7 @@ class Forecast(TypedDict, total=False):
|
|||||||
native_templow: float | None
|
native_templow: float | None
|
||||||
templow: None
|
templow: None
|
||||||
wind_bearing: float | str | None
|
wind_bearing: float | str | None
|
||||||
|
native_wind_gust_speed: float | None
|
||||||
native_wind_speed: float | None
|
native_wind_speed: float | None
|
||||||
wind_speed: None
|
wind_speed: None
|
||||||
native_dew_point: float | None
|
native_dew_point: float | None
|
||||||
@ -218,6 +222,7 @@ class WeatherEntity(Entity):
|
|||||||
_attr_native_visibility: float | None = None
|
_attr_native_visibility: float | None = None
|
||||||
_attr_native_visibility_unit: str | None = None
|
_attr_native_visibility_unit: str | None = None
|
||||||
_attr_native_precipitation_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: float | None = None
|
||||||
_attr_native_wind_speed_unit: str | None = None
|
_attr_native_wind_speed_unit: str | None = None
|
||||||
_attr_native_dew_point: float | None = None
|
_attr_native_dew_point: float | None = None
|
||||||
@ -418,6 +423,11 @@ class WeatherEntity(Entity):
|
|||||||
"""Return the humidity in native units."""
|
"""Return the humidity in native units."""
|
||||||
return self._attr_humidity
|
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
|
@final
|
||||||
@property
|
@property
|
||||||
def wind_speed(self) -> float | None:
|
def wind_speed(self) -> float | None:
|
||||||
@ -686,6 +696,20 @@ class WeatherEntity(Entity):
|
|||||||
if (wind_bearing := self.wind_bearing) is not None:
|
if (wind_bearing := self.wind_bearing) is not None:
|
||||||
data[ATTR_WEATHER_WIND_BEARING] = wind_bearing
|
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:
|
if (wind_speed := self.native_wind_speed) is not None:
|
||||||
from_unit = self.native_wind_speed_unit or self._default_wind_speed_unit
|
from_unit = self.native_wind_speed_unit or self._default_wind_speed_unit
|
||||||
to_unit = self._wind_speed_unit
|
to_unit = self._wind_speed_unit
|
||||||
@ -828,6 +852,27 @@ class WeatherEntity(Entity):
|
|||||||
ROUNDING_PRECISION,
|
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 (
|
if (
|
||||||
forecast_wind_speed := forecast_entry.pop(
|
forecast_wind_speed := forecast_entry.pop(
|
||||||
ATTR_FORECAST_NATIVE_WIND_SPEED,
|
ATTR_FORECAST_NATIVE_WIND_SPEED,
|
||||||
|
@ -29,6 +29,7 @@ ATTR_WEATHER_TEMPERATURE_UNIT = "temperature_unit"
|
|||||||
ATTR_WEATHER_VISIBILITY = "visibility"
|
ATTR_WEATHER_VISIBILITY = "visibility"
|
||||||
ATTR_WEATHER_VISIBILITY_UNIT = "visibility_unit"
|
ATTR_WEATHER_VISIBILITY_UNIT = "visibility_unit"
|
||||||
ATTR_WEATHER_WIND_BEARING = "wind_bearing"
|
ATTR_WEATHER_WIND_BEARING = "wind_bearing"
|
||||||
|
ATTR_WEATHER_WIND_GUST_SPEED = "wind_gust_speed"
|
||||||
ATTR_WEATHER_WIND_SPEED = "wind_speed"
|
ATTR_WEATHER_WIND_SPEED = "wind_speed"
|
||||||
ATTR_WEATHER_WIND_SPEED_UNIT = "wind_speed_unit"
|
ATTR_WEATHER_WIND_SPEED_UNIT = "wind_speed_unit"
|
||||||
ATTR_WEATHER_PRECIPITATION_UNIT = "precipitation_unit"
|
ATTR_WEATHER_PRECIPITATION_UNIT = "precipitation_unit"
|
||||||
|
@ -63,6 +63,9 @@
|
|||||||
"wind_bearing": {
|
"wind_bearing": {
|
||||||
"name": "Wind bearing"
|
"name": "Wind bearing"
|
||||||
},
|
},
|
||||||
|
"wind_gust_speed": {
|
||||||
|
"name": "Wind gust speed"
|
||||||
|
},
|
||||||
"wind_speed": {
|
"wind_speed": {
|
||||||
"name": "Wind speed"
|
"name": "Wind speed"
|
||||||
},
|
},
|
||||||
|
@ -14,6 +14,7 @@ from homeassistant.components.weather import (
|
|||||||
ATTR_FORECAST_TEMP,
|
ATTR_FORECAST_TEMP,
|
||||||
ATTR_FORECAST_TEMP_LOW,
|
ATTR_FORECAST_TEMP_LOW,
|
||||||
ATTR_FORECAST_WIND_BEARING,
|
ATTR_FORECAST_WIND_BEARING,
|
||||||
|
ATTR_FORECAST_WIND_GUST_SPEED,
|
||||||
ATTR_FORECAST_WIND_SPEED,
|
ATTR_FORECAST_WIND_SPEED,
|
||||||
ATTR_WEATHER_APPARENT_TEMPERATURE,
|
ATTR_WEATHER_APPARENT_TEMPERATURE,
|
||||||
ATTR_WEATHER_OZONE,
|
ATTR_WEATHER_OZONE,
|
||||||
@ -25,6 +26,7 @@ from homeassistant.components.weather import (
|
|||||||
ATTR_WEATHER_VISIBILITY,
|
ATTR_WEATHER_VISIBILITY,
|
||||||
ATTR_WEATHER_VISIBILITY_UNIT,
|
ATTR_WEATHER_VISIBILITY_UNIT,
|
||||||
ATTR_WEATHER_WIND_BEARING,
|
ATTR_WEATHER_WIND_BEARING,
|
||||||
|
ATTR_WEATHER_WIND_GUST_SPEED,
|
||||||
ATTR_WEATHER_WIND_SPEED,
|
ATTR_WEATHER_WIND_SPEED,
|
||||||
ATTR_WEATHER_WIND_SPEED_UNIT,
|
ATTR_WEATHER_WIND_SPEED_UNIT,
|
||||||
ROUNDING_PRECISION,
|
ROUNDING_PRECISION,
|
||||||
@ -77,6 +79,7 @@ class MockWeatherEntity(WeatherEntity):
|
|||||||
self._attr_native_temperature_unit = UnitOfTemperature.CELSIUS
|
self._attr_native_temperature_unit = UnitOfTemperature.CELSIUS
|
||||||
self._attr_native_visibility = 30
|
self._attr_native_visibility = 30
|
||||||
self._attr_native_visibility_unit = UnitOfLength.KILOMETERS
|
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 = 3
|
||||||
self._attr_native_wind_speed_unit = UnitOfSpeed.METERS_PER_SECOND
|
self._attr_native_wind_speed_unit = UnitOfSpeed.METERS_PER_SECOND
|
||||||
self._attr_forecast = [
|
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("native_unit", (None,))
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("state_unit", "unit_system"),
|
("state_unit", "unit_system"),
|
||||||
|
@ -13,6 +13,7 @@ from homeassistant.components.weather import (
|
|||||||
ATTR_FORECAST_NATIVE_PRESSURE,
|
ATTR_FORECAST_NATIVE_PRESSURE,
|
||||||
ATTR_FORECAST_NATIVE_TEMP,
|
ATTR_FORECAST_NATIVE_TEMP,
|
||||||
ATTR_FORECAST_NATIVE_TEMP_LOW,
|
ATTR_FORECAST_NATIVE_TEMP_LOW,
|
||||||
|
ATTR_FORECAST_NATIVE_WIND_GUST_SPEED,
|
||||||
ATTR_FORECAST_NATIVE_WIND_SPEED,
|
ATTR_FORECAST_NATIVE_WIND_SPEED,
|
||||||
ATTR_FORECAST_PRECIPITATION,
|
ATTR_FORECAST_PRECIPITATION,
|
||||||
ATTR_FORECAST_PRESSURE,
|
ATTR_FORECAST_PRESSURE,
|
||||||
@ -80,6 +81,11 @@ class MockWeather(MockEntity, WeatherEntity):
|
|||||||
"""Return the humidity."""
|
"""Return the humidity."""
|
||||||
return self._handle("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
|
@property
|
||||||
def native_wind_speed(self) -> float | None:
|
def native_wind_speed(self) -> float | None:
|
||||||
"""Return the wind speed."""
|
"""Return the wind speed."""
|
||||||
@ -219,6 +225,7 @@ class MockWeatherMockForecast(MockWeather):
|
|||||||
ATTR_FORECAST_NATIVE_DEW_POINT: self.native_dew_point,
|
ATTR_FORECAST_NATIVE_DEW_POINT: self.native_dew_point,
|
||||||
ATTR_FORECAST_CLOUD_COVERAGE: self.cloud_coverage,
|
ATTR_FORECAST_CLOUD_COVERAGE: self.cloud_coverage,
|
||||||
ATTR_FORECAST_NATIVE_PRESSURE: self.native_pressure,
|
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_NATIVE_WIND_SPEED: self.native_wind_speed,
|
||||||
ATTR_FORECAST_WIND_BEARING: self.wind_bearing,
|
ATTR_FORECAST_WIND_BEARING: self.wind_bearing,
|
||||||
ATTR_FORECAST_NATIVE_PRECIPITATION: self._values.get(
|
ATTR_FORECAST_NATIVE_PRECIPITATION: self._values.get(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user