diff --git a/homeassistant/components/nws/__init__.py b/homeassistant/components/nws/__init__.py index 1a046c4a05d..66e791e627a 100644 --- a/homeassistant/components/nws/__init__.py +++ b/homeassistant/components/nws/__init__.py @@ -78,7 +78,7 @@ async def async_setup(hass: HomeAssistant, config: dict): for component in PLATFORMS: hass.async_create_task( - discovery.async_load_platform(hass, component, DOMAIN, {}, config) + discovery.async_load_platform(hass, component, DOMAIN, entry, config) ) return True @@ -129,18 +129,21 @@ class NwsData: return self.nws.forecast_hourly @staticmethod - async def _async_update_item(update_call, update_type, station_name, success): + async def _async_update_item( + update_call, update_type, station_name, previous_success + ): + """Update item and handle logging.""" try: _LOGGER.debug("Updating %s for station %s", update_type, station_name) await update_call() - if success: + if not previous_success: _LOGGER.warning( "Success updating %s for station %s", update_type, station_name ) - success = True + success = True except (aiohttp.ClientError, asyncio.TimeoutError) as err: - if success: + if previous_success: _LOGGER.warning( "Error updating %s for station %s: %s", update_type, @@ -148,23 +151,24 @@ class NwsData: err, ) success = False + return success async def async_update(self, now=None): """Update all data.""" - await self._async_update_item( + self.update_observation_success = await self._async_update_item( self.nws.update_observation, "observation", self.station, self.update_observation_success, ) - await self._async_update_item( + self.update_forecast_success = await self._async_update_item( self.nws.update_forecast, "forecast", self.station, self.update_forecast_success, ) - await self._async_update_item( + self.update_forecast_hourly_success = await self._async_update_item( self.nws.update_forecast_hourly, "forecast_hourly", self.station, diff --git a/homeassistant/components/nws/weather.py b/homeassistant/components/nws/weather.py index 0c409bef3ca..8e4e7e560cb 100644 --- a/homeassistant/components/nws/weather.py +++ b/homeassistant/components/nws/weather.py @@ -73,11 +73,13 @@ def convert_condition(time, weather): return cond, max(prec_probs) -async def async_setup_platform(hass, config, async_add_entities, discovery_info): +async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): """Set up the NWS weather platform.""" - latitude = config.get(CONF_LATITUDE, hass.config.latitude) - longitude = config.get(CONF_LONGITUDE, hass.config.longitude) - station = config.get(CONF_STATION) + if discovery_info is None: + return + latitude = discovery_info.get(CONF_LATITUDE, hass.config.latitude) + longitude = discovery_info.get(CONF_LONGITUDE, hass.config.longitude) + station = discovery_info.get(CONF_STATION) nws_data = hass.data[DOMAIN][base_unique_id(latitude, longitude)] @@ -134,7 +136,7 @@ class NWSWeather(WeatherEntity): else: self._forecast = self.nws.forecast_hourly - self.async_schedule_update_ha_state() + self.async_write_ha_state() @property def should_poll(self) -> bool: diff --git a/tests/components/nws/test_init.py b/tests/components/nws/test_init.py index 015e4ad81c8..e6fe5707a0d 100644 --- a/tests/components/nws/test_init.py +++ b/tests/components/nws/test_init.py @@ -31,7 +31,12 @@ DUPLICATE_CONFIG = { async def test_no_config(hass, mock_simple_nws): """Test that nws does not setup with no config.""" with assert_setup_component(0): - assert await async_setup_component(hass, DOMAIN, {}) is True + assert await async_setup_component(hass, DOMAIN, {}) + await hass.async_block_till_done() + + entity_registry = await hass.helpers.entity_registry.async_get_registry() + assert len(entity_registry.entities) == 0 + assert DOMAIN not in hass.data @@ -39,29 +44,49 @@ async def test_successful_minimal_config(hass, mock_simple_nws): """Test that nws setup with minimal config.""" hass.config.latitude = 40.0 hass.config.longitude = -75.0 - with assert_setup_component(1): - assert await async_setup_component(hass, DOMAIN, MINIMAL_CONFIG) is True + with assert_setup_component(1, DOMAIN): + assert await async_setup_component(hass, DOMAIN, MINIMAL_CONFIG) + await hass.async_block_till_done() + + entity_registry = await hass.helpers.entity_registry.async_get_registry() + assert len(entity_registry.entities) == 2 + assert DOMAIN in hass.data assert nws.base_unique_id(40.0, -75.0) in hass.data[DOMAIN] async def test_successful_latlon_config(hass, mock_simple_nws): """Test that nws setup with latlon config.""" - with assert_setup_component(1): - assert await async_setup_component(hass, DOMAIN, LATLON_CONFIG) is True + with assert_setup_component(1, DOMAIN): + assert await async_setup_component(hass, DOMAIN, LATLON_CONFIG) + await hass.async_block_till_done() + + entity_registry = await hass.helpers.entity_registry.async_get_registry() + assert len(entity_registry.entities) == 2 + assert DOMAIN in hass.data assert nws.base_unique_id(45.0, -75.0) in hass.data[DOMAIN] async def test_successful_full_config(hass, mock_simple_nws): """Test that nws setup with full config.""" - with assert_setup_component(1): - assert await async_setup_component(hass, DOMAIN, FULL_CONFIG) is True + with assert_setup_component(1, DOMAIN): + assert await async_setup_component(hass, DOMAIN, FULL_CONFIG) + await hass.async_block_till_done() + + entity_registry = await hass.helpers.entity_registry.async_get_registry() + assert len(entity_registry.entities) == 2 + assert DOMAIN in hass.data assert nws.base_unique_id(45.0, -75.0) in hass.data[DOMAIN] async def test_unsuccessful_duplicate_config(hass, mock_simple_nws): """Test that nws setup with duplicate config.""" - assert await async_setup_component(hass, DOMAIN, DUPLICATE_CONFIG) is True + assert await async_setup_component(hass, DOMAIN, DUPLICATE_CONFIG) + await hass.async_block_till_done() + + entity_registry = await hass.helpers.entity_registry.async_get_registry() + assert len(entity_registry.entities) == 2 + assert len(hass.data[DOMAIN]) == 1 diff --git a/tests/components/nws/test_weather.py b/tests/components/nws/test_weather.py index d0e097326c7..4ebc4580ff8 100644 --- a/tests/components/nws/test_weather.py +++ b/tests/components/nws/test_weather.py @@ -21,16 +21,6 @@ from tests.components.nws.const import ( NONE_OBSERVATION, ) -HOURLY_CONFIG = { - "weather": { - "platform": "nws", - "api_key": "x@example.com", - "latitude": 40.0, - "longitude": -85.0, - "mode": "hourly", - } -} - @pytest.mark.parametrize( "units,result_observation,result_forecast", @@ -40,7 +30,7 @@ HOURLY_CONFIG = { ], ) async def test_imperial_metric( - hass, units, result_observation, result_forecast, mock_simple_nws + hass, units, result_observation, result_forecast, mock_simple_nws, caplog ): """Test with imperial and metric units.""" hass.config.units = units @@ -73,6 +63,9 @@ async def test_imperial_metric( for key, value in result_forecast.items(): assert forecast[0].get(key) == value + assert "Error updating observation" not in caplog.text + assert "Success updating observation" not in caplog.text + async def test_none_values(hass, mock_simple_nws): """Test with none values in observation and forecast dicts.""" @@ -136,14 +129,18 @@ async def test_error_observation(hass, mock_simple_nws, caplog): assert await async_setup_component(hass, nws.DOMAIN, MINIMAL_CONFIG) await hass.async_block_till_done() + assert "Error updating observation for station ABC" in caplog.text + assert "Success updating observation for station ABC" not in caplog.text + caplog.clear() + instance.update_observation.side_effect = None future_time = dt_util.utcnow() + timedelta(minutes=15) async_fire_time_changed(hass, future_time) await hass.async_block_till_done() - assert "Error updating observation" in caplog.text - assert "Success updating observation" in caplog.text + assert "Error updating observation for station ABC" not in caplog.text + assert "Success updating observation for station ABC" in caplog.text async def test_error_forecast(hass, caplog, mock_simple_nws): @@ -154,14 +151,18 @@ async def test_error_forecast(hass, caplog, mock_simple_nws): assert await async_setup_component(hass, nws.DOMAIN, MINIMAL_CONFIG) await hass.async_block_till_done() + assert "Error updating forecast for station ABC" in caplog.text + assert "Success updating forecast for station ABC" not in caplog.text + caplog.clear() + instance.update_forecast.side_effect = None future_time = dt_util.utcnow() + timedelta(minutes=15) async_fire_time_changed(hass, future_time) await hass.async_block_till_done() - assert "Error updating forecast" in caplog.text - assert "Success updating forecast" in caplog.text + assert "Error updating forecast for station ABC" not in caplog.text + assert "Success updating forecast for station ABC" in caplog.text async def test_error_forecast_hourly(hass, caplog, mock_simple_nws): @@ -172,11 +173,15 @@ async def test_error_forecast_hourly(hass, caplog, mock_simple_nws): assert await async_setup_component(hass, nws.DOMAIN, MINIMAL_CONFIG) await hass.async_block_till_done() + assert "Error updating forecast_hourly for station ABC" in caplog.text + assert "Success updating forecast_hourly for station ABC" not in caplog.text + caplog.clear() + instance.update_forecast_hourly.side_effect = None future_time = dt_util.utcnow() + timedelta(minutes=15) async_fire_time_changed(hass, future_time) await hass.async_block_till_done() - assert "Error updating forecast_hourly" in caplog.text - assert "Success updating forecast_hourly" in caplog.text + assert "Error updating forecast_hourly for station ABC" not in caplog.text + assert "Success updating forecast_hourly for station ABC" in caplog.text