Add support for identify buttons to WMS WebControl pro (#143339)

* Remove _attr_name = None from generic base class

* Add support for identify buttons to WMS WebControl pro

* Fix PERF401 as suggested by joostlek

* Fix fixture name after rebase

* Split test

---------

Co-authored-by: Joostlek <joostlek@outlook.com>
This commit is contained in:
Marc Hörsken 2025-05-14 18:06:21 +02:00 committed by GitHub
parent 7963665c40
commit 9d451b6358
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 130 additions and 2 deletions

View File

@ -15,7 +15,12 @@ from homeassistant.helpers.typing import UNDEFINED
from .const import DOMAIN, MANUFACTURER
PLATFORMS: list[Platform] = [Platform.COVER, Platform.LIGHT, Platform.SCENE]
PLATFORMS: list[Platform] = [
Platform.BUTTON,
Platform.COVER,
Platform.LIGHT,
Platform.SCENE,
]
type WebControlProConfigEntry = ConfigEntry[WebControlPro]

View File

@ -0,0 +1,40 @@
"""Identify support for WMS WebControl pro."""
from __future__ import annotations
from wmspro.const import WMS_WebControl_pro_API_actionDescription
from homeassistant.components.button import ButtonDeviceClass, ButtonEntity
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from . import WebControlProConfigEntry
from .entity import WebControlProGenericEntity
async def async_setup_entry(
hass: HomeAssistant,
config_entry: WebControlProConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up the WMS based identify buttons from a config entry."""
hub = config_entry.runtime_data
entities: list[WebControlProGenericEntity] = [
WebControlProIdentifyButton(config_entry.entry_id, dest)
for dest in hub.dests.values()
if dest.action(WMS_WebControl_pro_API_actionDescription.Identify)
]
async_add_entities(entities)
class WebControlProIdentifyButton(WebControlProGenericEntity, ButtonEntity):
"""Representation of a WMS based identify button."""
_attr_device_class = ButtonDeviceClass.IDENTIFY
async def async_press(self) -> None:
"""Handle the button press."""
action = self._dest.action(WMS_WebControl_pro_API_actionDescription.Identify)
await action()

View File

@ -45,6 +45,7 @@ class WebControlProCover(WebControlProGenericEntity, CoverEntity):
"""Base representation of a WMS based cover."""
_drive_action_desc: WMS_WebControl_pro_API_actionDescription
_attr_name = None
@property
def current_cover_position(self) -> int | None:

View File

@ -15,7 +15,6 @@ class WebControlProGenericEntity(Entity):
_attr_attribution = ATTRIBUTION
_attr_has_entity_name = True
_attr_name = None
def __init__(self, config_entry_id: str, dest: Destination) -> None:
"""Initialize the entity with destination channel."""

View File

@ -42,6 +42,7 @@ class WebControlProLight(WebControlProGenericEntity, LightEntity):
"""Representation of a WMS based light."""
_attr_color_mode = ColorMode.ONOFF
_attr_name = None
_attr_supported_color_modes = {ColorMode.ONOFF}
@property

View File

@ -0,0 +1,16 @@
# serializer version: 1
# name: test_button_update
StateSnapshot({
'attributes': ReadOnlyDict({
'attribution': 'Data provided by WMS WebControl pro API',
'device_class': 'identify',
'friendly_name': 'Markise Identify',
}),
'context': <ANY>,
'entity_id': 'button.markise_identify',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'unknown',
})
# ---

View File

@ -0,0 +1,66 @@
"""Test the wmspro button support."""
from unittest.mock import AsyncMock, patch
from syrupy import SnapshotAssertion
from homeassistant.components.button import DOMAIN as BUTTON_DOMAIN, SERVICE_PRESS
from homeassistant.const import ATTR_ENTITY_ID
from homeassistant.core import HomeAssistant
from . import setup_config_entry
from tests.common import MockConfigEntry
async def test_button_update(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_hub_ping: AsyncMock,
mock_hub_configuration_prod_awning_dimmer: AsyncMock,
mock_hub_status_prod_awning: AsyncMock,
mock_action_call: AsyncMock,
snapshot: SnapshotAssertion,
) -> None:
"""Test that a button entity is created and updated correctly."""
assert await setup_config_entry(hass, mock_config_entry)
assert len(mock_hub_ping.mock_calls) == 1
assert len(mock_hub_configuration_prod_awning_dimmer.mock_calls) == 1
assert len(mock_hub_status_prod_awning.mock_calls) == 2
entity = hass.states.get("button.markise_identify")
assert entity is not None
assert entity == snapshot
async def test_button_press(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_hub_ping: AsyncMock,
mock_hub_configuration_prod_awning_dimmer: AsyncMock,
mock_hub_status_prod_awning: AsyncMock,
mock_action_call: AsyncMock,
) -> None:
"""Test that a button entity is pressed correctly."""
assert await setup_config_entry(hass, mock_config_entry)
with patch(
"wmspro.destination.Destination.refresh",
return_value=True,
):
before = len(mock_hub_status_prod_awning.mock_calls)
entity = hass.states.get("button.markise_identify")
before_state = entity.state
await hass.services.async_call(
BUTTON_DOMAIN,
SERVICE_PRESS,
{ATTR_ENTITY_ID: entity.entity_id},
blocking=True,
)
entity = hass.states.get("button.markise_identify")
assert entity is not None
assert entity.state != before_state
assert len(mock_hub_status_prod_awning.mock_calls) == before