core/homeassistant/components/husqvarna_automower/button.py

106 lines
3.4 KiB
Python

"""Creates button entities for the Husqvarna Automower integration."""
from collections.abc import Awaitable, Callable
from dataclasses import dataclass
import logging
from typing import Any
from aioautomower.model import MowerAttributes
from aioautomower.session import AutomowerSession
from homeassistant.components.button import ButtonEntity, ButtonEntityDescription
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.util import dt as dt_util
from . import AutomowerConfigEntry
from .coordinator import AutomowerDataUpdateCoordinator
from .entity import (
AutomowerAvailableEntity,
_check_error_free,
handle_sending_exception,
)
_LOGGER = logging.getLogger(__name__)
async def _async_set_time(
session: AutomowerSession,
mower_id: str,
) -> None:
"""Set datetime for the mower."""
# dt_util returns the current (aware) local datetime, set in the frontend.
# We assume it's the timezone in which the mower is.
await session.commands.set_datetime(
mower_id,
dt_util.now(),
)
@dataclass(frozen=True, kw_only=True)
class AutomowerButtonEntityDescription(ButtonEntityDescription):
"""Describes Automower button entities."""
available_fn: Callable[[MowerAttributes], bool] = lambda _: True
exists_fn: Callable[[MowerAttributes], bool] = lambda _: True
press_fn: Callable[[AutomowerSession, str], Awaitable[Any]]
BUTTON_TYPES: tuple[AutomowerButtonEntityDescription, ...] = (
AutomowerButtonEntityDescription(
key="confirm_error",
translation_key="confirm_error",
available_fn=lambda data: data.mower.is_error_confirmable,
exists_fn=lambda data: data.capabilities.can_confirm_error,
press_fn=lambda session, mower_id: session.commands.error_confirm(mower_id),
),
AutomowerButtonEntityDescription(
key="sync_clock",
translation_key="sync_clock",
available_fn=_check_error_free,
press_fn=_async_set_time,
),
)
async def async_setup_entry(
hass: HomeAssistant,
entry: AutomowerConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up button platform."""
coordinator = entry.runtime_data
async_add_entities(
AutomowerButtonEntity(mower_id, coordinator, description)
for mower_id in coordinator.data
for description in BUTTON_TYPES
if description.exists_fn(coordinator.data[mower_id])
)
class AutomowerButtonEntity(AutomowerAvailableEntity, ButtonEntity):
"""Defining the AutomowerButtonEntity."""
entity_description: AutomowerButtonEntityDescription
def __init__(
self,
mower_id: str,
coordinator: AutomowerDataUpdateCoordinator,
description: AutomowerButtonEntityDescription,
) -> None:
"""Set up AutomowerButtonEntity."""
super().__init__(mower_id, coordinator)
self.entity_description = description
self._attr_unique_id = f"{mower_id}_{description.key}"
@property
def available(self) -> bool:
"""Return the available attribute of the entity."""
return self.entity_description.available_fn(self.mower_attributes)
@handle_sending_exception()
async def async_press(self) -> None:
"""Send a command to the mower."""
await self.entity_description.press_fn(self.coordinator.api, self.mower_id)