101 lines
3.4 KiB
Python
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
|