core/homeassistant/components/lamarzocco/coordinator.py

101 lines
3.4 KiB
Python

"""Coordinator for La Marzocco API."""
from collections.abc import Callable, Coroutine
from datetime import timedelta
import logging
from typing import Any
from lmcloud import LMCloud as LaMarzoccoClient
from lmcloud.exceptions import AuthFail, RequestNotSuccessful
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_HOST
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryAuthFailed
from homeassistant.helpers.httpx_client import get_async_client
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
from .const import CONF_MACHINE, DOMAIN
SCAN_INTERVAL = timedelta(seconds=30)
_LOGGER = logging.getLogger(__name__)
class LaMarzoccoUpdateCoordinator(DataUpdateCoordinator[None]):
"""Class to handle fetching data from the La Marzocco API centrally."""
config_entry: ConfigEntry
def __init__(self, hass: HomeAssistant) -> None:
"""Initialize coordinator."""
super().__init__(hass, _LOGGER, name=DOMAIN, update_interval=SCAN_INTERVAL)
self.lm = LaMarzoccoClient(
callback_websocket_notify=self.async_update_listeners,
)
self.local_connection_configured = (
self.config_entry.data.get(CONF_HOST) is not None
)
async def _async_update_data(self) -> None:
"""Fetch data from API endpoint."""
if not self.lm.initialized:
await self._async_init_client()
await self._async_handle_request(
self.lm.update_local_machine_status, force_update=True
)
_LOGGER.debug("Current status: %s", str(self.lm.current_status))
async def _async_init_client(self) -> None:
"""Initialize the La Marzocco Client."""
# Initialize cloud API
_LOGGER.debug("Initializing Cloud API")
await self._async_handle_request(
self.lm.init_cloud_api,
credentials=self.config_entry.data,
machine_serial=self.config_entry.data[CONF_MACHINE],
)
_LOGGER.debug("Model name: %s", self.lm.model_name)
# initialize local API
if (host := self.config_entry.data.get(CONF_HOST)) is not None:
_LOGGER.debug("Initializing local API")
await self.lm.init_local_api(
host=host,
client=get_async_client(self.hass),
)
_LOGGER.debug("Init WebSocket in Background Task")
self.config_entry.async_create_background_task(
hass=self.hass,
target=self.lm.lm_local_api.websocket_connect(
callback=self.lm.on_websocket_message_received,
use_sigterm_handler=False,
),
name="lm_websocket_task",
)
self.lm.initialized = True
async def _async_handle_request(
self,
func: Callable[..., Coroutine[None, None, None]],
*args: Any,
**kwargs: Any,
) -> None:
"""Handle a request to the API."""
try:
await func(*args, **kwargs)
except AuthFail as ex:
msg = "Authentication failed."
_LOGGER.debug(msg, exc_info=True)
raise ConfigEntryAuthFailed(msg) from ex
except RequestNotSuccessful as ex:
_LOGGER.debug(ex, exc_info=True)
raise UpdateFailed("Querying API failed. Error: %s" % ex) from ex