Add entity descriptions in AdGuard Home sensors (#75179)

This commit is contained in:
Franck Nijhof 2022-07-14 22:04:19 +02:00 committed by GitHub
parent 72906bf154
commit d004adf833
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 102 additions and 192 deletions

View File

@ -138,8 +138,8 @@ class AdGuardHomeEntity(Entity):
self,
adguard: AdGuardHome,
entry: ConfigEntry,
name: str,
icon: str,
name: str | None,
icon: str | None,
enabled_default: bool = True,
) -> None:
"""Initialize the AdGuard Home entity."""
@ -151,12 +151,12 @@ class AdGuardHomeEntity(Entity):
self.adguard = adguard
@property
def name(self) -> str:
def name(self) -> str | None:
"""Return the name of the entity."""
return self._name
@property
def icon(self) -> str:
def icon(self) -> str | None:
"""Return the mdi icon of the entity."""
return self._icon

View File

@ -1,11 +1,14 @@
"""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
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
@ -19,6 +22,81 @@ SCAN_INTERVAL = timedelta(seconds=300)
PARALLEL_UPDATES = 4
@dataclass
class AdGuardHomeEntityDescriptionMixin:
"""Mixin for required keys."""
value_fn: Callable[[AdGuardHome], Callable[[], 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.stats.avg_processing_time,
entity_registry_enabled_default=False,
),
)
async def async_setup_entry(
hass: HomeAssistant,
entry: ConfigEntry,
@ -34,215 +112,47 @@ async def async_setup_entry(
hass.data[DOMAIN][entry.entry_id][DATA_ADGUARD_VERSION] = version
sensors = [
AdGuardHomeDNSQueriesSensor(adguard, entry),
AdGuardHomeBlockedFilteringSensor(adguard, entry),
AdGuardHomePercentageBlockedSensor(adguard, entry),
AdGuardHomeReplacedParentalSensor(adguard, entry),
AdGuardHomeReplacedSafeBrowsingSensor(adguard, entry),
AdGuardHomeReplacedSafeSearchSensor(adguard, entry),
AdGuardHomeAverageProcessingTimeSensor(adguard, entry),
AdGuardHomeRulesCountSensor(adguard, entry),
]
async_add_entities(sensors, True)
async_add_entities(
[AdGuardHomeSensor(adguard, entry, description) for description in SENSORS],
True,
)
class AdGuardHomeSensor(AdGuardHomeDeviceEntity, SensorEntity):
"""Defines a AdGuard Home sensor."""
entity_description: AdGuardHomeEntityDescription
def __init__(
self,
adguard: AdGuardHome,
entry: ConfigEntry,
name: str,
icon: str,
measurement: str,
unit_of_measurement: str,
enabled_default: bool = True,
description: AdGuardHomeEntityDescription,
) -> None:
"""Initialize AdGuard Home sensor."""
self._state: int | str | None = None
self._unit_of_measurement = unit_of_measurement
self.measurement = measurement
self.entity_description = description
super().__init__(adguard, entry, name, icon, enabled_default)
@property
def unique_id(self) -> str:
"""Return the unique ID for this sensor."""
return "_".join(
self._attr_unique_id = "_".join(
[
DOMAIN,
self.adguard.host,
str(self.adguard.port),
adguard.host,
str(adguard.port),
"sensor",
self.measurement,
description.key,
]
)
@property
def native_value(self) -> int | str | None:
"""Return the state of the sensor."""
return self._state
@property
def native_unit_of_measurement(self) -> str | None:
"""Return the unit this state is expressed in."""
return self._unit_of_measurement
class AdGuardHomeDNSQueriesSensor(AdGuardHomeSensor):
"""Defines a AdGuard Home DNS Queries sensor."""
def __init__(self, adguard: AdGuardHome, entry: ConfigEntry) -> None:
"""Initialize AdGuard Home sensor."""
super().__init__(
adguard,
entry,
"DNS queries",
"mdi:magnify",
"dns_queries",
"queries",
description.name,
description.icon,
description.entity_registry_enabled_default,
)
async def _adguard_update(self) -> None:
"""Update AdGuard Home entity."""
self._state = await self.adguard.stats.dns_queries()
class AdGuardHomeBlockedFilteringSensor(AdGuardHomeSensor):
"""Defines a AdGuard Home blocked by filtering sensor."""
def __init__(self, adguard: AdGuardHome, entry: ConfigEntry) -> None:
"""Initialize AdGuard Home sensor."""
super().__init__(
adguard,
entry,
"DNS queries blocked",
"mdi:magnify-close",
"blocked_filtering",
"queries",
enabled_default=False,
)
async def _adguard_update(self) -> None:
"""Update AdGuard Home entity."""
self._state = await self.adguard.stats.blocked_filtering()
class AdGuardHomePercentageBlockedSensor(AdGuardHomeSensor):
"""Defines a AdGuard Home blocked percentage sensor."""
def __init__(self, adguard: AdGuardHome, entry: ConfigEntry) -> None:
"""Initialize AdGuard Home sensor."""
super().__init__(
adguard,
entry,
"DNS queries blocked ratio",
"mdi:magnify-close",
"blocked_percentage",
PERCENTAGE,
)
async def _adguard_update(self) -> None:
"""Update AdGuard Home entity."""
percentage = await self.adguard.stats.blocked_percentage()
self._state = f"{percentage:.2f}"
class AdGuardHomeReplacedParentalSensor(AdGuardHomeSensor):
"""Defines a AdGuard Home replaced by parental control sensor."""
def __init__(self, adguard: AdGuardHome, entry: ConfigEntry) -> None:
"""Initialize AdGuard Home sensor."""
super().__init__(
adguard,
entry,
"Parental control blocked",
"mdi:human-male-girl",
"blocked_parental",
"requests",
)
async def _adguard_update(self) -> None:
"""Update AdGuard Home entity."""
self._state = await self.adguard.stats.replaced_parental()
class AdGuardHomeReplacedSafeBrowsingSensor(AdGuardHomeSensor):
"""Defines a AdGuard Home replaced by safe browsing sensor."""
def __init__(self, adguard: AdGuardHome, entry: ConfigEntry) -> None:
"""Initialize AdGuard Home sensor."""
super().__init__(
adguard,
entry,
"Safe browsing blocked",
"mdi:shield-half-full",
"blocked_safebrowsing",
"requests",
)
async def _adguard_update(self) -> None:
"""Update AdGuard Home entity."""
self._state = await self.adguard.stats.replaced_safebrowsing()
class AdGuardHomeReplacedSafeSearchSensor(AdGuardHomeSensor):
"""Defines a AdGuard Home replaced by safe search sensor."""
def __init__(self, adguard: AdGuardHome, entry: ConfigEntry) -> None:
"""Initialize AdGuard Home sensor."""
super().__init__(
adguard,
entry,
"Safe searches enforced",
"mdi:shield-search",
"enforced_safesearch",
"requests",
)
async def _adguard_update(self) -> None:
"""Update AdGuard Home entity."""
self._state = await self.adguard.stats.replaced_safesearch()
class AdGuardHomeAverageProcessingTimeSensor(AdGuardHomeSensor):
"""Defines a AdGuard Home average processing time sensor."""
def __init__(self, adguard: AdGuardHome, entry: ConfigEntry) -> None:
"""Initialize AdGuard Home sensor."""
super().__init__(
adguard,
entry,
"Average processing speed",
"mdi:speedometer",
"average_speed",
TIME_MILLISECONDS,
)
async def _adguard_update(self) -> None:
"""Update AdGuard Home entity."""
average = await self.adguard.stats.avg_processing_time()
self._state = f"{average:.2f}"
class AdGuardHomeRulesCountSensor(AdGuardHomeSensor):
"""Defines a AdGuard Home rules count sensor."""
def __init__(self, adguard: AdGuardHome, entry: ConfigEntry) -> None:
"""Initialize AdGuard Home sensor."""
super().__init__(
adguard,
entry,
"Rules count",
"mdi:counter",
"rules_count",
"rules",
enabled_default=False,
)
async def _adguard_update(self) -> None:
"""Update AdGuard Home entity."""
self._state = await self.adguard.filtering.rules_count(allowlist=False)
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}"