core/homeassistant/components/adguard/sensor.py

163 lines
5.3 KiB
Python
Raw Normal View History

"""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,
SensorStateClass,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import PERCENTAGE, UnitOfTime
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",
translation_key="dns_queries",
icon="mdi:magnify",
native_unit_of_measurement="queries",
value_fn=lambda adguard: adguard.stats.dns_queries(),
state_class=SensorStateClass.TOTAL,
),
AdGuardHomeEntityDescription(
key="blocked_filtering",
translation_key="dns_queries_blocked",
icon="mdi:magnify-close",
native_unit_of_measurement="queries",
value_fn=lambda adguard: adguard.stats.blocked_filtering(),
state_class=SensorStateClass.TOTAL,
),
AdGuardHomeEntityDescription(
key="blocked_percentage",
translation_key="dns_queries_blocked_ratio",
icon="mdi:magnify-close",
native_unit_of_measurement=PERCENTAGE,
value_fn=lambda adguard: adguard.stats.blocked_percentage(),
state_class=SensorStateClass.MEASUREMENT,
),
AdGuardHomeEntityDescription(
key="blocked_parental",
translation_key="parental_control_blocked",
icon="mdi:human-male-girl",
native_unit_of_measurement="requests",
value_fn=lambda adguard: adguard.stats.replaced_parental(),
state_class=SensorStateClass.TOTAL,
),
AdGuardHomeEntityDescription(
key="blocked_safebrowsing",
translation_key="safe_browsing_blocked",
icon="mdi:shield-half-full",
native_unit_of_measurement="requests",
value_fn=lambda adguard: adguard.stats.replaced_safebrowsing(),
state_class=SensorStateClass.TOTAL,
),
AdGuardHomeEntityDescription(
key="enforced_safesearch",
translation_key="safe_searches_enforced",
icon="mdi:shield-search",
native_unit_of_measurement="requests",
value_fn=lambda adguard: adguard.stats.replaced_safesearch(),
state_class=SensorStateClass.TOTAL,
),
AdGuardHomeEntityDescription(
key="average_speed",
translation_key="average_processing_speed",
icon="mdi:speedometer",
native_unit_of_measurement=UnitOfTime.MILLISECONDS,
value_fn=lambda adguard: adguard.stats.avg_processing_time(),
state_class=SensorStateClass.MEASUREMENT,
),
AdGuardHomeEntityDescription(
key="rules_count",
translation_key="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,
state_class=SensorStateClass.MEASUREMENT,
),
)
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),
2019-07-31 19:25:30 +00:00
"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}"