"""AdGuard Control Hub binary sensor platform.""" import logging from typing import Any, Dict, List, Optional from homeassistant.components.binary_sensor import ( BinarySensorEntity, BinarySensorDeviceClass, ) from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.update_coordinator import CoordinatorEntity from homeassistant.helpers.entity import DeviceInfo, EntityCategory from .api import AdGuardHomeAPI from .const import DOMAIN, MANUFACTURER _LOGGER = logging.getLogger(__name__) async def async_setup_entry( hass: HomeAssistant, config_entry: ConfigEntry, async_add_entities: AddEntitiesCallback, ) -> None: """Set up AdGuard Control Hub binary sensor platform.""" coordinator = hass.data[DOMAIN][config_entry.entry_id]["coordinator"] api = hass.data[DOMAIN][config_entry.entry_id]["api"] entities: List[BinarySensorEntity] = [] # Add main binary sensors entities.extend([ AdGuardProtectionBinarySensor(coordinator, api), AdGuardServerRunningBinarySensor(coordinator, api), AdGuardSafeBrowsingBinarySensor(coordinator, api), AdGuardParentalControlBinarySensor(coordinator, api), AdGuardSafeSearchBinarySensor(coordinator, api), ]) # Add client-specific binary sensors for client_name in coordinator.clients: entities.extend([ AdGuardClientFilteringBinarySensor(coordinator, api, client_name), ]) async_add_entities(entities) class AdGuardBaseBinarySensor(CoordinatorEntity, BinarySensorEntity): """Base AdGuard binary sensor.""" def __init__(self, coordinator, api: AdGuardHomeAPI) -> None: """Initialize the binary sensor.""" super().__init__(coordinator) self.api = api @property def device_info(self) -> DeviceInfo: """Return device info.""" return DeviceInfo( identifiers={(DOMAIN, "adguard_home")}, name="AdGuard Home", manufacturer=MANUFACTURER, model="AdGuard Home", configuration_url=self.api.base_url, ) class AdGuardProtectionBinarySensor(AdGuardBaseBinarySensor): """AdGuard protection status binary sensor.""" def __init__(self, coordinator, api: AdGuardHomeAPI) -> None: """Initialize the binary sensor.""" super().__init__(coordinator, api) self._attr_name = "AdGuard Protection Status" self._attr_unique_id = f"{DOMAIN}_protection_status" self._attr_device_class = BinarySensorDeviceClass.SAFETY self._attr_icon = "mdi:shield-check" @property def is_on(self) -> bool: """Return true if protection is enabled.""" return self.coordinator.protection_status.get("protection_enabled", False) class AdGuardServerRunningBinarySensor(AdGuardBaseBinarySensor): """AdGuard server running binary sensor.""" def __init__(self, coordinator, api: AdGuardHomeAPI) -> None: """Initialize the binary sensor.""" super().__init__(coordinator, api) self._attr_name = "AdGuard Server Running" self._attr_unique_id = f"{DOMAIN}_server_running" self._attr_device_class = BinarySensorDeviceClass.RUNNING self._attr_icon = "mdi:server" self._attr_entity_category = EntityCategory.DIAGNOSTIC @property def is_on(self) -> bool: """Return true if server is running.""" return self.coordinator.protection_status.get("running", False) @property def available(self) -> bool: """Return if entity is available.""" return bool(self.coordinator.protection_status) class AdGuardSafeBrowsingBinarySensor(AdGuardBaseBinarySensor): """AdGuard safe browsing binary sensor.""" def __init__(self, coordinator, api: AdGuardHomeAPI) -> None: """Initialize the binary sensor.""" super().__init__(coordinator, api) self._attr_name = "AdGuard Safe Browsing" self._attr_unique_id = f"{DOMAIN}_safe_browsing" self._attr_device_class = BinarySensorDeviceClass.SAFETY self._attr_icon = "mdi:web-check" @property def is_on(self) -> bool: """Return true if safe browsing is enabled.""" return self.coordinator.protection_status.get("safebrowsing_enabled", False) class AdGuardParentalControlBinarySensor(AdGuardBaseBinarySensor): """AdGuard parental control binary sensor.""" def __init__(self, coordinator, api: AdGuardHomeAPI) -> None: """Initialize the binary sensor.""" super().__init__(coordinator, api) self._attr_name = "AdGuard Parental Control" self._attr_unique_id = f"{DOMAIN}_parental_control" self._attr_device_class = BinarySensorDeviceClass.SAFETY self._attr_icon = "mdi:account-child" @property def is_on(self) -> bool: """Return true if parental control is enabled.""" return self.coordinator.protection_status.get("parental_enabled", False) class AdGuardSafeSearchBinarySensor(AdGuardBaseBinarySensor): """AdGuard safe search binary sensor.""" def __init__(self, coordinator, api: AdGuardHomeAPI) -> None: """Initialize the binary sensor.""" super().__init__(coordinator, api) self._attr_name = "AdGuard Safe Search" self._attr_unique_id = f"{DOMAIN}_safe_search" self._attr_device_class = BinarySensorDeviceClass.SAFETY self._attr_icon = "mdi:magnify-scan" @property def is_on(self) -> bool: """Return true if safe search is enabled.""" return self.coordinator.protection_status.get("safesearch_enabled", False) class AdGuardClientFilteringBinarySensor(CoordinatorEntity, BinarySensorEntity): """AdGuard client filtering binary sensor.""" def __init__(self, coordinator, api: AdGuardHomeAPI, client_name: str) -> None: """Initialize the binary sensor.""" super().__init__(coordinator) self.api = api self._client_name = client_name self._attr_name = f"AdGuard {client_name} Filtering" self._attr_unique_id = f"{DOMAIN}_{client_name.lower().replace(' ', '_')}_filtering" self._attr_device_class = BinarySensorDeviceClass.SAFETY self._attr_icon = "mdi:filter-check" @property def device_info(self) -> DeviceInfo: """Return device info.""" return DeviceInfo( identifiers={(DOMAIN, f"client_{self._client_name}")}, name=f"AdGuard Client: {self._client_name}", manufacturer=MANUFACTURER, model="AdGuard Client", via_device=(DOMAIN, "adguard_home"), ) @property def is_on(self) -> bool: """Return true if client filtering is enabled.""" client = self.coordinator.clients.get(self._client_name, {}) return client.get("filtering_enabled", True) @property def available(self) -> bool: """Return if entity is available.""" return self._client_name in self.coordinator.clients