Compare commits
2 commits
dev
...
hassio_sta
Author | SHA1 | Date | |
---|---|---|---|
|
7360ea0677 | ||
|
6a23d452bc |
5 changed files with 157 additions and 52 deletions
|
@ -63,8 +63,6 @@ from .const import (
|
|||
ATTR_PASSWORD,
|
||||
ATTR_REPOSITORY,
|
||||
ATTR_SLUG,
|
||||
ATTR_STARTED,
|
||||
ATTR_STATE,
|
||||
ATTR_URL,
|
||||
ATTR_VERSION,
|
||||
DATA_KEY_ADDONS,
|
||||
|
@ -718,7 +716,7 @@ def async_register_supervisor_in_dev_reg(
|
|||
params = DeviceInfo(
|
||||
identifiers={(DOMAIN, "supervisor")},
|
||||
manufacturer="Home Assistant",
|
||||
model=SupervisorEntityModel.SUPERVIOSR,
|
||||
model=SupervisorEntityModel.SUPERVISOR,
|
||||
sw_version=supervisor_dict[ATTR_VERSION],
|
||||
name="Home Assistant Supervisor",
|
||||
entry_type=dr.DeviceEntryType.SERVICE,
|
||||
|
@ -765,7 +763,6 @@ class HassioDataUpdateCoordinator(DataUpdateCoordinator):
|
|||
new_data: dict[str, Any] = {}
|
||||
supervisor_info = get_supervisor_info(self.hass) or {}
|
||||
addons_info = get_addons_info(self.hass)
|
||||
addons_stats = get_addons_stats(self.hass)
|
||||
addons_changelogs = get_addons_changelogs(self.hass)
|
||||
store_data = get_store(self.hass) or {}
|
||||
|
||||
|
@ -777,7 +774,6 @@ class HassioDataUpdateCoordinator(DataUpdateCoordinator):
|
|||
new_data[DATA_KEY_ADDONS] = {
|
||||
addon[ATTR_SLUG]: {
|
||||
**addon,
|
||||
**((addons_stats or {}).get(addon[ATTR_SLUG]) or {}),
|
||||
ATTR_AUTO_UPDATE: (addons_info.get(addon[ATTR_SLUG]) or {}).get(
|
||||
ATTR_AUTO_UPDATE, False
|
||||
),
|
||||
|
@ -793,11 +789,9 @@ class HassioDataUpdateCoordinator(DataUpdateCoordinator):
|
|||
|
||||
new_data[DATA_KEY_CORE] = {
|
||||
**(get_core_info(self.hass) or {}),
|
||||
**get_core_stats(self.hass),
|
||||
}
|
||||
new_data[DATA_KEY_SUPERVISOR] = {
|
||||
**supervisor_info,
|
||||
**get_supervisor_stats(self.hass),
|
||||
}
|
||||
new_data[DATA_KEY_HOST] = get_host_info(self.hass) or {}
|
||||
|
||||
|
@ -857,27 +851,16 @@ class HassioDataUpdateCoordinator(DataUpdateCoordinator):
|
|||
(
|
||||
self.hass.data[DATA_INFO],
|
||||
self.hass.data[DATA_CORE_INFO],
|
||||
self.hass.data[DATA_CORE_STATS],
|
||||
self.hass.data[DATA_SUPERVISOR_INFO],
|
||||
self.hass.data[DATA_SUPERVISOR_STATS],
|
||||
self.hass.data[DATA_OS_INFO],
|
||||
) = await asyncio.gather(
|
||||
self.hassio.get_info(),
|
||||
self.hassio.get_core_info(),
|
||||
self.hassio.get_core_stats(),
|
||||
self.hassio.get_supervisor_info(),
|
||||
self.hassio.get_supervisor_stats(),
|
||||
self.hassio.get_os_info(),
|
||||
)
|
||||
|
||||
all_addons = self.hass.data[DATA_SUPERVISOR_INFO].get("addons", [])
|
||||
started_addons = [
|
||||
addon for addon in all_addons if addon[ATTR_STATE] == ATTR_STARTED
|
||||
]
|
||||
stats_data = await asyncio.gather(
|
||||
*[self._update_addon_stats(addon[ATTR_SLUG]) for addon in started_addons]
|
||||
)
|
||||
self.hass.data[DATA_ADDONS_STATS] = dict(stats_data)
|
||||
self.hass.data[DATA_ADDONS_CHANGELOGS] = dict(
|
||||
await asyncio.gather(
|
||||
*[
|
||||
|
@ -892,15 +875,6 @@ class HassioDataUpdateCoordinator(DataUpdateCoordinator):
|
|||
)
|
||||
)
|
||||
|
||||
async def _update_addon_stats(self, slug):
|
||||
"""Update single addon stats."""
|
||||
try:
|
||||
stats = await self.hassio.get_addon_stats(slug)
|
||||
return (slug, stats)
|
||||
except HassioAPIError as err:
|
||||
_LOGGER.warning("Could not fetch stats for %s: %s", slug, err)
|
||||
return (slug, None)
|
||||
|
||||
async def _update_addon_changelog(self, slug):
|
||||
"""Return the changelog for an add-on."""
|
||||
try:
|
||||
|
@ -936,3 +910,41 @@ class HassioDataUpdateCoordinator(DataUpdateCoordinator):
|
|||
await super()._async_refresh(
|
||||
log_failures, raise_on_auth_failed, scheduled, raise_on_entry_error
|
||||
)
|
||||
|
||||
|
||||
class HassioStatsDataUpdateCoordinator(DataUpdateCoordinator[dict[str, Any]]):
|
||||
"""Custom coordinator for Hass.io stats."""
|
||||
|
||||
config_entry: ConfigEntry
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
hass: HomeAssistant,
|
||||
model: SupervisorEntityModel,
|
||||
*,
|
||||
addon_slug: str | None = None,
|
||||
) -> None:
|
||||
"""Initialize coordinator."""
|
||||
super().__init__(
|
||||
hass,
|
||||
_LOGGER,
|
||||
name="_".join([x for x in (DOMAIN, model, addon_slug) if x]),
|
||||
update_interval=HASSIO_UPDATE_INTERVAL,
|
||||
)
|
||||
self.hassio: HassIO = hass.data[DOMAIN]
|
||||
self.model = model
|
||||
self.addon_slug = addon_slug
|
||||
|
||||
async def _async_update_data(self) -> dict[str, Any]:
|
||||
"""Fetch the latest data from the source."""
|
||||
try:
|
||||
if self.model == SupervisorEntityModel.ADDON:
|
||||
return await self.hassio.get_addon_stats(self.addon_slug)
|
||||
|
||||
if self.model == SupervisorEntityModel.SUPERVISOR:
|
||||
return await self.hassio.get_supervisor_stats()
|
||||
|
||||
# SupervisorEntityModel.CORE
|
||||
return await self.hassio.get_core_stats()
|
||||
except HassioAPIError as err:
|
||||
raise UpdateFailed(f"Error communicating with Supervisor: {err}") from err
|
||||
|
|
|
@ -77,5 +77,5 @@ class SupervisorEntityModel(str, Enum):
|
|||
ADDON = "Home Assistant Add-on"
|
||||
OS = "Home Assistant Operating System"
|
||||
CORE = "Home Assistant Core"
|
||||
SUPERVIOSR = "Home Assistant Supervisor"
|
||||
SUPERVISOR = "Home Assistant Supervisor"
|
||||
HOST = "Home Assistant Host"
|
||||
|
|
|
@ -6,7 +6,7 @@ from typing import Any
|
|||
from homeassistant.helpers.entity import DeviceInfo, EntityDescription
|
||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||
|
||||
from . import DOMAIN, HassioDataUpdateCoordinator
|
||||
from . import DOMAIN, HassioDataUpdateCoordinator, HassioStatsDataUpdateCoordinator
|
||||
from .const import (
|
||||
ATTR_SLUG,
|
||||
DATA_KEY_ADDONS,
|
||||
|
@ -17,14 +17,16 @@ from .const import (
|
|||
)
|
||||
|
||||
|
||||
class HassioAddonEntity(CoordinatorEntity[HassioDataUpdateCoordinator]):
|
||||
class HassioAddonEntity(
|
||||
CoordinatorEntity[HassioDataUpdateCoordinator | HassioStatsDataUpdateCoordinator]
|
||||
):
|
||||
"""Base entity for a Hass.io add-on."""
|
||||
|
||||
_attr_has_entity_name = True
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: HassioDataUpdateCoordinator,
|
||||
coordinator: HassioDataUpdateCoordinator | HassioStatsDataUpdateCoordinator,
|
||||
entity_description: EntityDescription,
|
||||
addon: dict[str, Any],
|
||||
) -> None:
|
||||
|
@ -46,14 +48,16 @@ class HassioAddonEntity(CoordinatorEntity[HassioDataUpdateCoordinator]):
|
|||
)
|
||||
|
||||
|
||||
class HassioOSEntity(CoordinatorEntity[HassioDataUpdateCoordinator]):
|
||||
class HassioOSEntity(
|
||||
CoordinatorEntity[HassioDataUpdateCoordinator | HassioStatsDataUpdateCoordinator]
|
||||
):
|
||||
"""Base Entity for Hass.io OS."""
|
||||
|
||||
_attr_has_entity_name = True
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: HassioDataUpdateCoordinator,
|
||||
coordinator: HassioDataUpdateCoordinator | HassioStatsDataUpdateCoordinator,
|
||||
entity_description: EntityDescription,
|
||||
) -> None:
|
||||
"""Initialize base entity."""
|
||||
|
@ -72,14 +76,16 @@ class HassioOSEntity(CoordinatorEntity[HassioDataUpdateCoordinator]):
|
|||
)
|
||||
|
||||
|
||||
class HassioHostEntity(CoordinatorEntity[HassioDataUpdateCoordinator]):
|
||||
class HassioHostEntity(
|
||||
CoordinatorEntity[HassioDataUpdateCoordinator | HassioStatsDataUpdateCoordinator]
|
||||
):
|
||||
"""Base Entity for Hass.io host."""
|
||||
|
||||
_attr_has_entity_name = True
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: HassioDataUpdateCoordinator,
|
||||
coordinator: HassioDataUpdateCoordinator | HassioStatsDataUpdateCoordinator,
|
||||
entity_description: EntityDescription,
|
||||
) -> None:
|
||||
"""Initialize base entity."""
|
||||
|
@ -98,14 +104,16 @@ class HassioHostEntity(CoordinatorEntity[HassioDataUpdateCoordinator]):
|
|||
)
|
||||
|
||||
|
||||
class HassioSupervisorEntity(CoordinatorEntity[HassioDataUpdateCoordinator]):
|
||||
class HassioSupervisorEntity(
|
||||
CoordinatorEntity[HassioDataUpdateCoordinator | HassioStatsDataUpdateCoordinator]
|
||||
):
|
||||
"""Base Entity for Supervisor."""
|
||||
|
||||
_attr_has_entity_name = True
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: HassioDataUpdateCoordinator,
|
||||
coordinator: HassioDataUpdateCoordinator | HassioStatsDataUpdateCoordinator,
|
||||
entity_description: EntityDescription,
|
||||
) -> None:
|
||||
"""Initialize base entity."""
|
||||
|
@ -125,14 +133,16 @@ class HassioSupervisorEntity(CoordinatorEntity[HassioDataUpdateCoordinator]):
|
|||
)
|
||||
|
||||
|
||||
class HassioCoreEntity(CoordinatorEntity[HassioDataUpdateCoordinator]):
|
||||
class HassioCoreEntity(
|
||||
CoordinatorEntity[HassioDataUpdateCoordinator | HassioStatsDataUpdateCoordinator]
|
||||
):
|
||||
"""Base Entity for Core."""
|
||||
|
||||
_attr_has_entity_name = True
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: HassioDataUpdateCoordinator,
|
||||
coordinator: HassioDataUpdateCoordinator | HassioStatsDataUpdateCoordinator,
|
||||
entity_description: EntityDescription,
|
||||
) -> None:
|
||||
"""Initialize base entity."""
|
||||
|
|
|
@ -12,10 +12,11 @@ from homeassistant.const import PERCENTAGE, EntityCategory, UnitOfInformation
|
|||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from . import ADDONS_COORDINATOR
|
||||
from . import ADDONS_COORDINATOR, HassioStatsDataUpdateCoordinator
|
||||
from .const import (
|
||||
ATTR_CPU_PERCENT,
|
||||
ATTR_MEMORY_PERCENT,
|
||||
ATTR_SLUG,
|
||||
ATTR_VERSION,
|
||||
ATTR_VERSION_LATEST,
|
||||
DATA_KEY_ADDONS,
|
||||
|
@ -23,6 +24,7 @@ from .const import (
|
|||
DATA_KEY_HOST,
|
||||
DATA_KEY_OS,
|
||||
DATA_KEY_SUPERVISOR,
|
||||
SupervisorEntityModel,
|
||||
)
|
||||
from .entity import (
|
||||
HassioAddonEntity,
|
||||
|
@ -64,10 +66,8 @@ STATS_ENTITY_DESCRIPTIONS = (
|
|||
),
|
||||
)
|
||||
|
||||
ADDON_ENTITY_DESCRIPTIONS = COMMON_ENTITY_DESCRIPTIONS + STATS_ENTITY_DESCRIPTIONS
|
||||
CORE_ENTITY_DESCRIPTIONS = STATS_ENTITY_DESCRIPTIONS
|
||||
ADDON_ENTITY_DESCRIPTIONS = COMMON_ENTITY_DESCRIPTIONS
|
||||
OS_ENTITY_DESCRIPTIONS = COMMON_ENTITY_DESCRIPTIONS
|
||||
SUPERVISOR_ENTITY_DESCRIPTIONS = STATS_ENTITY_DESCRIPTIONS
|
||||
|
||||
HOST_ENTITY_DESCRIPTIONS = (
|
||||
SensorEntityDescription(
|
||||
|
@ -120,6 +120,9 @@ async def async_setup_entry(
|
|||
entities: list[
|
||||
HassioOSSensor | HassioAddonSensor | CoreSensor | SupervisorSensor | HostSensor
|
||||
] = []
|
||||
stats_entities: list[
|
||||
AddonStatsSensor | CoreStatsSensor | SupervisorStatsSensor
|
||||
] = []
|
||||
|
||||
for addon in coordinator.data[DATA_KEY_ADDONS].values():
|
||||
for entity_description in ADDON_ENTITY_DESCRIPTIONS:
|
||||
|
@ -130,19 +133,35 @@ async def async_setup_entry(
|
|||
entity_description=entity_description,
|
||||
)
|
||||
)
|
||||
for entity_description in STATS_ENTITY_DESCRIPTIONS:
|
||||
stats_entities.append(
|
||||
AddonStatsSensor(
|
||||
addon=addon,
|
||||
coordinator=HassioStatsDataUpdateCoordinator(
|
||||
hass=hass,
|
||||
model=SupervisorEntityModel.ADDON,
|
||||
addon_slug=addon[ATTR_SLUG],
|
||||
),
|
||||
entity_description=entity_description,
|
||||
)
|
||||
)
|
||||
|
||||
for entity_description in CORE_ENTITY_DESCRIPTIONS:
|
||||
entities.append(
|
||||
CoreSensor(
|
||||
coordinator=coordinator,
|
||||
for entity_description in STATS_ENTITY_DESCRIPTIONS:
|
||||
stats_entities.append(
|
||||
CoreStatsSensor(
|
||||
coordinator=HassioStatsDataUpdateCoordinator(
|
||||
hass=hass,
|
||||
model=SupervisorEntityModel.CORE,
|
||||
),
|
||||
entity_description=entity_description,
|
||||
)
|
||||
)
|
||||
|
||||
for entity_description in SUPERVISOR_ENTITY_DESCRIPTIONS:
|
||||
entities.append(
|
||||
SupervisorSensor(
|
||||
coordinator=coordinator,
|
||||
stats_entities.append(
|
||||
SupervisorStatsSensor(
|
||||
coordinator=HassioStatsDataUpdateCoordinator(
|
||||
hass=hass,
|
||||
model=SupervisorEntityModel.SUPERVISOR,
|
||||
),
|
||||
entity_description=entity_description,
|
||||
)
|
||||
)
|
||||
|
@ -165,6 +184,7 @@ async def async_setup_entry(
|
|||
)
|
||||
|
||||
async_add_entities(entities)
|
||||
async_add_entities(stats_entities, True)
|
||||
|
||||
|
||||
class HassioAddonSensor(HassioAddonEntity, SensorEntity):
|
||||
|
@ -212,3 +232,63 @@ class HostSensor(HassioHostEntity, SensorEntity):
|
|||
def native_value(self) -> str:
|
||||
"""Return native value of entity."""
|
||||
return self.coordinator.data[DATA_KEY_HOST][self.entity_description.key]
|
||||
|
||||
|
||||
class AddonStatsSensor(HassioAddonEntity, SensorEntity):
|
||||
"""Sensor to track a Hass.io add-on stats attribute."""
|
||||
|
||||
coordinator: HassioStatsDataUpdateCoordinator
|
||||
|
||||
@property
|
||||
def native_value(self) -> str:
|
||||
"""Return native value of entity."""
|
||||
return self.coordinator.data[self.entity_description.key]
|
||||
|
||||
@property
|
||||
def available(self) -> bool:
|
||||
"""Return True if entity is available."""
|
||||
return (
|
||||
self.coordinator.last_update_success
|
||||
and self.coordinator.data is not None
|
||||
and self.entity_description.key in self.coordinator.data
|
||||
)
|
||||
|
||||
|
||||
class CoreStatsSensor(HassioCoreEntity, SensorEntity):
|
||||
"""Sensor to track a Hass.io core stats attribute."""
|
||||
|
||||
coordinator: HassioStatsDataUpdateCoordinator
|
||||
|
||||
@property
|
||||
def native_value(self) -> str:
|
||||
"""Return native value of entity."""
|
||||
return self.coordinator.data[self.entity_description.key]
|
||||
|
||||
@property
|
||||
def available(self) -> bool:
|
||||
"""Return True if entity is available."""
|
||||
return (
|
||||
self.coordinator.last_update_success
|
||||
and self.coordinator.data is not None
|
||||
and self.entity_description.key in self.coordinator.data
|
||||
)
|
||||
|
||||
|
||||
class SupervisorStatsSensor(HassioSupervisorEntity, SensorEntity):
|
||||
"""Sensor to track a Hass.io supervisor stats attribute."""
|
||||
|
||||
coordinator: HassioStatsDataUpdateCoordinator
|
||||
|
||||
@property
|
||||
def native_value(self) -> str:
|
||||
"""Return native value of entity."""
|
||||
return self.coordinator.data[self.entity_description.key]
|
||||
|
||||
@property
|
||||
def available(self) -> bool:
|
||||
"""Return True if entity is available."""
|
||||
return (
|
||||
self.coordinator.last_update_success
|
||||
and self.coordinator.data is not None
|
||||
and self.entity_description.key in self.coordinator.data
|
||||
)
|
||||
|
|
|
@ -18,6 +18,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
|||
|
||||
from . import (
|
||||
ADDONS_COORDINATOR,
|
||||
HassioDataUpdateCoordinator,
|
||||
async_update_addon,
|
||||
async_update_core,
|
||||
async_update_os,
|
||||
|
@ -89,6 +90,8 @@ async def async_setup_entry(
|
|||
class SupervisorAddonUpdateEntity(HassioAddonEntity, UpdateEntity):
|
||||
"""Update entity to handle updates for the Supervisor add-ons."""
|
||||
|
||||
coordinator: HassioDataUpdateCoordinator
|
||||
|
||||
_attr_supported_features = (
|
||||
UpdateEntityFeature.INSTALL
|
||||
| UpdateEntityFeature.BACKUP
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue