diff --git a/homeassistant/components/shelly/button.py b/homeassistant/components/shelly/button.py index 2a594a638ce..131682319fa 100644 --- a/homeassistant/components/shelly/button.py +++ b/homeassistant/components/shelly/button.py @@ -30,6 +30,7 @@ from .const import ( MODEL_FRANKEVER_WATER_VALVE, ROLE_GENERIC, SHELLY_GAS_MODELS, + SHELLY_WALL_DISPLAY_MODELS, ) from .coordinator import ShellyBlockCoordinator, ShellyConfigEntry, ShellyRpcCoordinator from .entity import ( @@ -62,6 +63,7 @@ class ShellyButtonDescription[ """Class to describe a Button entity.""" press_action: str + params: dict[str, Any] | None = None supported: Callable[[_ShellyCoordinatorT], bool] = lambda _: True @@ -103,6 +105,20 @@ BUTTONS: Final[list[ShellyButtonDescription[Any]]] = [ press_action="trigger_shelly_gas_unmute", supported=lambda coordinator: coordinator.model in SHELLY_GAS_MODELS, ), + ShellyButtonDescription[ShellyRpcCoordinator]( + key="turn_on_screen", + name="Turn on the screen", + press_action="wall_display_set_screen", + params={"value": True}, + supported=lambda coordinator: coordinator.model in SHELLY_WALL_DISPLAY_MODELS, + ), + ShellyButtonDescription[ShellyRpcCoordinator]( + key="turn_off_screen", + name="Turn off the screen", + press_action="wall_display_set_screen", + params={"value": False}, + supported=lambda coordinator: coordinator.model in SHELLY_WALL_DISPLAY_MODELS, + ), ] @@ -317,7 +333,7 @@ class ShellyButton(ShellyBaseButton): if TYPE_CHECKING: assert method is not None - await method() + await method(**(self.entity_description.params or {})) class ShellyBluTrvButton(ShellyRpcAttributeEntity, ButtonEntity): diff --git a/homeassistant/components/shelly/const.py b/homeassistant/components/shelly/const.py index 52fd6dba2fe..f51a4dfc7b5 100644 --- a/homeassistant/components/shelly/const.py +++ b/homeassistant/components/shelly/const.py @@ -223,6 +223,11 @@ UPTIME_DEVIATION: Final = 60 ENTRY_RELOAD_COOLDOWN = 60 SHELLY_GAS_MODELS = [MODEL_GAS] +SHELLY_WALL_DISPLAY_MODELS = ( + MODEL_WALL_DISPLAY, + MODEL_WALL_DISPLAY_X2, + MODEL_WALL_DISPLAY_XL, +) CONF_BLE_SCANNER_MODE = "ble_scanner_mode" diff --git a/tests/components/shelly/snapshots/test_button.ambr b/tests/components/shelly/snapshots/test_button.ambr index 2f890ab2152..9d70cf75370 100644 --- a/tests/components/shelly/snapshots/test_button.ambr +++ b/tests/components/shelly/snapshots/test_button.ambr @@ -144,6 +144,102 @@ 'state': 'unknown', }) # --- +# name: test_wall_display_screen_buttons[turn_off-False][button.test_name_turn_off_the_screen-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'button', + 'entity_category': None, + 'entity_id': 'button.test_name_turn_off_the_screen', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Turn off the screen', + 'platform': 'shelly', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': '123456789ABC-turn_off_screen', + 'unit_of_measurement': None, + }) +# --- +# name: test_wall_display_screen_buttons[turn_off-False][button.test_name_turn_off_the_screen-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Test name Turn off the screen', + }), + 'context': , + 'entity_id': 'button.test_name_turn_off_the_screen', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'unknown', + }) +# --- +# name: test_wall_display_screen_buttons[turn_on-True][button.test_name_turn_on_the_screen-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'button', + 'entity_category': None, + 'entity_id': 'button.test_name_turn_on_the_screen', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Turn on the screen', + 'platform': 'shelly', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': '123456789ABC-turn_on_screen', + 'unit_of_measurement': None, + }) +# --- +# name: test_wall_display_screen_buttons[turn_on-True][button.test_name_turn_on_the_screen-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Test name Turn on the screen', + }), + 'context': , + 'entity_id': 'button.test_name_turn_on_the_screen', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'unknown', + }) +# --- # name: test_wall_display_virtual_button[button.test_name_button-entry] EntityRegistryEntrySnapshot({ 'aliases': set({ diff --git a/tests/components/shelly/snapshots/test_devices.ambr b/tests/components/shelly/snapshots/test_devices.ambr index 65e8528984d..17cc33572d4 100644 --- a/tests/components/shelly/snapshots/test_devices.ambr +++ b/tests/components/shelly/snapshots/test_devices.ambr @@ -5374,6 +5374,102 @@ 'state': 'unknown', }) # --- +# name: test_device[wall_display_xl][button.test_name_turn_off_the_screen-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'button', + 'entity_category': None, + 'entity_id': 'button.test_name_turn_off_the_screen', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Turn off the screen', + 'platform': 'shelly', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': '123456789ABC-turn_off_screen', + 'unit_of_measurement': None, + }) +# --- +# name: test_device[wall_display_xl][button.test_name_turn_off_the_screen-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Test name Turn off the screen', + }), + 'context': , + 'entity_id': 'button.test_name_turn_off_the_screen', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'unknown', + }) +# --- +# name: test_device[wall_display_xl][button.test_name_turn_on_the_screen-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'button', + 'entity_category': None, + 'entity_id': 'button.test_name_turn_on_the_screen', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Turn on the screen', + 'platform': 'shelly', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': '123456789ABC-turn_on_screen', + 'unit_of_measurement': None, + }) +# --- +# name: test_device[wall_display_xl][button.test_name_turn_on_the_screen-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Test name Turn on the screen', + }), + 'context': , + 'entity_id': 'button.test_name_turn_on_the_screen', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'unknown', + }) +# --- # name: test_device[wall_display_xl][event.test_name_input_0-entry] EntityRegistryEntrySnapshot({ 'aliases': set({ diff --git a/tests/components/shelly/test_button.py b/tests/components/shelly/test_button.py index 8b618ef7187..bfc240d639d 100644 --- a/tests/components/shelly/test_button.py +++ b/tests/components/shelly/test_button.py @@ -3,7 +3,7 @@ from copy import deepcopy from unittest.mock import Mock -from aioshelly.const import MODEL_BLU_GATEWAY_G3, MODEL_PLUS_SMOKE +from aioshelly.const import MODEL_BLU_GATEWAY_G3, MODEL_PLUS_SMOKE, MODEL_WALL_DISPLAY from aioshelly.exceptions import DeviceConnectionError, InvalidAuthError, RpcCallError import pytest from syrupy.assertion import SnapshotAssertion @@ -538,3 +538,31 @@ async def test_rpc_smoke_mute_alarm_button( ) mock_rpc_device.mock_update() mock_rpc_device.smoke_mute_alarm.assert_called_once_with(0) + + +@pytest.mark.parametrize(("action", "value"), [("turn_on", True), ("turn_off", False)]) +async def test_wall_display_screen_buttons( + hass: HomeAssistant, + entity_registry: EntityRegistry, + mock_rpc_device: Mock, + snapshot: SnapshotAssertion, + action: str, + value: bool, +) -> None: + """Test a Wall Display screen buttons.""" + await init_integration(hass, 2, model=MODEL_WALL_DISPLAY) + entity_id = f"button.test_name_{action}_the_screen" + + assert (state := hass.states.get(entity_id)) + assert state == snapshot(name=f"{entity_id}-state") + + assert (entry := entity_registry.async_get(entity_id)) + assert entry == snapshot(name=f"{entity_id}-entry") + + await hass.services.async_call( + BUTTON_DOMAIN, + SERVICE_PRESS, + {ATTR_ENTITY_ID: entity_id}, + blocking=True, + ) + mock_rpc_device.wall_display_set_screen.assert_called_once_with(value=value)