Implement Cloud coverage in Weather entity component (#95068)

This commit is contained in:
G Johansson 2023-06-22 23:10:36 +02:00 committed by GitHub
parent b8de7df609
commit eafddaae83
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 36 additions and 5 deletions

View File

@ -31,6 +31,7 @@ from homeassistant.util.unit_system import US_CUSTOMARY_SYSTEM
from .const import ( from .const import (
ATTR_WEATHER_APPARENT_TEMPERATURE, ATTR_WEATHER_APPARENT_TEMPERATURE,
ATTR_WEATHER_CLOUD_COVERAGE,
ATTR_WEATHER_DEW_POINT, ATTR_WEATHER_DEW_POINT,
ATTR_WEATHER_HUMIDITY, ATTR_WEATHER_HUMIDITY,
ATTR_WEATHER_OZONE, ATTR_WEATHER_OZONE,
@ -87,6 +88,7 @@ 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"
ATTR_FORECAST_DEW_POINT: Final = "dew_point" ATTR_FORECAST_DEW_POINT: Final = "dew_point"
ATTR_FORECAST_CLOUD_COVERAGE: Final = "cloud_coverage"
ENTITY_ID_FORMAT = DOMAIN + ".{}" ENTITY_ID_FORMAT = DOMAIN + ".{}"
@ -124,6 +126,7 @@ class Forecast(TypedDict, total=False):
condition: str | None condition: str | None
datetime: Required[str] datetime: Required[str]
precipitation_probability: int | None precipitation_probability: int | None
cloud_coverage: int | None
native_precipitation: float | None native_precipitation: float | None
precipitation: None precipitation: None
native_pressure: float | None native_pressure: float | None
@ -173,6 +176,7 @@ class WeatherEntity(Entity):
_attr_forecast: list[Forecast] | None = None _attr_forecast: list[Forecast] | None = None
_attr_humidity: float | None = None _attr_humidity: float | None = None
_attr_ozone: float | None = None _attr_ozone: float | None = None
_attr_cloud_coverage: int | None = None
_attr_precision: float _attr_precision: float
_attr_pressure: None = ( _attr_pressure: None = (
None # Provide backwards compatibility. Use _attr_native_pressure None # Provide backwards compatibility. Use _attr_native_pressure
@ -481,6 +485,11 @@ class WeatherEntity(Entity):
"""Return the ozone level.""" """Return the ozone level."""
return self._attr_ozone return self._attr_ozone
@property
def cloud_coverage(self) -> float | None:
"""Return the Cloud coverage in %."""
return self._attr_cloud_coverage
@final @final
@property @property
def visibility(self) -> float | None: def visibility(self) -> float | None:
@ -596,7 +605,7 @@ class WeatherEntity(Entity):
@final @final
@property @property
def state_attributes(self) -> dict[str, Any]: def state_attributes(self) -> dict[str, Any]: # noqa: C901
"""Return the state attributes, converted. """Return the state attributes, converted.
Attributes are configured from native units to user-configured units. Attributes are configured from native units to user-configured units.
@ -655,6 +664,9 @@ class WeatherEntity(Entity):
if (ozone := self.ozone) is not None: if (ozone := self.ozone) is not None:
data[ATTR_WEATHER_OZONE] = ozone data[ATTR_WEATHER_OZONE] = ozone
if (cloud_coverage := self.cloud_coverage) is not None:
data[ATTR_WEATHER_CLOUD_COVERAGE] = cloud_coverage
if (pressure := self.native_pressure) is not None: if (pressure := self.native_pressure) is not None:
from_unit = self.native_pressure_unit or self._default_pressure_unit from_unit = self.native_pressure_unit or self._default_pressure_unit
to_unit = self._pressure_unit to_unit = self._pressure_unit

View File

@ -32,6 +32,7 @@ ATTR_WEATHER_WIND_BEARING = "wind_bearing"
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"
ATTR_WEATHER_CLOUD_COVERAGE = "cloud_coverage"
DOMAIN: Final = "weather" DOMAIN: Final = "weather"

View File

@ -30,6 +30,9 @@
"ozone": { "ozone": {
"name": "Ozone" "name": "Ozone"
}, },
"cloud_coverage": {
"name": "Cloud coverage"
},
"precipitation_unit": { "precipitation_unit": {
"name": "Precipitation unit" "name": "Precipitation unit"
}, },

View File

@ -31,7 +31,10 @@ from homeassistant.components.weather import (
WeatherEntity, WeatherEntity,
round_temperature, round_temperature,
) )
from homeassistant.components.weather.const import ATTR_WEATHER_DEW_POINT from homeassistant.components.weather.const import (
ATTR_WEATHER_CLOUD_COVERAGE,
ATTR_WEATHER_DEW_POINT,
)
from homeassistant.const import ( from homeassistant.const import (
ATTR_FRIENDLY_NAME, ATTR_FRIENDLY_NAME,
PRECISION_HALVES, PRECISION_HALVES,
@ -522,21 +525,26 @@ async def test_precipitation_no_unit(
) )
async def test_wind_bearing_and_ozone( async def test_wind_bearing_ozone_and_cloud_coverage(
hass: HomeAssistant, hass: HomeAssistant,
enable_custom_integrations: None, enable_custom_integrations: None,
) -> None: ) -> None:
"""Test wind bearing.""" """Test wind bearing, ozone and cloud coverage."""
wind_bearing_value = 180 wind_bearing_value = 180
ozone_value = 10 ozone_value = 10
cloud_coverage = 75
entity0 = await create_entity( entity0 = await create_entity(
hass, wind_bearing=wind_bearing_value, ozone=ozone_value hass,
wind_bearing=wind_bearing_value,
ozone=ozone_value,
cloud_coverage=cloud_coverage,
) )
state = hass.states.get(entity0.entity_id) state = hass.states.get(entity0.entity_id)
assert float(state.attributes[ATTR_WEATHER_WIND_BEARING]) == 180 assert float(state.attributes[ATTR_WEATHER_WIND_BEARING]) == 180
assert float(state.attributes[ATTR_WEATHER_OZONE]) == 10 assert float(state.attributes[ATTR_WEATHER_OZONE]) == 10
assert float(state.attributes[ATTR_WEATHER_CLOUD_COVERAGE]) == 75
async def test_none_forecast( async def test_none_forecast(

View File

@ -5,6 +5,7 @@ Call init before using it in your tests to ensure clean test data.
from __future__ import annotations from __future__ import annotations
from homeassistant.components.weather import ( from homeassistant.components.weather import (
ATTR_FORECAST_CLOUD_COVERAGE,
ATTR_FORECAST_NATIVE_APPARENT_TEMP, ATTR_FORECAST_NATIVE_APPARENT_TEMP,
ATTR_FORECAST_NATIVE_DEW_POINT, ATTR_FORECAST_NATIVE_DEW_POINT,
ATTR_FORECAST_NATIVE_PRECIPITATION, ATTR_FORECAST_NATIVE_PRECIPITATION,
@ -98,6 +99,11 @@ class MockWeather(MockEntity, WeatherEntity):
"""Return the ozone level.""" """Return the ozone level."""
return self._handle("ozone") return self._handle("ozone")
@property
def cloud_coverage(self) -> float | None:
"""Return the cloud coverage in %."""
return self._handle("cloud_coverage")
@property @property
def native_visibility(self) -> float | None: def native_visibility(self) -> float | None:
"""Return the visibility.""" """Return the visibility."""
@ -210,6 +216,7 @@ class MockWeatherMockForecast(MockWeather):
ATTR_FORECAST_NATIVE_APPARENT_TEMP: self.native_apparent_temperature, ATTR_FORECAST_NATIVE_APPARENT_TEMP: self.native_apparent_temperature,
ATTR_FORECAST_NATIVE_TEMP_LOW: self.native_temperature, ATTR_FORECAST_NATIVE_TEMP_LOW: self.native_temperature,
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_NATIVE_PRESSURE: self.native_pressure, ATTR_FORECAST_NATIVE_PRESSURE: self.native_pressure,
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,