From 71466e50127b68e0ee63b17401d6bce2e96a72bd Mon Sep 17 00:00:00 2001 From: Maciej Bieniek Date: Mon, 22 May 2023 19:55:54 +0000 Subject: [PATCH] Add new sensors to AccuWeather (#93362) * Add solar irradiance and condition sensors * Use entity_registry_enabled_by_default fixture --- .../components/accuweather/sensor.py | 27 ++ tests/components/accuweather/test_sensor.py | 421 +++++++----------- 2 files changed, 180 insertions(+), 268 deletions(-) diff --git a/homeassistant/components/accuweather/sensor.py b/homeassistant/components/accuweather/sensor.py index 5d0c70de4e1..5a85b4a4c38 100644 --- a/homeassistant/components/accuweather/sensor.py +++ b/homeassistant/components/accuweather/sensor.py @@ -16,6 +16,7 @@ from homeassistant.const import ( CONCENTRATION_PARTS_PER_CUBIC_METER, PERCENTAGE, UV_INDEX, + UnitOfIrradiance, UnitOfLength, UnitOfSpeed, UnitOfTemperature, @@ -104,6 +105,16 @@ FORECAST_SENSOR_TYPES: tuple[AccuWeatherSensorDescription, ...] = ( native_unit_of_measurement=UnitOfTime.HOURS, value_fn=lambda data: cast(float, data), ), + AccuWeatherSensorDescription( + key="LongPhraseDay", + name="Condition day", + value_fn=lambda data: cast(str, data), + ), + AccuWeatherSensorDescription( + key="LongPhraseNight", + name="Condition night", + value_fn=lambda data: cast(str, data), + ), AccuWeatherSensorDescription( key="Mold", icon="mdi:blur", @@ -154,6 +165,22 @@ FORECAST_SENSOR_TYPES: tuple[AccuWeatherSensorDescription, ...] = ( native_unit_of_measurement=UnitOfTemperature.CELSIUS, value_fn=lambda data: cast(float, data[ATTR_VALUE]), ), + AccuWeatherSensorDescription( + key="SolarIrradianceDay", + icon="mdi:weather-sunny", + name="Solar irradiance day", + entity_registry_enabled_default=False, + native_unit_of_measurement=UnitOfIrradiance.WATTS_PER_SQUARE_METER, + value_fn=lambda data: cast(float, data[ATTR_VALUE]), + ), + AccuWeatherSensorDescription( + key="SolarIrradianceNight", + icon="mdi:weather-sunny", + name="Solar irradiance night", + entity_registry_enabled_default=False, + native_unit_of_measurement=UnitOfIrradiance.WATTS_PER_SQUARE_METER, + value_fn=lambda data: cast(float, data[ATTR_VALUE]), + ), AccuWeatherSensorDescription( key="ThunderstormProbabilityDay", icon="mdi:weather-lightning", diff --git a/tests/components/accuweather/test_sensor.py b/tests/components/accuweather/test_sensor.py index f27aa158e0e..35f86bdb039 100644 --- a/tests/components/accuweather/test_sensor.py +++ b/tests/components/accuweather/test_sensor.py @@ -2,11 +2,10 @@ from datetime import timedelta from unittest.mock import PropertyMock, patch -from homeassistant.components.accuweather.const import ATTRIBUTION, DOMAIN +from homeassistant.components.accuweather.const import ATTRIBUTION from homeassistant.components.sensor import ( ATTR_OPTIONS, ATTR_STATE_CLASS, - DOMAIN as SENSOR_DOMAIN, SensorDeviceClass, SensorStateClass, ) @@ -20,6 +19,7 @@ from homeassistant.const import ( PERCENTAGE, STATE_UNAVAILABLE, UV_INDEX, + UnitOfIrradiance, UnitOfLength, UnitOfSpeed, UnitOfTemperature, @@ -41,7 +41,9 @@ from tests.common import ( ) -async def test_sensor_without_forecast(hass: HomeAssistant) -> None: +async def test_sensor_without_forecast( + hass: HomeAssistant, entity_registry_enabled_by_default: None +) -> None: """Test states of the sensor without forecast.""" await init_integration(hass) registry = er.async_get(hass) @@ -118,271 +120,6 @@ async def test_sensor_without_forecast(hass: HomeAssistant) -> None: assert entry assert entry.unique_id == "0123456-uvindex" - -async def test_sensor_with_forecast(hass: HomeAssistant) -> None: - """Test states of the sensor with forecast.""" - await init_integration(hass, forecast=True) - registry = er.async_get(hass) - - state = hass.states.get("sensor.home_hours_of_sun_0d") - assert state - assert state.state == "7.2" - assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION - assert state.attributes.get(ATTR_ICON) == "mdi:weather-partly-cloudy" - assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == UnitOfTime.HOURS - assert state.attributes.get(ATTR_STATE_CLASS) is None - - entry = registry.async_get("sensor.home_hours_of_sun_0d") - assert entry - assert entry.unique_id == "0123456-hoursofsun-0" - - state = hass.states.get("sensor.home_realfeel_temperature_max_0d") - assert state - assert state.state == "29.8" - assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION - assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == UnitOfTemperature.CELSIUS - assert state.attributes.get(ATTR_DEVICE_CLASS) == SensorDeviceClass.TEMPERATURE - assert state.attributes.get(ATTR_STATE_CLASS) is None - - entry = registry.async_get("sensor.home_realfeel_temperature_max_0d") - assert entry - - state = hass.states.get("sensor.home_realfeel_temperature_min_0d") - assert state - assert state.state == "15.1" - assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION - assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == UnitOfTemperature.CELSIUS - assert state.attributes.get(ATTR_DEVICE_CLASS) == SensorDeviceClass.TEMPERATURE - assert state.attributes.get(ATTR_STATE_CLASS) is None - - entry = registry.async_get("sensor.home_realfeel_temperature_min_0d") - assert entry - assert entry.unique_id == "0123456-realfeeltemperaturemin-0" - - state = hass.states.get("sensor.home_thunderstorm_probability_day_0d") - assert state - assert state.state == "40" - assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION - assert state.attributes.get(ATTR_ICON) == "mdi:weather-lightning" - assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == PERCENTAGE - assert state.attributes.get(ATTR_STATE_CLASS) is None - - entry = registry.async_get("sensor.home_thunderstorm_probability_day_0d") - assert entry - assert entry.unique_id == "0123456-thunderstormprobabilityday-0" - - state = hass.states.get("sensor.home_thunderstorm_probability_night_0d") - assert state - assert state.state == "40" - assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION - assert state.attributes.get(ATTR_ICON) == "mdi:weather-lightning" - assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == PERCENTAGE - assert state.attributes.get(ATTR_STATE_CLASS) is None - - entry = registry.async_get("sensor.home_thunderstorm_probability_night_0d") - assert entry - assert entry.unique_id == "0123456-thunderstormprobabilitynight-0" - - state = hass.states.get("sensor.home_uv_index_0d") - assert state - assert state.state == "5" - assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION - assert state.attributes.get(ATTR_ICON) == "mdi:weather-sunny" - assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == UV_INDEX - assert state.attributes.get("level") == "moderate" - assert state.attributes.get(ATTR_STATE_CLASS) is None - - entry = registry.async_get("sensor.home_uv_index_0d") - assert entry - assert entry.unique_id == "0123456-uvindex-0" - - state = hass.states.get("sensor.home_air_quality_0d") - assert state - assert state.state == "good" - assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION - assert state.attributes.get(ATTR_ICON) == "mdi:air-filter" - assert state.attributes.get(ATTR_DEVICE_CLASS) == SensorDeviceClass.ENUM - assert state.attributes.get(ATTR_OPTIONS) == [ - "good", - "hazardous", - "high", - "low", - "moderate", - "unhealthy", - ] - - entry = registry.async_get("sensor.home_air_quality_0d") - assert entry - assert entry.unique_id == "0123456-airquality-0" - - -async def test_sensor_disabled(hass: HomeAssistant) -> None: - """Test sensor disabled by default.""" - await init_integration(hass) - registry = er.async_get(hass) - - entry = registry.async_get("sensor.home_apparent_temperature") - assert entry - assert entry.unique_id == "0123456-apparenttemperature" - assert entry.disabled - assert entry.disabled_by is er.RegistryEntryDisabler.INTEGRATION - - # Test enabling entity - updated_entry = registry.async_update_entity( - entry.entity_id, **{"disabled_by": None} - ) - - assert updated_entry != entry - assert updated_entry.disabled is False - - -async def test_sensor_enabled_without_forecast(hass: HomeAssistant) -> None: - """Test enabling an advanced sensor.""" - registry = er.async_get(hass) - - registry.async_get_or_create( - SENSOR_DOMAIN, - DOMAIN, - "0123456-apparenttemperature", - suggested_object_id="home_apparent_temperature", - disabled_by=None, - ) - registry.async_get_or_create( - SENSOR_DOMAIN, - DOMAIN, - "0123456-cloudcover", - suggested_object_id="home_cloud_cover", - disabled_by=None, - ) - registry.async_get_or_create( - SENSOR_DOMAIN, - DOMAIN, - "0123456-dewpoint", - suggested_object_id="home_dew_point", - disabled_by=None, - ) - registry.async_get_or_create( - SENSOR_DOMAIN, - DOMAIN, - "0123456-realfeeltemperatureshade", - suggested_object_id="home_realfeel_temperature_shade", - disabled_by=None, - ) - registry.async_get_or_create( - SENSOR_DOMAIN, - DOMAIN, - "0123456-wetbulbtemperature", - suggested_object_id="home_wet_bulb_temperature", - disabled_by=None, - ) - registry.async_get_or_create( - SENSOR_DOMAIN, - DOMAIN, - "0123456-wind", - suggested_object_id="home_wind", - disabled_by=None, - ) - registry.async_get_or_create( - SENSOR_DOMAIN, - DOMAIN, - "0123456-windchilltemperature", - suggested_object_id="home_wind_chill_temperature", - disabled_by=None, - ) - registry.async_get_or_create( - SENSOR_DOMAIN, - DOMAIN, - "0123456-windgust", - suggested_object_id="home_wind_gust", - disabled_by=None, - ) - registry.async_get_or_create( - SENSOR_DOMAIN, - DOMAIN, - "0123456-cloudcoverday-0", - suggested_object_id="home_cloud_cover_day_0d", - disabled_by=None, - ) - registry.async_get_or_create( - SENSOR_DOMAIN, - DOMAIN, - "0123456-cloudcovernight-0", - suggested_object_id="home_cloud_cover_night_0d", - disabled_by=None, - ) - registry.async_get_or_create( - SENSOR_DOMAIN, - DOMAIN, - "0123456-grass-0", - suggested_object_id="home_grass_pollen_0d", - disabled_by=None, - ) - registry.async_get_or_create( - SENSOR_DOMAIN, - DOMAIN, - "0123456-mold-0", - suggested_object_id="home_mold_pollen_0d", - disabled_by=None, - ) - registry.async_get_or_create( - SENSOR_DOMAIN, - DOMAIN, - "0123456-ragweed-0", - suggested_object_id="home_ragweed_pollen_0d", - disabled_by=None, - ) - registry.async_get_or_create( - SENSOR_DOMAIN, - DOMAIN, - "0123456-realfeeltemperatureshademax-0", - suggested_object_id="home_realfeel_temperature_shade_max_0d", - disabled_by=None, - ) - registry.async_get_or_create( - SENSOR_DOMAIN, - DOMAIN, - "0123456-realfeeltemperatureshademin-0", - suggested_object_id="home_realfeel_temperature_shade_min_0d", - disabled_by=None, - ) - registry.async_get_or_create( - SENSOR_DOMAIN, - DOMAIN, - "0123456-tree-0", - suggested_object_id="home_tree_pollen_0d", - disabled_by=None, - ) - registry.async_get_or_create( - SENSOR_DOMAIN, - DOMAIN, - "0123456-windgustday-0", - suggested_object_id="home_wind_gust_day_0d", - disabled_by=None, - ) - registry.async_get_or_create( - SENSOR_DOMAIN, - DOMAIN, - "0123456-windgustnight-0", - suggested_object_id="home_wind_gust_night_0d", - disabled_by=None, - ) - registry.async_get_or_create( - SENSOR_DOMAIN, - DOMAIN, - "0123456-windday-0", - suggested_object_id="home_wind_day_0d", - disabled_by=None, - ) - registry.async_get_or_create( - SENSOR_DOMAIN, - DOMAIN, - "0123456-windnight-0", - suggested_object_id="home_wind_night_0d", - disabled_by=None, - ) - - await init_integration(hass, forecast=True) - state = hass.states.get("sensor.home_apparent_temperature") assert state assert state.state == "22.8" @@ -487,6 +224,101 @@ async def test_sensor_enabled_without_forecast(hass: HomeAssistant) -> None: assert entry assert entry.unique_id == "0123456-wind" + +async def test_sensor_with_forecast( + hass: HomeAssistant, entity_registry_enabled_by_default: None +) -> None: + """Test states of the sensor with forecast.""" + await init_integration(hass, forecast=True) + registry = er.async_get(hass) + + state = hass.states.get("sensor.home_hours_of_sun_0d") + assert state + assert state.state == "7.2" + assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION + assert state.attributes.get(ATTR_ICON) == "mdi:weather-partly-cloudy" + assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == UnitOfTime.HOURS + assert state.attributes.get(ATTR_STATE_CLASS) is None + + entry = registry.async_get("sensor.home_hours_of_sun_0d") + assert entry + assert entry.unique_id == "0123456-hoursofsun-0" + + state = hass.states.get("sensor.home_realfeel_temperature_max_0d") + assert state + assert state.state == "29.8" + assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION + assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == UnitOfTemperature.CELSIUS + assert state.attributes.get(ATTR_DEVICE_CLASS) == SensorDeviceClass.TEMPERATURE + assert state.attributes.get(ATTR_STATE_CLASS) is None + + entry = registry.async_get("sensor.home_realfeel_temperature_max_0d") + assert entry + + state = hass.states.get("sensor.home_realfeel_temperature_min_0d") + assert state + assert state.state == "15.1" + assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION + assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == UnitOfTemperature.CELSIUS + assert state.attributes.get(ATTR_DEVICE_CLASS) == SensorDeviceClass.TEMPERATURE + assert state.attributes.get(ATTR_STATE_CLASS) is None + + entry = registry.async_get("sensor.home_realfeel_temperature_min_0d") + assert entry + assert entry.unique_id == "0123456-realfeeltemperaturemin-0" + + state = hass.states.get("sensor.home_thunderstorm_probability_day_0d") + assert state + assert state.state == "40" + assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION + assert state.attributes.get(ATTR_ICON) == "mdi:weather-lightning" + assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == PERCENTAGE + assert state.attributes.get(ATTR_STATE_CLASS) is None + + entry = registry.async_get("sensor.home_thunderstorm_probability_day_0d") + assert entry + assert entry.unique_id == "0123456-thunderstormprobabilityday-0" + + state = hass.states.get("sensor.home_thunderstorm_probability_night_0d") + assert state + assert state.state == "40" + assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION + assert state.attributes.get(ATTR_ICON) == "mdi:weather-lightning" + assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == PERCENTAGE + assert state.attributes.get(ATTR_STATE_CLASS) is None + + entry = registry.async_get("sensor.home_thunderstorm_probability_night_0d") + assert entry + assert entry.unique_id == "0123456-thunderstormprobabilitynight-0" + + state = hass.states.get("sensor.home_uv_index_0d") + assert state + assert state.state == "5" + assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION + assert state.attributes.get(ATTR_ICON) == "mdi:weather-sunny" + assert state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == UV_INDEX + assert state.attributes.get("level") == "moderate" + assert state.attributes.get(ATTR_STATE_CLASS) is None + + entry = registry.async_get("sensor.home_uv_index_0d") + assert entry + assert entry.unique_id == "0123456-uvindex-0" + + state = hass.states.get("sensor.home_air_quality_0d") + assert state + assert state.state == "good" + assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION + assert state.attributes.get(ATTR_ICON) == "mdi:air-filter" + assert state.attributes.get(ATTR_DEVICE_CLASS) == SensorDeviceClass.ENUM + assert state.attributes.get(ATTR_OPTIONS) == [ + "good", + "hazardous", + "high", + "low", + "moderate", + "unhealthy", + ] + state = hass.states.get("sensor.home_cloud_cover_day_0d") assert state assert state.state == "58" @@ -662,6 +494,59 @@ async def test_sensor_enabled_without_forecast(hass: HomeAssistant) -> None: assert entry assert entry.unique_id == "0123456-windgustnight-0" + entry = registry.async_get("sensor.home_air_quality_0d") + assert entry + assert entry.unique_id == "0123456-airquality-0" + + state = hass.states.get("sensor.home_solar_irradiance_day_0d") + assert state + assert state.state == "7447.1" + assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION + assert state.attributes.get(ATTR_ICON) == "mdi:weather-sunny" + assert ( + state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) + == UnitOfIrradiance.WATTS_PER_SQUARE_METER + ) + + entry = registry.async_get("sensor.home_solar_irradiance_day_0d") + assert entry + assert entry.unique_id == "0123456-solarirradianceday-0" + + state = hass.states.get("sensor.home_solar_irradiance_night_0d") + assert state + assert state.state == "271.6" + assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION + assert state.attributes.get(ATTR_ICON) == "mdi:weather-sunny" + assert ( + state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) + == UnitOfIrradiance.WATTS_PER_SQUARE_METER + ) + + entry = registry.async_get("sensor.home_solar_irradiance_night_0d") + assert entry + assert entry.unique_id == "0123456-solarirradiancenight-0" + + state = hass.states.get("sensor.home_condition_day_0d") + assert state + assert ( + state.state + == "Clouds and sunshine with a couple of showers and a thunderstorm around late this afternoon" + ) + assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION + + entry = registry.async_get("sensor.home_condition_day_0d") + assert entry + assert entry.unique_id == "0123456-longphraseday-0" + + state = hass.states.get("sensor.home_condition_night_0d") + assert state + assert state.state == "Partly cloudy" + assert state.attributes.get(ATTR_ATTRIBUTION) == ATTRIBUTION + + entry = registry.async_get("sensor.home_condition_night_0d") + assert entry + assert entry.unique_id == "0123456-longphrasenight-0" + async def test_availability(hass: HomeAssistant) -> None: """Ensure that we mark the entities unavailable correctly when service is offline."""