diff --git a/homeassistant/components/idasen_desk/__init__.py b/homeassistant/components/idasen_desk/__init__.py index 9496752dce7..0a17ebec96c 100644 --- a/homeassistant/components/idasen_desk/__init__.py +++ b/homeassistant/components/idasen_desk/__init__.py @@ -24,7 +24,7 @@ from homeassistant.helpers.update_coordinator import DataUpdateCoordinator from .const import DOMAIN -PLATFORMS: list[Platform] = [Platform.COVER] +PLATFORMS: list[Platform] = [Platform.BUTTON, Platform.COVER] _LOGGER = logging.getLogger(__name__) diff --git a/homeassistant/components/idasen_desk/button.py b/homeassistant/components/idasen_desk/button.py new file mode 100644 index 00000000000..6cae9a42895 --- /dev/null +++ b/homeassistant/components/idasen_desk/button.py @@ -0,0 +1,101 @@ +"""Representation of Idasen Desk buttons.""" +from collections.abc import Callable, Coroutine +from dataclasses import dataclass +import logging +from typing import Any, Final + +from homeassistant.components.button import ( + ButtonDeviceClass, + ButtonEntity, + ButtonEntityDescription, +) +from homeassistant.config_entries import ConfigEntry +from homeassistant.const import EntityCategory +from homeassistant.core import HomeAssistant +from homeassistant.helpers.device_registry import DeviceInfo +from homeassistant.helpers.entity_platform import AddEntitiesCallback + +from . import DeskData, IdasenDeskCoordinator +from .const import DOMAIN + +_LOGGER = logging.getLogger(__name__) + + +@dataclass +class IdasenDeskButtonDescriptionMixin: + """Mixin to describe a IdasenDesk button entity.""" + + press_action: Callable[ + [IdasenDeskCoordinator], Callable[[], Coroutine[Any, Any, Any]] + ] + + +@dataclass +class IdasenDeskButtonDescription( + ButtonEntityDescription, IdasenDeskButtonDescriptionMixin +): + """Class to describe a IdasenDesk button entity.""" + + +BUTTONS: Final = [ + IdasenDeskButtonDescription( + key="connect", + name="Connect", + icon="mdi:bluetooth-connect", + device_class=ButtonDeviceClass.RESTART, + entity_category=EntityCategory.CONFIG, + press_action=lambda coordinator: coordinator.async_connect, + ), + IdasenDeskButtonDescription( + key="disconnect", + name="Disconnect", + icon="mdi:bluetooth-off", + device_class=ButtonDeviceClass.RESTART, + entity_category=EntityCategory.CONFIG, + press_action=lambda coordinator: coordinator.async_disconnect, + ), +] + + +async def async_setup_entry( + hass: HomeAssistant, + entry: ConfigEntry, + async_add_entities: AddEntitiesCallback, +) -> None: + """Set buttons for device.""" + data: DeskData = hass.data[DOMAIN][entry.entry_id] + async_add_entities( + IdasenDeskButton(data.address, data.device_info, data.coordinator, button) + for button in BUTTONS + ) + + +class IdasenDeskButton(ButtonEntity): + """Defines a IdasenDesk button.""" + + entity_description: IdasenDeskButtonDescription + _attr_has_entity_name = True + + def __init__( + self, + address: str, + device_info: DeviceInfo, + coordinator: IdasenDeskCoordinator, + description: IdasenDeskButtonDescription, + ) -> None: + """Initialize the IdasenDesk button entity.""" + self.entity_description = description + + self._attr_unique_id = f"{self.entity_description.key}-{address}" + self._attr_device_info = device_info + self._address = address + self._coordinator = coordinator + + async def async_press(self) -> None: + """Triggers the IdasenDesk button press service.""" + _LOGGER.debug( + "Trigger %s for %s", + self.entity_description.key, + self._address, + ) + await self.entity_description.press_action(self._coordinator)() diff --git a/tests/components/idasen_desk/test_buttons.py b/tests/components/idasen_desk/test_buttons.py new file mode 100644 index 00000000000..d576b2fe580 --- /dev/null +++ b/tests/components/idasen_desk/test_buttons.py @@ -0,0 +1,33 @@ +"""Test the IKEA Idasen Desk connection buttons.""" +from unittest.mock import MagicMock + +from homeassistant.core import HomeAssistant + +from . import init_integration + + +async def test_connect_button( + hass: HomeAssistant, + mock_desk_api: MagicMock, +) -> None: + """Test pressing the connect button.""" + await init_integration(hass) + + await hass.services.async_call( + "button", "press", {"entity_id": "button.test_connect"}, blocking=True + ) + assert mock_desk_api.connect.call_count == 2 + + +async def test_disconnect_button( + hass: HomeAssistant, + mock_desk_api: MagicMock, +) -> None: + """Test pressing the disconnect button.""" + await init_integration(hass) + mock_desk_api.is_connected = True + + await hass.services.async_call( + "button", "press", {"entity_id": "button.test_disconnect"}, blocking=True + ) + mock_desk_api.disconnect.assert_called_once()