core/homeassistant/components/tplink/switch.py

136 lines
3.7 KiB
Python

"""Support for TPLink switch entities."""
from __future__ import annotations
from dataclasses import dataclass
import logging
from typing import Any, cast
from kasa import Feature
from homeassistant.components.switch import (
DOMAIN as SWITCH_DOMAIN,
SwitchEntity,
SwitchEntityDescription,
)
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import TPLinkConfigEntry
from .entity import (
CoordinatedTPLinkFeatureEntity,
TPLinkFeatureEntityDescription,
async_refresh_after,
)
_LOGGER = logging.getLogger(__name__)
@dataclass(frozen=True, kw_only=True)
class TPLinkSwitchEntityDescription(
SwitchEntityDescription, TPLinkFeatureEntityDescription
):
"""Base class for a TPLink feature based switch entity description."""
# Coordinator is used to centralize the data updates
# For actions the integration handles locking of concurrent device request
PARALLEL_UPDATES = 0
SWITCH_DESCRIPTIONS: tuple[TPLinkSwitchEntityDescription, ...] = (
TPLinkSwitchEntityDescription(
key="state",
),
TPLinkSwitchEntityDescription(
key="led",
),
TPLinkSwitchEntityDescription(
key="auto_update_enabled",
),
TPLinkSwitchEntityDescription(
key="auto_off_enabled",
),
TPLinkSwitchEntityDescription(
key="smooth_transitions",
),
TPLinkSwitchEntityDescription(
key="fan_sleep_mode",
),
TPLinkSwitchEntityDescription(
key="child_lock",
),
TPLinkSwitchEntityDescription(
key="pir_enabled",
),
TPLinkSwitchEntityDescription(
key="motion_detection",
),
TPLinkSwitchEntityDescription(
key="person_detection",
),
TPLinkSwitchEntityDescription(
key="tamper_detection",
),
TPLinkSwitchEntityDescription(
key="baby_cry_detection",
),
TPLinkSwitchEntityDescription(
key="carpet_boost",
),
)
SWITCH_DESCRIPTIONS_MAP = {desc.key: desc for desc in SWITCH_DESCRIPTIONS}
async def async_setup_entry(
hass: HomeAssistant,
config_entry: TPLinkConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up switches."""
data = config_entry.runtime_data
parent_coordinator = data.parent_coordinator
device = parent_coordinator.device
known_child_device_ids: set[str] = set()
first_check = True
def _check_device() -> None:
entities = CoordinatedTPLinkFeatureEntity.entities_for_device_and_its_children(
hass=hass,
device=device,
coordinator=parent_coordinator,
feature_type=Feature.Switch,
entity_class=TPLinkSwitch,
descriptions=SWITCH_DESCRIPTIONS_MAP,
platform_domain=SWITCH_DOMAIN,
known_child_device_ids=known_child_device_ids,
first_check=first_check,
)
async_add_entities(entities)
_check_device()
first_check = False
config_entry.async_on_unload(parent_coordinator.async_add_listener(_check_device))
class TPLinkSwitch(CoordinatedTPLinkFeatureEntity, SwitchEntity):
"""Representation of a feature-based TPLink switch."""
entity_description: TPLinkSwitchEntityDescription
@async_refresh_after
async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn the switch on."""
await self._feature.set_value(True)
@async_refresh_after
async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn the switch off."""
await self._feature.set_value(False)
@callback
def _async_update_attrs(self) -> bool:
"""Update the entity's attributes."""
self._attr_is_on = cast(bool | None, self._feature.value)
return True