mirror of
https://github.com/home-assistant/core.git
synced 2025-07-30 00:27:19 +00:00
Merge branch 'dev' into homee-switch
This commit is contained in:
commit
45708c6f9b
@ -716,109 +716,6 @@ def _get_domains(hass: core.HomeAssistant, config: dict[str, Any]) -> set[str]:
|
||||
return domains
|
||||
|
||||
|
||||
class _WatchPendingSetups:
|
||||
"""Periodic log and dispatch of setups that are pending."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
hass: core.HomeAssistant,
|
||||
setup_started: dict[tuple[str, str | None], float],
|
||||
) -> None:
|
||||
"""Initialize the WatchPendingSetups class."""
|
||||
self._hass = hass
|
||||
self._setup_started = setup_started
|
||||
self._duration_count = 0
|
||||
self._handle: asyncio.TimerHandle | None = None
|
||||
self._previous_was_empty = True
|
||||
self._loop = hass.loop
|
||||
|
||||
def _async_watch(self) -> None:
|
||||
"""Periodic log of setups that are pending."""
|
||||
now = monotonic()
|
||||
self._duration_count += SLOW_STARTUP_CHECK_INTERVAL
|
||||
|
||||
remaining_with_setup_started: defaultdict[str, float] = defaultdict(float)
|
||||
for integration_group, start_time in self._setup_started.items():
|
||||
domain, _ = integration_group
|
||||
remaining_with_setup_started[domain] += now - start_time
|
||||
|
||||
if remaining_with_setup_started:
|
||||
_LOGGER.debug("Integration remaining: %s", remaining_with_setup_started)
|
||||
elif waiting_tasks := self._hass._active_tasks: # noqa: SLF001
|
||||
_LOGGER.debug("Waiting on tasks: %s", waiting_tasks)
|
||||
self._async_dispatch(remaining_with_setup_started)
|
||||
if (
|
||||
self._setup_started
|
||||
and self._duration_count % LOG_SLOW_STARTUP_INTERVAL == 0
|
||||
):
|
||||
# We log every LOG_SLOW_STARTUP_INTERVAL until all integrations are done
|
||||
# once we take over LOG_SLOW_STARTUP_INTERVAL (60s) to start up
|
||||
_LOGGER.warning(
|
||||
"Waiting on integrations to complete setup: %s",
|
||||
self._setup_started,
|
||||
)
|
||||
|
||||
_LOGGER.debug("Running timeout Zones: %s", self._hass.timeout.zones)
|
||||
self._async_schedule_next()
|
||||
|
||||
def _async_dispatch(self, remaining_with_setup_started: dict[str, float]) -> None:
|
||||
"""Dispatch the signal."""
|
||||
if remaining_with_setup_started or not self._previous_was_empty:
|
||||
async_dispatcher_send_internal(
|
||||
self._hass, SIGNAL_BOOTSTRAP_INTEGRATIONS, remaining_with_setup_started
|
||||
)
|
||||
self._previous_was_empty = not remaining_with_setup_started
|
||||
|
||||
def _async_schedule_next(self) -> None:
|
||||
"""Schedule the next call."""
|
||||
self._handle = self._loop.call_later(
|
||||
SLOW_STARTUP_CHECK_INTERVAL, self._async_watch
|
||||
)
|
||||
|
||||
def async_start(self) -> None:
|
||||
"""Start watching."""
|
||||
self._async_schedule_next()
|
||||
|
||||
def async_stop(self) -> None:
|
||||
"""Stop watching."""
|
||||
self._async_dispatch({})
|
||||
if self._handle:
|
||||
self._handle.cancel()
|
||||
self._handle = None
|
||||
|
||||
|
||||
async def async_setup_multi_components(
|
||||
hass: core.HomeAssistant,
|
||||
domains: set[str],
|
||||
config: dict[str, Any],
|
||||
) -> None:
|
||||
"""Set up multiple domains. Log on failure."""
|
||||
# Avoid creating tasks for domains that were setup in a previous stage
|
||||
domains_not_yet_setup = domains - hass.config.components
|
||||
# Create setup tasks for base platforms first since everything will have
|
||||
# to wait to be imported, and the sooner we can get the base platforms
|
||||
# loaded the sooner we can start loading the rest of the integrations.
|
||||
futures = {
|
||||
domain: hass.async_create_task_internal(
|
||||
async_setup_component(hass, domain, config),
|
||||
f"setup component {domain}",
|
||||
eager_start=True,
|
||||
)
|
||||
for domain in sorted(
|
||||
domains_not_yet_setup, key=SETUP_ORDER_SORT_KEY, reverse=True
|
||||
)
|
||||
}
|
||||
results = await asyncio.gather(*futures.values(), return_exceptions=True)
|
||||
for idx, domain in enumerate(futures):
|
||||
result = results[idx]
|
||||
if isinstance(result, BaseException):
|
||||
_LOGGER.error(
|
||||
"Error setting up integration %s - received exception",
|
||||
domain,
|
||||
exc_info=(type(result), result, result.__traceback__),
|
||||
)
|
||||
|
||||
|
||||
async def _async_resolve_domains_to_setup(
|
||||
hass: core.HomeAssistant, config: dict[str, Any]
|
||||
) -> tuple[set[str], dict[str, loader.Integration]]:
|
||||
@ -1038,7 +935,7 @@ async def _async_set_up_integrations(
|
||||
for dep in integration.all_dependencies
|
||||
)
|
||||
async_set_domains_to_be_loaded(hass, to_be_loaded)
|
||||
await async_setup_multi_components(hass, domain_group, config)
|
||||
await _async_setup_multi_components(hass, domain_group, config)
|
||||
|
||||
# Enables after dependencies when setting up stage 1 domains
|
||||
async_set_domains_to_be_loaded(hass, stage_1_domains)
|
||||
@ -1050,7 +947,7 @@ async def _async_set_up_integrations(
|
||||
async with hass.timeout.async_timeout(
|
||||
STAGE_1_TIMEOUT, cool_down=COOLDOWN_TIME
|
||||
):
|
||||
await async_setup_multi_components(hass, stage_1_domains, config)
|
||||
await _async_setup_multi_components(hass, stage_1_domains, config)
|
||||
except TimeoutError:
|
||||
_LOGGER.warning(
|
||||
"Setup timed out for stage 1 waiting on %s - moving forward",
|
||||
@ -1066,7 +963,7 @@ async def _async_set_up_integrations(
|
||||
async with hass.timeout.async_timeout(
|
||||
STAGE_2_TIMEOUT, cool_down=COOLDOWN_TIME
|
||||
):
|
||||
await async_setup_multi_components(hass, stage_2_domains, config)
|
||||
await _async_setup_multi_components(hass, stage_2_domains, config)
|
||||
except TimeoutError:
|
||||
_LOGGER.warning(
|
||||
"Setup timed out for stage 2 waiting on %s - moving forward",
|
||||
@ -1092,3 +989,106 @@ async def _async_set_up_integrations(
|
||||
"Integration setup times: %s",
|
||||
dict(sorted(setup_time.items(), key=itemgetter(1), reverse=True)),
|
||||
)
|
||||
|
||||
|
||||
class _WatchPendingSetups:
|
||||
"""Periodic log and dispatch of setups that are pending."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
hass: core.HomeAssistant,
|
||||
setup_started: dict[tuple[str, str | None], float],
|
||||
) -> None:
|
||||
"""Initialize the WatchPendingSetups class."""
|
||||
self._hass = hass
|
||||
self._setup_started = setup_started
|
||||
self._duration_count = 0
|
||||
self._handle: asyncio.TimerHandle | None = None
|
||||
self._previous_was_empty = True
|
||||
self._loop = hass.loop
|
||||
|
||||
def _async_watch(self) -> None:
|
||||
"""Periodic log of setups that are pending."""
|
||||
now = monotonic()
|
||||
self._duration_count += SLOW_STARTUP_CHECK_INTERVAL
|
||||
|
||||
remaining_with_setup_started: defaultdict[str, float] = defaultdict(float)
|
||||
for integration_group, start_time in self._setup_started.items():
|
||||
domain, _ = integration_group
|
||||
remaining_with_setup_started[domain] += now - start_time
|
||||
|
||||
if remaining_with_setup_started:
|
||||
_LOGGER.debug("Integration remaining: %s", remaining_with_setup_started)
|
||||
elif waiting_tasks := self._hass._active_tasks: # noqa: SLF001
|
||||
_LOGGER.debug("Waiting on tasks: %s", waiting_tasks)
|
||||
self._async_dispatch(remaining_with_setup_started)
|
||||
if (
|
||||
self._setup_started
|
||||
and self._duration_count % LOG_SLOW_STARTUP_INTERVAL == 0
|
||||
):
|
||||
# We log every LOG_SLOW_STARTUP_INTERVAL until all integrations are done
|
||||
# once we take over LOG_SLOW_STARTUP_INTERVAL (60s) to start up
|
||||
_LOGGER.warning(
|
||||
"Waiting on integrations to complete setup: %s",
|
||||
self._setup_started,
|
||||
)
|
||||
|
||||
_LOGGER.debug("Running timeout Zones: %s", self._hass.timeout.zones)
|
||||
self._async_schedule_next()
|
||||
|
||||
def _async_dispatch(self, remaining_with_setup_started: dict[str, float]) -> None:
|
||||
"""Dispatch the signal."""
|
||||
if remaining_with_setup_started or not self._previous_was_empty:
|
||||
async_dispatcher_send_internal(
|
||||
self._hass, SIGNAL_BOOTSTRAP_INTEGRATIONS, remaining_with_setup_started
|
||||
)
|
||||
self._previous_was_empty = not remaining_with_setup_started
|
||||
|
||||
def _async_schedule_next(self) -> None:
|
||||
"""Schedule the next call."""
|
||||
self._handle = self._loop.call_later(
|
||||
SLOW_STARTUP_CHECK_INTERVAL, self._async_watch
|
||||
)
|
||||
|
||||
def async_start(self) -> None:
|
||||
"""Start watching."""
|
||||
self._async_schedule_next()
|
||||
|
||||
def async_stop(self) -> None:
|
||||
"""Stop watching."""
|
||||
self._async_dispatch({})
|
||||
if self._handle:
|
||||
self._handle.cancel()
|
||||
self._handle = None
|
||||
|
||||
|
||||
async def _async_setup_multi_components(
|
||||
hass: core.HomeAssistant,
|
||||
domains: set[str],
|
||||
config: dict[str, Any],
|
||||
) -> None:
|
||||
"""Set up multiple domains. Log on failure."""
|
||||
# Avoid creating tasks for domains that were setup in a previous stage
|
||||
domains_not_yet_setup = domains - hass.config.components
|
||||
# Create setup tasks for base platforms first since everything will have
|
||||
# to wait to be imported, and the sooner we can get the base platforms
|
||||
# loaded the sooner we can start loading the rest of the integrations.
|
||||
futures = {
|
||||
domain: hass.async_create_task_internal(
|
||||
async_setup_component(hass, domain, config),
|
||||
f"setup component {domain}",
|
||||
eager_start=True,
|
||||
)
|
||||
for domain in sorted(
|
||||
domains_not_yet_setup, key=SETUP_ORDER_SORT_KEY, reverse=True
|
||||
)
|
||||
}
|
||||
results = await asyncio.gather(*futures.values(), return_exceptions=True)
|
||||
for idx, domain in enumerate(futures):
|
||||
result = results[idx]
|
||||
if isinstance(result, BaseException):
|
||||
_LOGGER.error(
|
||||
"Error setting up integration %s - received exception",
|
||||
domain,
|
||||
exc_info=(type(result), result, result.__traceback__),
|
||||
)
|
||||
|
@ -16,7 +16,7 @@
|
||||
"error": {
|
||||
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
|
||||
"invalid_api_key": "[%key:common::config_flow::error::invalid_api_key%]",
|
||||
"requests_exceeded": "The allowed number of requests to Accuweather API has been exceeded. You have to wait or change API Key."
|
||||
"requests_exceeded": "The allowed number of requests to the AccuWeather API has been exceeded. You have to wait or change the API key."
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
|
@ -6,21 +6,18 @@ from datetime import timedelta
|
||||
import logging
|
||||
|
||||
from homeassistant.components.air_quality import DOMAIN as AIR_QUALITY_PLATFORM
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_API_KEY, CONF_LATITUDE, CONF_LONGITUDE, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
|
||||
from .const import CONF_USE_NEAREST, DOMAIN, MIN_UPDATE_INTERVAL
|
||||
from .coordinator import AirlyDataUpdateCoordinator
|
||||
from .coordinator import AirlyConfigEntry, AirlyDataUpdateCoordinator
|
||||
|
||||
PLATFORMS = [Platform.SENSOR]
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
type AirlyConfigEntry = ConfigEntry[AirlyDataUpdateCoordinator]
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, entry: AirlyConfigEntry) -> bool:
|
||||
"""Set up Airly as config entry."""
|
||||
@ -60,7 +57,14 @@ async def async_setup_entry(hass: HomeAssistant, entry: AirlyConfigEntry) -> boo
|
||||
update_interval = timedelta(minutes=MIN_UPDATE_INTERVAL)
|
||||
|
||||
coordinator = AirlyDataUpdateCoordinator(
|
||||
hass, websession, api_key, latitude, longitude, update_interval, use_nearest
|
||||
hass,
|
||||
entry,
|
||||
websession,
|
||||
api_key,
|
||||
latitude,
|
||||
longitude,
|
||||
update_interval,
|
||||
use_nearest,
|
||||
)
|
||||
await coordinator.async_config_entry_first_refresh()
|
||||
|
||||
|
@ -10,6 +10,7 @@ from aiohttp.client_exceptions import ClientConnectorError
|
||||
from airly import Airly
|
||||
from airly.exceptions import AirlyError
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||
from homeassistant.util import dt as dt_util
|
||||
@ -27,6 +28,8 @@ from .const import (
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
type AirlyConfigEntry = ConfigEntry[AirlyDataUpdateCoordinator]
|
||||
|
||||
|
||||
def set_update_interval(instances_count: int, requests_remaining: int) -> timedelta:
|
||||
"""Return data update interval.
|
||||
@ -58,9 +61,12 @@ def set_update_interval(instances_count: int, requests_remaining: int) -> timede
|
||||
class AirlyDataUpdateCoordinator(DataUpdateCoordinator[dict[str, str | float | int]]):
|
||||
"""Define an object to hold Airly data."""
|
||||
|
||||
config_entry: AirlyConfigEntry
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
hass: HomeAssistant,
|
||||
config_entry: AirlyConfigEntry,
|
||||
session: ClientSession,
|
||||
api_key: str,
|
||||
latitude: float,
|
||||
@ -76,7 +82,13 @@ class AirlyDataUpdateCoordinator(DataUpdateCoordinator[dict[str, str | float | i
|
||||
self.airly = Airly(api_key, session, language=language)
|
||||
self.use_nearest = use_nearest
|
||||
|
||||
super().__init__(hass, _LOGGER, name=DOMAIN, update_interval=update_interval)
|
||||
super().__init__(
|
||||
hass,
|
||||
_LOGGER,
|
||||
config_entry=config_entry,
|
||||
name=DOMAIN,
|
||||
update_interval=update_interval,
|
||||
)
|
||||
|
||||
async def _async_update_data(self) -> dict[str, str | float | int]:
|
||||
"""Update data via library."""
|
||||
|
@ -13,7 +13,7 @@ from homeassistant.const import (
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from . import AirlyConfigEntry
|
||||
from .coordinator import AirlyConfigEntry
|
||||
|
||||
TO_REDACT = {CONF_API_KEY, CONF_LATITUDE, CONF_LONGITUDE, CONF_UNIQUE_ID}
|
||||
|
||||
|
@ -24,7 +24,6 @@ from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||
|
||||
from . import AirlyConfigEntry, AirlyDataUpdateCoordinator
|
||||
from .const import (
|
||||
ATTR_ADVICE,
|
||||
ATTR_API_ADVICE,
|
||||
@ -52,6 +51,7 @@ from .const import (
|
||||
SUFFIX_PERCENT,
|
||||
URL,
|
||||
)
|
||||
from .coordinator import AirlyConfigEntry, AirlyDataUpdateCoordinator
|
||||
|
||||
PARALLEL_UPDATES = 1
|
||||
|
||||
|
@ -9,8 +9,8 @@ from airly import Airly
|
||||
from homeassistant.components import system_health
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
|
||||
from . import AirlyConfigEntry
|
||||
from .const import DOMAIN
|
||||
from .coordinator import AirlyConfigEntry
|
||||
|
||||
|
||||
@callback
|
||||
|
@ -15,13 +15,11 @@ from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
|
||||
from .coordinator import AirNowDataUpdateCoordinator
|
||||
from .coordinator import AirNowConfigEntry, AirNowDataUpdateCoordinator
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
PLATFORMS = [Platform.SENSOR]
|
||||
|
||||
type AirNowConfigEntry = ConfigEntry[AirNowDataUpdateCoordinator]
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, entry: AirNowConfigEntry) -> bool:
|
||||
"""Set up AirNow from a config entry."""
|
||||
@ -38,7 +36,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: AirNowConfigEntry) -> bo
|
||||
# Setup the Coordinator
|
||||
session = async_get_clientsession(hass)
|
||||
coordinator = AirNowDataUpdateCoordinator(
|
||||
hass, session, api_key, latitude, longitude, distance, update_interval
|
||||
hass, entry, session, api_key, latitude, longitude, distance, update_interval
|
||||
)
|
||||
|
||||
# Sync with Coordinator
|
||||
|
@ -10,6 +10,7 @@ from pyairnow import WebServiceAPI
|
||||
from pyairnow.conv import aqi_to_concentration
|
||||
from pyairnow.errors import AirNowError
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||
|
||||
@ -34,13 +35,18 @@ from .const import (
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
type AirNowConfigEntry = ConfigEntry[AirNowDataUpdateCoordinator]
|
||||
|
||||
|
||||
class AirNowDataUpdateCoordinator(DataUpdateCoordinator[dict[str, Any]]):
|
||||
"""The AirNow update coordinator."""
|
||||
|
||||
config_entry: AirNowConfigEntry
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
hass: HomeAssistant,
|
||||
config_entry: AirNowConfigEntry,
|
||||
session: ClientSession,
|
||||
api_key: str,
|
||||
latitude: float,
|
||||
@ -55,7 +61,13 @@ class AirNowDataUpdateCoordinator(DataUpdateCoordinator[dict[str, Any]]):
|
||||
|
||||
self.airnow = WebServiceAPI(api_key, session=session)
|
||||
|
||||
super().__init__(hass, _LOGGER, name=DOMAIN, update_interval=update_interval)
|
||||
super().__init__(
|
||||
hass,
|
||||
_LOGGER,
|
||||
config_entry=config_entry,
|
||||
name=DOMAIN,
|
||||
update_interval=update_interval,
|
||||
)
|
||||
|
||||
async def _async_update_data(self) -> dict[str, Any]:
|
||||
"""Update data via library."""
|
||||
|
@ -13,7 +13,7 @@ from homeassistant.const import (
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from . import AirNowConfigEntry
|
||||
from .coordinator import AirNowConfigEntry
|
||||
|
||||
ATTR_LATITUDE_CAP = "Latitude"
|
||||
ATTR_LONGITUDE_CAP = "Longitude"
|
||||
|
@ -25,7 +25,6 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.typing import StateType
|
||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||
|
||||
from . import AirNowConfigEntry, AirNowDataUpdateCoordinator
|
||||
from .const import (
|
||||
ATTR_API_AQI,
|
||||
ATTR_API_AQI_DESCRIPTION,
|
||||
@ -43,6 +42,7 @@ from .const import (
|
||||
DOMAIN,
|
||||
US_TZ_OFFSETS,
|
||||
)
|
||||
from .coordinator import AirNowConfigEntry, AirNowDataUpdateCoordinator
|
||||
|
||||
ATTRIBUTION = "Data provided by AirNow"
|
||||
|
||||
|
@ -15,7 +15,6 @@ from aioairzone.const import (
|
||||
)
|
||||
from aioairzone.localapi import AirzoneLocalApi, ConnectionOptions
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_HOST, CONF_ID, CONF_PORT, Platform
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers import (
|
||||
@ -25,7 +24,7 @@ from homeassistant.helpers import (
|
||||
)
|
||||
|
||||
from .const import DOMAIN, MANUFACTURER
|
||||
from .coordinator import AirzoneUpdateCoordinator
|
||||
from .coordinator import AirzoneConfigEntry, AirzoneUpdateCoordinator
|
||||
|
||||
PLATFORMS: list[Platform] = [
|
||||
Platform.BINARY_SENSOR,
|
||||
@ -38,8 +37,6 @@ PLATFORMS: list[Platform] = [
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
type AirzoneConfigEntry = ConfigEntry[AirzoneUpdateCoordinator]
|
||||
|
||||
|
||||
async def _async_migrate_unique_ids(
|
||||
hass: HomeAssistant,
|
||||
@ -90,7 +87,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: AirzoneConfigEntry) -> b
|
||||
)
|
||||
|
||||
airzone = AirzoneLocalApi(aiohttp_client.async_get_clientsession(hass), options)
|
||||
coordinator = AirzoneUpdateCoordinator(hass, airzone)
|
||||
coordinator = AirzoneUpdateCoordinator(hass, entry, airzone)
|
||||
await coordinator.async_config_entry_first_refresh()
|
||||
await _async_migrate_unique_ids(hass, entry, coordinator)
|
||||
|
||||
|
@ -25,8 +25,7 @@ from homeassistant.const import EntityCategory
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from . import AirzoneConfigEntry
|
||||
from .coordinator import AirzoneUpdateCoordinator
|
||||
from .coordinator import AirzoneConfigEntry, AirzoneUpdateCoordinator
|
||||
from .entity import AirzoneEntity, AirzoneSystemEntity, AirzoneZoneEntity
|
||||
|
||||
|
||||
|
@ -50,9 +50,8 @@ from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from . import AirzoneConfigEntry
|
||||
from .const import API_TEMPERATURE_STEP, TEMP_UNIT_LIB_TO_HASS
|
||||
from .coordinator import AirzoneUpdateCoordinator
|
||||
from .coordinator import AirzoneConfigEntry, AirzoneUpdateCoordinator
|
||||
from .entity import AirzoneZoneEntity
|
||||
|
||||
BASE_FAN_SPEEDS: Final[dict[int, str]] = {
|
||||
|
@ -10,6 +10,7 @@ from typing import Any
|
||||
from aioairzone.exceptions import AirzoneError
|
||||
from aioairzone.localapi import AirzoneLocalApi
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||
|
||||
@ -19,17 +20,27 @@ SCAN_INTERVAL = timedelta(seconds=60)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
type AirzoneConfigEntry = ConfigEntry[AirzoneUpdateCoordinator]
|
||||
|
||||
|
||||
class AirzoneUpdateCoordinator(DataUpdateCoordinator[dict[str, Any]]):
|
||||
"""Class to manage fetching data from the Airzone device."""
|
||||
|
||||
def __init__(self, hass: HomeAssistant, airzone: AirzoneLocalApi) -> None:
|
||||
config_entry: AirzoneConfigEntry
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
hass: HomeAssistant,
|
||||
config_entry: AirzoneConfigEntry,
|
||||
airzone: AirzoneLocalApi,
|
||||
) -> None:
|
||||
"""Initialize."""
|
||||
self.airzone = airzone
|
||||
|
||||
super().__init__(
|
||||
hass,
|
||||
_LOGGER,
|
||||
config_entry=config_entry,
|
||||
name=DOMAIN,
|
||||
update_interval=SCAN_INTERVAL,
|
||||
)
|
||||
|
@ -10,7 +10,7 @@ from homeassistant.components.diagnostics import async_redact_data
|
||||
from homeassistant.const import CONF_UNIQUE_ID
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from . import AirzoneConfigEntry
|
||||
from .coordinator import AirzoneConfigEntry
|
||||
|
||||
TO_REDACT_API = [
|
||||
API_MAC,
|
||||
|
@ -31,9 +31,8 @@ from homeassistant.helpers import device_registry as dr
|
||||
from homeassistant.helpers.device_registry import DeviceInfo
|
||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||
|
||||
from . import AirzoneConfigEntry
|
||||
from .const import DOMAIN, MANUFACTURER
|
||||
from .coordinator import AirzoneUpdateCoordinator
|
||||
from .coordinator import AirzoneConfigEntry, AirzoneUpdateCoordinator
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
@ -27,8 +27,7 @@ from homeassistant.const import EntityCategory
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from . import AirzoneConfigEntry
|
||||
from .coordinator import AirzoneUpdateCoordinator
|
||||
from .coordinator import AirzoneConfigEntry, AirzoneUpdateCoordinator
|
||||
from .entity import AirzoneEntity, AirzoneZoneEntity
|
||||
|
||||
|
||||
|
@ -30,9 +30,8 @@ from homeassistant.const import (
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from . import AirzoneConfigEntry
|
||||
from .const import TEMP_UNIT_LIB_TO_HASS
|
||||
from .coordinator import AirzoneUpdateCoordinator
|
||||
from .coordinator import AirzoneConfigEntry, AirzoneUpdateCoordinator
|
||||
from .entity import (
|
||||
AirzoneEntity,
|
||||
AirzoneHotWaterEntity,
|
||||
|
@ -16,8 +16,7 @@ from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from . import AirzoneConfigEntry
|
||||
from .coordinator import AirzoneUpdateCoordinator
|
||||
from .coordinator import AirzoneConfigEntry, AirzoneUpdateCoordinator
|
||||
from .entity import AirzoneEntity, AirzoneZoneEntity
|
||||
|
||||
|
||||
|
@ -30,9 +30,8 @@ from homeassistant.const import ATTR_TEMPERATURE, STATE_OFF
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from . import AirzoneConfigEntry
|
||||
from .const import TEMP_UNIT_LIB_TO_HASS
|
||||
from .coordinator import AirzoneUpdateCoordinator
|
||||
from .coordinator import AirzoneConfigEntry, AirzoneUpdateCoordinator
|
||||
from .entity import AirzoneHotWaterEntity
|
||||
|
||||
OPERATION_LIB_TO_HASS: Final[dict[HotWaterOperation, str]] = {
|
||||
|
@ -2,14 +2,11 @@
|
||||
|
||||
import amberelectric
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_API_TOKEN
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from .const import CONF_SITE_ID, PLATFORMS
|
||||
from .coordinator import AmberUpdateCoordinator
|
||||
|
||||
type AmberConfigEntry = ConfigEntry[AmberUpdateCoordinator]
|
||||
from .coordinator import AmberConfigEntry, AmberUpdateCoordinator
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, entry: AmberConfigEntry) -> bool:
|
||||
@ -19,7 +16,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: AmberConfigEntry) -> boo
|
||||
api_instance = amberelectric.AmberApi(api_client)
|
||||
site_id = entry.data[CONF_SITE_ID]
|
||||
|
||||
coordinator = AmberUpdateCoordinator(hass, api_instance, site_id)
|
||||
coordinator = AmberUpdateCoordinator(hass, entry, api_instance, site_id)
|
||||
await coordinator.async_config_entry_first_refresh()
|
||||
entry.runtime_data = coordinator
|
||||
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
|
||||
|
@ -12,9 +12,8 @@ from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||
|
||||
from . import AmberConfigEntry
|
||||
from .const import ATTRIBUTION
|
||||
from .coordinator import AmberUpdateCoordinator
|
||||
from .coordinator import AmberConfigEntry, AmberUpdateCoordinator
|
||||
|
||||
PRICE_SPIKE_ICONS = {
|
||||
"none": "mdi:power-plug",
|
||||
|
@ -13,11 +13,14 @@ from amberelectric.models.forecast_interval import ForecastInterval
|
||||
from amberelectric.models.price_descriptor import PriceDescriptor
|
||||
from amberelectric.rest import ApiException
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||
|
||||
from .const import LOGGER
|
||||
|
||||
type AmberConfigEntry = ConfigEntry[AmberUpdateCoordinator]
|
||||
|
||||
|
||||
def is_current(interval: ActualInterval | CurrentInterval | ForecastInterval) -> bool:
|
||||
"""Return true if the supplied interval is a CurrentInterval."""
|
||||
@ -70,13 +73,20 @@ def normalize_descriptor(descriptor: PriceDescriptor | None) -> str | None:
|
||||
class AmberUpdateCoordinator(DataUpdateCoordinator):
|
||||
"""AmberUpdateCoordinator - In charge of downloading the data for a site, which all the sensors read."""
|
||||
|
||||
config_entry: AmberConfigEntry
|
||||
|
||||
def __init__(
|
||||
self, hass: HomeAssistant, api: amberelectric.AmberApi, site_id: str
|
||||
self,
|
||||
hass: HomeAssistant,
|
||||
config_entry: AmberConfigEntry,
|
||||
api: amberelectric.AmberApi,
|
||||
site_id: str,
|
||||
) -> None:
|
||||
"""Initialise the data service."""
|
||||
super().__init__(
|
||||
hass,
|
||||
LOGGER,
|
||||
config_entry=config_entry,
|
||||
name="amberelectric",
|
||||
update_interval=timedelta(minutes=1),
|
||||
)
|
||||
|
@ -22,9 +22,8 @@ from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||
|
||||
from . import AmberConfigEntry
|
||||
from .const import ATTRIBUTION
|
||||
from .coordinator import AmberUpdateCoordinator, normalize_descriptor
|
||||
from .coordinator import AmberConfigEntry, AmberUpdateCoordinator, normalize_descriptor
|
||||
|
||||
UNIT = f"{CURRENCY_DOLLAR}/{UnitOfEnergy.KILO_WATT_HOUR}"
|
||||
|
||||
|
@ -4,13 +4,10 @@ from __future__ import annotations
|
||||
|
||||
from aioambient.open_api import OpenAPI
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from .coordinator import AmbientNetworkDataUpdateCoordinator
|
||||
|
||||
type AmbientNetworkConfigEntry = ConfigEntry[AmbientNetworkDataUpdateCoordinator]
|
||||
from .coordinator import AmbientNetworkConfigEntry, AmbientNetworkDataUpdateCoordinator
|
||||
|
||||
PLATFORMS: list[Platform] = [Platform.SENSOR]
|
||||
|
||||
@ -21,7 +18,7 @@ async def async_setup_entry(
|
||||
"""Set up the Ambient Weather Network from a config entry."""
|
||||
|
||||
api = OpenAPI()
|
||||
coordinator = AmbientNetworkDataUpdateCoordinator(hass, api)
|
||||
coordinator = AmbientNetworkDataUpdateCoordinator(hass, entry, api)
|
||||
await coordinator.async_config_entry_first_refresh()
|
||||
entry.runtime_data = coordinator
|
||||
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
|
||||
|
@ -19,17 +19,27 @@ from .helper import get_station_name
|
||||
|
||||
SCAN_INTERVAL = timedelta(minutes=5)
|
||||
|
||||
type AmbientNetworkConfigEntry = ConfigEntry[AmbientNetworkDataUpdateCoordinator]
|
||||
|
||||
|
||||
class AmbientNetworkDataUpdateCoordinator(DataUpdateCoordinator[dict[str, Any]]):
|
||||
"""The Ambient Network Data Update Coordinator."""
|
||||
|
||||
config_entry: ConfigEntry
|
||||
config_entry: AmbientNetworkConfigEntry
|
||||
station_name: str
|
||||
last_measured: datetime | None = None
|
||||
|
||||
def __init__(self, hass: HomeAssistant, api: OpenAPI) -> None:
|
||||
def __init__(
|
||||
self, hass: HomeAssistant, config_entry: AmbientNetworkConfigEntry, api: OpenAPI
|
||||
) -> None:
|
||||
"""Initialize the coordinator."""
|
||||
super().__init__(hass, LOGGER, name=DOMAIN, update_interval=SCAN_INTERVAL)
|
||||
super().__init__(
|
||||
hass,
|
||||
LOGGER,
|
||||
config_entry=config_entry,
|
||||
name=DOMAIN,
|
||||
update_interval=SCAN_INTERVAL,
|
||||
)
|
||||
self.api = api
|
||||
|
||||
async def _async_update_data(self) -> dict[str, Any]:
|
||||
|
@ -28,8 +28,7 @@ from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.util import dt as dt_util
|
||||
|
||||
from . import AmbientNetworkConfigEntry
|
||||
from .coordinator import AmbientNetworkDataUpdateCoordinator
|
||||
from .coordinator import AmbientNetworkConfigEntry, AmbientNetworkDataUpdateCoordinator
|
||||
from .entity import AmbientNetworkEntity
|
||||
|
||||
TYPE_AQI_PM25 = "aqi_pm25"
|
||||
|
@ -48,7 +48,7 @@ async def async_setup_entry(
|
||||
continue
|
||||
names[integration] = integrations[integration].title
|
||||
|
||||
coordinator = HomeassistantAnalyticsDataUpdateCoordinator(hass, client)
|
||||
coordinator = HomeassistantAnalyticsDataUpdateCoordinator(hass, entry, client)
|
||||
|
||||
await coordinator.async_config_entry_first_refresh()
|
||||
|
||||
|
@ -46,12 +46,16 @@ class HomeassistantAnalyticsDataUpdateCoordinator(DataUpdateCoordinator[Analytic
|
||||
config_entry: AnalyticsInsightsConfigEntry
|
||||
|
||||
def __init__(
|
||||
self, hass: HomeAssistant, client: HomeassistantAnalyticsClient
|
||||
self,
|
||||
hass: HomeAssistant,
|
||||
config_entry: AnalyticsInsightsConfigEntry,
|
||||
client: HomeassistantAnalyticsClient,
|
||||
) -> None:
|
||||
"""Initialize the Homeassistant Analytics data coordinator."""
|
||||
super().__init__(
|
||||
hass,
|
||||
LOGGER,
|
||||
config_entry=config_entry,
|
||||
name=DOMAIN,
|
||||
update_interval=timedelta(hours=12),
|
||||
)
|
||||
|
@ -35,6 +35,7 @@ class AndroidIPCamDataUpdateCoordinator(DataUpdateCoordinator[None]):
|
||||
super().__init__(
|
||||
self.hass,
|
||||
_LOGGER,
|
||||
config_entry=config_entry,
|
||||
name=f"{DOMAIN} {config_entry.data[CONF_HOST]}",
|
||||
update_interval=timedelta(seconds=10),
|
||||
)
|
||||
|
@ -35,16 +35,12 @@ async def async_setup_entry(
|
||||
|
||||
@callback
|
||||
def is_available_updated(is_available: bool) -> None:
|
||||
if is_available:
|
||||
_LOGGER.info(
|
||||
"Reconnected to %s at %s", entry.data[CONF_NAME], entry.data[CONF_HOST]
|
||||
)
|
||||
else:
|
||||
_LOGGER.warning(
|
||||
"Disconnected from %s at %s",
|
||||
entry.data[CONF_NAME],
|
||||
entry.data[CONF_HOST],
|
||||
)
|
||||
_LOGGER.info(
|
||||
"%s %s at %s",
|
||||
"Reconnected to" if is_available else "Disconnected from",
|
||||
entry.data[CONF_NAME],
|
||||
entry.data[CONF_HOST],
|
||||
)
|
||||
|
||||
api.add_is_available_updated_callback(is_available_updated)
|
||||
|
||||
|
@ -18,8 +18,7 @@ from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import ConfigEntryNotReady
|
||||
from homeassistant.helpers import aiohttp_client
|
||||
|
||||
from .coordinator import AnovaCoordinator
|
||||
from .models import AnovaConfigEntry, AnovaData
|
||||
from .coordinator import AnovaConfigEntry, AnovaCoordinator, AnovaData
|
||||
|
||||
PLATFORMS = [Platform.SENSOR]
|
||||
|
||||
@ -59,7 +58,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: AnovaConfigEntry) -> boo
|
||||
# websocket client
|
||||
assert api.websocket_handler is not None
|
||||
devices = list(api.websocket_handler.devices.values())
|
||||
coordinators = [AnovaCoordinator(hass, device) for device in devices]
|
||||
coordinators = [AnovaCoordinator(hass, entry, device) for device in devices]
|
||||
entry.runtime_data = AnovaData(api_jwt=api.jwt, coordinators=coordinators, api=api)
|
||||
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
|
||||
return True
|
||||
|
@ -1,8 +1,9 @@
|
||||
"""Support for Anova Coordinators."""
|
||||
|
||||
from dataclasses import dataclass
|
||||
import logging
|
||||
|
||||
from anova_wifi import APCUpdate, APCWifiDevice
|
||||
from anova_wifi import AnovaApi, APCUpdate, APCWifiDevice
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant
|
||||
@ -14,15 +15,33 @@ from .const import DOMAIN
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@dataclass
|
||||
class AnovaData:
|
||||
"""Data for the Anova integration."""
|
||||
|
||||
api_jwt: str
|
||||
coordinators: list["AnovaCoordinator"]
|
||||
api: AnovaApi
|
||||
|
||||
|
||||
type AnovaConfigEntry = ConfigEntry[AnovaData]
|
||||
|
||||
|
||||
class AnovaCoordinator(DataUpdateCoordinator[APCUpdate]):
|
||||
"""Anova custom coordinator."""
|
||||
|
||||
config_entry: ConfigEntry
|
||||
config_entry: AnovaConfigEntry
|
||||
|
||||
def __init__(self, hass: HomeAssistant, anova_device: APCWifiDevice) -> None:
|
||||
def __init__(
|
||||
self,
|
||||
hass: HomeAssistant,
|
||||
config_entry: AnovaConfigEntry,
|
||||
anova_device: APCWifiDevice,
|
||||
) -> None:
|
||||
"""Set up Anova Coordinator."""
|
||||
super().__init__(
|
||||
hass,
|
||||
config_entry=config_entry,
|
||||
name="Anova Precision Cooker",
|
||||
logger=_LOGGER,
|
||||
)
|
||||
|
@ -1,20 +0,0 @@
|
||||
"""Dataclass models for the Anova integration."""
|
||||
|
||||
from dataclasses import dataclass
|
||||
|
||||
from anova_wifi import AnovaApi
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
|
||||
from .coordinator import AnovaCoordinator
|
||||
|
||||
type AnovaConfigEntry = ConfigEntry[AnovaData]
|
||||
|
||||
|
||||
@dataclass
|
||||
class AnovaData:
|
||||
"""Data for the Anova integration."""
|
||||
|
||||
api_jwt: str
|
||||
coordinators: list[AnovaCoordinator]
|
||||
api: AnovaApi
|
@ -18,9 +18,8 @@ from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.typing import StateType
|
||||
|
||||
from .coordinator import AnovaCoordinator
|
||||
from .coordinator import AnovaConfigEntry, AnovaCoordinator
|
||||
from .entity import AnovaDescriptionEntity
|
||||
from .models import AnovaConfigEntry
|
||||
|
||||
|
||||
@dataclass(frozen=True, kw_only=True)
|
||||
|
@ -4,13 +4,10 @@ from __future__ import annotations
|
||||
|
||||
from typing import Final
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_HOST, CONF_PORT, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from .coordinator import APCUPSdCoordinator
|
||||
|
||||
type APCUPSdConfigEntry = ConfigEntry[APCUPSdCoordinator]
|
||||
from .coordinator import APCUPSdConfigEntry, APCUPSdCoordinator
|
||||
|
||||
PLATFORMS: Final = (Platform.BINARY_SENSOR, Platform.SENSOR)
|
||||
|
||||
@ -20,7 +17,7 @@ async def async_setup_entry(
|
||||
) -> bool:
|
||||
"""Use config values to set up a function enabling status retrieval."""
|
||||
host, port = config_entry.data[CONF_HOST], config_entry.data[CONF_PORT]
|
||||
coordinator = APCUPSdCoordinator(hass, host, port)
|
||||
coordinator = APCUPSdCoordinator(hass, config_entry, host, port)
|
||||
|
||||
await coordinator.async_config_entry_first_refresh()
|
||||
|
||||
|
@ -12,8 +12,7 @@ from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||
|
||||
from . import APCUPSdConfigEntry
|
||||
from .coordinator import APCUPSdCoordinator
|
||||
from .coordinator import APCUPSdConfigEntry, APCUPSdCoordinator
|
||||
|
||||
PARALLEL_UPDATES = 0
|
||||
|
||||
|
@ -25,6 +25,8 @@ _LOGGER = logging.getLogger(__name__)
|
||||
UPDATE_INTERVAL: Final = timedelta(seconds=60)
|
||||
REQUEST_REFRESH_COOLDOWN: Final = 5
|
||||
|
||||
type APCUPSdConfigEntry = ConfigEntry[APCUPSdCoordinator]
|
||||
|
||||
|
||||
class APCUPSdData(dict[str, str]):
|
||||
"""Store data about an APCUPSd and provide a few helper methods for easier accesses."""
|
||||
@ -57,13 +59,20 @@ class APCUPSdCoordinator(DataUpdateCoordinator[APCUPSdData]):
|
||||
updates from the server.
|
||||
"""
|
||||
|
||||
config_entry: ConfigEntry
|
||||
config_entry: APCUPSdConfigEntry
|
||||
|
||||
def __init__(self, hass: HomeAssistant, host: str, port: int) -> None:
|
||||
def __init__(
|
||||
self,
|
||||
hass: HomeAssistant,
|
||||
config_entry: APCUPSdConfigEntry,
|
||||
host: str,
|
||||
port: int,
|
||||
) -> None:
|
||||
"""Initialize the data object."""
|
||||
super().__init__(
|
||||
hass,
|
||||
_LOGGER,
|
||||
config_entry=config_entry,
|
||||
name=DOMAIN,
|
||||
update_interval=UPDATE_INTERVAL,
|
||||
request_refresh_debouncer=Debouncer(
|
||||
|
@ -7,7 +7,7 @@ from typing import Any
|
||||
from homeassistant.components.diagnostics import async_redact_data
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from . import APCUPSdConfigEntry
|
||||
from .coordinator import APCUPSdConfigEntry
|
||||
|
||||
TO_REDACT = {"SERIALNO", "HOSTNAME"}
|
||||
|
||||
|
@ -24,9 +24,8 @@ from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||
|
||||
from . import APCUPSdConfigEntry
|
||||
from .const import LAST_S_TEST
|
||||
from .coordinator import APCUPSdCoordinator
|
||||
from .coordinator import APCUPSdConfigEntry, APCUPSdCoordinator
|
||||
|
||||
PARALLEL_UPDATES = 0
|
||||
|
||||
|
@ -5,18 +5,15 @@ from __future__ import annotations
|
||||
from aioaquacell import AquacellApi
|
||||
from aioaquacell.const import Brand
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
|
||||
from .const import CONF_BRAND
|
||||
from .coordinator import AquacellCoordinator
|
||||
from .coordinator import AquacellConfigEntry, AquacellCoordinator
|
||||
|
||||
PLATFORMS = [Platform.SENSOR]
|
||||
|
||||
type AquacellConfigEntry = ConfigEntry[AquacellCoordinator]
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, entry: AquacellConfigEntry) -> bool:
|
||||
"""Set up Aquacell from a config entry."""
|
||||
@ -26,7 +23,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: AquacellConfigEntry) ->
|
||||
|
||||
aquacell_api = AquacellApi(session, brand)
|
||||
|
||||
coordinator = AquacellCoordinator(hass, aquacell_api)
|
||||
coordinator = AquacellCoordinator(hass, entry, aquacell_api)
|
||||
|
||||
await coordinator.async_config_entry_first_refresh()
|
||||
entry.runtime_data = coordinator
|
||||
@ -36,6 +33,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: AquacellConfigEntry) ->
|
||||
return True
|
||||
|
||||
|
||||
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
async def async_unload_entry(hass: HomeAssistant, entry: AquacellConfigEntry) -> bool:
|
||||
"""Unload a config entry."""
|
||||
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
|
||||
|
@ -26,17 +26,25 @@ from .const import (
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
type AquacellConfigEntry = ConfigEntry[AquacellCoordinator]
|
||||
|
||||
|
||||
class AquacellCoordinator(DataUpdateCoordinator[dict[str, Softener]]):
|
||||
"""My aquacell coordinator."""
|
||||
|
||||
config_entry: ConfigEntry
|
||||
config_entry: AquacellConfigEntry
|
||||
|
||||
def __init__(self, hass: HomeAssistant, aquacell_api: AquacellApi) -> None:
|
||||
def __init__(
|
||||
self,
|
||||
hass: HomeAssistant,
|
||||
config_entry: AquacellConfigEntry,
|
||||
aquacell_api: AquacellApi,
|
||||
) -> None:
|
||||
"""Initialize coordinator."""
|
||||
super().__init__(
|
||||
hass,
|
||||
_LOGGER,
|
||||
config_entry=config_entry,
|
||||
name="Aquacell Coordinator",
|
||||
update_interval=UPDATE_INTERVAL,
|
||||
)
|
||||
|
@ -18,8 +18,7 @@ from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.typing import StateType
|
||||
|
||||
from . import AquacellConfigEntry
|
||||
from .coordinator import AquacellCoordinator
|
||||
from .coordinator import AquacellConfigEntry, AquacellCoordinator
|
||||
from .entity import AquacellEntity
|
||||
|
||||
PARALLEL_UPDATES = 1
|
||||
|
@ -13,7 +13,7 @@ PLATFORMS: list[Platform] = [Platform.SENSOR]
|
||||
async def async_setup_entry(hass: HomeAssistant, entry: ArveConfigEntry) -> bool:
|
||||
"""Set up Arve from a config entry."""
|
||||
|
||||
coordinator = ArveCoordinator(hass)
|
||||
coordinator = ArveCoordinator(hass, entry)
|
||||
|
||||
await coordinator.async_config_entry_first_refresh()
|
||||
|
||||
|
@ -30,11 +30,12 @@ class ArveCoordinator(DataUpdateCoordinator[ArveSensProData]):
|
||||
config_entry: ArveConfigEntry
|
||||
devices: ArveDevices
|
||||
|
||||
def __init__(self, hass: HomeAssistant) -> None:
|
||||
def __init__(self, hass: HomeAssistant, config_entry: ArveConfigEntry) -> None:
|
||||
"""Initialize Arve coordinator."""
|
||||
super().__init__(
|
||||
hass,
|
||||
LOGGER,
|
||||
config_entry=config_entry,
|
||||
name=DOMAIN,
|
||||
update_interval=timedelta(seconds=60),
|
||||
)
|
||||
|
@ -1093,16 +1093,18 @@ class PipelineRun:
|
||||
agent_id = conversation.HOME_ASSISTANT_AGENT
|
||||
processed_locally = True
|
||||
|
||||
# It was already handled, create response and add to chat history
|
||||
if intent_response is not None:
|
||||
with (
|
||||
chat_session.async_get_chat_session(
|
||||
self.hass, user_input.conversation_id
|
||||
) as session,
|
||||
conversation.async_get_chat_log(
|
||||
self.hass, session, user_input
|
||||
) as chat_log,
|
||||
):
|
||||
with (
|
||||
chat_session.async_get_chat_session(
|
||||
self.hass, user_input.conversation_id
|
||||
) as session,
|
||||
conversation.async_get_chat_log(
|
||||
self.hass,
|
||||
session,
|
||||
user_input,
|
||||
) as chat_log,
|
||||
):
|
||||
# It was already handled, create response and add to chat history
|
||||
if intent_response is not None:
|
||||
speech: str = intent_response.speech.get("plain", {}).get(
|
||||
"speech", ""
|
||||
)
|
||||
@ -1117,21 +1119,21 @@ class PipelineRun:
|
||||
conversation_id=session.conversation_id,
|
||||
)
|
||||
|
||||
else:
|
||||
# Fall back to pipeline conversation agent
|
||||
conversation_result = await conversation.async_converse(
|
||||
hass=self.hass,
|
||||
text=user_input.text,
|
||||
conversation_id=user_input.conversation_id,
|
||||
device_id=user_input.device_id,
|
||||
context=user_input.context,
|
||||
language=user_input.language,
|
||||
agent_id=user_input.agent_id,
|
||||
extra_system_prompt=user_input.extra_system_prompt,
|
||||
)
|
||||
speech = conversation_result.response.speech.get("plain", {}).get(
|
||||
"speech", ""
|
||||
)
|
||||
else:
|
||||
# Fall back to pipeline conversation agent
|
||||
conversation_result = await conversation.async_converse(
|
||||
hass=self.hass,
|
||||
text=user_input.text,
|
||||
conversation_id=user_input.conversation_id,
|
||||
device_id=user_input.device_id,
|
||||
context=user_input.context,
|
||||
language=user_input.language,
|
||||
agent_id=user_input.agent_id,
|
||||
extra_system_prompt=user_input.extra_system_prompt,
|
||||
)
|
||||
speech = conversation_result.response.speech.get("plain", {}).get(
|
||||
"speech", ""
|
||||
)
|
||||
|
||||
except Exception as src_error:
|
||||
_LOGGER.exception("Unexpected error during intent recognition")
|
||||
|
@ -23,7 +23,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: AuroraAbbConfigEntry) ->
|
||||
|
||||
comport = entry.data[CONF_PORT]
|
||||
address = entry.data[CONF_ADDRESS]
|
||||
coordinator = AuroraAbbDataUpdateCoordinator(hass, comport, address)
|
||||
coordinator = AuroraAbbDataUpdateCoordinator(hass, entry, comport, address)
|
||||
await coordinator.async_config_entry_first_refresh()
|
||||
|
||||
entry.runtime_data = coordinator
|
||||
|
@ -21,12 +21,26 @@ type AuroraAbbConfigEntry = ConfigEntry[AuroraAbbDataUpdateCoordinator]
|
||||
class AuroraAbbDataUpdateCoordinator(DataUpdateCoordinator[dict[str, float]]):
|
||||
"""Class to manage fetching AuroraAbbPowerone data."""
|
||||
|
||||
def __init__(self, hass: HomeAssistant, comport: str, address: int) -> None:
|
||||
config_entry: AuroraAbbConfigEntry
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
hass: HomeAssistant,
|
||||
config_entry: AuroraAbbConfigEntry,
|
||||
comport: str,
|
||||
address: int,
|
||||
) -> None:
|
||||
"""Initialize the data update coordinator."""
|
||||
self.available_prev = False
|
||||
self.available = False
|
||||
self.client = AuroraSerialClient(address, comport, parity="N", timeout=1)
|
||||
super().__init__(hass, _LOGGER, name=DOMAIN, update_interval=SCAN_INTERVAL)
|
||||
super().__init__(
|
||||
hass,
|
||||
_LOGGER,
|
||||
config_entry=config_entry,
|
||||
name=DOMAIN,
|
||||
update_interval=SCAN_INTERVAL,
|
||||
)
|
||||
|
||||
def _update_data(self) -> dict[str, float]:
|
||||
"""Fetch new state data for the sensors.
|
||||
|
@ -45,7 +45,7 @@ async def async_setup_entry(
|
||||
# Initiate a Data Update Coordinator for each service
|
||||
for service in services:
|
||||
service["coordinator"] = AussieBroadbandDataUpdateCoordinator(
|
||||
hass, client, service["service_id"]
|
||||
hass, entry, client, service["service_id"]
|
||||
)
|
||||
await service["coordinator"].async_config_entry_first_refresh()
|
||||
|
||||
|
@ -34,11 +34,20 @@ type AussieBroadbandConfigEntry = ConfigEntry[list[AussieBroadbandServiceData]]
|
||||
class AussieBroadbandDataUpdateCoordinator(DataUpdateCoordinator[dict[str, Any]]):
|
||||
"""Aussie Broadand data update coordinator."""
|
||||
|
||||
def __init__(self, hass: HomeAssistant, client: AussieBB, service_id: str) -> None:
|
||||
config_entry: AussieBroadbandConfigEntry
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
hass: HomeAssistant,
|
||||
config_entry: AussieBroadbandConfigEntry,
|
||||
client: AussieBB,
|
||||
service_id: str,
|
||||
) -> None:
|
||||
"""Initialize Atag coordinator."""
|
||||
super().__init__(
|
||||
hass,
|
||||
_LOGGER,
|
||||
config_entry=config_entry,
|
||||
name=f"Aussie Broadband {service_id}",
|
||||
update_interval=timedelta(minutes=DEFAULT_UPDATE_INTERVAL),
|
||||
)
|
||||
|
@ -6,18 +6,15 @@ import asyncio
|
||||
|
||||
from autarco import Autarco, AutarcoConnectionError
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_EMAIL, CONF_PASSWORD, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import ConfigEntryNotReady
|
||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
|
||||
from .coordinator import AutarcoDataUpdateCoordinator
|
||||
from .coordinator import AutarcoConfigEntry, AutarcoDataUpdateCoordinator
|
||||
|
||||
PLATFORMS: list[Platform] = [Platform.SENSOR]
|
||||
|
||||
type AutarcoConfigEntry = ConfigEntry[list[AutarcoDataUpdateCoordinator]]
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, entry: AutarcoConfigEntry) -> bool:
|
||||
"""Set up Autarco from a config entry."""
|
||||
@ -34,7 +31,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: AutarcoConfigEntry) -> b
|
||||
raise ConfigEntryNotReady from err
|
||||
|
||||
coordinators: list[AutarcoDataUpdateCoordinator] = [
|
||||
AutarcoDataUpdateCoordinator(hass, client, site) for site in account_sites
|
||||
AutarcoDataUpdateCoordinator(hass, entry, client, site)
|
||||
for site in account_sites
|
||||
]
|
||||
|
||||
await asyncio.gather(
|
||||
|
@ -22,6 +22,8 @@ from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, Upda
|
||||
|
||||
from .const import DOMAIN, LOGGER, SCAN_INTERVAL
|
||||
|
||||
type AutarcoConfigEntry = ConfigEntry[list[AutarcoDataUpdateCoordinator]]
|
||||
|
||||
|
||||
class AutarcoData(NamedTuple):
|
||||
"""Class for defining data in dict."""
|
||||
@ -35,11 +37,12 @@ class AutarcoData(NamedTuple):
|
||||
class AutarcoDataUpdateCoordinator(DataUpdateCoordinator[AutarcoData]):
|
||||
"""Class to manage fetching Autarco data from the API."""
|
||||
|
||||
config_entry: ConfigEntry
|
||||
config_entry: AutarcoConfigEntry
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
hass: HomeAssistant,
|
||||
config_entry: AutarcoConfigEntry,
|
||||
client: Autarco,
|
||||
account_site: AccountSite,
|
||||
) -> None:
|
||||
@ -47,6 +50,7 @@ class AutarcoDataUpdateCoordinator(DataUpdateCoordinator[AutarcoData]):
|
||||
super().__init__(
|
||||
hass,
|
||||
LOGGER,
|
||||
config_entry=config_entry,
|
||||
name=DOMAIN,
|
||||
update_interval=SCAN_INTERVAL,
|
||||
)
|
||||
|
@ -6,7 +6,7 @@ from typing import Any
|
||||
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from . import AutarcoConfigEntry, AutarcoDataUpdateCoordinator
|
||||
from .coordinator import AutarcoConfigEntry, AutarcoDataUpdateCoordinator
|
||||
|
||||
|
||||
async def async_get_config_entry_diagnostics(
|
||||
|
@ -20,9 +20,8 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.typing import StateType
|
||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||
|
||||
from . import AutarcoConfigEntry
|
||||
from .const import DOMAIN
|
||||
from .coordinator import AutarcoDataUpdateCoordinator
|
||||
from .coordinator import AutarcoConfigEntry, AutarcoDataUpdateCoordinator
|
||||
|
||||
|
||||
@dataclass(frozen=True, kw_only=True)
|
||||
|
@ -9,9 +9,7 @@ from homeassistant.const import Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from .const import CONF_PAT, CONF_PROJECT
|
||||
from .coordinator import AzureDevOpsDataUpdateCoordinator
|
||||
|
||||
type AzureDevOpsConfigEntry = ConfigEntry[AzureDevOpsDataUpdateCoordinator]
|
||||
from .coordinator import AzureDevOpsConfigEntry, AzureDevOpsDataUpdateCoordinator
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@ -22,11 +20,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: AzureDevOpsConfigEntry)
|
||||
"""Set up Azure DevOps from a config entry."""
|
||||
|
||||
# Create the data update coordinator
|
||||
coordinator = AzureDevOpsDataUpdateCoordinator(
|
||||
hass,
|
||||
_LOGGER,
|
||||
entry=entry,
|
||||
)
|
||||
coordinator = AzureDevOpsDataUpdateCoordinator(hass, entry, _LOGGER)
|
||||
|
||||
# Store the coordinator in runtime data
|
||||
entry.runtime_data = coordinator
|
||||
|
@ -28,6 +28,8 @@ from .data import AzureDevOpsData
|
||||
BUILDS_QUERY: Final = "?queryOrder=queueTimeDescending&maxBuildsPerDefinition=1"
|
||||
IGNORED_CATEGORIES: Final[list[Category]] = [Category.COMPLETED, Category.REMOVED]
|
||||
|
||||
type AzureDevOpsConfigEntry = ConfigEntry[AzureDevOpsDataUpdateCoordinator]
|
||||
|
||||
|
||||
def ado_exception_none_handler(func: Callable) -> Callable:
|
||||
"""Handle exceptions or None to always return a value or raise."""
|
||||
@ -50,28 +52,29 @@ class AzureDevOpsDataUpdateCoordinator(DataUpdateCoordinator[AzureDevOpsData]):
|
||||
"""Class to manage and fetch Azure DevOps data."""
|
||||
|
||||
client: DevOpsClient
|
||||
config_entry: AzureDevOpsConfigEntry
|
||||
organization: str
|
||||
project: Project
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
hass: HomeAssistant,
|
||||
config_entry: AzureDevOpsConfigEntry,
|
||||
logger: logging.Logger,
|
||||
*,
|
||||
entry: ConfigEntry,
|
||||
) -> None:
|
||||
"""Initialize global Azure DevOps data updater."""
|
||||
self.title = entry.title
|
||||
self.title = config_entry.title
|
||||
|
||||
super().__init__(
|
||||
hass=hass,
|
||||
logger=logger,
|
||||
config_entry=config_entry,
|
||||
name=DOMAIN,
|
||||
update_interval=timedelta(seconds=300),
|
||||
)
|
||||
|
||||
self.client = DevOpsClient(session=async_get_clientsession(hass))
|
||||
self.organization = entry.data[CONF_ORG]
|
||||
self.organization = config_entry.data[CONF_ORG]
|
||||
|
||||
@ado_exception_none_handler
|
||||
async def authorize(
|
||||
|
@ -21,8 +21,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.typing import StateType
|
||||
from homeassistant.util import dt as dt_util
|
||||
|
||||
from . import AzureDevOpsConfigEntry
|
||||
from .coordinator import AzureDevOpsDataUpdateCoordinator
|
||||
from .coordinator import AzureDevOpsConfigEntry, AzureDevOpsDataUpdateCoordinator
|
||||
from .entity import AzureDevOpsEntity
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
@ -85,7 +85,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: BlinkConfigEntry) -> boo
|
||||
auth_data = deepcopy(dict(entry.data))
|
||||
blink.auth = Auth(auth_data, no_prompt=True, session=session)
|
||||
blink.refresh_rate = entry.options.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL)
|
||||
coordinator = BlinkUpdateCoordinator(hass, blink)
|
||||
coordinator = BlinkUpdateCoordinator(hass, entry, blink)
|
||||
|
||||
try:
|
||||
await blink.start()
|
||||
|
@ -23,12 +23,17 @@ type BlinkConfigEntry = ConfigEntry[BlinkUpdateCoordinator]
|
||||
class BlinkUpdateCoordinator(DataUpdateCoordinator[dict[str, Any]]):
|
||||
"""BlinkUpdateCoordinator - In charge of downloading the data for a site."""
|
||||
|
||||
def __init__(self, hass: HomeAssistant, api: Blink) -> None:
|
||||
config_entry: BlinkConfigEntry
|
||||
|
||||
def __init__(
|
||||
self, hass: HomeAssistant, config_entry: BlinkConfigEntry, api: Blink
|
||||
) -> None:
|
||||
"""Initialize the data service."""
|
||||
self.api = api
|
||||
super().__init__(
|
||||
hass,
|
||||
_LOGGER,
|
||||
config_entry=config_entry,
|
||||
name=DOMAIN,
|
||||
update_interval=timedelta(seconds=SCAN_INTERVAL),
|
||||
)
|
||||
|
@ -7,14 +7,11 @@ from typing import Final
|
||||
from aiohttp import CookieJar
|
||||
from pybravia import BraviaClient
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_HOST, CONF_MAC, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.aiohttp_client import async_create_clientsession
|
||||
|
||||
from .coordinator import BraviaTVCoordinator
|
||||
|
||||
BraviaTVConfigEntry = ConfigEntry[BraviaTVCoordinator]
|
||||
from .coordinator import BraviaTVConfigEntry, BraviaTVCoordinator
|
||||
|
||||
PLATFORMS: Final[list[Platform]] = [
|
||||
Platform.BUTTON,
|
||||
@ -36,8 +33,8 @@ async def async_setup_entry(
|
||||
client = BraviaClient(host, mac, session=session)
|
||||
coordinator = BraviaTVCoordinator(
|
||||
hass=hass,
|
||||
config_entry=config_entry,
|
||||
client=client,
|
||||
config=config_entry.data,
|
||||
)
|
||||
config_entry.async_on_unload(config_entry.add_update_listener(update_listener))
|
||||
|
||||
|
@ -14,8 +14,7 @@ from homeassistant.const import EntityCategory
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from . import BraviaTVConfigEntry
|
||||
from .coordinator import BraviaTVCoordinator
|
||||
from .coordinator import BraviaTVConfigEntry, BraviaTVCoordinator
|
||||
from .entity import BraviaTVEntity
|
||||
|
||||
|
||||
|
@ -6,7 +6,6 @@ from collections.abc import Awaitable, Callable, Coroutine, Iterable
|
||||
from datetime import datetime, timedelta
|
||||
from functools import wraps
|
||||
import logging
|
||||
from types import MappingProxyType
|
||||
from typing import Any, Concatenate, Final
|
||||
|
||||
from pybravia import (
|
||||
@ -20,6 +19,7 @@ from pybravia import (
|
||||
)
|
||||
|
||||
from homeassistant.components.media_player import MediaType
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_CLIENT_ID, CONF_PIN
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import ConfigEntryAuthFailed
|
||||
@ -39,6 +39,8 @@ _LOGGER = logging.getLogger(__name__)
|
||||
|
||||
SCAN_INTERVAL: Final = timedelta(seconds=10)
|
||||
|
||||
type BraviaTVConfigEntry = ConfigEntry["BraviaTVCoordinator"]
|
||||
|
||||
|
||||
def catch_braviatv_errors[_BraviaTVCoordinatorT: BraviaTVCoordinator, **_P](
|
||||
func: Callable[Concatenate[_BraviaTVCoordinatorT, _P], Awaitable[None]],
|
||||
@ -64,19 +66,21 @@ def catch_braviatv_errors[_BraviaTVCoordinatorT: BraviaTVCoordinator, **_P](
|
||||
class BraviaTVCoordinator(DataUpdateCoordinator[None]):
|
||||
"""Representation of a Bravia TV Coordinator."""
|
||||
|
||||
config_entry: BraviaTVConfigEntry
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
hass: HomeAssistant,
|
||||
config_entry: BraviaTVConfigEntry,
|
||||
client: BraviaClient,
|
||||
config: MappingProxyType[str, Any],
|
||||
) -> None:
|
||||
"""Initialize Bravia TV Client."""
|
||||
|
||||
self.client = client
|
||||
self.pin = config[CONF_PIN]
|
||||
self.use_psk = config.get(CONF_USE_PSK, False)
|
||||
self.client_id = config.get(CONF_CLIENT_ID, LEGACY_CLIENT_ID)
|
||||
self.nickname = config.get(CONF_NICKNAME, NICKNAME_PREFIX)
|
||||
self.pin = config_entry.data[CONF_PIN]
|
||||
self.use_psk = config_entry.data.get(CONF_USE_PSK, False)
|
||||
self.client_id = config_entry.data.get(CONF_CLIENT_ID, LEGACY_CLIENT_ID)
|
||||
self.nickname = config_entry.data.get(CONF_NICKNAME, NICKNAME_PREFIX)
|
||||
self.source: str | None = None
|
||||
self.source_list: list[str] = []
|
||||
self.source_map: dict[str, dict] = {}
|
||||
@ -98,6 +102,7 @@ class BraviaTVCoordinator(DataUpdateCoordinator[None]):
|
||||
super().__init__(
|
||||
hass,
|
||||
_LOGGER,
|
||||
config_entry=config_entry,
|
||||
name=DOMAIN,
|
||||
update_interval=SCAN_INTERVAL,
|
||||
request_refresh_debouncer=Debouncer(
|
||||
|
@ -6,7 +6,7 @@ from homeassistant.components.diagnostics import async_redact_data
|
||||
from homeassistant.const import CONF_MAC, CONF_PIN
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from . import BraviaTVConfigEntry
|
||||
from .coordinator import BraviaTVConfigEntry
|
||||
|
||||
TO_REDACT = {CONF_MAC, CONF_PIN, "macAddr"}
|
||||
|
||||
|
@ -3,8 +3,8 @@
|
||||
from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC, DeviceInfo
|
||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||
|
||||
from . import BraviaTVCoordinator
|
||||
from .const import ATTR_MANUFACTURER, DOMAIN
|
||||
from .coordinator import BraviaTVCoordinator
|
||||
|
||||
|
||||
class BraviaTVEntity(CoordinatorEntity[BraviaTVCoordinator]):
|
||||
|
@ -18,8 +18,8 @@ from homeassistant.components.media_player import (
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from . import BraviaTVConfigEntry
|
||||
from .const import SourceType
|
||||
from .coordinator import BraviaTVConfigEntry
|
||||
from .entity import BraviaTVEntity
|
||||
|
||||
|
||||
|
@ -9,7 +9,7 @@ from homeassistant.components.remote import ATTR_NUM_REPEATS, RemoteEntity
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from . import BraviaTVConfigEntry
|
||||
from .coordinator import BraviaTVConfigEntry
|
||||
from .entity import BraviaTVEntity
|
||||
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
},
|
||||
"data_description": {
|
||||
"email": "[%key:component::bring::config::step::user::data_description::email%]",
|
||||
"password": "[%key:component::bring::config::step::user::data_description::email%]"
|
||||
"password": "[%key:component::bring::config::step::user::data_description::password%]"
|
||||
}
|
||||
},
|
||||
"reconfigure": {
|
||||
@ -37,7 +37,7 @@
|
||||
},
|
||||
"data_description": {
|
||||
"email": "[%key:component::bring::config::step::user::data_description::email%]",
|
||||
"password": "[%key:component::bring::config::step::user::data_description::email%]"
|
||||
"password": "[%key:component::bring::config::step::user::data_description::password%]"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -5,17 +5,14 @@ from __future__ import annotations
|
||||
from brother import Brother, SnmpError
|
||||
|
||||
from homeassistant.components.snmp import async_get_snmp_engine
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_HOST, CONF_TYPE, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import ConfigEntryNotReady
|
||||
|
||||
from .coordinator import BrotherDataUpdateCoordinator
|
||||
from .coordinator import BrotherConfigEntry, BrotherDataUpdateCoordinator
|
||||
|
||||
PLATFORMS = [Platform.SENSOR]
|
||||
|
||||
type BrotherConfigEntry = ConfigEntry[BrotherDataUpdateCoordinator]
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, entry: BrotherConfigEntry) -> bool:
|
||||
"""Set up Brother from a config entry."""
|
||||
@ -30,7 +27,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: BrotherConfigEntry) -> b
|
||||
except (ConnectionError, SnmpError, TimeoutError) as error:
|
||||
raise ConfigEntryNotReady from error
|
||||
|
||||
coordinator = BrotherDataUpdateCoordinator(hass, brother)
|
||||
coordinator = BrotherDataUpdateCoordinator(hass, entry, brother)
|
||||
await coordinator.async_config_entry_first_refresh()
|
||||
|
||||
entry.runtime_data = coordinator
|
||||
|
@ -5,6 +5,7 @@ import logging
|
||||
|
||||
from brother import Brother, BrotherSensors, SnmpError, UnsupportedModelError
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||
|
||||
@ -12,17 +13,24 @@ from .const import DOMAIN, UPDATE_INTERVAL
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
type BrotherConfigEntry = ConfigEntry[BrotherDataUpdateCoordinator]
|
||||
|
||||
|
||||
class BrotherDataUpdateCoordinator(DataUpdateCoordinator[BrotherSensors]):
|
||||
"""Class to manage fetching Brother data from the printer."""
|
||||
|
||||
def __init__(self, hass: HomeAssistant, brother: Brother) -> None:
|
||||
config_entry: BrotherConfigEntry
|
||||
|
||||
def __init__(
|
||||
self, hass: HomeAssistant, config_entry: BrotherConfigEntry, brother: Brother
|
||||
) -> None:
|
||||
"""Initialize."""
|
||||
self.brother = brother
|
||||
|
||||
super().__init__(
|
||||
hass,
|
||||
_LOGGER,
|
||||
config_entry=config_entry,
|
||||
name=DOMAIN,
|
||||
update_interval=UPDATE_INTERVAL,
|
||||
)
|
||||
|
@ -7,7 +7,7 @@ from typing import Any
|
||||
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from . import BrotherConfigEntry
|
||||
from .coordinator import BrotherConfigEntry
|
||||
|
||||
|
||||
async def async_get_config_entry_diagnostics(
|
||||
|
@ -24,8 +24,8 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.typing import StateType
|
||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||
|
||||
from . import BrotherConfigEntry, BrotherDataUpdateCoordinator
|
||||
from .const import DOMAIN
|
||||
from .coordinator import BrotherConfigEntry, BrotherDataUpdateCoordinator
|
||||
|
||||
ATTR_COUNTER = "counter"
|
||||
ATTR_REMAINING_PAGES = "remaining_pages"
|
||||
|
@ -38,6 +38,7 @@ class BSBLanUpdateCoordinator(DataUpdateCoordinator[BSBLanCoordinatorData]):
|
||||
super().__init__(
|
||||
hass,
|
||||
logger=LOGGER,
|
||||
config_entry=config_entry,
|
||||
name=f"{DOMAIN}_{config_entry.data[CONF_HOST]}",
|
||||
update_interval=self._get_update_interval(),
|
||||
)
|
||||
|
@ -4,23 +4,20 @@ from __future__ import annotations
|
||||
|
||||
from aioelectricitymaps import ElectricityMaps
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_API_KEY, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
|
||||
from .coordinator import CO2SignalCoordinator
|
||||
from .coordinator import CO2SignalConfigEntry, CO2SignalCoordinator
|
||||
|
||||
PLATFORMS = [Platform.SENSOR]
|
||||
|
||||
type CO2SignalConfigEntry = ConfigEntry[CO2SignalCoordinator]
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, entry: CO2SignalConfigEntry) -> bool:
|
||||
"""Set up CO2 Signal from a config entry."""
|
||||
session = async_get_clientsession(hass)
|
||||
coordinator = CO2SignalCoordinator(
|
||||
hass, ElectricityMaps(token=entry.data[CONF_API_KEY], session=session)
|
||||
hass, entry, ElectricityMaps(token=entry.data[CONF_API_KEY], session=session)
|
||||
)
|
||||
await coordinator.async_config_entry_first_refresh()
|
||||
|
||||
|
@ -22,16 +22,27 @@ from .helpers import fetch_latest_carbon_intensity
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
type CO2SignalConfigEntry = ConfigEntry[CO2SignalCoordinator]
|
||||
|
||||
|
||||
class CO2SignalCoordinator(DataUpdateCoordinator[CarbonIntensityResponse]):
|
||||
"""Data update coordinator."""
|
||||
|
||||
config_entry: ConfigEntry
|
||||
config_entry: CO2SignalConfigEntry
|
||||
|
||||
def __init__(self, hass: HomeAssistant, client: ElectricityMaps) -> None:
|
||||
def __init__(
|
||||
self,
|
||||
hass: HomeAssistant,
|
||||
config_entry: CO2SignalConfigEntry,
|
||||
client: ElectricityMaps,
|
||||
) -> None:
|
||||
"""Initialize the coordinator."""
|
||||
super().__init__(
|
||||
hass, _LOGGER, name=DOMAIN, update_interval=timedelta(minutes=15)
|
||||
hass,
|
||||
_LOGGER,
|
||||
config_entry=config_entry,
|
||||
name=DOMAIN,
|
||||
update_interval=timedelta(minutes=15),
|
||||
)
|
||||
self.client = client
|
||||
|
||||
|
@ -9,7 +9,7 @@ from homeassistant.components.diagnostics import async_redact_data
|
||||
from homeassistant.const import CONF_API_KEY
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from . import CO2SignalConfigEntry
|
||||
from .coordinator import CO2SignalConfigEntry
|
||||
|
||||
TO_REDACT = {CONF_API_KEY}
|
||||
|
||||
|
@ -18,9 +18,8 @@ from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||
|
||||
from . import CO2SignalConfigEntry
|
||||
from .const import ATTRIBUTION, DOMAIN
|
||||
from .coordinator import CO2SignalCoordinator
|
||||
from .coordinator import CO2SignalConfigEntry, CO2SignalCoordinator
|
||||
|
||||
|
||||
@dataclass(frozen=True, kw_only=True)
|
||||
|
@ -4,7 +4,6 @@ from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from datetime import datetime, timedelta
|
||||
from typing import cast
|
||||
|
||||
from homeassistant.components.binary_sensor import BinarySensorEntity
|
||||
from homeassistant.const import (
|
||||
@ -43,9 +42,7 @@ async def async_setup_platform(
|
||||
if not discovery_info:
|
||||
return
|
||||
|
||||
discovery_info = cast(DiscoveryInfoType, discovery_info)
|
||||
binary_sensor_config = discovery_info
|
||||
|
||||
command: str = binary_sensor_config[CONF_COMMAND]
|
||||
payload_off: str = binary_sensor_config[CONF_PAYLOAD_OFF]
|
||||
payload_on: str = binary_sensor_config[CONF_PAYLOAD_ON]
|
||||
|
@ -4,7 +4,7 @@ from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from datetime import datetime, timedelta
|
||||
from typing import TYPE_CHECKING, Any, cast
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from homeassistant.components.cover import CoverEntity
|
||||
from homeassistant.const import (
|
||||
@ -41,7 +41,6 @@ async def async_setup_platform(
|
||||
return
|
||||
|
||||
covers = []
|
||||
discovery_info = cast(DiscoveryInfoType, discovery_info)
|
||||
entities: dict[str, dict[str, Any]] = {
|
||||
slugify(discovery_info[CONF_NAME]): discovery_info
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import subprocess
|
||||
from typing import Any, cast
|
||||
from typing import Any
|
||||
|
||||
from homeassistant.components.notify import BaseNotificationService
|
||||
from homeassistant.const import CONF_COMMAND
|
||||
@ -26,7 +26,6 @@ def get_service(
|
||||
if not discovery_info:
|
||||
return None
|
||||
|
||||
discovery_info = cast(DiscoveryInfoType, discovery_info)
|
||||
notify_config = discovery_info
|
||||
command: str = notify_config[CONF_COMMAND]
|
||||
timeout: int = notify_config[CONF_COMMAND_TIMEOUT]
|
||||
|
@ -6,7 +6,7 @@ import asyncio
|
||||
from collections.abc import Mapping
|
||||
from datetime import datetime, timedelta
|
||||
import json
|
||||
from typing import Any, cast
|
||||
from typing import Any
|
||||
|
||||
from jsonpath import jsonpath
|
||||
|
||||
@ -51,9 +51,7 @@ async def async_setup_platform(
|
||||
if not discovery_info:
|
||||
return
|
||||
|
||||
discovery_info = cast(DiscoveryInfoType, discovery_info)
|
||||
sensor_config = discovery_info
|
||||
|
||||
command: str = sensor_config[CONF_COMMAND]
|
||||
command_timeout: int = sensor_config[CONF_COMMAND_TIMEOUT]
|
||||
json_attributes: list[str] | None = sensor_config.get(CONF_JSON_ATTRIBUTES)
|
||||
|
@ -4,7 +4,7 @@ from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from datetime import datetime, timedelta
|
||||
from typing import TYPE_CHECKING, Any, cast
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from homeassistant.components.switch import ENTITY_ID_FORMAT, SwitchEntity
|
||||
from homeassistant.const import (
|
||||
@ -40,7 +40,6 @@ async def async_setup_platform(
|
||||
return
|
||||
|
||||
switches = []
|
||||
discovery_info = cast(DiscoveryInfoType, discovery_info)
|
||||
entities: dict[str, dict[str, Any]] = {
|
||||
slugify(discovery_info[CONF_NAME]): discovery_info
|
||||
}
|
||||
|
@ -79,6 +79,9 @@ async def async_converse(
|
||||
extra_system_prompt: str | None = None,
|
||||
) -> ConversationResult:
|
||||
"""Process text and get intent."""
|
||||
if agent_id is None:
|
||||
agent_id = HOME_ASSISTANT_AGENT
|
||||
|
||||
agent = async_get_agent(hass, agent_id)
|
||||
|
||||
if agent is None:
|
||||
|
@ -1,9 +1,11 @@
|
||||
"""Conversation history."""
|
||||
"""Conversation chat log."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from collections.abc import AsyncGenerator, Generator
|
||||
from contextlib import contextmanager
|
||||
from contextvars import ContextVar
|
||||
from dataclasses import dataclass, field, replace
|
||||
import logging
|
||||
|
||||
@ -19,10 +21,14 @@ from . import trace
|
||||
from .const import DOMAIN
|
||||
from .models import ConversationInput, ConversationResult
|
||||
|
||||
DATA_CHAT_HISTORY: HassKey[dict[str, ChatLog]] = HassKey("conversation_chat_log")
|
||||
DATA_CHAT_LOGS: HassKey[dict[str, ChatLog]] = HassKey("conversation_chat_logs")
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
current_chat_log: ContextVar[ChatLog | None] = ContextVar(
|
||||
"current_chat_log", default=None
|
||||
)
|
||||
|
||||
|
||||
@contextmanager
|
||||
def async_get_chat_log(
|
||||
@ -31,41 +37,50 @@ def async_get_chat_log(
|
||||
user_input: ConversationInput | None = None,
|
||||
) -> Generator[ChatLog]:
|
||||
"""Return chat log for a specific chat session."""
|
||||
all_history = hass.data.get(DATA_CHAT_HISTORY)
|
||||
if all_history is None:
|
||||
all_history = {}
|
||||
hass.data[DATA_CHAT_HISTORY] = all_history
|
||||
if chat_log := current_chat_log.get():
|
||||
# If a chat log is already active and it's the requested conversation ID,
|
||||
# return that. We won't update the last updated time in this case.
|
||||
if chat_log.conversation_id == session.conversation_id:
|
||||
yield chat_log
|
||||
return
|
||||
|
||||
history = all_history.get(session.conversation_id)
|
||||
all_chat_logs = hass.data.get(DATA_CHAT_LOGS)
|
||||
if all_chat_logs is None:
|
||||
all_chat_logs = {}
|
||||
hass.data[DATA_CHAT_LOGS] = all_chat_logs
|
||||
|
||||
if history:
|
||||
history = replace(history, content=history.content.copy())
|
||||
chat_log = all_chat_logs.get(session.conversation_id)
|
||||
|
||||
if chat_log:
|
||||
chat_log = replace(chat_log, content=chat_log.content.copy())
|
||||
else:
|
||||
history = ChatLog(hass, session.conversation_id)
|
||||
chat_log = ChatLog(hass, session.conversation_id)
|
||||
|
||||
if user_input is not None:
|
||||
history.async_add_user_content(UserContent(content=user_input.text))
|
||||
chat_log.async_add_user_content(UserContent(content=user_input.text))
|
||||
|
||||
last_message = history.content[-1]
|
||||
last_message = chat_log.content[-1]
|
||||
|
||||
yield history
|
||||
token = current_chat_log.set(chat_log)
|
||||
yield chat_log
|
||||
current_chat_log.reset(token)
|
||||
|
||||
if history.content[-1] is last_message:
|
||||
if chat_log.content[-1] is last_message:
|
||||
LOGGER.debug(
|
||||
"History opened but no assistant message was added, ignoring update"
|
||||
"Chat Log opened but no assistant message was added, ignoring update"
|
||||
)
|
||||
return
|
||||
|
||||
if session.conversation_id not in all_history:
|
||||
if session.conversation_id not in all_chat_logs:
|
||||
|
||||
@callback
|
||||
def do_cleanup() -> None:
|
||||
"""Handle cleanup."""
|
||||
all_history.pop(session.conversation_id)
|
||||
all_chat_logs.pop(session.conversation_id)
|
||||
|
||||
session.async_on_cleanup(do_cleanup)
|
||||
|
||||
all_history[session.conversation_id] = history
|
||||
all_chat_logs[session.conversation_id] = chat_log
|
||||
|
||||
|
||||
class ConverseError(HomeAssistantError):
|
||||
@ -112,7 +127,7 @@ class AssistantContent:
|
||||
|
||||
role: str = field(init=False, default="assistant")
|
||||
agent_id: str
|
||||
content: str
|
||||
content: str | None = None
|
||||
tool_calls: list[llm.ToolInput] | None = None
|
||||
|
||||
|
||||
@ -143,6 +158,7 @@ class ChatLog:
|
||||
@callback
|
||||
def async_add_user_content(self, content: UserContent) -> None:
|
||||
"""Add user content to the log."""
|
||||
LOGGER.debug("Adding user content: %s", content)
|
||||
self.content.append(content)
|
||||
|
||||
@callback
|
||||
@ -150,14 +166,24 @@ class ChatLog:
|
||||
self, content: AssistantContent
|
||||
) -> None:
|
||||
"""Add assistant content to the log."""
|
||||
LOGGER.debug("Adding assistant content: %s", content)
|
||||
if content.tool_calls is not None:
|
||||
raise ValueError("Tool calls not allowed")
|
||||
self.content.append(content)
|
||||
|
||||
async def async_add_assistant_content(
|
||||
self, content: AssistantContent
|
||||
self,
|
||||
content: AssistantContent,
|
||||
/,
|
||||
tool_call_tasks: dict[str, asyncio.Task] | None = None,
|
||||
) -> AsyncGenerator[ToolResultContent]:
|
||||
"""Add assistant content."""
|
||||
"""Add assistant content and execute tool calls.
|
||||
|
||||
tool_call_tasks can contains tasks for tool calls that are already in progress.
|
||||
|
||||
This method is an async generator and will yield the tool results as they come in.
|
||||
"""
|
||||
LOGGER.debug("Adding assistant content: %s", content)
|
||||
self.content.append(content)
|
||||
|
||||
if content.tool_calls is None:
|
||||
@ -166,13 +192,22 @@ class ChatLog:
|
||||
if self.llm_api is None:
|
||||
raise ValueError("No LLM API configured")
|
||||
|
||||
if tool_call_tasks is None:
|
||||
tool_call_tasks = {}
|
||||
for tool_input in content.tool_calls:
|
||||
if tool_input.id not in tool_call_tasks:
|
||||
tool_call_tasks[tool_input.id] = self.hass.async_create_task(
|
||||
self.llm_api.async_call_tool(tool_input),
|
||||
name=f"llm_tool_{tool_input.id}",
|
||||
)
|
||||
|
||||
for tool_input in content.tool_calls:
|
||||
LOGGER.debug(
|
||||
"Tool call: %s(%s)", tool_input.tool_name, tool_input.tool_args
|
||||
)
|
||||
|
||||
try:
|
||||
tool_result = await self.llm_api.async_call_tool(tool_input)
|
||||
tool_result = await tool_call_tasks[tool_input.id]
|
||||
except (HomeAssistantError, vol.Invalid) as e:
|
||||
tool_result = {"error": type(e).__name__}
|
||||
if str(e):
|
||||
|
@ -381,7 +381,7 @@ class DefaultAgent(ConversationEntity):
|
||||
speech: str = response.speech.get("plain", {}).get("speech", "")
|
||||
chat_log.async_add_assistant_content_without_tools(
|
||||
AssistantContent(
|
||||
agent_id=user_input.agent_id, # type: ignore[arg-type]
|
||||
agent_id=user_input.agent_id,
|
||||
content=speech,
|
||||
)
|
||||
)
|
||||
|
@ -195,7 +195,7 @@ async def websocket_hass_agent_debug(
|
||||
conversation_id=None,
|
||||
device_id=msg.get("device_id"),
|
||||
language=msg.get("language", hass.config.language),
|
||||
agent_id=None,
|
||||
agent_id=agent.entity_id,
|
||||
)
|
||||
result_dict: dict[str, Any] | None = None
|
||||
|
||||
|
@ -37,7 +37,7 @@ class ConversationInput:
|
||||
language: str
|
||||
"""Language of the request."""
|
||||
|
||||
agent_id: str | None = None
|
||||
agent_id: str
|
||||
"""Agent to use for processing."""
|
||||
|
||||
extra_system_prompt: str | None = None
|
||||
|
@ -6,18 +6,15 @@ from pydiscovergy import Discovergy
|
||||
from pydiscovergy.authentication import BasicAuth
|
||||
import pydiscovergy.error as discovergyError
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_EMAIL, CONF_PASSWORD, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
|
||||
from homeassistant.helpers.httpx_client import get_async_client
|
||||
|
||||
from .coordinator import DiscovergyUpdateCoordinator
|
||||
from .coordinator import DiscovergyConfigEntry, DiscovergyUpdateCoordinator
|
||||
|
||||
PLATFORMS = [Platform.SENSOR]
|
||||
|
||||
type DiscovergyConfigEntry = ConfigEntry[list[DiscovergyUpdateCoordinator]]
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, entry: DiscovergyConfigEntry) -> bool:
|
||||
"""Set up Discovergy from a config entry."""
|
||||
@ -46,6 +43,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: DiscovergyConfigEntry) -
|
||||
# so we have data when entities are added
|
||||
coordinator = DiscovergyUpdateCoordinator(
|
||||
hass=hass,
|
||||
config_entry=entry,
|
||||
meter=meter,
|
||||
discovergy_client=client,
|
||||
)
|
||||
|
@ -9,19 +9,25 @@ from pydiscovergy import Discovergy
|
||||
from pydiscovergy.error import DiscovergyClientError, HTTPError, InvalidLogin
|
||||
from pydiscovergy.models import Meter, Reading
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import ConfigEntryAuthFailed
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
type DiscovergyConfigEntry = ConfigEntry[list[DiscovergyUpdateCoordinator]]
|
||||
|
||||
|
||||
class DiscovergyUpdateCoordinator(DataUpdateCoordinator[Reading]):
|
||||
"""The Discovergy update coordinator."""
|
||||
|
||||
config_entry: DiscovergyConfigEntry
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
hass: HomeAssistant,
|
||||
config_entry: DiscovergyConfigEntry,
|
||||
meter: Meter,
|
||||
discovergy_client: Discovergy,
|
||||
) -> None:
|
||||
@ -32,6 +38,7 @@ class DiscovergyUpdateCoordinator(DataUpdateCoordinator[Reading]):
|
||||
super().__init__(
|
||||
hass,
|
||||
_LOGGER,
|
||||
config_entry=config_entry,
|
||||
name=f"Discovergy meter {meter.meter_id}",
|
||||
update_interval=timedelta(seconds=30),
|
||||
)
|
||||
|
@ -8,7 +8,7 @@ from typing import Any
|
||||
from homeassistant.components.diagnostics import async_redact_data
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from . import DiscovergyConfigEntry
|
||||
from .coordinator import DiscovergyConfigEntry
|
||||
|
||||
TO_REDACT_METER = {
|
||||
"serial_number",
|
||||
|
@ -24,9 +24,8 @@ from homeassistant.helpers.device_registry import DeviceInfo
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||
|
||||
from . import DiscovergyConfigEntry
|
||||
from .const import DOMAIN, MANUFACTURER
|
||||
from .coordinator import DiscovergyUpdateCoordinator
|
||||
from .coordinator import DiscovergyConfigEntry, DiscovergyUpdateCoordinator
|
||||
|
||||
PARALLEL_UPDATES = 0
|
||||
|
||||
|
@ -29,7 +29,7 @@ async def async_setup_entry(
|
||||
f"Unable to connect to Dremel 3D Printer: {ex}"
|
||||
) from ex
|
||||
|
||||
coordinator = Dremel3DPrinterDataUpdateCoordinator(hass, api)
|
||||
coordinator = Dremel3DPrinterDataUpdateCoordinator(hass, config_entry, api)
|
||||
await coordinator.async_config_entry_first_refresh()
|
||||
config_entry.runtime_data = coordinator
|
||||
platforms = list(PLATFORMS)
|
||||
|
@ -18,11 +18,14 @@ class Dremel3DPrinterDataUpdateCoordinator(DataUpdateCoordinator[None]):
|
||||
|
||||
config_entry: DremelConfigEntry
|
||||
|
||||
def __init__(self, hass: HomeAssistant, api: Dremel3DPrinter) -> None:
|
||||
def __init__(
|
||||
self, hass: HomeAssistant, config_entry: DremelConfigEntry, api: Dremel3DPrinter
|
||||
) -> None:
|
||||
"""Initialize Dremel 3D Printer data update coordinator."""
|
||||
super().__init__(
|
||||
hass=hass,
|
||||
logger=LOGGER,
|
||||
config_entry=config_entry,
|
||||
name=DOMAIN,
|
||||
update_interval=timedelta(seconds=10),
|
||||
)
|
||||
|
@ -16,7 +16,7 @@ async def async_setup_entry(
|
||||
device_registry = dr.async_get(hass)
|
||||
if device_registry.async_get_device(identifiers={(DOMAIN, entry.entry_id)}):
|
||||
device_registry.async_clear_config_entry(entry.entry_id)
|
||||
coordinator = DwdWeatherWarningsCoordinator(hass)
|
||||
coordinator = DwdWeatherWarningsCoordinator(hass, entry)
|
||||
await coordinator.async_config_entry_first_refresh()
|
||||
|
||||
entry.runtime_data = coordinator
|
||||
|
@ -28,10 +28,16 @@ class DwdWeatherWarningsCoordinator(DataUpdateCoordinator[None]):
|
||||
config_entry: DwdWeatherWarningsConfigEntry
|
||||
api: DwdWeatherWarningsAPI
|
||||
|
||||
def __init__(self, hass: HomeAssistant) -> None:
|
||||
def __init__(
|
||||
self, hass: HomeAssistant, config_entry: DwdWeatherWarningsConfigEntry
|
||||
) -> None:
|
||||
"""Initialize the dwd_weather_warnings coordinator."""
|
||||
super().__init__(
|
||||
hass, LOGGER, name=DOMAIN, update_interval=DEFAULT_SCAN_INTERVAL
|
||||
hass,
|
||||
LOGGER,
|
||||
config_entry=config_entry,
|
||||
name=DOMAIN,
|
||||
update_interval=DEFAULT_SCAN_INTERVAL,
|
||||
)
|
||||
|
||||
self._device_tracker = None
|
||||
|
@ -2,25 +2,22 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.device_registry import DeviceEntry
|
||||
|
||||
from .const import DOMAIN
|
||||
from .coordinator import EheimDigitalUpdateCoordinator
|
||||
from .coordinator import EheimDigitalConfigEntry, EheimDigitalUpdateCoordinator
|
||||
|
||||
PLATFORMS = [Platform.CLIMATE, Platform.LIGHT]
|
||||
|
||||
type EheimDigitalConfigEntry = ConfigEntry[EheimDigitalUpdateCoordinator]
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant, entry: EheimDigitalConfigEntry
|
||||
) -> bool:
|
||||
"""Set up EHEIM Digital from a config entry."""
|
||||
|
||||
coordinator = EheimDigitalUpdateCoordinator(hass)
|
||||
coordinator = EheimDigitalUpdateCoordinator(hass, entry)
|
||||
await coordinator.async_config_entry_first_refresh()
|
||||
entry.runtime_data = coordinator
|
||||
|
||||
|
@ -23,9 +23,8 @@ from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from . import EheimDigitalConfigEntry
|
||||
from .const import HEATER_BIO_MODE, HEATER_PRESET_TO_HEATER_MODE, HEATER_SMART_MODE
|
||||
from .coordinator import EheimDigitalUpdateCoordinator
|
||||
from .coordinator import EheimDigitalConfigEntry, EheimDigitalUpdateCoordinator
|
||||
from .entity import EheimDigitalEntity
|
||||
|
||||
# Coordinator is used to centralize the data updates
|
||||
|
@ -22,18 +22,26 @@ type AsyncSetupDeviceEntitiesCallback = Callable[
|
||||
[str | dict[str, EheimDigitalDevice]], None
|
||||
]
|
||||
|
||||
type EheimDigitalConfigEntry = ConfigEntry[EheimDigitalUpdateCoordinator]
|
||||
|
||||
|
||||
class EheimDigitalUpdateCoordinator(
|
||||
DataUpdateCoordinator[dict[str, EheimDigitalDevice]]
|
||||
):
|
||||
"""The EHEIM Digital data update coordinator."""
|
||||
|
||||
config_entry: ConfigEntry
|
||||
config_entry: EheimDigitalConfigEntry
|
||||
|
||||
def __init__(self, hass: HomeAssistant) -> None:
|
||||
def __init__(
|
||||
self, hass: HomeAssistant, config_entry: EheimDigitalConfigEntry
|
||||
) -> None:
|
||||
"""Initialize the EHEIM Digital data update coordinator."""
|
||||
super().__init__(
|
||||
hass, LOGGER, name=DOMAIN, update_interval=DEFAULT_SCAN_INTERVAL
|
||||
hass,
|
||||
LOGGER,
|
||||
config_entry=config_entry,
|
||||
name=DOMAIN,
|
||||
update_interval=DEFAULT_SCAN_INTERVAL,
|
||||
)
|
||||
self.hub = EheimDigitalHub(
|
||||
host=self.config_entry.data[CONF_HOST],
|
||||
|
@ -19,9 +19,8 @@ from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.util.color import brightness_to_value, value_to_brightness
|
||||
|
||||
from . import EheimDigitalConfigEntry
|
||||
from .const import EFFECT_DAYCL_MODE, EFFECT_TO_LIGHT_MODE
|
||||
from .coordinator import EheimDigitalUpdateCoordinator
|
||||
from .coordinator import EheimDigitalConfigEntry, EheimDigitalUpdateCoordinator
|
||||
from .entity import EheimDigitalEntity
|
||||
|
||||
BRIGHTNESS_SCALE = (1, 100)
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
from pyemoncms import EmoncmsClient
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_API_KEY, CONF_URL, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
@ -10,12 +9,10 @@ from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue
|
||||
|
||||
from .const import DOMAIN, EMONCMS_UUID_DOC_URL, LOGGER
|
||||
from .coordinator import EmoncmsCoordinator
|
||||
from .coordinator import EmonCMSConfigEntry, EmoncmsCoordinator
|
||||
|
||||
PLATFORMS: list[Platform] = [Platform.SENSOR]
|
||||
|
||||
type EmonCMSConfigEntry = ConfigEntry[EmoncmsCoordinator]
|
||||
|
||||
|
||||
def _migrate_unique_id(
|
||||
hass: HomeAssistant, entry: EmonCMSConfigEntry, emoncms_unique_id: str
|
||||
@ -68,7 +65,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: EmonCMSConfigEntry) -> b
|
||||
session=async_get_clientsession(hass),
|
||||
)
|
||||
await _check_unique_id_migration(hass, entry, emoncms_client)
|
||||
coordinator = EmoncmsCoordinator(hass, emoncms_client)
|
||||
coordinator = EmoncmsCoordinator(hass, entry, emoncms_client)
|
||||
await coordinator.async_config_entry_first_refresh()
|
||||
entry.runtime_data = coordinator
|
||||
|
||||
@ -77,11 +74,11 @@ async def async_setup_entry(hass: HomeAssistant, entry: EmonCMSConfigEntry) -> b
|
||||
return True
|
||||
|
||||
|
||||
async def update_listener(hass: HomeAssistant, entry: ConfigEntry):
|
||||
async def update_listener(hass: HomeAssistant, entry: EmonCMSConfigEntry):
|
||||
"""Handle options update."""
|
||||
await hass.config_entries.async_reload(entry.entry_id)
|
||||
|
||||
|
||||
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
async def async_unload_entry(hass: HomeAssistant, entry: EmonCMSConfigEntry) -> bool:
|
||||
"""Unload a config entry."""
|
||||
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user