From fd3a9ebeb5349545346b3359cbe5244ddb84391f Mon Sep 17 00:00:00 2001 From: claude <6687499+pike00@users.noreply.github.com> Date: Thu, 16 Jul 2026 08:34:57 -0500 Subject: [PATCH 1/2] Add support for OpenWeatherMap One Call API v4.0 --- .../components/openweathermap/__init__.py | 6 +- .../components/openweathermap/const.py | 2 + .../components/openweathermap/coordinator.py | 2 + .../components/openweathermap/strings.json | 2 +- .../components/openweathermap/utils.py | 26 +- .../components/openweathermap/weather.py | 5 +- tests/components/openweathermap/conftest.py | 4 +- .../openweathermap/snapshots/test_sensor.ambr | 963 ++++++++++++++++++ .../snapshots/test_weather.ambr | 91 ++ .../openweathermap/test_config_flow.py | 14 +- .../components/openweathermap/test_sensor.py | 5 +- .../components/openweathermap/test_weather.py | 9 +- 12 files changed, 1109 insertions(+), 20 deletions(-) diff --git a/homeassistant/components/openweathermap/__init__.py b/homeassistant/components/openweathermap/__init__.py index ae8a1634cf6a1..29c1fa0181f1c 100644 --- a/homeassistant/components/openweathermap/__init__.py +++ b/homeassistant/components/openweathermap/__init__.py @@ -3,8 +3,6 @@ from dataclasses import dataclass import logging -from pyopenweathermap import create_owm_client - from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_API_KEY, CONF_LANGUAGE, CONF_MODE from homeassistant.core import HomeAssistant @@ -12,7 +10,7 @@ from .const import CONFIG_FLOW_VERSION, DEFAULT_OWM_MODE, OWM_MODES, PLATFORMS from .coordinator import OWMUpdateCoordinator, get_owm_update_coordinator from .repairs import async_create_issue, async_delete_issue -from .utils import build_data_and_options +from .utils import build_data_and_options, get_owm_client _LOGGER = logging.getLogger(__name__) @@ -40,7 +38,7 @@ async def async_setup_entry( else: async_delete_issue(hass, entry.entry_id) - owm_client = create_owm_client(api_key, mode, lang=language) + owm_client = get_owm_client(api_key, mode, language) owm_coordinator = get_owm_update_coordinator(mode)(hass, entry, owm_client) await owm_coordinator.async_config_entry_first_refresh() diff --git a/homeassistant/components/openweathermap/const.py b/homeassistant/components/openweathermap/const.py index 08408f0198197..de12ed5e1715c 100644 --- a/homeassistant/components/openweathermap/const.py +++ b/homeassistant/components/openweathermap/const.py @@ -65,9 +65,11 @@ OWM_MODE_FREE_CURRENT = "current" OWM_MODE_FREE_FORECAST = "forecast" OWM_MODE_V30 = "v3.0" +OWM_MODE_V40 = "v4.0" OWM_MODE_AIRPOLLUTION = "air_pollution" OWM_MODES = [ OWM_MODE_V30, + OWM_MODE_V40, OWM_MODE_FREE_CURRENT, OWM_MODE_FREE_FORECAST, OWM_MODE_AIRPOLLUTION, diff --git a/homeassistant/components/openweathermap/coordinator.py b/homeassistant/components/openweathermap/coordinator.py index 4750df1e31b79..8460cd07e30b2 100644 --- a/homeassistant/components/openweathermap/coordinator.py +++ b/homeassistant/components/openweathermap/coordinator.py @@ -69,6 +69,7 @@ OWM_MODE_FREE_CURRENT, OWM_MODE_FREE_FORECAST, OWM_MODE_V30, + OWM_MODE_V40, WEATHER_CODE_SUNNY_OR_CLEAR_NIGHT, ) @@ -309,6 +310,7 @@ def get_owm_update_coordinator(mode: str) -> type[OWMUpdateCoordinator]: """Create coordinator with a factory.""" coordinators = { OWM_MODE_V30: WeatherUpdateCoordinator, + OWM_MODE_V40: WeatherUpdateCoordinator, OWM_MODE_FREE_CURRENT: WeatherUpdateCoordinator, OWM_MODE_FREE_FORECAST: WeatherUpdateCoordinator, OWM_MODE_AIRPOLLUTION: AirPollutionUpdateCoordinator, diff --git a/homeassistant/components/openweathermap/strings.json b/homeassistant/components/openweathermap/strings.json index 37419d82b8fae..6b7fd082b8b9c 100644 --- a/homeassistant/components/openweathermap/strings.json +++ b/homeassistant/components/openweathermap/strings.json @@ -69,7 +69,7 @@ }, "exceptions": { "service_minute_forecast_mode": { - "message": "Minute forecast is available only when {name} mode is set to v3.0" + "message": "Minute forecast is available only when {name} mode is set to v3.0 or v4.0" } }, "issues": { diff --git a/homeassistant/components/openweathermap/utils.py b/homeassistant/components/openweathermap/utils.py index ba5378fb31cea..949811ac6aa1e 100644 --- a/homeassistant/components/openweathermap/utils.py +++ b/homeassistant/components/openweathermap/utils.py @@ -3,20 +3,42 @@ from typing import Any from pyopenweathermap import RequestError, create_owm_client +from pyopenweathermap.client.onecall_client import OWMOneCallClient from homeassistant.const import CONF_LANGUAGE, CONF_MODE -from .const import DEFAULT_LANGUAGE, DEFAULT_OWM_MODE +from .const import DEFAULT_LANGUAGE, DEFAULT_OWM_MODE, OWM_MODE_V40 OPTION_DEFAULTS = {CONF_LANGUAGE: DEFAULT_LANGUAGE, CONF_MODE: DEFAULT_OWM_MODE} +class OWMOneCallClientV4(OWMOneCallClient): + """OWM client for One Call API 4.0.""" + + def _get_url(self, lat: float, lon: float) -> str: + return ( + "https://api.openweathermap.org/data/4.0/onecall?" + f"lat={lat}&" + f"lon={lon}&" + f"appid={self.api_key}&" + f"units={self.units}&" + f"lang={self.lang}" + ) + + +def get_owm_client(api_key: str, mode: str, language: str = DEFAULT_LANGUAGE) -> Any: + """Get the OWM client.""" + if mode == OWM_MODE_V40: + return OWMOneCallClientV4(api_key, mode, lang=language) + return create_owm_client(api_key, mode, lang=language) + + async def validate_api_key(api_key, mode): """Validate API key.""" api_key_valid = None errors, description_placeholders = {}, {} try: - owm_client = create_owm_client(api_key, mode) + owm_client = get_owm_client(api_key, mode) api_key_valid = await owm_client.validate_key() except RequestError as error: errors["base"] = "cannot_connect" diff --git a/homeassistant/components/openweathermap/weather.py b/homeassistant/components/openweathermap/weather.py index 84c8c4f18dc63..d7491702cde13 100644 --- a/homeassistant/components/openweathermap/weather.py +++ b/homeassistant/components/openweathermap/weather.py @@ -44,6 +44,7 @@ OWM_MODE_AIRPOLLUTION, OWM_MODE_FREE_FORECAST, OWM_MODE_V30, + OWM_MODE_V40, ) from .coordinator import OWMUpdateCoordinator @@ -106,7 +107,7 @@ def __init__( ) self.mode = mode - if mode == OWM_MODE_V30: + if mode in (OWM_MODE_V30, OWM_MODE_V40): self._attr_supported_features = ( WeatherEntityFeature.FORECAST_DAILY | WeatherEntityFeature.FORECAST_HOURLY @@ -117,7 +118,7 @@ def __init__( async def async_get_minute_forecast(self) -> dict[str, list[dict]] | dict: """Return Minute forecast.""" - if self.mode == OWM_MODE_V30: + if self.mode in (OWM_MODE_V30, OWM_MODE_V40): return self.coordinator.data[ATTR_API_MINUTE_FORECAST] raise ServiceValidationError( translation_domain=DOMAIN, diff --git a/tests/components/openweathermap/conftest.py b/tests/components/openweathermap/conftest.py index b534d8fd98c78..f1166e41c25a2 100644 --- a/tests/components/openweathermap/conftest.py +++ b/tests/components/openweathermap/conftest.py @@ -155,11 +155,11 @@ def owm_client_mock() -> Generator[AsyncMock]: client.validate_key.return_value = True with ( patch( - "homeassistant.components.openweathermap.create_owm_client", + "homeassistant.components.openweathermap.get_owm_client", return_value=client, ), patch( - "homeassistant.components.openweathermap.utils.create_owm_client", + "homeassistant.components.openweathermap.utils.get_owm_client", return_value=client, ), ): diff --git a/tests/components/openweathermap/snapshots/test_sensor.ambr b/tests/components/openweathermap/snapshots/test_sensor.ambr index d4c07e43cf0bb..6ce816861b404 100644 --- a/tests/components/openweathermap/snapshots/test_sensor.ambr +++ b/tests/components/openweathermap/snapshots/test_sensor.ambr @@ -2372,3 +2372,966 @@ 'state': '35.388', }) # --- +# name: test_sensor_states[v4.0][sensor.openweathermap_apparent_temperature-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.openweathermap_apparent_temperature', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Apparent temperature', + 'options': dict({ + 'sensor': dict({ + 'suggested_display_precision': 1, + }), + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Apparent temperature', + 'platform': 'openweathermap', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'feels_like_temperature', + 'unique_id': '12.34-56.78-feels_like_temperature', + 'unit_of_measurement': , + }) +# --- +# name: test_sensor_states[v4.0][sensor.openweathermap_apparent_temperature-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by OpenWeatherMap', + 'device_class': 'temperature', + 'friendly_name': 'OpenWeatherMap Apparent temperature', + 'state_class': , + 'unit_of_measurement': , + }), + 'context': , + 'entity_id': 'sensor.openweathermap_apparent_temperature', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '2.07', + }) +# --- +# name: test_sensor_states[v4.0][sensor.openweathermap_cloud_coverage-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.openweathermap_cloud_coverage', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Cloud coverage', + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Cloud coverage', + 'platform': 'openweathermap', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'clouds', + 'unique_id': '12.34-56.78-clouds', + 'unit_of_measurement': '%', + }) +# --- +# name: test_sensor_states[v4.0][sensor.openweathermap_cloud_coverage-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by OpenWeatherMap', + 'friendly_name': 'OpenWeatherMap Cloud coverage', + 'state_class': , + 'unit_of_measurement': '%', + }), + 'context': , + 'entity_id': 'sensor.openweathermap_cloud_coverage', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '75', + }) +# --- +# name: test_sensor_states[v4.0][sensor.openweathermap_condition-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.openweathermap_condition', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Condition', + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Condition', + 'platform': 'openweathermap', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'condition', + 'unique_id': '12.34-56.78-condition', + 'unit_of_measurement': None, + }) +# --- +# name: test_sensor_states[v4.0][sensor.openweathermap_condition-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by OpenWeatherMap', + 'friendly_name': 'OpenWeatherMap Condition', + }), + 'context': , + 'entity_id': 'sensor.openweathermap_condition', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'cloudy', + }) +# --- +# name: test_sensor_states[v4.0][sensor.openweathermap_dew_point_temperature-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.openweathermap_dew_point_temperature', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Dew point temperature', + 'options': dict({ + 'sensor': dict({ + 'suggested_display_precision': 1, + }), + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Dew point temperature', + 'platform': 'openweathermap', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'dew_point', + 'unique_id': '12.34-56.78-dew_point', + 'unit_of_measurement': , + }) +# --- +# name: test_sensor_states[v4.0][sensor.openweathermap_dew_point_temperature-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by OpenWeatherMap', + 'device_class': 'temperature', + 'friendly_name': 'OpenWeatherMap Dew point temperature', + 'state_class': , + 'unit_of_measurement': , + }), + 'context': , + 'entity_id': 'sensor.openweathermap_dew_point_temperature', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '3.99', + }) +# --- +# name: test_sensor_states[v4.0][sensor.openweathermap_humidity-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.openweathermap_humidity', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Humidity', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Humidity', + 'platform': 'openweathermap', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': '12.34-56.78-humidity', + 'unit_of_measurement': '%', + }) +# --- +# name: test_sensor_states[v4.0][sensor.openweathermap_humidity-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by OpenWeatherMap', + 'device_class': 'humidity', + 'friendly_name': 'OpenWeatherMap Humidity', + 'state_class': , + 'unit_of_measurement': '%', + }), + 'context': , + 'entity_id': 'sensor.openweathermap_humidity', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '82', + }) +# --- +# name: test_sensor_states[v4.0][sensor.openweathermap_precipitation_kind-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.openweathermap_precipitation_kind', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Precipitation kind', + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Precipitation kind', + 'platform': 'openweathermap', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'precipitation_kind', + 'unique_id': '12.34-56.78-precipitation_kind', + 'unit_of_measurement': None, + }) +# --- +# name: test_sensor_states[v4.0][sensor.openweathermap_precipitation_kind-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by OpenWeatherMap', + 'friendly_name': 'OpenWeatherMap Precipitation kind', + }), + 'context': , + 'entity_id': 'sensor.openweathermap_precipitation_kind', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'Rain', + }) +# --- +# name: test_sensor_states[v4.0][sensor.openweathermap_pressure-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.openweathermap_pressure', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Pressure', + 'options': dict({ + 'sensor': dict({ + 'suggested_display_precision': 0, + }), + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Pressure', + 'platform': 'openweathermap', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': '12.34-56.78-pressure', + 'unit_of_measurement': , + }) +# --- +# name: test_sensor_states[v4.0][sensor.openweathermap_pressure-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by OpenWeatherMap', + 'device_class': 'pressure', + 'friendly_name': 'OpenWeatherMap Pressure', + 'state_class': , + 'unit_of_measurement': , + }), + 'context': , + 'entity_id': 'sensor.openweathermap_pressure', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '1000', + }) +# --- +# name: test_sensor_states[v4.0][sensor.openweathermap_rain_intensity-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.openweathermap_rain_intensity', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Rain intensity', + 'options': dict({ + 'sensor': dict({ + 'suggested_display_precision': 0, + }), + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Rain intensity', + 'platform': 'openweathermap', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'rain', + 'unique_id': '12.34-56.78-rain', + 'unit_of_measurement': , + }) +# --- +# name: test_sensor_states[v4.0][sensor.openweathermap_rain_intensity-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by OpenWeatherMap', + 'device_class': 'precipitation_intensity', + 'friendly_name': 'OpenWeatherMap Rain intensity', + 'state_class': , + 'unit_of_measurement': , + }), + 'context': , + 'entity_id': 'sensor.openweathermap_rain_intensity', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '1.21', + }) +# --- +# name: test_sensor_states[v4.0][sensor.openweathermap_snow_intensity-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.openweathermap_snow_intensity', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Snow intensity', + 'options': dict({ + 'sensor': dict({ + 'suggested_display_precision': 0, + }), + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Snow intensity', + 'platform': 'openweathermap', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'snow', + 'unique_id': '12.34-56.78-snow', + 'unit_of_measurement': , + }) +# --- +# name: test_sensor_states[v4.0][sensor.openweathermap_snow_intensity-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by OpenWeatherMap', + 'device_class': 'precipitation_intensity', + 'friendly_name': 'OpenWeatherMap Snow intensity', + 'state_class': , + 'unit_of_measurement': , + }), + 'context': , + 'entity_id': 'sensor.openweathermap_snow_intensity', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '0', + }) +# --- +# name: test_sensor_states[v4.0][sensor.openweathermap_temperature-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.openweathermap_temperature', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Temperature', + 'options': dict({ + 'sensor': dict({ + 'suggested_display_precision': 1, + }), + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Temperature', + 'platform': 'openweathermap', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': '12.34-56.78-temperature', + 'unit_of_measurement': , + }) +# --- +# name: test_sensor_states[v4.0][sensor.openweathermap_temperature-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by OpenWeatherMap', + 'device_class': 'temperature', + 'friendly_name': 'OpenWeatherMap Temperature', + 'state_class': , + 'unit_of_measurement': , + }), + 'context': , + 'entity_id': 'sensor.openweathermap_temperature', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '6.84', + }) +# --- +# name: test_sensor_states[v4.0][sensor.openweathermap_uv_index-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.openweathermap_uv_index', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'UV index', + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'UV index', + 'platform': 'openweathermap', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'uv_index', + 'unique_id': '12.34-56.78-uv_index', + 'unit_of_measurement': 'UV index', + }) +# --- +# name: test_sensor_states[v4.0][sensor.openweathermap_uv_index-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by OpenWeatherMap', + 'friendly_name': 'OpenWeatherMap UV index', + 'state_class': , + 'unit_of_measurement': 'UV index', + }), + 'context': , + 'entity_id': 'sensor.openweathermap_uv_index', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '0.13', + }) +# --- +# name: test_sensor_states[v4.0][sensor.openweathermap_visibility-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.openweathermap_visibility', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Visibility', + 'options': dict({ + 'sensor': dict({ + 'suggested_display_precision': 0, + }), + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Visibility', + 'platform': 'openweathermap', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'visibility_distance', + 'unique_id': '12.34-56.78-visibility_distance', + 'unit_of_measurement': , + }) +# --- +# name: test_sensor_states[v4.0][sensor.openweathermap_visibility-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by OpenWeatherMap', + 'device_class': 'distance', + 'friendly_name': 'OpenWeatherMap Visibility', + 'state_class': , + 'unit_of_measurement': , + }), + 'context': , + 'entity_id': 'sensor.openweathermap_visibility', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '10000', + }) +# --- +# name: test_sensor_states[v4.0][sensor.openweathermap_weather-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.openweathermap_weather', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Weather', + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Weather', + 'platform': 'openweathermap', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'weather', + 'unique_id': '12.34-56.78-weather', + 'unit_of_measurement': None, + }) +# --- +# name: test_sensor_states[v4.0][sensor.openweathermap_weather-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by OpenWeatherMap', + 'friendly_name': 'OpenWeatherMap Weather', + }), + 'context': , + 'entity_id': 'sensor.openweathermap_weather', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'broken clouds', + }) +# --- +# name: test_sensor_states[v4.0][sensor.openweathermap_weather_code-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.openweathermap_weather_code', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Weather code', + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Weather code', + 'platform': 'openweathermap', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'weather_code', + 'unique_id': '12.34-56.78-weather_code', + 'unit_of_measurement': None, + }) +# --- +# name: test_sensor_states[v4.0][sensor.openweathermap_weather_code-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by OpenWeatherMap', + 'friendly_name': 'OpenWeatherMap Weather code', + }), + 'context': , + 'entity_id': 'sensor.openweathermap_weather_code', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '803', + }) +# --- +# name: test_sensor_states[v4.0][sensor.openweathermap_wind_direction-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.openweathermap_wind_direction', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Wind direction', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Wind direction', + 'platform': 'openweathermap', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': '12.34-56.78-wind_bearing', + 'unit_of_measurement': '°', + }) +# --- +# name: test_sensor_states[v4.0][sensor.openweathermap_wind_direction-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by OpenWeatherMap', + 'device_class': 'wind_direction', + 'friendly_name': 'OpenWeatherMap Wind direction', + 'state_class': , + 'unit_of_measurement': '°', + }), + 'context': , + 'entity_id': 'sensor.openweathermap_wind_direction', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '199', + }) +# --- +# name: test_sensor_states[v4.0][sensor.openweathermap_wind_gust_speed-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.openweathermap_wind_gust_speed', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Wind gust speed', + 'options': dict({ + 'sensor': dict({ + 'suggested_display_precision': 2, + }), + 'sensor.private': dict({ + 'suggested_unit_of_measurement': , + }), + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Wind gust speed', + 'platform': 'openweathermap', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'wind_gust', + 'unique_id': '12.34-56.78-wind_gust', + 'unit_of_measurement': , + }) +# --- +# name: test_sensor_states[v4.0][sensor.openweathermap_wind_gust_speed-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by OpenWeatherMap', + 'device_class': 'wind_speed', + 'friendly_name': 'OpenWeatherMap Wind gust speed', + 'state_class': , + 'unit_of_measurement': , + }), + 'context': , + 'entity_id': 'sensor.openweathermap_wind_gust_speed', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '42.516', + }) +# --- +# name: test_sensor_states[v4.0][sensor.openweathermap_wind_speed-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': dict({ + 'state_class': , + }), + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.openweathermap_wind_speed', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Wind speed', + 'options': dict({ + 'sensor': dict({ + 'suggested_display_precision': 2, + }), + 'sensor.private': dict({ + 'suggested_unit_of_measurement': , + }), + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Wind speed', + 'platform': 'openweathermap', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': '12.34-56.78-wind_speed', + 'unit_of_measurement': , + }) +# --- +# name: test_sensor_states[v4.0][sensor.openweathermap_wind_speed-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'attribution': 'Data provided by OpenWeatherMap', + 'device_class': 'wind_speed', + 'friendly_name': 'OpenWeatherMap Wind speed', + 'state_class': , + 'unit_of_measurement': , + }), + 'context': , + 'entity_id': 'sensor.openweathermap_wind_speed', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '35.388', + }) +# --- diff --git a/tests/components/openweathermap/snapshots/test_weather.ambr b/tests/components/openweathermap/snapshots/test_weather.ambr index 5fa2335380535..b82a05a5c01a7 100644 --- a/tests/components/openweathermap/snapshots/test_weather.ambr +++ b/tests/components/openweathermap/snapshots/test_weather.ambr @@ -23,6 +23,30 @@ }), }) # --- +# name: test_get_minute_forecast[v4.0][mock_service_response] + dict({ + 'weather.openweathermap': dict({ + 'forecast': list([ + dict({ + 'datetime': 1728672360, + 'precipitation': 0, + }), + dict({ + 'datetime': 1728672420, + 'precipitation': 1.23, + }), + dict({ + 'datetime': 1728672480, + 'precipitation': 4.5, + }), + dict({ + 'datetime': 1728672540, + 'precipitation': 0, + }), + ]), + }), + }) +# --- # name: test_weather_states[current][weather.openweathermap-entry] EntityRegistryEntrySnapshot({ 'aliases': list([ @@ -223,3 +247,70 @@ 'state': 'cloudy', }) # --- +# name: test_weather_states[v4.0][weather.openweathermap-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'weather', + 'entity_category': None, + 'entity_id': 'weather.openweathermap', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': None, + 'platform': 'openweathermap', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': , + 'translation_key': None, + 'unique_id': '12.34-56.78', + 'unit_of_measurement': None, + }) +# --- +# name: test_weather_states[v4.0][weather.openweathermap-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'apparent_temperature': 2.1, + 'attribution': 'Data provided by OpenWeatherMap', + 'cloud_coverage': 75, + 'dew_point': 4.0, + 'friendly_name': 'OpenWeatherMap', + 'humidity': 82, + 'precipitation_unit': , + 'pressure': 1000.0, + 'pressure_unit': , + 'supported_features': , + 'temperature': 6.8, + 'temperature_unit': , + 'visibility': 10.0, + 'visibility_unit': , + 'wind_bearing': 199, + 'wind_gust_speed': 42.52, + 'wind_speed': 35.39, + 'wind_speed_unit': , + }), + 'context': , + 'entity_id': 'weather.openweathermap', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'cloudy', + }) +# --- diff --git a/tests/components/openweathermap/test_config_flow.py b/tests/components/openweathermap/test_config_flow.py index 039498e5ec356..4f3545d555105 100644 --- a/tests/components/openweathermap/test_config_flow.py +++ b/tests/components/openweathermap/test_config_flow.py @@ -11,6 +11,7 @@ DEFAULT_OWM_MODE, DOMAIN, OWM_MODE_V30, + OWM_MODE_V40, ) from homeassistant.config_entries import SOURCE_USER, ConfigEntryState from homeassistant.const import ( @@ -46,11 +47,14 @@ VALID_YAML_CONFIG = {CONF_API_KEY: "foo"} +@pytest.mark.parametrize("mode", [OWM_MODE_V30, OWM_MODE_V40]) async def test_successful_config_flow( hass: HomeAssistant, owm_client_mock: AsyncMock, + mode: str, ) -> None: """Test that the form is served with valid input.""" + user_input = {**USER_INPUT, CONF_MODE: mode} result = await hass.config_entries.flow.async_init( DOMAIN, context={"source": SOURCE_USER} ) @@ -61,14 +65,14 @@ async def test_successful_config_flow( # create entry result = await hass.config_entries.flow.async_configure( result["flow_id"], - USER_INPUT, + user_input, ) await hass.async_block_till_done() assert result["type"] is FlowResultType.CREATE_ENTRY assert result["title"] == DEFAULT_NAME - assert result["data"][CONF_LATITUDE] == USER_INPUT[CONF_LOCATION][CONF_LATITUDE] - assert result["data"][CONF_LONGITUDE] == USER_INPUT[CONF_LOCATION][CONF_LONGITUDE] - assert result["data"][CONF_API_KEY] == USER_INPUT[CONF_API_KEY] + assert result["data"][CONF_LATITUDE] == user_input[CONF_LOCATION][CONF_LATITUDE] + assert result["data"][CONF_LONGITUDE] == user_input[CONF_LOCATION][CONF_LONGITUDE] + assert result["data"][CONF_API_KEY] == user_input[CONF_API_KEY] # validate entry state conf_entries = hass.config_entries.async_entries(DOMAIN) @@ -81,7 +85,7 @@ async def test_successful_config_flow( assert entry.state is ConfigEntryState.NOT_LOADED -@pytest.mark.parametrize("mode", [OWM_MODE_V30], indirect=True) +@pytest.mark.parametrize("mode", [OWM_MODE_V30, OWM_MODE_V40], indirect=True) async def test_abort_config_flow( hass: HomeAssistant, owm_client_mock: AsyncMock, diff --git a/tests/components/openweathermap/test_sensor.py b/tests/components/openweathermap/test_sensor.py index 516633e9bc2ee..9e26325523b57 100644 --- a/tests/components/openweathermap/test_sensor.py +++ b/tests/components/openweathermap/test_sensor.py @@ -10,6 +10,7 @@ OWM_MODE_FREE_CURRENT, OWM_MODE_FREE_FORECAST, OWM_MODE_V30, + OWM_MODE_V40, ) from homeassistant.const import Platform from homeassistant.core import HomeAssistant @@ -21,7 +22,9 @@ @pytest.mark.parametrize( - "mode", [OWM_MODE_V30, OWM_MODE_FREE_CURRENT, OWM_MODE_AIRPOLLUTION], indirect=True + "mode", + [OWM_MODE_V30, OWM_MODE_V40, OWM_MODE_FREE_CURRENT, OWM_MODE_AIRPOLLUTION], + indirect=True, ) async def test_sensor_states( hass: HomeAssistant, diff --git a/tests/components/openweathermap/test_weather.py b/tests/components/openweathermap/test_weather.py index f87201672efe8..279d9c1efa2af 100644 --- a/tests/components/openweathermap/test_weather.py +++ b/tests/components/openweathermap/test_weather.py @@ -10,6 +10,7 @@ OWM_MODE_FREE_CURRENT, OWM_MODE_FREE_FORECAST, OWM_MODE_V30, + OWM_MODE_V40, ) from homeassistant.components.openweathermap.weather import SERVICE_GET_MINUTE_FORECAST from homeassistant.const import Platform @@ -24,7 +25,7 @@ ENTITY_ID = "weather.openweathermap" -@pytest.mark.parametrize("mode", [OWM_MODE_V30], indirect=True) +@pytest.mark.parametrize("mode", [OWM_MODE_V30, OWM_MODE_V40], indirect=True) async def test_get_minute_forecast( hass: HomeAssistant, snapshot: SnapshotAssertion, @@ -61,7 +62,7 @@ async def test_get_minute_forecast_unavailable( with pytest.raises( ServiceValidationError, match="Minute forecast is available only when" - " OpenWeatherMap mode is set to v3.0", + " OpenWeatherMap mode is set to v3.0 or v4.0", ): await hass.services.async_call( DOMAIN, @@ -73,7 +74,9 @@ async def test_get_minute_forecast_unavailable( @pytest.mark.parametrize( - "mode", [OWM_MODE_V30, OWM_MODE_FREE_CURRENT, OWM_MODE_FREE_FORECAST], indirect=True + "mode", + [OWM_MODE_V30, OWM_MODE_V40, OWM_MODE_FREE_CURRENT, OWM_MODE_FREE_FORECAST], + indirect=True, ) async def test_weather_states( hass: HomeAssistant, From 2b2216f56baa8ab1a9e038a93104696ee1756bb0 Mon Sep 17 00:00:00 2001 From: claude <6687499+pike00@users.noreply.github.com> Date: Thu, 16 Jul 2026 09:35:20 -0500 Subject: [PATCH 2/2] Update snapshots to use EntityStateAttribute enums --- .../openweathermap/snapshots/test_sensor.ambr | 172 +++++++++--------- .../snapshots/test_weather.ambr | 36 ++-- 2 files changed, 104 insertions(+), 104 deletions(-) diff --git a/tests/components/openweathermap/snapshots/test_sensor.ambr b/tests/components/openweathermap/snapshots/test_sensor.ambr index 6ce816861b404..a1f0034e2f596 100644 --- a/tests/components/openweathermap/snapshots/test_sensor.ambr +++ b/tests/components/openweathermap/snapshots/test_sensor.ambr @@ -2379,7 +2379,7 @@ ]), 'area_id': None, 'capabilities': dict({ - 'state_class': , + : , }), 'config_entry_id': , 'config_subentry_id': , @@ -2417,11 +2417,11 @@ # name: test_sensor_states[v4.0][sensor.openweathermap_apparent_temperature-state] StateSnapshot({ 'attributes': ReadOnlyDict({ - 'attribution': 'Data provided by OpenWeatherMap', - 'device_class': 'temperature', - 'friendly_name': 'OpenWeatherMap Apparent temperature', - 'state_class': , - 'unit_of_measurement': , + : 'Data provided by OpenWeatherMap', + : 'temperature', + : 'OpenWeatherMap Apparent temperature', + : , + : , }), 'context': , 'entity_id': 'sensor.openweathermap_apparent_temperature', @@ -2438,7 +2438,7 @@ ]), 'area_id': None, 'capabilities': dict({ - 'state_class': , + : , }), 'config_entry_id': , 'config_subentry_id': , @@ -2467,16 +2467,16 @@ 'supported_features': 0, 'translation_key': 'clouds', 'unique_id': '12.34-56.78-clouds', - 'unit_of_measurement': '%', + 'unit_of_measurement': , }) # --- # name: test_sensor_states[v4.0][sensor.openweathermap_cloud_coverage-state] StateSnapshot({ 'attributes': ReadOnlyDict({ - 'attribution': 'Data provided by OpenWeatherMap', - 'friendly_name': 'OpenWeatherMap Cloud coverage', - 'state_class': , - 'unit_of_measurement': '%', + : 'Data provided by OpenWeatherMap', + : 'OpenWeatherMap Cloud coverage', + : , + : , }), 'context': , 'entity_id': 'sensor.openweathermap_cloud_coverage', @@ -2526,8 +2526,8 @@ # name: test_sensor_states[v4.0][sensor.openweathermap_condition-state] StateSnapshot({ 'attributes': ReadOnlyDict({ - 'attribution': 'Data provided by OpenWeatherMap', - 'friendly_name': 'OpenWeatherMap Condition', + : 'Data provided by OpenWeatherMap', + : 'OpenWeatherMap Condition', }), 'context': , 'entity_id': 'sensor.openweathermap_condition', @@ -2544,7 +2544,7 @@ ]), 'area_id': None, 'capabilities': dict({ - 'state_class': , + : , }), 'config_entry_id': , 'config_subentry_id': , @@ -2582,11 +2582,11 @@ # name: test_sensor_states[v4.0][sensor.openweathermap_dew_point_temperature-state] StateSnapshot({ 'attributes': ReadOnlyDict({ - 'attribution': 'Data provided by OpenWeatherMap', - 'device_class': 'temperature', - 'friendly_name': 'OpenWeatherMap Dew point temperature', - 'state_class': , - 'unit_of_measurement': , + : 'Data provided by OpenWeatherMap', + : 'temperature', + : 'OpenWeatherMap Dew point temperature', + : , + : , }), 'context': , 'entity_id': 'sensor.openweathermap_dew_point_temperature', @@ -2603,7 +2603,7 @@ ]), 'area_id': None, 'capabilities': dict({ - 'state_class': , + : , }), 'config_entry_id': , 'config_subentry_id': , @@ -2632,17 +2632,17 @@ 'supported_features': 0, 'translation_key': None, 'unique_id': '12.34-56.78-humidity', - 'unit_of_measurement': '%', + 'unit_of_measurement': , }) # --- # name: test_sensor_states[v4.0][sensor.openweathermap_humidity-state] StateSnapshot({ 'attributes': ReadOnlyDict({ - 'attribution': 'Data provided by OpenWeatherMap', - 'device_class': 'humidity', - 'friendly_name': 'OpenWeatherMap Humidity', - 'state_class': , - 'unit_of_measurement': '%', + : 'Data provided by OpenWeatherMap', + : 'humidity', + : 'OpenWeatherMap Humidity', + : , + : , }), 'context': , 'entity_id': 'sensor.openweathermap_humidity', @@ -2692,8 +2692,8 @@ # name: test_sensor_states[v4.0][sensor.openweathermap_precipitation_kind-state] StateSnapshot({ 'attributes': ReadOnlyDict({ - 'attribution': 'Data provided by OpenWeatherMap', - 'friendly_name': 'OpenWeatherMap Precipitation kind', + : 'Data provided by OpenWeatherMap', + : 'OpenWeatherMap Precipitation kind', }), 'context': , 'entity_id': 'sensor.openweathermap_precipitation_kind', @@ -2710,7 +2710,7 @@ ]), 'area_id': None, 'capabilities': dict({ - 'state_class': , + : , }), 'config_entry_id': , 'config_subentry_id': , @@ -2748,11 +2748,11 @@ # name: test_sensor_states[v4.0][sensor.openweathermap_pressure-state] StateSnapshot({ 'attributes': ReadOnlyDict({ - 'attribution': 'Data provided by OpenWeatherMap', - 'device_class': 'pressure', - 'friendly_name': 'OpenWeatherMap Pressure', - 'state_class': , - 'unit_of_measurement': , + : 'Data provided by OpenWeatherMap', + : 'pressure', + : 'OpenWeatherMap Pressure', + : , + : , }), 'context': , 'entity_id': 'sensor.openweathermap_pressure', @@ -2769,7 +2769,7 @@ ]), 'area_id': None, 'capabilities': dict({ - 'state_class': , + : , }), 'config_entry_id': , 'config_subentry_id': , @@ -2807,11 +2807,11 @@ # name: test_sensor_states[v4.0][sensor.openweathermap_rain_intensity-state] StateSnapshot({ 'attributes': ReadOnlyDict({ - 'attribution': 'Data provided by OpenWeatherMap', - 'device_class': 'precipitation_intensity', - 'friendly_name': 'OpenWeatherMap Rain intensity', - 'state_class': , - 'unit_of_measurement': , + : 'Data provided by OpenWeatherMap', + : 'precipitation_intensity', + : 'OpenWeatherMap Rain intensity', + : , + : , }), 'context': , 'entity_id': 'sensor.openweathermap_rain_intensity', @@ -2828,7 +2828,7 @@ ]), 'area_id': None, 'capabilities': dict({ - 'state_class': , + : , }), 'config_entry_id': , 'config_subentry_id': , @@ -2866,11 +2866,11 @@ # name: test_sensor_states[v4.0][sensor.openweathermap_snow_intensity-state] StateSnapshot({ 'attributes': ReadOnlyDict({ - 'attribution': 'Data provided by OpenWeatherMap', - 'device_class': 'precipitation_intensity', - 'friendly_name': 'OpenWeatherMap Snow intensity', - 'state_class': , - 'unit_of_measurement': , + : 'Data provided by OpenWeatherMap', + : 'precipitation_intensity', + : 'OpenWeatherMap Snow intensity', + : , + : , }), 'context': , 'entity_id': 'sensor.openweathermap_snow_intensity', @@ -2887,7 +2887,7 @@ ]), 'area_id': None, 'capabilities': dict({ - 'state_class': , + : , }), 'config_entry_id': , 'config_subentry_id': , @@ -2925,11 +2925,11 @@ # name: test_sensor_states[v4.0][sensor.openweathermap_temperature-state] StateSnapshot({ 'attributes': ReadOnlyDict({ - 'attribution': 'Data provided by OpenWeatherMap', - 'device_class': 'temperature', - 'friendly_name': 'OpenWeatherMap Temperature', - 'state_class': , - 'unit_of_measurement': , + : 'Data provided by OpenWeatherMap', + : 'temperature', + : 'OpenWeatherMap Temperature', + : , + : , }), 'context': , 'entity_id': 'sensor.openweathermap_temperature', @@ -2946,7 +2946,7 @@ ]), 'area_id': None, 'capabilities': dict({ - 'state_class': , + : , }), 'config_entry_id': , 'config_subentry_id': , @@ -2981,10 +2981,10 @@ # name: test_sensor_states[v4.0][sensor.openweathermap_uv_index-state] StateSnapshot({ 'attributes': ReadOnlyDict({ - 'attribution': 'Data provided by OpenWeatherMap', - 'friendly_name': 'OpenWeatherMap UV index', - 'state_class': , - 'unit_of_measurement': 'UV index', + : 'Data provided by OpenWeatherMap', + : 'OpenWeatherMap UV index', + : , + : 'UV index', }), 'context': , 'entity_id': 'sensor.openweathermap_uv_index', @@ -3001,7 +3001,7 @@ ]), 'area_id': None, 'capabilities': dict({ - 'state_class': , + : , }), 'config_entry_id': , 'config_subentry_id': , @@ -3039,11 +3039,11 @@ # name: test_sensor_states[v4.0][sensor.openweathermap_visibility-state] StateSnapshot({ 'attributes': ReadOnlyDict({ - 'attribution': 'Data provided by OpenWeatherMap', - 'device_class': 'distance', - 'friendly_name': 'OpenWeatherMap Visibility', - 'state_class': , - 'unit_of_measurement': , + : 'Data provided by OpenWeatherMap', + : 'distance', + : 'OpenWeatherMap Visibility', + : , + : , }), 'context': , 'entity_id': 'sensor.openweathermap_visibility', @@ -3093,8 +3093,8 @@ # name: test_sensor_states[v4.0][sensor.openweathermap_weather-state] StateSnapshot({ 'attributes': ReadOnlyDict({ - 'attribution': 'Data provided by OpenWeatherMap', - 'friendly_name': 'OpenWeatherMap Weather', + : 'Data provided by OpenWeatherMap', + : 'OpenWeatherMap Weather', }), 'context': , 'entity_id': 'sensor.openweathermap_weather', @@ -3144,8 +3144,8 @@ # name: test_sensor_states[v4.0][sensor.openweathermap_weather_code-state] StateSnapshot({ 'attributes': ReadOnlyDict({ - 'attribution': 'Data provided by OpenWeatherMap', - 'friendly_name': 'OpenWeatherMap Weather code', + : 'Data provided by OpenWeatherMap', + : 'OpenWeatherMap Weather code', }), 'context': , 'entity_id': 'sensor.openweathermap_weather_code', @@ -3162,7 +3162,7 @@ ]), 'area_id': None, 'capabilities': dict({ - 'state_class': , + : , }), 'config_entry_id': , 'config_subentry_id': , @@ -3197,11 +3197,11 @@ # name: test_sensor_states[v4.0][sensor.openweathermap_wind_direction-state] StateSnapshot({ 'attributes': ReadOnlyDict({ - 'attribution': 'Data provided by OpenWeatherMap', - 'device_class': 'wind_direction', - 'friendly_name': 'OpenWeatherMap Wind direction', - 'state_class': , - 'unit_of_measurement': '°', + : 'Data provided by OpenWeatherMap', + : 'wind_direction', + : 'OpenWeatherMap Wind direction', + : , + : '°', }), 'context': , 'entity_id': 'sensor.openweathermap_wind_direction', @@ -3218,7 +3218,7 @@ ]), 'area_id': None, 'capabilities': dict({ - 'state_class': , + : , }), 'config_entry_id': , 'config_subentry_id': , @@ -3259,11 +3259,11 @@ # name: test_sensor_states[v4.0][sensor.openweathermap_wind_gust_speed-state] StateSnapshot({ 'attributes': ReadOnlyDict({ - 'attribution': 'Data provided by OpenWeatherMap', - 'device_class': 'wind_speed', - 'friendly_name': 'OpenWeatherMap Wind gust speed', - 'state_class': , - 'unit_of_measurement': , + : 'Data provided by OpenWeatherMap', + : 'wind_speed', + : 'OpenWeatherMap Wind gust speed', + : , + : , }), 'context': , 'entity_id': 'sensor.openweathermap_wind_gust_speed', @@ -3280,7 +3280,7 @@ ]), 'area_id': None, 'capabilities': dict({ - 'state_class': , + : , }), 'config_entry_id': , 'config_subentry_id': , @@ -3321,11 +3321,11 @@ # name: test_sensor_states[v4.0][sensor.openweathermap_wind_speed-state] StateSnapshot({ 'attributes': ReadOnlyDict({ - 'attribution': 'Data provided by OpenWeatherMap', - 'device_class': 'wind_speed', - 'friendly_name': 'OpenWeatherMap Wind speed', - 'state_class': , - 'unit_of_measurement': , + : 'Data provided by OpenWeatherMap', + : 'wind_speed', + : 'OpenWeatherMap Wind speed', + : , + : , }), 'context': , 'entity_id': 'sensor.openweathermap_wind_speed', diff --git a/tests/components/openweathermap/snapshots/test_weather.ambr b/tests/components/openweathermap/snapshots/test_weather.ambr index b82a05a5c01a7..e5d22beef9277 100644 --- a/tests/components/openweathermap/snapshots/test_weather.ambr +++ b/tests/components/openweathermap/snapshots/test_weather.ambr @@ -287,24 +287,24 @@ # name: test_weather_states[v4.0][weather.openweathermap-state] StateSnapshot({ 'attributes': ReadOnlyDict({ - 'apparent_temperature': 2.1, - 'attribution': 'Data provided by OpenWeatherMap', - 'cloud_coverage': 75, - 'dew_point': 4.0, - 'friendly_name': 'OpenWeatherMap', - 'humidity': 82, - 'precipitation_unit': , - 'pressure': 1000.0, - 'pressure_unit': , - 'supported_features': , - 'temperature': 6.8, - 'temperature_unit': , - 'visibility': 10.0, - 'visibility_unit': , - 'wind_bearing': 199, - 'wind_gust_speed': 42.52, - 'wind_speed': 35.39, - 'wind_speed_unit': , + : 2.1, + : 'Data provided by OpenWeatherMap', + : 75, + : 4.0, + : 'OpenWeatherMap', + : 82, + : , + : 1000.0, + : , + : , + : 6.8, + : , + : 10.0, + : , + : 199, + : 42.52, + : 35.39, + : , }), 'context': , 'entity_id': 'weather.openweathermap',