From 34a1dd4120ce9f8edc0e31e94719a462b23f82ea Mon Sep 17 00:00:00 2001 From: Raman Gupta <7243222+raman325@users.noreply.github.com> Date: Sun, 11 Apr 2021 05:59:42 -0400 Subject: [PATCH] Add new attributes to Climacell (#48707) * Add new attributes to Climacell * fix logic * test new properties --- .../components/climacell/__init__.py | 12 +++ homeassistant/components/climacell/const.py | 11 +++ homeassistant/components/climacell/weather.py | 90 ++++++++++++++++++- tests/components/climacell/test_weather.py | 14 ++- tests/fixtures/climacell/v3_realtime.json | 11 +++ tests/fixtures/climacell/v4.json | 5 +- 6 files changed, 139 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/climacell/__init__.py b/homeassistant/components/climacell/__init__.py index 8095f7991bd..39412520653 100644 --- a/homeassistant/components/climacell/__init__.py +++ b/homeassistant/components/climacell/__init__.py @@ -35,28 +35,34 @@ from homeassistant.helpers.update_coordinator import ( from .const import ( ATTRIBUTION, + CC_ATTR_CLOUD_COVER, CC_ATTR_CONDITION, CC_ATTR_HUMIDITY, CC_ATTR_OZONE, CC_ATTR_PRECIPITATION, CC_ATTR_PRECIPITATION_PROBABILITY, + CC_ATTR_PRECIPITATION_TYPE, CC_ATTR_PRESSURE, CC_ATTR_TEMPERATURE, CC_ATTR_TEMPERATURE_HIGH, CC_ATTR_TEMPERATURE_LOW, CC_ATTR_VISIBILITY, CC_ATTR_WIND_DIRECTION, + CC_ATTR_WIND_GUST, CC_ATTR_WIND_SPEED, + CC_V3_ATTR_CLOUD_COVER, CC_V3_ATTR_CONDITION, CC_V3_ATTR_HUMIDITY, CC_V3_ATTR_OZONE, CC_V3_ATTR_PRECIPITATION, CC_V3_ATTR_PRECIPITATION_DAILY, CC_V3_ATTR_PRECIPITATION_PROBABILITY, + CC_V3_ATTR_PRECIPITATION_TYPE, CC_V3_ATTR_PRESSURE, CC_V3_ATTR_TEMPERATURE, CC_V3_ATTR_VISIBILITY, CC_V3_ATTR_WIND_DIRECTION, + CC_V3_ATTR_WIND_GUST, CC_V3_ATTR_WIND_SPEED, CONF_TIMESTEP, DEFAULT_FORECAST_TYPE, @@ -223,6 +229,9 @@ class ClimaCellDataUpdateCoordinator(DataUpdateCoordinator): CC_V3_ATTR_CONDITION, CC_V3_ATTR_VISIBILITY, CC_V3_ATTR_OZONE, + CC_V3_ATTR_WIND_GUST, + CC_V3_ATTR_CLOUD_COVER, + CC_V3_ATTR_PRECIPITATION_TYPE, ] ) data[FORECASTS][HOURLY] = await self._api.forecast_hourly( @@ -276,6 +285,9 @@ class ClimaCellDataUpdateCoordinator(DataUpdateCoordinator): CC_ATTR_CONDITION, CC_ATTR_VISIBILITY, CC_ATTR_OZONE, + CC_ATTR_WIND_GUST, + CC_ATTR_CLOUD_COVER, + CC_ATTR_PRECIPITATION_TYPE, ], [ CC_ATTR_TEMPERATURE_LOW, diff --git a/homeassistant/components/climacell/const.py b/homeassistant/components/climacell/const.py index 01d85dcc161..6d451fa6f06 100644 --- a/homeassistant/components/climacell/const.py +++ b/homeassistant/components/climacell/const.py @@ -35,6 +35,11 @@ MAX_FORECASTS = { NOWCAST: 30, } +# Additional attributes +ATTR_WIND_GUST = "wind_gust" +ATTR_CLOUD_COVER = "cloud_cover" +ATTR_PRECIPITATION_TYPE = "precipitation_type" + # V4 constants CONDITIONS = { WeatherCode.WIND: ATTR_CONDITION_WINDY, @@ -76,6 +81,9 @@ CC_ATTR_CONDITION = "weatherCode" CC_ATTR_VISIBILITY = "visibility" CC_ATTR_PRECIPITATION = "precipitationIntensityAvg" CC_ATTR_PRECIPITATION_PROBABILITY = "precipitationProbability" +CC_ATTR_WIND_GUST = "windGust" +CC_ATTR_CLOUD_COVER = "cloudCover" +CC_ATTR_PRECIPITATION_TYPE = "precipitationType" # V3 constants CONDITIONS_V3 = { @@ -117,3 +125,6 @@ CC_V3_ATTR_VISIBILITY = "visibility" CC_V3_ATTR_PRECIPITATION = "precipitation" CC_V3_ATTR_PRECIPITATION_DAILY = "precipitation_accumulation" CC_V3_ATTR_PRECIPITATION_PROBABILITY = "precipitation_probability" +CC_V3_ATTR_WIND_GUST = "wind_gust" +CC_V3_ATTR_CLOUD_COVER = "cloud_cover" +CC_V3_ATTR_PRECIPITATION_TYPE = "precipitation_type" diff --git a/homeassistant/components/climacell/weather.py b/homeassistant/components/climacell/weather.py index 012f987171e..0808a4bd734 100644 --- a/homeassistant/components/climacell/weather.py +++ b/homeassistant/components/climacell/weather.py @@ -3,9 +3,17 @@ from __future__ import annotations from datetime import datetime import logging -from typing import Any, Callable +from typing import Any, Callable, Mapping -from pyclimacell.const import CURRENT, DAILY, FORECASTS, HOURLY, NOWCAST, WeatherCode +from pyclimacell.const import ( + CURRENT, + DAILY, + FORECASTS, + HOURLY, + NOWCAST, + PrecipitationType, + WeatherCode, +) from homeassistant.components.weather import ( ATTR_FORECAST_CONDITION, @@ -38,11 +46,16 @@ from homeassistant.util.pressure import convert as pressure_convert from . import ClimaCellEntity from .const import ( + ATTR_CLOUD_COVER, + ATTR_PRECIPITATION_TYPE, + ATTR_WIND_GUST, + CC_ATTR_CLOUD_COVER, CC_ATTR_CONDITION, CC_ATTR_HUMIDITY, CC_ATTR_OZONE, CC_ATTR_PRECIPITATION, CC_ATTR_PRECIPITATION_PROBABILITY, + CC_ATTR_PRECIPITATION_TYPE, CC_ATTR_PRESSURE, CC_ATTR_TEMPERATURE, CC_ATTR_TEMPERATURE_HIGH, @@ -50,13 +63,16 @@ from .const import ( CC_ATTR_TIMESTAMP, CC_ATTR_VISIBILITY, CC_ATTR_WIND_DIRECTION, + CC_ATTR_WIND_GUST, CC_ATTR_WIND_SPEED, + CC_V3_ATTR_CLOUD_COVER, CC_V3_ATTR_CONDITION, CC_V3_ATTR_HUMIDITY, CC_V3_ATTR_OZONE, CC_V3_ATTR_PRECIPITATION, CC_V3_ATTR_PRECIPITATION_DAILY, CC_V3_ATTR_PRECIPITATION_PROBABILITY, + CC_V3_ATTR_PRECIPITATION_TYPE, CC_V3_ATTR_PRESSURE, CC_V3_ATTR_TEMPERATURE, CC_V3_ATTR_TEMPERATURE_HIGH, @@ -64,6 +80,7 @@ from .const import ( CC_V3_ATTR_TIMESTAMP, CC_V3_ATTR_VISIBILITY, CC_V3_ATTR_WIND_DIRECTION, + CC_V3_ATTR_WIND_GUST, CC_V3_ATTR_WIND_SPEED, CLEAR_CONDITIONS, CONDITIONS, @@ -149,6 +166,38 @@ class BaseClimaCellWeatherEntity(ClimaCellEntity, WeatherEntity): return {k: v for k, v in data.items() if v is not None} + @property + def extra_state_attributes(self) -> Mapping[str, Any] | None: + """Return additional state attributes.""" + wind_gust = self.wind_gust + if wind_gust and self.hass.config.units.is_metric: + wind_gust = distance_convert( + self.wind_gust, LENGTH_MILES, LENGTH_KILOMETERS + ) + cloud_cover = self.cloud_cover + if cloud_cover is not None: + cloud_cover /= 100 + return { + ATTR_CLOUD_COVER: cloud_cover, + ATTR_WIND_GUST: wind_gust, + ATTR_PRECIPITATION_TYPE: self.precipitation_type, + } + + @property + def cloud_cover(self): + """Return cloud cover.""" + raise NotImplementedError + + @property + def wind_gust(self): + """Return wind gust speed.""" + raise NotImplementedError + + @property + def precipitation_type(self): + """Return precipitation type.""" + raise NotImplementedError + class ClimaCellWeatherEntity(BaseClimaCellWeatherEntity): """Entity that talks to ClimaCell v4 API to retrieve weather data.""" @@ -195,6 +244,24 @@ class ClimaCellWeatherEntity(BaseClimaCellWeatherEntity): """Return the humidity.""" return self._get_current_property(CC_ATTR_HUMIDITY) + @property + def wind_gust(self): + """Return the wind gust speed.""" + return self._get_current_property(CC_ATTR_WIND_GUST) + + @property + def cloud_cover(self): + """Reteurn the cloud cover.""" + return self._get_current_property(CC_ATTR_CLOUD_COVER) + + @property + def precipitation_type(self): + """Return precipitation type.""" + precipitation_type = self._get_current_property(CC_ATTR_PRECIPITATION_TYPE) + if precipitation_type is None: + return None + return PrecipitationType(precipitation_type).name.lower() + @property def wind_speed(self): """Return the wind speed.""" @@ -338,6 +405,25 @@ class ClimaCellV3WeatherEntity(BaseClimaCellWeatherEntity): """Return the humidity.""" return self._get_cc_value(self.coordinator.data[CURRENT], CC_V3_ATTR_HUMIDITY) + @property + def wind_gust(self): + """Return the wind gust speed.""" + return self._get_cc_value(self.coordinator.data[CURRENT], CC_V3_ATTR_WIND_GUST) + + @property + def cloud_cover(self): + """Reteurn the cloud cover.""" + return self._get_cc_value( + self.coordinator.data[CURRENT], CC_V3_ATTR_CLOUD_COVER + ) + + @property + def precipitation_type(self): + """Return precipitation type.""" + return self._get_cc_value( + self.coordinator.data[CURRENT], CC_V3_ATTR_PRECIPITATION_TYPE + ) + @property def wind_speed(self): """Return the wind speed.""" diff --git a/tests/components/climacell/test_weather.py b/tests/components/climacell/test_weather.py index 646c5cd114b..779b0afa2c0 100644 --- a/tests/components/climacell/test_weather.py +++ b/tests/components/climacell/test_weather.py @@ -13,7 +13,13 @@ from homeassistant.components.climacell.config_flow import ( _get_config_schema, _get_unique_id, ) -from homeassistant.components.climacell.const import ATTRIBUTION, DOMAIN +from homeassistant.components.climacell.const import ( + ATTR_CLOUD_COVER, + ATTR_PRECIPITATION_TYPE, + ATTR_WIND_GUST, + ATTRIBUTION, + DOMAIN, +) from homeassistant.components.weather import ( ATTR_CONDITION_CLOUDY, ATTR_CONDITION_RAINY, @@ -222,6 +228,9 @@ async def test_v3_weather( assert weather_state.attributes[ATTR_WEATHER_VISIBILITY] == 9.994026240000002 assert weather_state.attributes[ATTR_WEATHER_WIND_BEARING] == 320.31 assert weather_state.attributes[ATTR_WEATHER_WIND_SPEED] == 14.62893696 + assert weather_state.attributes[ATTR_CLOUD_COVER] == 1 + assert weather_state.attributes[ATTR_WIND_GUST] == 24.075786240000003 + assert weather_state.attributes[ATTR_PRECIPITATION_TYPE] == "rain" async def test_v4_weather( @@ -382,3 +391,6 @@ async def test_v4_weather( assert weather_state.attributes[ATTR_WEATHER_VISIBILITY] == 13.116153600000002 assert weather_state.attributes[ATTR_WEATHER_WIND_BEARING] == 315.14 assert weather_state.attributes[ATTR_WEATHER_WIND_SPEED] == 15.01517952 + assert weather_state.attributes[ATTR_CLOUD_COVER] == 1 + assert weather_state.attributes[ATTR_WIND_GUST] == 20.34210816 + assert weather_state.attributes[ATTR_PRECIPITATION_TYPE] == "rain" diff --git a/tests/fixtures/climacell/v3_realtime.json b/tests/fixtures/climacell/v3_realtime.json index 8ed05fe5383..c4226ab5ad9 100644 --- a/tests/fixtures/climacell/v3_realtime.json +++ b/tests/fixtures/climacell/v3_realtime.json @@ -32,6 +32,17 @@ "value": 52.625, "units": "ppb" }, + "wind_gust": { + "value": 14.96, + "units": "mph" + }, + "precipitation_type": { + "value": "rain" + }, + "cloud_cover": { + "value": 100, + "units": "%" + }, "observation_time": { "value": "2021-03-07T18:54:06.055Z" } diff --git a/tests/fixtures/climacell/v4.json b/tests/fixtures/climacell/v4.json index d667284a4ad..7d778ba9f51 100644 --- a/tests/fixtures/climacell/v4.json +++ b/tests/fixtures/climacell/v4.json @@ -7,7 +7,10 @@ "windDirection": 315.14, "weatherCode": 1000, "visibility": 8.15, - "pollutantO3": 46.53 + "pollutantO3": 46.53, + "windGust": 12.64, + "cloudCover": 100, + "precipitationType": 1 }, "forecasts": { "nowcast": [