From fe9366eee6012ddebd9f8406d0004563dcf12635 Mon Sep 17 00:00:00 2001 From: Maciej Bieniek Date: Sat, 24 Jun 2023 10:38:20 +0000 Subject: [PATCH] Add new properties to the weather entity in Accuweather integration (#95110) * Add new properties to the current conditions * Add new properties to forecast * Use existing constants * Update tests --- .../components/accuweather/weather.py | 69 ++++++++++++++++--- tests/components/accuweather/test_weather.py | 18 +++++ 2 files changed, 76 insertions(+), 11 deletions(-) diff --git a/homeassistant/components/accuweather/weather.py b/homeassistant/components/accuweather/weather.py index f801f2a5e46..20cb12179ee 100644 --- a/homeassistant/components/accuweather/weather.py +++ b/homeassistant/components/accuweather/weather.py @@ -4,10 +4,13 @@ from __future__ import annotations from typing import cast from homeassistant.components.weather import ( + ATTR_FORECAST_CLOUD_COVERAGE, ATTR_FORECAST_CONDITION, + ATTR_FORECAST_NATIVE_APPARENT_TEMP, ATTR_FORECAST_NATIVE_PRECIPITATION, ATTR_FORECAST_NATIVE_TEMP, ATTR_FORECAST_NATIVE_TEMP_LOW, + ATTR_FORECAST_NATIVE_WIND_GUST_SPEED, ATTR_FORECAST_NATIVE_WIND_SPEED, ATTR_FORECAST_PRECIPITATION_PROBABILITY, ATTR_FORECAST_TIME, @@ -29,7 +32,16 @@ from homeassistant.helpers.update_coordinator import CoordinatorEntity from homeassistant.util.dt import utc_from_timestamp from . import AccuWeatherDataUpdateCoordinator -from .const import API_METRIC, ATTR_FORECAST, ATTRIBUTION, CONDITION_CLASSES, DOMAIN +from .const import ( + API_METRIC, + ATTR_DIRECTION, + ATTR_FORECAST, + ATTR_SPEED, + ATTR_VALUE, + ATTRIBUTION, + CONDITION_CLASSES, + DOMAIN, +) PARALLEL_UPDATES = 1 @@ -79,35 +91,61 @@ class AccuWeatherEntity( except IndexError: return None + @property + def cloud_coverage(self) -> float: + """Return the Cloud coverage in %.""" + return cast(float, self.coordinator.data["CloudCover"]) + + @property + def native_apparent_temperature(self) -> float: + """Return the apparent temperature.""" + return cast( + float, self.coordinator.data["ApparentTemperature"][API_METRIC][ATTR_VALUE] + ) + @property def native_temperature(self) -> float: """Return the temperature.""" - return cast(float, self.coordinator.data["Temperature"][API_METRIC]["Value"]) + return cast(float, self.coordinator.data["Temperature"][API_METRIC][ATTR_VALUE]) @property def native_pressure(self) -> float: """Return the pressure.""" - return cast(float, self.coordinator.data["Pressure"][API_METRIC]["Value"]) + return cast(float, self.coordinator.data["Pressure"][API_METRIC][ATTR_VALUE]) + + @property + def native_dew_point(self) -> float: + """Return the dew point.""" + return cast(float, self.coordinator.data["DewPoint"][API_METRIC][ATTR_VALUE]) @property def humidity(self) -> int: """Return the humidity.""" return cast(int, self.coordinator.data["RelativeHumidity"]) + @property + def native_wind_gust_speed(self) -> float: + """Return the wind gust speed.""" + return cast( + float, self.coordinator.data["WindGust"][ATTR_SPEED][API_METRIC][ATTR_VALUE] + ) + @property def native_wind_speed(self) -> float: """Return the wind speed.""" - return cast(float, self.coordinator.data["Wind"]["Speed"][API_METRIC]["Value"]) + return cast( + float, self.coordinator.data["Wind"][ATTR_SPEED][API_METRIC][ATTR_VALUE] + ) @property def wind_bearing(self) -> int: """Return the wind bearing.""" - return cast(int, self.coordinator.data["Wind"]["Direction"]["Degrees"]) + return cast(int, self.coordinator.data["Wind"][ATTR_DIRECTION]["Degrees"]) @property def native_visibility(self) -> float: """Return the visibility.""" - return cast(float, self.coordinator.data["Visibility"][API_METRIC]["Value"]) + return cast(float, self.coordinator.data["Visibility"][API_METRIC][ATTR_VALUE]) @property def forecast(self) -> list[Forecast] | None: @@ -118,14 +156,23 @@ class AccuWeatherEntity( return [ { ATTR_FORECAST_TIME: utc_from_timestamp(item["EpochDate"]).isoformat(), - ATTR_FORECAST_NATIVE_TEMP: item["TemperatureMax"]["Value"], - ATTR_FORECAST_NATIVE_TEMP_LOW: item["TemperatureMin"]["Value"], - ATTR_FORECAST_NATIVE_PRECIPITATION: item["TotalLiquidDay"]["Value"], + ATTR_FORECAST_CLOUD_COVERAGE: item["CloudCoverDay"], + ATTR_FORECAST_NATIVE_TEMP: item["TemperatureMax"][ATTR_VALUE], + ATTR_FORECAST_NATIVE_TEMP_LOW: item["TemperatureMin"][ATTR_VALUE], + ATTR_FORECAST_NATIVE_APPARENT_TEMP: item["RealFeelTemperatureMax"][ + ATTR_VALUE + ], + ATTR_FORECAST_NATIVE_PRECIPITATION: item["TotalLiquidDay"][ATTR_VALUE], ATTR_FORECAST_PRECIPITATION_PROBABILITY: item[ "PrecipitationProbabilityDay" ], - ATTR_FORECAST_NATIVE_WIND_SPEED: item["WindDay"]["Speed"]["Value"], - ATTR_FORECAST_WIND_BEARING: item["WindDay"]["Direction"]["Degrees"], + ATTR_FORECAST_NATIVE_WIND_SPEED: item["WindDay"][ATTR_SPEED][ + ATTR_VALUE + ], + ATTR_FORECAST_NATIVE_WIND_GUST_SPEED: item["WindGustDay"][ATTR_SPEED][ + ATTR_VALUE + ], + ATTR_FORECAST_WIND_BEARING: item["WindDay"][ATTR_DIRECTION]["Degrees"], ATTR_FORECAST_CONDITION: [ k for k, v in CONDITION_CLASSES.items() if item["IconDay"] in v ][0], diff --git a/tests/components/accuweather/test_weather.py b/tests/components/accuweather/test_weather.py index de1703128dd..dd5dca8c069 100644 --- a/tests/components/accuweather/test_weather.py +++ b/tests/components/accuweather/test_weather.py @@ -5,6 +5,8 @@ from unittest.mock import PropertyMock, patch from homeassistant.components.accuweather.const import ATTRIBUTION from homeassistant.components.weather import ( ATTR_FORECAST, + ATTR_FORECAST_APPARENT_TEMP, + ATTR_FORECAST_CLOUD_COVERAGE, ATTR_FORECAST_CONDITION, ATTR_FORECAST_PRECIPITATION, ATTR_FORECAST_PRECIPITATION_PROBABILITY, @@ -12,12 +14,17 @@ from homeassistant.components.weather import ( ATTR_FORECAST_TEMP_LOW, ATTR_FORECAST_TIME, ATTR_FORECAST_WIND_BEARING, + ATTR_FORECAST_WIND_GUST_SPEED, ATTR_FORECAST_WIND_SPEED, + ATTR_WEATHER_APPARENT_TEMPERATURE, + ATTR_WEATHER_CLOUD_COVERAGE, + ATTR_WEATHER_DEW_POINT, ATTR_WEATHER_HUMIDITY, ATTR_WEATHER_PRESSURE, ATTR_WEATHER_TEMPERATURE, ATTR_WEATHER_VISIBILITY, ATTR_WEATHER_WIND_BEARING, + ATTR_WEATHER_WIND_GUST_SPEED, ATTR_WEATHER_WIND_SPEED, ) from homeassistant.const import ATTR_ATTRIBUTION, ATTR_ENTITY_ID, STATE_UNAVAILABLE @@ -50,6 +57,10 @@ async def test_weather_without_forecast(hass: HomeAssistant) -> None: assert state.attributes.get(ATTR_WEATHER_VISIBILITY) == 16.1 assert state.attributes.get(ATTR_WEATHER_WIND_BEARING) == 180 assert state.attributes.get(ATTR_WEATHER_WIND_SPEED) == 14.5 # 4.03 m/s -> km/h + assert state.attributes.get(ATTR_WEATHER_APPARENT_TEMPERATURE) == 22.8 + assert state.attributes.get(ATTR_WEATHER_DEW_POINT) == 16.2 + assert state.attributes.get(ATTR_WEATHER_CLOUD_COVERAGE) == 10 + assert state.attributes.get(ATTR_WEATHER_WIND_GUST_SPEED) == 20.3 assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION entry = registry.async_get("weather.home") @@ -71,6 +82,10 @@ async def test_weather_with_forecast(hass: HomeAssistant) -> None: assert state.attributes.get(ATTR_WEATHER_VISIBILITY) == 16.1 assert state.attributes.get(ATTR_WEATHER_WIND_BEARING) == 180 assert state.attributes.get(ATTR_WEATHER_WIND_SPEED) == 14.5 # 4.03 m/s -> km/h + assert state.attributes.get(ATTR_WEATHER_APPARENT_TEMPERATURE) == 22.8 + assert state.attributes.get(ATTR_WEATHER_DEW_POINT) == 16.2 + assert state.attributes.get(ATTR_WEATHER_CLOUD_COVERAGE) == 10 + assert state.attributes.get(ATTR_WEATHER_WIND_GUST_SPEED) == 20.3 assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION forecast = state.attributes.get(ATTR_FORECAST)[0] assert forecast.get(ATTR_FORECAST_CONDITION) == "lightning-rainy" @@ -81,6 +96,9 @@ async def test_weather_with_forecast(hass: HomeAssistant) -> None: assert forecast.get(ATTR_FORECAST_TIME) == "2020-07-26T05:00:00+00:00" assert forecast.get(ATTR_FORECAST_WIND_BEARING) == 166 assert forecast.get(ATTR_FORECAST_WIND_SPEED) == 13.0 # 3.61 m/s -> km/h + assert forecast.get(ATTR_FORECAST_CLOUD_COVERAGE) == 58 + assert forecast.get(ATTR_FORECAST_APPARENT_TEMP) == 29.8 + assert forecast.get(ATTR_FORECAST_WIND_GUST_SPEED) == 29.6 entry = registry.async_get("weather.home") assert entry