From 88d2472c642bd9ea544488cbe90fbae2af3580f5 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Mon, 24 Mar 2025 21:19:41 +0100 Subject: [PATCH] feat: refactor the coordinator and client to dynamically get and use the type ID from config --- custom_components/ecocito/__init__.py | 22 ++++++++++++++++----- custom_components/ecocito/client.py | 14 ++++++------- custom_components/ecocito/coordinator.py | 25 ++++++++++++++---------- 3 files changed, 38 insertions(+), 23 deletions(-) diff --git a/custom_components/ecocito/__init__.py b/custom_components/ecocito/__init__.py index fae677f..edda777 100644 --- a/custom_components/ecocito/__init__.py +++ b/custom_components/ecocito/__init__.py @@ -9,6 +9,14 @@ from homeassistant.const import CONF_DOMAIN, CONF_PASSWORD, CONF_USERNAME, Platf from homeassistant.core import HomeAssistant from .client import EcocitoClient +from .const import ( + ECOCITO_DEFAULT_REFRESH_MIN, + ECOCITO_GARBAGE_COLLECTION_TYPE, + ECOCITO_GARBAGE_TYPE, + ECOCITO_RECYCLE_TYPE, + ECOCITO_RECYCLING_COLLECTION_TYPE, + ECOCITO_REFRESH_MIN_KEY, +) from .coordinator import ( GarbageCollectionsDataUpdateCoordinator, RecyclingCollectionsDataUpdateCoordinator, @@ -40,18 +48,22 @@ async def async_setup_entry(hass: HomeAssistant, entry: EcocitoConfigEntry) -> b entry.data[CONF_PASSWORD], ) await client.authenticate() + + garbage_id = entry.data.get(ECOCITO_GARBAGE_TYPE, ECOCITO_GARBAGE_COLLECTION_TYPE) + recycle_id = entry.data.get(ECOCITO_RECYCLE_TYPE, ECOCITO_RECYCLING_COLLECTION_TYPE) + refresh_time = entry.data.get(ECOCITO_REFRESH_MIN_KEY, ECOCITO_DEFAULT_REFRESH_MIN) data = EcocitoData( - garbage_collections=GarbageCollectionsDataUpdateCoordinator(hass, client, 0), + garbage_collections=GarbageCollectionsDataUpdateCoordinator(hass, client, 0, garbage_id, refresh_time), garbage_collections_previous=GarbageCollectionsDataUpdateCoordinator( - hass, client, -1 + hass, client, -1, garbage_id, refresh_time ), recycling_collections=RecyclingCollectionsDataUpdateCoordinator( - hass, client, 0 + hass, client, 0, recycle_id, refresh_time ), recycling_collections_previous=RecyclingCollectionsDataUpdateCoordinator( - hass, client, -1 + hass, client, -1, recycle_id, refresh_time ), - waste_depot_visits=WasteDepotVisitsDataUpdateCoordinator(hass, client, 0), + waste_depot_visits=WasteDepotVisitsDataUpdateCoordinator(hass, client, 0, refresh_time), ) for field in fields(data): coordinator = getattr(data, field.name) diff --git a/custom_components/ecocito/client.py b/custom_components/ecocito/client.py index d4084a0..79aad0d 100644 --- a/custom_components/ecocito/client.py +++ b/custom_components/ecocito/client.py @@ -17,12 +17,10 @@ from .const import ( ECOCITO_ERROR_AUTHENTICATION, ECOCITO_ERROR_FETCHING, ECOCITO_ERROR_UNHANDLED, - ECOCITO_GARBAGE_COLLECTION_TYPE, ECOCITO_LOGIN_ENDPOINT, ECOCITO_LOGIN_PASSWORD_KEY, ECOCITO_LOGIN_URI, ECOCITO_LOGIN_USERNAME_KEY, - ECOCITO_RECYCLING_COLLECTION_TYPE, ECOCITO_WASTE_DEPOSIT_ENDPOINT, LOGGER, ) @@ -83,7 +81,7 @@ class EcocitoClient: except aiohttp.ClientError as e: raise EcocitoError(ECOCITO_ERROR_AUTHENTICATION.format(exc=e)) from e - async def get_collection_types(self) -> dict: + async def get_collection_types(self) -> dict[int, str]: """Return the mapping of collection type ID with their label.""" async with aiohttp.ClientSession(cookie_jar=self._cookies) as session: try: @@ -96,7 +94,7 @@ class EcocitoClient: try: select = html.find("select", {"id": "Filtres_IdMatiere"}) return { - item.attrs["value"]: item.text + int(item.attrs["value"]): item.text for item in select.find_all("option") if "value" in item.attrs } @@ -147,13 +145,13 @@ class EcocitoClient: ECOCITO_ERROR_FETCHING.format(exc=e, type="collection events") ) from e - async def get_garbage_collections(self, year: int) -> list[CollectionEvent]: + async def get_garbage_collections(self, year: int, type_id: int) -> list[CollectionEvent]: """Return the list of the garbage collections for a year.""" - return await self.get_collection_events(ECOCITO_GARBAGE_COLLECTION_TYPE, year) + return await self.get_collection_events(str(type_id), year) - async def get_recycling_collections(self, year: int) -> list[CollectionEvent]: + async def get_recycling_collections(self, year: int, type_id: int) -> list[CollectionEvent]: """Return the list of the recycling collections for a year.""" - return await self.get_collection_events(ECOCITO_RECYCLING_COLLECTION_TYPE, year) + return await self.get_collection_events(str(type_id), year) async def get_waste_depot_visits(self, year: int) -> list[WasteDepotVisit]: """Return the list of the waste depot visits for a year.""" diff --git a/custom_components/ecocito/coordinator.py b/custom_components/ecocito/coordinator.py index 18dd62f..140de4b 100644 --- a/custom_components/ecocito/coordinator.py +++ b/custom_components/ecocito/coordinator.py @@ -28,13 +28,14 @@ class EcocitoDataUpdateCoordinator(DataUpdateCoordinator[T], Generic[T], ABC): self, hass: HomeAssistant, client: EcocitoClient, + refresh_interval: int = 60 ) -> None: """Initialize the coordinator.""" super().__init__( hass=hass, logger=LOGGER, name=DOMAIN, - update_interval=timedelta(minutes=5), + update_interval=timedelta(minutes=refresh_interval), ) self.client = client self._time_zone = ZoneInfo(hass.config.time_zone) @@ -53,23 +54,26 @@ class EcocitoDataUpdateCoordinator(DataUpdateCoordinator[T], Generic[T], ABC): """Fetch the actual data.""" raise NotImplementedError - +# TODO Fuse both coordinators? Since there's no hardcoded ID anymore, the duplicate may +# not really be needed anymore. +# Also later we could build any number of sensors, not just 2 (possibly only 1 also). class GarbageCollectionsDataUpdateCoordinator( EcocitoDataUpdateCoordinator[list[CollectionEvent]] ): """Garbage collections list update from Ecocito.""" def __init__( - self, hass: HomeAssistant, client: EcocitoClient, year_offset: int + self, hass: HomeAssistant, client: EcocitoClient, year_offset: int, garbage_id: int, refresh_time: int ) -> None: """Initialize the coordinator.""" - super().__init__(hass, client) + super().__init__(hass, client, refresh_time) self._year_offset = year_offset + self._garbage_id = garbage_id async def _fetch_data(self) -> list[CollectionEvent]: """Fetch the data.""" return await self.client.get_garbage_collections( - datetime.now(tz=self._time_zone).year + self._year_offset + datetime.now(tz=self._time_zone).year + self._year_offset, self._garbage_id ) @@ -79,16 +83,17 @@ class RecyclingCollectionsDataUpdateCoordinator( """Recycling collections list update from Ecocito.""" def __init__( - self, hass: HomeAssistant, client: EcocitoClient, year_offset: int + self, hass: HomeAssistant, client: EcocitoClient, year_offset: int, recycle_id: int, refresh_time: int ) -> None: """Initialize the coordinator.""" - super().__init__(hass, client) + super().__init__(hass, client, refresh_time) self._year_offset = year_offset + self._recycle_id = recycle_id async def _fetch_data(self) -> list[CollectionEvent]: """Fetch the data.""" return await self.client.get_recycling_collections( - datetime.now(tz=self._time_zone).year + self._year_offset + datetime.now(tz=self._time_zone).year + self._year_offset, self._recycle_id ) @@ -98,10 +103,10 @@ class WasteDepotVisitsDataUpdateCoordinator( """Waste depot visits list update from Ecocito.""" def __init__( - self, hass: HomeAssistant, client: EcocitoClient, year_offset: int + self, hass: HomeAssistant, client: EcocitoClient, year_offset: int, refresh_time: int ) -> None: """Initialize the coordinator.""" - super().__init__(hass, client) + super().__init__(hass, client, refresh_time) self._year_offset = year_offset async def _fetch_data(self) -> list[CollectionEvent]: