Home Assistant Unofficial Reference 2024.12.1
__init__.py
Go to the documentation of this file.
1 """The ReCollect Waste integration."""
2 
3 from __future__ import annotations
4 
5 from datetime import date, timedelta
6 from typing import Any
7 
8 from aiorecollect.client import Client, PickupEvent
9 from aiorecollect.errors import RecollectError
10 
11 from homeassistant.config_entries import ConfigEntry
12 from homeassistant.const import Platform
13 from homeassistant.core import HomeAssistant, callback
14 from homeassistant.helpers import aiohttp_client, entity_registry as er
15 from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
16 
17 from .const import CONF_PLACE_ID, CONF_SERVICE_ID, DOMAIN, LOGGER
18 
19 DEFAULT_NAME = "recollect_waste"
20 DEFAULT_UPDATE_INTERVAL = timedelta(days=1)
21 
22 PLATFORMS = [Platform.CALENDAR, Platform.SENSOR]
23 
24 
25 async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
26  """Set up RainMachine as config entry."""
27  session = aiohttp_client.async_get_clientsession(hass)
28  client = Client(
29  entry.data[CONF_PLACE_ID], entry.data[CONF_SERVICE_ID], session=session
30  )
31 
32  async def async_get_pickup_events() -> list[PickupEvent]:
33  """Get the next pickup."""
34  try:
35  # Retrieve today through to 35 days in the future, to get
36  # coverage across a full two months boundary so that no
37  # upcoming pickups are missed. The api.recollect.net base API
38  # call returns only the current month when no dates are passed.
39  # This ensures that data about when the next pickup is will be
40  # returned when the next pickup is the first day of the next month.
41  # Ex: Today is August 31st, tomorrow is a pickup on September 1st.
42  today = date.today()
43  return await client.async_get_pickup_events(
44  start_date=today,
45  end_date=today + timedelta(days=35),
46  )
47  except RecollectError as err:
48  raise UpdateFailed(
49  f"Error while requesting data from ReCollect: {err}"
50  ) from err
51 
52  coordinator = DataUpdateCoordinator(
53  hass,
54  LOGGER,
55  config_entry=entry,
56  name=(
57  f"Place {entry.data[CONF_PLACE_ID]}, Service {entry.data[CONF_SERVICE_ID]}"
58  ),
59  update_interval=DEFAULT_UPDATE_INTERVAL,
60  update_method=async_get_pickup_events,
61  )
62 
63  await coordinator.async_config_entry_first_refresh()
64  hass.data.setdefault(DOMAIN, {})
65  hass.data[DOMAIN][entry.entry_id] = coordinator
66 
67  await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
68 
69  entry.async_on_unload(entry.add_update_listener(async_reload_entry))
70 
71  return True
72 
73 
74 async def async_reload_entry(hass: HomeAssistant, entry: ConfigEntry) -> None:
75  """Handle an options update."""
76  await hass.config_entries.async_reload(entry.entry_id)
77 
78 
79 async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
80  """Unload an RainMachine config entry."""
81  unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
82  if unload_ok:
83  hass.data[DOMAIN].pop(entry.entry_id)
84 
85  return unload_ok
86 
87 
88 async def async_migrate_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
89  """Migrate an old config entry."""
90  version = entry.version
91 
92  LOGGER.debug("Migrating from version %s", version)
93 
94  # 1 -> 2: Update unique ID of existing, single sensor entity to be consistent with
95  # common format for platforms going forward:
96  if version == 1:
97  version = 2
98  hass.config_entries.async_update_entry(entry, version=version)
99 
100  @callback
101  def migrate_unique_id(entity_entry: er.RegistryEntry) -> dict[str, Any]:
102  """Migrate the unique ID to a new format."""
103  return {
104  "new_unique_id": (
105  f"{entry.data[CONF_PLACE_ID]}_"
106  f"{entry.data[CONF_SERVICE_ID]}_"
107  "current_pickup"
108  )
109  }
110 
111  await er.async_migrate_entries(hass, entry.entry_id, migrate_unique_id)
112 
113  LOGGER.debug("Migration to version %s successful", version)
114 
115  return True
bool async_setup_entry(HomeAssistant hass, ConfigEntry entry)
Definition: __init__.py:25
None async_reload_entry(HomeAssistant hass, ConfigEntry entry)
Definition: __init__.py:74
bool async_migrate_entry(HomeAssistant hass, ConfigEntry entry)
Definition: __init__.py:88
bool async_unload_entry(HomeAssistant hass, ConfigEntry entry)
Definition: __init__.py:79