2023-01-11 13:30:52 +00:00
|
|
|
"""Files to interact with a the ESPHome dashboard."""
|
|
|
|
from __future__ import annotations
|
|
|
|
|
2023-01-11 20:28:31 +00:00
|
|
|
import asyncio
|
|
|
|
from datetime import timedelta
|
|
|
|
import logging
|
|
|
|
|
|
|
|
import aiohttp
|
|
|
|
from esphome_dashboard_api import ConfiguredDevice, ESPHomeDashboardAPI
|
2023-01-11 13:30:52 +00:00
|
|
|
|
|
|
|
from homeassistant.core import HomeAssistant, callback
|
2023-01-11 20:28:31 +00:00
|
|
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
|
|
|
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
|
|
|
|
2023-01-11 13:30:52 +00:00
|
|
|
KEY_DASHBOARD = "esphome_dashboard"
|
|
|
|
|
|
|
|
|
|
|
|
@callback
|
|
|
|
def async_get_dashboard(hass: HomeAssistant) -> ESPHomeDashboard | None:
|
|
|
|
"""Get an instance of the dashboard if set."""
|
|
|
|
return hass.data.get(KEY_DASHBOARD)
|
|
|
|
|
|
|
|
|
|
|
|
def async_set_dashboard_info(
|
2023-01-11 20:28:31 +00:00
|
|
|
hass: HomeAssistant, addon_slug: str, host: str, port: int
|
2023-01-11 13:30:52 +00:00
|
|
|
) -> None:
|
|
|
|
"""Set the dashboard info."""
|
2023-01-11 20:28:31 +00:00
|
|
|
hass.data[KEY_DASHBOARD] = ESPHomeDashboard(
|
|
|
|
hass,
|
|
|
|
addon_slug,
|
|
|
|
f"http://{host}:{port}",
|
|
|
|
async_get_clientsession(hass),
|
|
|
|
)
|
2023-01-11 13:30:52 +00:00
|
|
|
|
|
|
|
|
2023-01-11 20:28:31 +00:00
|
|
|
class ESPHomeDashboard(DataUpdateCoordinator[dict[str, ConfiguredDevice]]):
|
2023-01-11 13:30:52 +00:00
|
|
|
"""Class to interact with the ESPHome dashboard."""
|
|
|
|
|
2023-01-11 20:28:31 +00:00
|
|
|
_first_fetch_lock: asyncio.Lock | None = None
|
|
|
|
|
|
|
|
def __init__(
|
|
|
|
self,
|
|
|
|
hass: HomeAssistant,
|
|
|
|
addon_slug: str,
|
|
|
|
url: str,
|
|
|
|
session: aiohttp.ClientSession,
|
|
|
|
) -> None:
|
|
|
|
"""Initialize."""
|
|
|
|
super().__init__(
|
|
|
|
hass,
|
|
|
|
logging.getLogger(__name__),
|
|
|
|
name="ESPHome Dashboard",
|
|
|
|
update_interval=timedelta(minutes=5),
|
|
|
|
)
|
|
|
|
self.addon_slug = addon_slug
|
|
|
|
self.api = ESPHomeDashboardAPI(url, session)
|
|
|
|
|
2023-01-11 21:26:13 +00:00
|
|
|
async def ensure_data(self) -> None:
|
|
|
|
"""Ensure the update coordinator has data when this call finishes."""
|
|
|
|
if self.data:
|
|
|
|
return
|
|
|
|
|
|
|
|
if self._first_fetch_lock is not None:
|
|
|
|
async with self._first_fetch_lock:
|
|
|
|
# We know the data is fetched when lock is done
|
|
|
|
return
|
|
|
|
|
|
|
|
self._first_fetch_lock = asyncio.Lock()
|
|
|
|
|
|
|
|
async with self._first_fetch_lock:
|
|
|
|
await self.async_request_refresh()
|
|
|
|
|
|
|
|
self._first_fetch_lock = None
|
|
|
|
|
2023-01-11 20:28:31 +00:00
|
|
|
async def _async_update_data(self) -> dict:
|
|
|
|
"""Fetch device data."""
|
|
|
|
devices = await self.api.get_devices()
|
|
|
|
return {dev["name"]: dev for dev in devices["configured"]}
|