From 1f850f6374093ffed0b42ac0bfc175d628465915 Mon Sep 17 00:00:00 2001 From: Diogo Gomes Date: Wed, 21 Oct 2020 22:41:06 +0100 Subject: [PATCH] Enable co-existence of two IPMA weather entities for the same location (#40354) Co-authored-by: Paulus Schoutsen --- homeassistant/components/ipma/weather.py | 28 ++++++++++- tests/components/ipma/test_config_flow.py | 59 ++++++++++++++++++++++- tests/components/ipma/test_weather.py | 7 ++- 3 files changed, 89 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/ipma/weather.py b/homeassistant/components/ipma/weather.py index a2c47f43ffb..d8ac0c039da 100644 --- a/homeassistant/components/ipma/weather.py +++ b/homeassistant/components/ipma/weather.py @@ -25,7 +25,8 @@ from homeassistant.const import ( CONF_NAME, TEMP_CELSIUS, ) -from homeassistant.helpers import config_validation as cv +from homeassistant.core import callback +from homeassistant.helpers import config_validation as cv, entity_registry from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.util import Throttle from homeassistant.util.dt import now, parse_datetime @@ -89,10 +90,33 @@ async def async_setup_entry(hass, config_entry, async_add_entities): """Add a weather entity from a config_entry.""" latitude = config_entry.data[CONF_LATITUDE] longitude = config_entry.data[CONF_LONGITUDE] + mode = config_entry.data[CONF_MODE] api = await async_get_api(hass) location = await async_get_location(hass, api, latitude, longitude) + # Migrate old unique_id + @callback + def _async_migrator(entity_entry: entity_registry.RegistryEntry): + # Reject if new unique_id + if entity_entry.unique_id.count(",") == 2: + return None + + new_unique_id = ( + f"{location.station_latitude}, {location.station_longitude}, {mode}" + ) + + _LOGGER.info( + "Migrating unique_id from [%s] to [%s]", + entity_entry.unique_id, + new_unique_id, + ) + return {"new_unique_id": new_unique_id} + + await entity_registry.async_migrate_entries( + hass, config_entry.entry_id, _async_migrator + ) + async_add_entities([IPMAWeather(location, api, config_entry.data)], True) @@ -157,7 +181,7 @@ class IPMAWeather(WeatherEntity): @property def unique_id(self) -> str: """Return a unique id.""" - return f"{self._location.station_latitude}, {self._location.station_longitude}" + return f"{self._location.station_latitude}, {self._location.station_longitude}, {self._mode}" @property def attribution(self): diff --git a/tests/components/ipma/test_config_flow.py b/tests/components/ipma/test_config_flow.py index b45c4e89529..98c1667b2f6 100644 --- a/tests/components/ipma/test_config_flow.py +++ b/tests/components/ipma/test_config_flow.py @@ -1,9 +1,14 @@ """Tests for IPMA config flow.""" -from homeassistant.components.ipma import config_flow -from homeassistant.const import CONF_LATITUDE, CONF_LONGITUDE +from homeassistant.components.ipma import DOMAIN, config_flow +from homeassistant.const import CONF_LATITUDE, CONF_LONGITUDE, CONF_MODE +from homeassistant.helpers import entity_registry +from homeassistant.setup import async_setup_component + +from .test_weather import MockLocation from tests.async_mock import Mock, patch +from tests.common import MockConfigEntry, mock_registry async def test_show_config_form(): @@ -116,3 +121,53 @@ async def test_flow_entry_config_entry_already_exists(): assert len(config_form.mock_calls) == 1 assert len(config_entries.mock_calls) == 1 assert len(flow._errors) == 1 + + +async def test_config_entry_migration(hass): + """Tests config entry without mode in unique_id can be migrated.""" + ipma_entry = MockConfigEntry( + domain=DOMAIN, + title="Home", + data={CONF_LATITUDE: 0, CONF_LONGITUDE: 0, CONF_MODE: "daily"}, + ) + ipma_entry.add_to_hass(hass) + + ipma_entry2 = MockConfigEntry( + domain=DOMAIN, + title="Home", + data={CONF_LATITUDE: 0, CONF_LONGITUDE: 0, CONF_MODE: "hourly"}, + ) + ipma_entry2.add_to_hass(hass) + + mock_registry( + hass, + { + "weather.hometown": entity_registry.RegistryEntry( + entity_id="weather.hometown", + unique_id="0, 0", + platform="ipma", + config_entry_id=ipma_entry.entry_id, + ), + "weather.hometown_2": entity_registry.RegistryEntry( + entity_id="weather.hometown_2", + unique_id="0, 0, hourly", + platform="ipma", + config_entry_id=ipma_entry.entry_id, + ), + }, + ) + + with patch( + "homeassistant.components.ipma.weather.async_get_location", + return_value=MockLocation(), + ): + assert await async_setup_component(hass, DOMAIN, {}) + await hass.async_block_till_done() + + ent_reg = await entity_registry.async_get_registry(hass) + + weather_home = ent_reg.async_get("weather.hometown") + assert weather_home.unique_id == "0, 0, daily" + + weather_home2 = ent_reg.async_get("weather.hometown_2") + assert weather_home2.unique_id == "0, 0, hourly" diff --git a/tests/components/ipma/test_weather.py b/tests/components/ipma/test_weather.py index bfe7eefbb4c..02e46816bbc 100644 --- a/tests/components/ipma/test_weather.py +++ b/tests/components/ipma/test_weather.py @@ -24,7 +24,12 @@ from homeassistant.util.dt import now from tests.async_mock import patch from tests.common import MockConfigEntry -TEST_CONFIG = {"name": "HomeTown", "latitude": "40.00", "longitude": "-8.00"} +TEST_CONFIG = { + "name": "HomeTown", + "latitude": "40.00", + "longitude": "-8.00", + "mode": "daily", +} class MockLocation: