core/homeassistant/components/adguard/sensor.py

151 lines
4.8 KiB
Python

"""Support for AdGuard Home sensors."""
from __future__ import annotations
from collections.abc import Callable, Coroutine
from dataclasses import dataclass
from datetime import timedelta
from typing import Any
from adguardhome import AdGuardHome, AdGuardHomeConnectionError
from homeassistant.components.sensor import SensorEntity, SensorEntityDescription
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import PERCENTAGE, TIME_MILLISECONDS
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import PlatformNotReady
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DATA_ADGUARD_CLIENT, DATA_ADGUARD_VERSION, DOMAIN
from .entity import AdGuardHomeEntity
SCAN_INTERVAL = timedelta(seconds=300)
PARALLEL_UPDATES = 4
@dataclass
class AdGuardHomeEntityDescriptionMixin:
"""Mixin for required keys."""
value_fn: Callable[[AdGuardHome], Coroutine[Any, Any, int | float]]
@dataclass
class AdGuardHomeEntityDescription(
SensorEntityDescription, AdGuardHomeEntityDescriptionMixin
):
"""Describes AdGuard Home sensor entity."""
SENSORS: tuple[AdGuardHomeEntityDescription, ...] = (
AdGuardHomeEntityDescription(
key="dns_queries",
name="DNS queries",
icon="mdi:magnify",
native_unit_of_measurement="queries",
value_fn=lambda adguard: adguard.stats.dns_queries(),
),
AdGuardHomeEntityDescription(
key="blocked_filtering",
name="DNS queries blocked",
icon="mdi:magnify-close",
native_unit_of_measurement="queries",
value_fn=lambda adguard: adguard.stats.blocked_filtering(),
),
AdGuardHomeEntityDescription(
key="blocked_percentage",
name="DNS queries blocked ratio",
icon="mdi:magnify-close",
native_unit_of_measurement=PERCENTAGE,
value_fn=lambda adguard: adguard.stats.blocked_percentage(),
),
AdGuardHomeEntityDescription(
key="blocked_parental",
name="Parental control blocked",
icon="mdi:human-male-girl",
native_unit_of_measurement="requests",
value_fn=lambda adguard: adguard.stats.replaced_parental(),
),
AdGuardHomeEntityDescription(
key="blocked_safebrowsing",
name="Safe browsing blocked",
icon="mdi:shield-half-full",
native_unit_of_measurement="requests",
value_fn=lambda adguard: adguard.stats.replaced_safebrowsing(),
),
AdGuardHomeEntityDescription(
key="enforced_safesearch",
name="Safe searches enforced",
icon="mdi:shield-search",
native_unit_of_measurement="requests",
value_fn=lambda adguard: adguard.stats.replaced_safesearch(),
),
AdGuardHomeEntityDescription(
key="average_speed",
name="Average processing speed",
icon="mdi:speedometer",
native_unit_of_measurement=TIME_MILLISECONDS,
value_fn=lambda adguard: adguard.stats.avg_processing_time(),
),
AdGuardHomeEntityDescription(
key="rules_count",
name="Rules count",
icon="mdi:counter",
native_unit_of_measurement="rules",
value_fn=lambda adguard: adguard.filtering.rules_count(allowlist=False),
entity_registry_enabled_default=False,
),
)
async def async_setup_entry(
hass: HomeAssistant,
entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up AdGuard Home sensor based on a config entry."""
adguard = hass.data[DOMAIN][entry.entry_id][DATA_ADGUARD_CLIENT]
try:
version = await adguard.version()
except AdGuardHomeConnectionError as exception:
raise PlatformNotReady from exception
hass.data[DOMAIN][entry.entry_id][DATA_ADGUARD_VERSION] = version
async_add_entities(
[AdGuardHomeSensor(adguard, entry, description) for description in SENSORS],
True,
)
class AdGuardHomeSensor(AdGuardHomeEntity, SensorEntity):
"""Defines a AdGuard Home sensor."""
entity_description: AdGuardHomeEntityDescription
def __init__(
self,
adguard: AdGuardHome,
entry: ConfigEntry,
description: AdGuardHomeEntityDescription,
) -> None:
"""Initialize AdGuard Home sensor."""
super().__init__(adguard, entry)
self.entity_description = description
self._attr_unique_id = "_".join(
[
DOMAIN,
adguard.host,
str(adguard.port),
"sensor",
description.key,
]
)
async def _adguard_update(self) -> None:
"""Update AdGuard Home entity."""
value = await self.entity_description.value_fn(self.adguard)
self._attr_native_value = value
if isinstance(value, float):
self._attr_native_value = f"{value:.2f}"