coordinator.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. """Integration 101 Template integration using DataUpdateCoordinator."""
  2. from dataclasses import dataclass
  3. from datetime import timedelta
  4. import logging
  5. import asyncio
  6. from homeassistant.config_entries import ConfigEntry
  7. from homeassistant.const import (
  8. CONF_HOST,
  9. CONF_PASSWORD,
  10. CONF_SCAN_INTERVAL,
  11. CONF_USERNAME,
  12. )
  13. from homeassistant.core import DOMAIN, HomeAssistant
  14. from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
  15. from homeassistant.helpers.aiohttp_client import async_get_clientsession
  16. from .api import RouterAPI, APIAuthError, Device, DeviceType
  17. from .const import (DEFAULT_SCAN_INTERVAL,
  18. EP_CELLINFO,
  19. EP_DEVICESTATUS,
  20. EP_LANINFO)
  21. _LOGGER = logging.getLogger(__name__)
  22. @dataclass
  23. class RouterAPIData:
  24. """Class to hold api data."""
  25. data: dict
  26. class RouterCoordinator(DataUpdateCoordinator):
  27. """My example coordinator."""
  28. data: RouterAPIData
  29. def __init__(self, hass: HomeAssistant, config_entry: ConfigEntry) -> None:
  30. """Initialize coordinator."""
  31. # Set variables from values entered in config flow setup
  32. self.host = config_entry.data[CONF_HOST]
  33. self.user = config_entry.data[CONF_USERNAME]
  34. self.pwd = config_entry.data[CONF_PASSWORD]
  35. # set variables from options. You need a default here incase options have not been set
  36. self.poll_interval = config_entry.options.get(
  37. CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL
  38. )
  39. # Initialise DataUpdateCoordinator
  40. super().__init__(
  41. hass,
  42. _LOGGER,
  43. name=f"{DOMAIN} ({config_entry.unique_id})",
  44. # Method to call on every update interval.
  45. update_method=self.async_update_data,
  46. # Polling interval. Will only be polled if there are subscribers.
  47. # Using config option here but you can just use a value.
  48. update_interval=timedelta(seconds=self.poll_interval),
  49. )
  50. session = async_get_clientsession(
  51. hass=hass,
  52. verify_ssl=False
  53. )
  54. # Initialise your api here
  55. self.api = RouterAPI(host=self.host,
  56. user=self.user,
  57. pwd=self.pwd,
  58. session=session)
  59. async def async_update_data(self):
  60. """Fetch data from API endpoint.
  61. This is the place to pre-process the data to lookup tables
  62. so entities can quickly look up their data.
  63. """
  64. try:
  65. # First login to refresh session
  66. if await self.api.async_login():
  67. # Get API endpoints
  68. endpoints = [EP_CELLINFO,
  69. EP_DEVICESTATUS,
  70. EP_LANINFO]
  71. results = await asyncio.gather(
  72. *[self.api.async_query_api(oid=endpoint) for endpoint in endpoints],
  73. return_exceptions=True)
  74. return RouterAPIData({
  75. endpoints[i]: results[i]
  76. for i in len(endpoints)
  77. })
  78. except APIAuthError as err:
  79. _LOGGER.error(err)
  80. raise UpdateFailed(err) from err
  81. except Exception as err:
  82. # This will show entities as unavailable by raising UpdateFailed exception
  83. raise UpdateFailed(f"Error communicating with API: {err}") from err
  84. # # What is returned here is stored in self.data by the DataUpdateCoordinator
  85. # return RouterAPIData(self.api.controller_name, devices)