Add sensors for supervisor host (#89461)
Co-authored-by: Franck Nijhof <git@frenck.dev>
This commit is contained in:
parent
07b25939a2
commit
11e21378b1
7 changed files with 122 additions and 13 deletions
|
@ -69,6 +69,7 @@ from .const import (
|
||||||
ATTR_VERSION,
|
ATTR_VERSION,
|
||||||
DATA_KEY_ADDONS,
|
DATA_KEY_ADDONS,
|
||||||
DATA_KEY_CORE,
|
DATA_KEY_CORE,
|
||||||
|
DATA_KEY_HOST,
|
||||||
DATA_KEY_OS,
|
DATA_KEY_OS,
|
||||||
DATA_KEY_SUPERVISOR,
|
DATA_KEY_SUPERVISOR,
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
|
@ -668,6 +669,22 @@ def async_register_os_in_dev_reg(
|
||||||
dev_reg.async_get_or_create(config_entry_id=entry_id, **params)
|
dev_reg.async_get_or_create(config_entry_id=entry_id, **params)
|
||||||
|
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def async_register_host_in_dev_reg(
|
||||||
|
entry_id: str,
|
||||||
|
dev_reg: dr.DeviceRegistry,
|
||||||
|
) -> None:
|
||||||
|
"""Register host in the device registry."""
|
||||||
|
params = DeviceInfo(
|
||||||
|
identifiers={(DOMAIN, "host")},
|
||||||
|
manufacturer="Home Assistant",
|
||||||
|
model=SupervisorEntityModel.HOST,
|
||||||
|
name="Home Assistant Host",
|
||||||
|
entry_type=dr.DeviceEntryType.SERVICE,
|
||||||
|
)
|
||||||
|
dev_reg.async_get_or_create(config_entry_id=entry_id, **params)
|
||||||
|
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_register_core_in_dev_reg(
|
def async_register_core_in_dev_reg(
|
||||||
entry_id: str,
|
entry_id: str,
|
||||||
|
@ -777,6 +794,7 @@ class HassioDataUpdateCoordinator(DataUpdateCoordinator):
|
||||||
**supervisor_info,
|
**supervisor_info,
|
||||||
**get_supervisor_stats(self.hass),
|
**get_supervisor_stats(self.hass),
|
||||||
}
|
}
|
||||||
|
new_data[DATA_KEY_HOST] = get_host_info(self.hass) or {}
|
||||||
|
|
||||||
# If this is the initial refresh, register all addons and return the dict
|
# If this is the initial refresh, register all addons and return the dict
|
||||||
if not self.data:
|
if not self.data:
|
||||||
|
@ -789,6 +807,7 @@ class HassioDataUpdateCoordinator(DataUpdateCoordinator):
|
||||||
async_register_supervisor_in_dev_reg(
|
async_register_supervisor_in_dev_reg(
|
||||||
self.entry_id, self.dev_reg, new_data[DATA_KEY_SUPERVISOR]
|
self.entry_id, self.dev_reg, new_data[DATA_KEY_SUPERVISOR]
|
||||||
)
|
)
|
||||||
|
async_register_host_in_dev_reg(self.entry_id, self.dev_reg)
|
||||||
if self.is_hass_os:
|
if self.is_hass_os:
|
||||||
async_register_os_in_dev_reg(
|
async_register_os_in_dev_reg(
|
||||||
self.entry_id, self.dev_reg, new_data[DATA_KEY_OS]
|
self.entry_id, self.dev_reg, new_data[DATA_KEY_OS]
|
||||||
|
|
|
@ -68,6 +68,7 @@ DATA_KEY_ADDONS = "addons"
|
||||||
DATA_KEY_OS = "os"
|
DATA_KEY_OS = "os"
|
||||||
DATA_KEY_SUPERVISOR = "supervisor"
|
DATA_KEY_SUPERVISOR = "supervisor"
|
||||||
DATA_KEY_CORE = "core"
|
DATA_KEY_CORE = "core"
|
||||||
|
DATA_KEY_HOST = "host"
|
||||||
|
|
||||||
|
|
||||||
class SupervisorEntityModel(str, Enum):
|
class SupervisorEntityModel(str, Enum):
|
||||||
|
@ -77,3 +78,4 @@ class SupervisorEntityModel(str, Enum):
|
||||||
OS = "Home Assistant Operating System"
|
OS = "Home Assistant Operating System"
|
||||||
CORE = "Home Assistant Core"
|
CORE = "Home Assistant Core"
|
||||||
SUPERVIOSR = "Home Assistant Supervisor"
|
SUPERVIOSR = "Home Assistant Supervisor"
|
||||||
|
HOST = "Home Assistant Host"
|
||||||
|
|
|
@ -11,6 +11,7 @@ from .const import (
|
||||||
ATTR_SLUG,
|
ATTR_SLUG,
|
||||||
DATA_KEY_ADDONS,
|
DATA_KEY_ADDONS,
|
||||||
DATA_KEY_CORE,
|
DATA_KEY_CORE,
|
||||||
|
DATA_KEY_HOST,
|
||||||
DATA_KEY_OS,
|
DATA_KEY_OS,
|
||||||
DATA_KEY_SUPERVISOR,
|
DATA_KEY_SUPERVISOR,
|
||||||
)
|
)
|
||||||
|
@ -71,6 +72,32 @@ class HassioOSEntity(CoordinatorEntity[HassioDataUpdateCoordinator]):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class HassioHostEntity(CoordinatorEntity[HassioDataUpdateCoordinator]):
|
||||||
|
"""Base Entity for Hass.io host."""
|
||||||
|
|
||||||
|
_attr_has_entity_name = True
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
coordinator: HassioDataUpdateCoordinator,
|
||||||
|
entity_description: EntityDescription,
|
||||||
|
) -> None:
|
||||||
|
"""Initialize base entity."""
|
||||||
|
super().__init__(coordinator)
|
||||||
|
self.entity_description = entity_description
|
||||||
|
self._attr_unique_id = f"home_assistant_host_{entity_description.key}"
|
||||||
|
self._attr_device_info = DeviceInfo(identifiers={(DOMAIN, "host")})
|
||||||
|
|
||||||
|
@property
|
||||||
|
def available(self) -> bool:
|
||||||
|
"""Return True if entity is available."""
|
||||||
|
return (
|
||||||
|
super().available
|
||||||
|
and DATA_KEY_HOST in self.coordinator.data
|
||||||
|
and self.entity_description.key in self.coordinator.data[DATA_KEY_HOST]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class HassioSupervisorEntity(CoordinatorEntity[HassioDataUpdateCoordinator]):
|
class HassioSupervisorEntity(CoordinatorEntity[HassioDataUpdateCoordinator]):
|
||||||
"""Base Entity for Supervisor."""
|
"""Base Entity for Supervisor."""
|
||||||
|
|
||||||
|
|
|
@ -2,12 +2,13 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from homeassistant.components.sensor import (
|
from homeassistant.components.sensor import (
|
||||||
|
SensorDeviceClass,
|
||||||
SensorEntity,
|
SensorEntity,
|
||||||
SensorEntityDescription,
|
SensorEntityDescription,
|
||||||
SensorStateClass,
|
SensorStateClass,
|
||||||
)
|
)
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import PERCENTAGE
|
from homeassistant.const import PERCENTAGE, EntityCategory, UnitOfInformation
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
|
@ -19,12 +20,14 @@ from .const import (
|
||||||
ATTR_VERSION_LATEST,
|
ATTR_VERSION_LATEST,
|
||||||
DATA_KEY_ADDONS,
|
DATA_KEY_ADDONS,
|
||||||
DATA_KEY_CORE,
|
DATA_KEY_CORE,
|
||||||
|
DATA_KEY_HOST,
|
||||||
DATA_KEY_OS,
|
DATA_KEY_OS,
|
||||||
DATA_KEY_SUPERVISOR,
|
DATA_KEY_SUPERVISOR,
|
||||||
)
|
)
|
||||||
from .entity import (
|
from .entity import (
|
||||||
HassioAddonEntity,
|
HassioAddonEntity,
|
||||||
HassioCoreEntity,
|
HassioCoreEntity,
|
||||||
|
HassioHostEntity,
|
||||||
HassioOSEntity,
|
HassioOSEntity,
|
||||||
HassioSupervisorEntity,
|
HassioSupervisorEntity,
|
||||||
)
|
)
|
||||||
|
@ -66,6 +69,45 @@ CORE_ENTITY_DESCRIPTIONS = STATS_ENTITY_DESCRIPTIONS
|
||||||
OS_ENTITY_DESCRIPTIONS = COMMON_ENTITY_DESCRIPTIONS
|
OS_ENTITY_DESCRIPTIONS = COMMON_ENTITY_DESCRIPTIONS
|
||||||
SUPERVISOR_ENTITY_DESCRIPTIONS = STATS_ENTITY_DESCRIPTIONS
|
SUPERVISOR_ENTITY_DESCRIPTIONS = STATS_ENTITY_DESCRIPTIONS
|
||||||
|
|
||||||
|
HOST_ENTITY_DESCRIPTIONS = (
|
||||||
|
SensorEntityDescription(
|
||||||
|
entity_registry_enabled_default=False,
|
||||||
|
key="agent_version",
|
||||||
|
name="OS Agent version",
|
||||||
|
entity_category=EntityCategory.DIAGNOSTIC,
|
||||||
|
),
|
||||||
|
SensorEntityDescription(
|
||||||
|
entity_registry_enabled_default=False,
|
||||||
|
key="apparmor_version",
|
||||||
|
name="Apparmor version",
|
||||||
|
entity_category=EntityCategory.DIAGNOSTIC,
|
||||||
|
),
|
||||||
|
SensorEntityDescription(
|
||||||
|
entity_registry_enabled_default=False,
|
||||||
|
key="disk_total",
|
||||||
|
name="Disk total",
|
||||||
|
native_unit_of_measurement=UnitOfInformation.GIGABYTES,
|
||||||
|
device_class=SensorDeviceClass.DATA_SIZE,
|
||||||
|
entity_category=EntityCategory.DIAGNOSTIC,
|
||||||
|
),
|
||||||
|
SensorEntityDescription(
|
||||||
|
entity_registry_enabled_default=False,
|
||||||
|
key="disk_used",
|
||||||
|
name="Disk used",
|
||||||
|
native_unit_of_measurement=UnitOfInformation.GIGABYTES,
|
||||||
|
device_class=SensorDeviceClass.DATA_SIZE,
|
||||||
|
entity_category=EntityCategory.DIAGNOSTIC,
|
||||||
|
),
|
||||||
|
SensorEntityDescription(
|
||||||
|
entity_registry_enabled_default=False,
|
||||||
|
key="disk_free",
|
||||||
|
name="Disk free",
|
||||||
|
native_unit_of_measurement=UnitOfInformation.GIGABYTES,
|
||||||
|
device_class=SensorDeviceClass.DATA_SIZE,
|
||||||
|
entity_category=EntityCategory.DIAGNOSTIC,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
|
@ -76,7 +118,7 @@ async def async_setup_entry(
|
||||||
coordinator = hass.data[ADDONS_COORDINATOR]
|
coordinator = hass.data[ADDONS_COORDINATOR]
|
||||||
|
|
||||||
entities: list[
|
entities: list[
|
||||||
HassioOSSensor | HassioAddonSensor | CoreSensor | SupervisorSensor
|
HassioOSSensor | HassioAddonSensor | CoreSensor | SupervisorSensor | HostSensor
|
||||||
] = []
|
] = []
|
||||||
|
|
||||||
for addon in coordinator.data[DATA_KEY_ADDONS].values():
|
for addon in coordinator.data[DATA_KEY_ADDONS].values():
|
||||||
|
@ -105,6 +147,14 @@ async def async_setup_entry(
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
for entity_description in HOST_ENTITY_DESCRIPTIONS:
|
||||||
|
entities.append(
|
||||||
|
HostSensor(
|
||||||
|
coordinator=coordinator,
|
||||||
|
entity_description=entity_description,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
if coordinator.is_hass_os:
|
if coordinator.is_hass_os:
|
||||||
for entity_description in OS_ENTITY_DESCRIPTIONS:
|
for entity_description in OS_ENTITY_DESCRIPTIONS:
|
||||||
entities.append(
|
entities.append(
|
||||||
|
@ -153,3 +203,12 @@ class SupervisorSensor(HassioSupervisorEntity, SensorEntity):
|
||||||
def native_value(self) -> str:
|
def native_value(self) -> str:
|
||||||
"""Return native value of entity."""
|
"""Return native value of entity."""
|
||||||
return self.coordinator.data[DATA_KEY_SUPERVISOR][self.entity_description.key]
|
return self.coordinator.data[DATA_KEY_SUPERVISOR][self.entity_description.key]
|
||||||
|
|
||||||
|
|
||||||
|
class HostSensor(HassioHostEntity, SensorEntity):
|
||||||
|
"""Sensor to track a host attribute."""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def native_value(self) -> str:
|
||||||
|
"""Return native value of entity."""
|
||||||
|
return self.coordinator.data[DATA_KEY_HOST][self.entity_description.key]
|
||||||
|
|
|
@ -211,5 +211,6 @@ async def test_diagnostics(
|
||||||
assert "core" in diagnostics["coordinator_data"]
|
assert "core" in diagnostics["coordinator_data"]
|
||||||
assert "supervisor" in diagnostics["coordinator_data"]
|
assert "supervisor" in diagnostics["coordinator_data"]
|
||||||
assert "os" in diagnostics["coordinator_data"]
|
assert "os" in diagnostics["coordinator_data"]
|
||||||
|
assert "host" in diagnostics["coordinator_data"]
|
||||||
|
|
||||||
assert len(diagnostics["devices"]) == 5
|
assert len(diagnostics["devices"]) == 6
|
||||||
|
|
|
@ -678,7 +678,7 @@ async def test_device_registry_calls(hass: HomeAssistant) -> None:
|
||||||
config_entry.add_to_hass(hass)
|
config_entry.add_to_hass(hass)
|
||||||
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
assert await hass.config_entries.async_setup(config_entry.entry_id)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert len(dev_reg.devices) == 5
|
assert len(dev_reg.devices) == 6
|
||||||
|
|
||||||
supervisor_mock_data = {
|
supervisor_mock_data = {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
|
@ -709,11 +709,11 @@ async def test_device_registry_calls(hass: HomeAssistant) -> None:
|
||||||
):
|
):
|
||||||
async_fire_time_changed(hass, dt_util.now() + timedelta(hours=1))
|
async_fire_time_changed(hass, dt_util.now() + timedelta(hours=1))
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert len(dev_reg.devices) == 4
|
assert len(dev_reg.devices) == 5
|
||||||
|
|
||||||
async_fire_time_changed(hass, dt_util.now() + timedelta(hours=2))
|
async_fire_time_changed(hass, dt_util.now() + timedelta(hours=2))
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert len(dev_reg.devices) == 4
|
assert len(dev_reg.devices) == 5
|
||||||
|
|
||||||
supervisor_mock_data = {
|
supervisor_mock_data = {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
|
@ -763,7 +763,7 @@ async def test_device_registry_calls(hass: HomeAssistant) -> None:
|
||||||
):
|
):
|
||||||
async_fire_time_changed(hass, dt_util.now() + timedelta(hours=3))
|
async_fire_time_changed(hass, dt_util.now() + timedelta(hours=3))
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert len(dev_reg.devices) == 4
|
assert len(dev_reg.devices) == 5
|
||||||
|
|
||||||
|
|
||||||
async def test_coordinator_updates(
|
async def test_coordinator_updates(
|
||||||
|
|
|
@ -44,14 +44,12 @@ def mock_all(aioclient_mock, request):
|
||||||
json={
|
json={
|
||||||
"result": "ok",
|
"result": "ok",
|
||||||
"data": {
|
"data": {
|
||||||
"result": "ok",
|
"agent_version": "1.0.0",
|
||||||
"data": {
|
|
||||||
"chassis": "vm",
|
"chassis": "vm",
|
||||||
"operating_system": "Debian GNU/Linux 10 (buster)",
|
"operating_system": "Debian GNU/Linux 10 (buster)",
|
||||||
"kernel": "4.19.0-6-amd64",
|
"kernel": "4.19.0-6-amd64",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
|
||||||
)
|
)
|
||||||
aioclient_mock.get(
|
aioclient_mock.get(
|
||||||
"http://127.0.0.1/core/info",
|
"http://127.0.0.1/core/info",
|
||||||
|
@ -179,6 +177,9 @@ def mock_all(aioclient_mock, request):
|
||||||
[
|
[
|
||||||
("sensor.home_assistant_operating_system_version", "1.0.0"),
|
("sensor.home_assistant_operating_system_version", "1.0.0"),
|
||||||
("sensor.home_assistant_operating_system_newest_version", "1.0.0"),
|
("sensor.home_assistant_operating_system_newest_version", "1.0.0"),
|
||||||
|
("sensor.home_assistant_host_os_agent_version", "1.0.0"),
|
||||||
|
("sensor.home_assistant_core_cpu_percent", "0.99"),
|
||||||
|
("sensor.home_assistant_supervisor_cpu_percent", "0.99"),
|
||||||
("sensor.test_version", "2.0.0"),
|
("sensor.test_version", "2.0.0"),
|
||||||
("sensor.test_newest_version", "2.0.1"),
|
("sensor.test_newest_version", "2.0.1"),
|
||||||
("sensor.test2_version", "3.1.0"),
|
("sensor.test2_version", "3.1.0"),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue