Add button platform to opentherm_gw (#125185)

* Add button platform to opentherm_gw

* Add tests for button.py

* Update tests/components/opentherm_gw/test_button.py

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
This commit is contained in:
mvn23 2024-09-04 19:20:05 +02:00 committed by GitHub
parent bad305dcbf
commit 892c32c8b7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 124 additions and 1 deletions

View File

@ -90,7 +90,7 @@ CONFIG_SCHEMA = vol.Schema(
extra=vol.ALLOW_EXTRA,
)
PLATFORMS = [Platform.BINARY_SENSOR, Platform.CLIMATE, Platform.SENSOR]
PLATFORMS = [Platform.BINARY_SENSOR, Platform.BUTTON, Platform.CLIMATE, Platform.SENSOR]
async def options_updated(hass: HomeAssistant, entry: ConfigEntry) -> None:

View File

@ -0,0 +1,73 @@
"""Support for OpenTherm Gateway buttons."""
from collections.abc import Awaitable, Callable
from dataclasses import dataclass
import pyotgw.vars as gw_vars
from homeassistant.components.button import (
ButtonDeviceClass,
ButtonEntity,
ButtonEntityDescription,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_ID, EntityCategory
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import OpenThermGatewayHub
from .const import (
DATA_GATEWAYS,
DATA_OPENTHERM_GW,
GATEWAY_DEVICE_DESCRIPTION,
OpenThermDataSource,
)
from .entity import OpenThermEntity, OpenThermEntityDescription
@dataclass(frozen=True, kw_only=True)
class OpenThermButtonEntityDescription(
ButtonEntityDescription, OpenThermEntityDescription
):
"""Describes an opentherm_gw button entity."""
action: Callable[[OpenThermGatewayHub], Awaitable]
BUTTON_DESCRIPTIONS: tuple[OpenThermButtonEntityDescription, ...] = (
OpenThermButtonEntityDescription(
key="restart_button",
device_class=ButtonDeviceClass.RESTART,
device_description=GATEWAY_DEVICE_DESCRIPTION,
action=lambda hub: hub.gateway.set_mode(gw_vars.OTGW_MODE_RESET),
),
)
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up the OpenTherm Gateway buttons."""
gw_hub = hass.data[DATA_OPENTHERM_GW][DATA_GATEWAYS][config_entry.data[CONF_ID]]
async_add_entities(
OpenThermButton(gw_hub, description) for description in BUTTON_DESCRIPTIONS
)
class OpenThermButton(OpenThermEntity, ButtonEntity):
"""Representation of an OpenTherm button."""
_attr_entity_category = EntityCategory.CONFIG
entity_description: OpenThermButtonEntityDescription
@callback
def receive_report(self, status: dict[OpenThermDataSource, dict]) -> None:
"""Handle status updates from the component."""
# We don't need any information from the reports here
async def async_press(self) -> None:
"""Perform button action."""
await self.entity_description.action(self._gateway)

View File

@ -0,0 +1,50 @@
"""Test opentherm_gw buttons."""
from unittest.mock import AsyncMock, MagicMock
from pyotgw.vars import OTGW_MODE_RESET
from homeassistant.components.button import DOMAIN as BUTTON_DOMAIN, SERVICE_PRESS
from homeassistant.components.opentherm_gw import DOMAIN as OPENTHERM_DOMAIN
from homeassistant.components.opentherm_gw.const import OpenThermDeviceIdentifier
from homeassistant.const import ATTR_ENTITY_ID, CONF_ID
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from .conftest import MINIMAL_STATUS
from tests.common import MockConfigEntry
async def test_restart_button(
hass: HomeAssistant,
entity_registry: er.EntityRegistry,
mock_config_entry: MockConfigEntry,
mock_pyotgw: MagicMock,
) -> None:
"""Test restart button."""
mock_pyotgw.return_value.set_mode = AsyncMock(return_value=MINIMAL_STATUS)
mock_config_entry.add_to_hass(hass)
await hass.config_entries.async_setup(mock_config_entry.entry_id)
await hass.async_block_till_done()
assert (
button_entity_id := entity_registry.async_get_entity_id(
BUTTON_DOMAIN,
OPENTHERM_DOMAIN,
f"{mock_config_entry.data[CONF_ID]}-{OpenThermDeviceIdentifier.GATEWAY}-restart_button",
)
) is not None
await hass.services.async_call(
BUTTON_DOMAIN,
SERVICE_PRESS,
{
ATTR_ENTITY_ID: button_entity_id,
},
blocking=True,
)
mock_pyotgw.return_value.set_mode.assert_awaited_once_with(OTGW_MODE_RESET)