From a515562a11e446ad7b33ccbebf0334ab34423338 Mon Sep 17 00:00:00 2001 From: Josef Zweck <24647999+zweckj@users.noreply.github.com> Date: Sat, 15 Jun 2024 11:33:29 +0200 Subject: [PATCH] Bring back auto on off switches to lamarzocco (#119421) * add auto on off switches --- .../components/lamarzocco/strings.json | 3 + homeassistant/components/lamarzocco/switch.py | 55 ++++++++++- .../lamarzocco/snapshots/test_switch.ambr | 92 +++++++++++++++++++ tests/components/lamarzocco/test_switch.py | 54 ++++++++++- 4 files changed, 201 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/lamarzocco/strings.json b/homeassistant/components/lamarzocco/strings.json index 744f4a0d63f..f6b979a30ae 100644 --- a/homeassistant/components/lamarzocco/strings.json +++ b/homeassistant/components/lamarzocco/strings.json @@ -139,6 +139,9 @@ } }, "switch": { + "auto_on_off": { + "name": "Auto on/off ({id})" + }, "steam_boiler": { "name": "Steam boiler" } diff --git a/homeassistant/components/lamarzocco/switch.py b/homeassistant/components/lamarzocco/switch.py index 1661917fcbc..e21cd2f3d94 100644 --- a/homeassistant/components/lamarzocco/switch.py +++ b/homeassistant/components/lamarzocco/switch.py @@ -13,7 +13,8 @@ from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback from . import LaMarzoccoConfigEntry -from .entity import LaMarzoccoEntity, LaMarzoccoEntityDescription +from .coordinator import LaMarzoccoUpdateCoordinator +from .entity import LaMarzoccoBaseEntity, LaMarzoccoEntity, LaMarzoccoEntityDescription @dataclass(frozen=True, kw_only=True) @@ -52,12 +53,21 @@ async def async_setup_entry( """Set up switch entities and services.""" coordinator = entry.runtime_data - async_add_entities( + + entities: list[SwitchEntity] = [] + entities.extend( LaMarzoccoSwitchEntity(coordinator, description) for description in ENTITIES if description.supported_fn(coordinator) ) + entities.extend( + LaMarzoccoAutoOnOffSwitchEntity(coordinator, wake_up_sleep_entry_id) + for wake_up_sleep_entry_id in coordinator.device.config.wake_up_sleep_entries + ) + + async_add_entities(entities) + class LaMarzoccoSwitchEntity(LaMarzoccoEntity, SwitchEntity): """Switches representing espresso machine power, prebrew, and auto on/off.""" @@ -78,3 +88,44 @@ class LaMarzoccoSwitchEntity(LaMarzoccoEntity, SwitchEntity): def is_on(self) -> bool: """Return true if device is on.""" return self.entity_description.is_on_fn(self.coordinator.device.config) + + +class LaMarzoccoAutoOnOffSwitchEntity(LaMarzoccoBaseEntity, SwitchEntity): + """Switch representing espresso machine auto on/off.""" + + coordinator: LaMarzoccoUpdateCoordinator + _attr_translation_key = "auto_on_off" + + def __init__( + self, + coordinator: LaMarzoccoUpdateCoordinator, + identifier: str, + ) -> None: + """Initialize the switch.""" + super().__init__(coordinator, f"auto_on_off_{identifier}") + self._identifier = identifier + self._attr_translation_placeholders = {"id": identifier} + + async def _async_enable(self, state: bool) -> None: + """Enable or disable the auto on/off schedule.""" + wake_up_sleep_entry = self.coordinator.device.config.wake_up_sleep_entries[ + self._identifier + ] + wake_up_sleep_entry.enabled = state + await self.coordinator.device.set_wake_up_sleep(wake_up_sleep_entry) + self.async_write_ha_state() + + async def async_turn_on(self, **kwargs: Any) -> None: + """Turn switch on.""" + await self._async_enable(True) + + async def async_turn_off(self, **kwargs: Any) -> None: + """Turn switch off.""" + await self._async_enable(False) + + @property + def is_on(self) -> bool: + """Return true if switch is on.""" + return self.coordinator.device.config.wake_up_sleep_entries[ + self._identifier + ].enabled diff --git a/tests/components/lamarzocco/snapshots/test_switch.ambr b/tests/components/lamarzocco/snapshots/test_switch.ambr index 00205f48c21..09864be1d5c 100644 --- a/tests/components/lamarzocco/snapshots/test_switch.ambr +++ b/tests/components/lamarzocco/snapshots/test_switch.ambr @@ -1,4 +1,96 @@ # serializer version: 1 +# name: test_auto_on_off_switches[entry.auto_on_off_Os2OswX] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'switch', + 'entity_category': None, + 'entity_id': 'switch.gs01234_auto_on_off_os2oswx', + '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': 'Auto on/off (Os2OswX)', + 'platform': 'lamarzocco', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'auto_on_off', + 'unique_id': 'GS01234_auto_on_off_Os2OswX', + 'unit_of_measurement': None, + }) +# --- +# name: test_auto_on_off_switches[entry.auto_on_off_aXFz5bJ] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'switch', + 'entity_category': None, + 'entity_id': 'switch.gs01234_auto_on_off_axfz5bj', + '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': 'Auto on/off (aXFz5bJ)', + 'platform': 'lamarzocco', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'auto_on_off', + 'unique_id': 'GS01234_auto_on_off_aXFz5bJ', + 'unit_of_measurement': None, + }) +# --- +# name: test_auto_on_off_switches[state.auto_on_off_Os2OswX] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'GS01234 Auto on/off (Os2OswX)', + }), + 'context': , + 'entity_id': 'switch.gs01234_auto_on_off_os2oswx', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'on', + }) +# --- +# name: test_auto_on_off_switches[state.auto_on_off_aXFz5bJ] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'GS01234 Auto on/off (aXFz5bJ)', + }), + 'context': , + 'entity_id': 'switch.gs01234_auto_on_off_axfz5bj', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'on', + }) +# --- # name: test_device DeviceRegistryEntrySnapshot({ 'area_id': None, diff --git a/tests/components/lamarzocco/test_switch.py b/tests/components/lamarzocco/test_switch.py index 19950a0c21e..4f60b264a1d 100644 --- a/tests/components/lamarzocco/test_switch.py +++ b/tests/components/lamarzocco/test_switch.py @@ -14,7 +14,7 @@ from homeassistant.const import ATTR_ENTITY_ID from homeassistant.core import HomeAssistant from homeassistant.helpers import device_registry as dr, entity_registry as er -from . import async_init_integration +from . import WAKE_UP_SLEEP_ENTRY_IDS, async_init_integration from tests.common import MockConfigEntry @@ -106,3 +106,55 @@ async def test_device( device = device_registry.async_get(entry.device_id) assert device assert device == snapshot + + +async def test_auto_on_off_switches( + hass: HomeAssistant, + mock_lamarzocco: MagicMock, + mock_config_entry: MockConfigEntry, + entity_registry: er.EntityRegistry, + snapshot: SnapshotAssertion, +) -> None: + """Test the auto on off/switches.""" + + await async_init_integration(hass, mock_config_entry) + + serial_number = mock_lamarzocco.serial_number + + for wake_up_sleep_entry_id in WAKE_UP_SLEEP_ENTRY_IDS: + state = hass.states.get( + f"switch.{serial_number}_auto_on_off_{wake_up_sleep_entry_id}" + ) + assert state + assert state == snapshot(name=f"state.auto_on_off_{wake_up_sleep_entry_id}") + + entry = entity_registry.async_get(state.entity_id) + assert entry + assert entry == snapshot(name=f"entry.auto_on_off_{wake_up_sleep_entry_id}") + + await hass.services.async_call( + SWITCH_DOMAIN, + SERVICE_TURN_OFF, + { + ATTR_ENTITY_ID: f"switch.{serial_number}_auto_on_off_{wake_up_sleep_entry_id}", + }, + blocking=True, + ) + + wake_up_sleep_entry = mock_lamarzocco.config.wake_up_sleep_entries[ + wake_up_sleep_entry_id + ] + wake_up_sleep_entry.enabled = False + + mock_lamarzocco.set_wake_up_sleep.assert_called_with(wake_up_sleep_entry) + + await hass.services.async_call( + SWITCH_DOMAIN, + SERVICE_TURN_ON, + { + ATTR_ENTITY_ID: f"switch.{serial_number}_auto_on_off_{wake_up_sleep_entry_id}", + }, + blocking=True, + ) + wake_up_sleep_entry.enabled = True + mock_lamarzocco.set_wake_up_sleep.assert_called_with(wake_up_sleep_entry)