1
0
mirror of https://github.com/home-assistant/core.git synced 2026-04-02 08:26:41 +01:00
Files
core/homeassistant/components/smartthings/button.py
2026-03-18 19:32:58 +01:00

210 lines
7.6 KiB
Python

"""Support for button entities through the SmartThings cloud API."""
from __future__ import annotations
from dataclasses import dataclass
from typing import Any
from pysmartthings import Attribute, Capability, Category, Command, SmartThings
from homeassistant.components.button import ButtonEntity, ButtonEntityDescription
from homeassistant.const import EntityCategory
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ServiceValidationError
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from . import FullDevice, SmartThingsConfigEntry
from .const import DOMAIN, MAIN
from .entity import SmartThingsEntity
@dataclass(frozen=True, kw_only=True)
class SmartThingsButtonDescription(ButtonEntityDescription):
"""Class describing SmartThings button entities."""
key: Capability
command: Command
command_identifier: str | None = None
components: list[str] | None = None
argument: int | str | list[Any] | dict[str, Any] | None = None
requires_remote_control_status: bool = False
requires_dishwasher_machine_state: set[str] | None = None
CAPABILITIES_TO_BUTTONS: dict[Capability | str, SmartThingsButtonDescription] = {
Capability.OVEN_OPERATING_STATE: SmartThingsButtonDescription(
key=Capability.OVEN_OPERATING_STATE,
translation_key="stop",
command=Command.STOP,
),
Capability.CUSTOM_WATER_FILTER: SmartThingsButtonDescription(
key=Capability.CUSTOM_WATER_FILTER,
translation_key="reset_water_filter",
command=Command.RESET_WATER_FILTER,
entity_category=EntityCategory.DIAGNOSTIC,
),
Capability.SAMSUNG_CE_HOOD_FILTER: SmartThingsButtonDescription(
key=Capability.SAMSUNG_CE_HOOD_FILTER,
translation_key="reset_hood_filter",
command=Command.RESET_HOOD_FILTER,
entity_category=EntityCategory.DIAGNOSTIC,
),
Capability.CUSTOM_HEPA_FILTER: SmartThingsButtonDescription(
key=Capability.CUSTOM_HEPA_FILTER,
translation_key="reset_hepa_filter",
command=Command.RESET_HEPA_FILTER,
entity_category=EntityCategory.DIAGNOSTIC,
components=[MAIN, "station"],
),
}
DISHWASHER_OPERATION_COMMANDS_TO_BUTTONS: dict[
Command | str, SmartThingsButtonDescription
] = {
Command.CANCEL: SmartThingsButtonDescription(
key=Capability.SAMSUNG_CE_DISHWASHER_OPERATION,
translation_key="cancel",
command_identifier="drain",
command=Command.CANCEL,
argument=[True],
requires_remote_control_status=True,
),
Command.PAUSE: SmartThingsButtonDescription(
key=Capability.SAMSUNG_CE_DISHWASHER_OPERATION,
translation_key="pause",
command=Command.PAUSE,
requires_remote_control_status=True,
requires_dishwasher_machine_state={"run"},
),
Command.RESUME: SmartThingsButtonDescription(
key=Capability.SAMSUNG_CE_DISHWASHER_OPERATION,
translation_key="resume",
command=Command.RESUME,
requires_remote_control_status=True,
requires_dishwasher_machine_state={"pause"},
),
Command.START: SmartThingsButtonDescription(
key=Capability.SAMSUNG_CE_DISHWASHER_OPERATION,
translation_key="start",
command=Command.START,
requires_remote_control_status=True,
requires_dishwasher_machine_state={"stop"},
),
}
DISHWASHER_CANCEL_AND_DRAIN_BUTTON = SmartThingsButtonDescription(
key=Capability.CUSTOM_SUPPORTED_OPTIONS,
translation_key="cancel_and_drain",
command_identifier="89",
command=Command.SET_COURSE,
argument="89",
requires_remote_control_status=True,
)
async def async_setup_entry(
hass: HomeAssistant,
entry: SmartThingsConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Add button entities for a config entry."""
entry_data = entry.runtime_data
entities: list[SmartThingsEntity] = []
entities.extend(
SmartThingsButtonEntity(
entry_data.client, device, description, Capability(capability), component
)
for capability, description in CAPABILITIES_TO_BUTTONS.items()
for device in entry_data.devices.values()
for component in description.components or [MAIN]
if component in device.status and capability in device.status[component]
)
entities.extend(
SmartThingsButtonEntity(
entry_data.client,
device,
description,
Capability.SAMSUNG_CE_DISHWASHER_OPERATION,
)
for device in entry_data.devices.values()
if Capability.SAMSUNG_CE_DISHWASHER_OPERATION in device.status[MAIN]
for description in DISHWASHER_OPERATION_COMMANDS_TO_BUTTONS.values()
)
entities.extend(
SmartThingsButtonEntity(
entry_data.client,
device,
DISHWASHER_CANCEL_AND_DRAIN_BUTTON,
Capability.CUSTOM_SUPPORTED_OPTIONS,
)
for device in entry_data.devices.values()
if (
device.device.components[MAIN].manufacturer_category == Category.DISHWASHER
and Capability.CUSTOM_SUPPORTED_OPTIONS in device.status[MAIN]
)
)
async_add_entities(entities)
class SmartThingsButtonEntity(SmartThingsEntity, ButtonEntity):
"""Define a SmartThings button."""
entity_description: SmartThingsButtonDescription
def __init__(
self,
client: SmartThings,
device: FullDevice,
entity_description: SmartThingsButtonDescription,
capability: Capability,
component: str = MAIN,
) -> None:
"""Initialize the instance."""
capabilities = set()
if entity_description.requires_remote_control_status:
capabilities.add(Capability.REMOTE_CONTROL_STATUS)
if entity_description.requires_dishwasher_machine_state:
capabilities.add(Capability.DISHWASHER_OPERATING_STATE)
super().__init__(client, device, capabilities)
self.entity_description = entity_description
self.button_capability = capability
self._attr_unique_id = f"{device.device.device_id}_{component}_{entity_description.key}_{entity_description.command}"
if entity_description.command_identifier is not None:
self._attr_unique_id += f"_{entity_description.command_identifier}"
async def async_press(self) -> None:
"""Press the button."""
self._validate_before_execute()
await self.execute_device_command(
self.button_capability,
self.entity_description.command,
self.entity_description.argument,
)
def _validate_before_execute(self) -> None:
"""Validate that the command can be executed."""
if (
self.entity_description.requires_remote_control_status
and self.get_attribute_value(
Capability.REMOTE_CONTROL_STATUS, Attribute.REMOTE_CONTROL_ENABLED
)
== "false"
):
raise ServiceValidationError(
translation_domain=DOMAIN, translation_key="remote_control_status"
)
if (
self.entity_description.requires_dishwasher_machine_state
and self.get_attribute_value(
Capability.DISHWASHER_OPERATING_STATE, Attribute.MACHINE_STATE
)
not in self.entity_description.requires_dishwasher_machine_state
):
state_list = " or ".join(
self.entity_description.requires_dishwasher_machine_state
)
raise ServiceValidationError(
f"Can only be updated when dishwasher machine state is {state_list}"
)