diff --git a/homeassistant/components/usgs_earthquakes_feed/geo_location.py b/homeassistant/components/usgs_earthquakes_feed/geo_location.py index d26f97b295d..6e3eb9b2337 100644 --- a/homeassistant/components/usgs_earthquakes_feed/geo_location.py +++ b/homeassistant/components/usgs_earthquakes_feed/geo_location.py @@ -4,9 +4,7 @@ from __future__ import annotations from datetime import timedelta import logging -from geojson_client.usgs_earthquake_hazards_program_feed import ( - UsgsEarthquakeHazardsProgramFeedManager, -) +from aio_geojson_usgs_earthquakes import UsgsEarthquakeHazardsProgramFeedManager import voluptuous as vol from homeassistant.components.geo_location import PLATFORM_SCHEMA, GeolocationEvent @@ -21,10 +19,14 @@ from homeassistant.const import ( LENGTH_KILOMETERS, ) from homeassistant.core import HomeAssistant, callback +from homeassistant.helpers import aiohttp_client import homeassistant.helpers.config_validation as cv -from homeassistant.helpers.dispatcher import async_dispatcher_connect, dispatcher_send +from homeassistant.helpers.dispatcher import ( + async_dispatcher_connect, + async_dispatcher_send, +) from homeassistant.helpers.entity_platform import AddEntitiesCallback -from homeassistant.helpers.event import track_time_interval +from homeassistant.helpers.event import async_track_time_interval from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType _LOGGER = logging.getLogger(__name__) @@ -87,10 +89,10 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( ) -def setup_platform( +async def async_setup_platform( hass: HomeAssistant, config: ConfigType, - add_entities: AddEntitiesCallback, + async_add_entities: AddEntitiesCallback, discovery_info: DiscoveryInfoType | None = None, ) -> None: """Set up the USGS Earthquake Hazards Program Feed platform.""" @@ -103,21 +105,22 @@ def setup_platform( radius_in_km = config[CONF_RADIUS] minimum_magnitude = config[CONF_MINIMUM_MAGNITUDE] # Initialize the entity manager. - feed = UsgsEarthquakesFeedEntityManager( + manager = UsgsEarthquakesFeedEntityManager( hass, - add_entities, + async_add_entities, scan_interval, coordinates, feed_type, radius_in_km, minimum_magnitude, ) + await manager.async_init() - def start_feed_manager(event): + async def start_feed_manager(event=None): """Start feed manager.""" - feed.startup() + await manager.async_update() - hass.bus.listen_once(EVENT_HOMEASSISTANT_START, start_feed_manager) + hass.bus.async_listen_once(EVENT_HOMEASSISTANT_START, start_feed_manager) class UsgsEarthquakesFeedEntityManager: @@ -126,7 +129,7 @@ class UsgsEarthquakesFeedEntityManager: def __init__( self, hass, - add_entities, + async_add_entities, scan_interval, coordinates, feed_type, @@ -136,7 +139,9 @@ class UsgsEarthquakesFeedEntityManager: """Initialize the Feed Entity Manager.""" self._hass = hass + websession = aiohttp_client.async_get_clientsession(hass) self._feed_manager = UsgsEarthquakeHazardsProgramFeedManager( + websession, self._generate_entity, self._update_entity, self._remove_entity, @@ -145,37 +150,42 @@ class UsgsEarthquakesFeedEntityManager: filter_radius=radius_in_km, filter_minimum_magnitude=minimum_magnitude, ) - self._add_entities = add_entities + self._async_add_entities = async_add_entities self._scan_interval = scan_interval - def startup(self): - """Start up this manager.""" - self._feed_manager.update() - self._init_regular_updates() + async def async_init(self): + """Schedule initial and regular updates based on configured time interval.""" - def _init_regular_updates(self): - """Schedule regular updates at the specified interval.""" - track_time_interval( - self._hass, lambda now: self._feed_manager.update(), self._scan_interval - ) + async def update(event_time): + """Update.""" + await self.async_update() + + # Trigger updates at regular intervals. + async_track_time_interval(self._hass, update, self._scan_interval) + _LOGGER.debug("Feed entity manager initialized") + + async def async_update(self): + """Refresh data.""" + await self._feed_manager.update() + _LOGGER.debug("Feed entity manager updated") def get_entry(self, external_id): """Get feed entry by external id.""" return self._feed_manager.feed_entries.get(external_id) - def _generate_entity(self, external_id): + async def _generate_entity(self, external_id): """Generate new entity.""" new_entity = UsgsEarthquakesEvent(self, external_id) # Add new entities to HA. - self._add_entities([new_entity], True) + self._async_add_entities([new_entity], True) - def _update_entity(self, external_id): + async def _update_entity(self, external_id): """Update entity.""" - dispatcher_send(self._hass, SIGNAL_UPDATE_ENTITY.format(external_id)) + async_dispatcher_send(self._hass, SIGNAL_UPDATE_ENTITY.format(external_id)) - def _remove_entity(self, external_id): + async def _remove_entity(self, external_id): """Remove entity.""" - dispatcher_send(self._hass, SIGNAL_DELETE_ENTITY.format(external_id)) + async_dispatcher_send(self._hass, SIGNAL_DELETE_ENTITY.format(external_id)) class UsgsEarthquakesEvent(GeolocationEvent): diff --git a/homeassistant/components/usgs_earthquakes_feed/manifest.json b/homeassistant/components/usgs_earthquakes_feed/manifest.json index 9c1f4566dc3..bd8ec9633bd 100644 --- a/homeassistant/components/usgs_earthquakes_feed/manifest.json +++ b/homeassistant/components/usgs_earthquakes_feed/manifest.json @@ -2,8 +2,8 @@ "domain": "usgs_earthquakes_feed", "name": "U.S. Geological Survey Earthquake Hazards (USGS)", "documentation": "https://www.home-assistant.io/integrations/usgs_earthquakes_feed", - "requirements": ["geojson_client==0.6"], + "requirements": ["aio_geojson_usgs_earthquakes==0.1"], "codeowners": ["@exxamalte"], "iot_class": "cloud_polling", - "loggers": ["geojson_client"] + "loggers": ["aio_geojson_usgs_earthquakes"] } diff --git a/requirements_all.txt b/requirements_all.txt index f63ff73eccf..d758df0a97c 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -106,6 +106,9 @@ aio_geojson_geonetnz_volcano==0.6 # homeassistant.components.nsw_rural_fire_service_feed aio_geojson_nsw_rfs_incidents==0.4 +# homeassistant.components.usgs_earthquakes_feed +aio_geojson_usgs_earthquakes==0.1 + # homeassistant.components.gdacs aio_georss_gdacs==0.7 @@ -699,9 +702,6 @@ geniushub-client==0.6.30 # homeassistant.components.geocaching geocachingapi==0.2.1 -# homeassistant.components.usgs_earthquakes_feed -geojson_client==0.6 - # homeassistant.components.aprs geopy==2.1.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 1e25b245d52..c2cf31965f6 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -93,6 +93,9 @@ aio_geojson_geonetnz_volcano==0.6 # homeassistant.components.nsw_rural_fire_service_feed aio_geojson_nsw_rfs_incidents==0.4 +# homeassistant.components.usgs_earthquakes_feed +aio_geojson_usgs_earthquakes==0.1 + # homeassistant.components.gdacs aio_georss_gdacs==0.7 @@ -499,9 +502,6 @@ gcal-sync==0.10.0 # homeassistant.components.geocaching geocachingapi==0.2.1 -# homeassistant.components.usgs_earthquakes_feed -geojson_client==0.6 - # homeassistant.components.aprs geopy==2.1.0 diff --git a/tests/components/usgs_earthquakes_feed/test_geo_location.py b/tests/components/usgs_earthquakes_feed/test_geo_location.py index ee845701d81..b8fcbbcbe7d 100644 --- a/tests/components/usgs_earthquakes_feed/test_geo_location.py +++ b/tests/components/usgs_earthquakes_feed/test_geo_location.py @@ -1,6 +1,9 @@ """The tests for the USGS Earthquake Hazards Program Feed platform.""" import datetime -from unittest.mock import MagicMock, call, patch +from unittest.mock import ANY, MagicMock, call, patch + +from aio_geojson_usgs_earthquakes import UsgsEarthquakeHazardsProgramFeed +from freezegun import freeze_time from homeassistant.components import geo_location from homeassistant.components.geo_location import ATTR_SOURCE @@ -111,11 +114,10 @@ async def test_setup(hass): # Patching 'utcnow' to gain more control over the timed update. utcnow = dt_util.utcnow() - with patch("homeassistant.util.dt.utcnow", return_value=utcnow), patch( - "geojson_client.usgs_earthquake_hazards_program_feed." - "UsgsEarthquakeHazardsProgramFeed" - ) as mock_feed: - mock_feed.return_value.update.return_value = ( + with freeze_time(utcnow), patch( + "aio_geojson_client.feed.GeoJsonFeed.update" + ) as mock_feed_update: + mock_feed_update.return_value = ( "OK", [mock_entry_1, mock_entry_2, mock_entry_3], ) @@ -184,9 +186,9 @@ async def test_setup(hass): } assert round(abs(float(state.state) - 25.5), 7) == 0 - # Simulate an update - one existing, one new entry, + # Simulate an update - two existing, one new entry, # one outdated entry - mock_feed.return_value.update.return_value = ( + mock_feed_update.return_value = ( "OK", [mock_entry_1, mock_entry_4, mock_entry_3], ) @@ -198,7 +200,7 @@ async def test_setup(hass): # Simulate an update - empty data, but successful update, # so no changes to entities. - mock_feed.return_value.update.return_value = "OK_NO_DATA", None + mock_feed_update.return_value = "OK_NO_DATA", None async_fire_time_changed(hass, utcnow + 2 * SCAN_INTERVAL) await hass.async_block_till_done() @@ -206,7 +208,7 @@ async def test_setup(hass): assert len(all_states) == 3 # Simulate an update - empty data, removes all entities - mock_feed.return_value.update.return_value = "ERROR", None + mock_feed_update.return_value = "ERROR", None async_fire_time_changed(hass, utcnow + 3 * SCAN_INTERVAL) await hass.async_block_till_done() @@ -220,10 +222,12 @@ async def test_setup_with_custom_location(hass): mock_entry_1 = _generate_mock_feed_entry("1234", "Title 1", 20.5, (-31.1, 150.1)) with patch( - "geojson_client.usgs_earthquake_hazards_program_feed." - "UsgsEarthquakeHazardsProgramFeed" - ) as mock_feed: - mock_feed.return_value.update.return_value = "OK", [mock_entry_1] + "aio_geojson_usgs_earthquakes.feed_manager.UsgsEarthquakeHazardsProgramFeed", + wraps=UsgsEarthquakeHazardsProgramFeed, + ) as mock_feed, patch( + "aio_geojson_client.feed.GeoJsonFeed.update" + ) as mock_feed_update: + mock_feed_update.return_value = "OK", [mock_entry_1] with assert_setup_component(1, geo_location.DOMAIN): assert await async_setup_component( @@ -240,6 +244,7 @@ async def test_setup_with_custom_location(hass): assert len(all_states) == 1 assert mock_feed.call_args == call( + ANY, (15.1, 25.2), "past_hour_m25_earthquakes", filter_minimum_magnitude=0.0,