diff --git a/homeassistant/components/lektrico/__init__.py b/homeassistant/components/lektrico/__init__.py index 70dbecca77a..746d14f3605 100644 --- a/homeassistant/components/lektrico/__init__.py +++ b/homeassistant/components/lektrico/__init__.py @@ -11,10 +11,10 @@ from homeassistant.core import HomeAssistant from .coordinator import LektricoDeviceDataUpdateCoordinator # List the platforms that charger supports. -CHARGERS_PLATFORMS = [Platform.SENSOR] +CHARGERS_PLATFORMS: list[Platform] = [Platform.BUTTON, Platform.SENSOR] # List the platforms that load balancer device supports. -LB_DEVICES_PLATFORMS = [Platform.SENSOR] +LB_DEVICES_PLATFORMS: list[Platform] = [Platform.BUTTON, Platform.SENSOR] type LektricoConfigEntry = ConfigEntry[LektricoDeviceDataUpdateCoordinator] diff --git a/homeassistant/components/lektrico/button.py b/homeassistant/components/lektrico/button.py new file mode 100644 index 00000000000..62aef12ff53 --- /dev/null +++ b/homeassistant/components/lektrico/button.py @@ -0,0 +1,102 @@ +"""Support for Lektrico buttons.""" + +from collections.abc import Callable, Coroutine +from dataclasses import dataclass +from typing import Any + +from lektricowifi import Device + +from homeassistant.components.button import ( + ButtonDeviceClass, + ButtonEntity, + ButtonEntityDescription, +) +from homeassistant.const import ATTR_SERIAL_NUMBER, CONF_TYPE, EntityCategory +from homeassistant.core import HomeAssistant +from homeassistant.helpers.entity_platform import AddEntitiesCallback + +from . import LektricoConfigEntry, LektricoDeviceDataUpdateCoordinator +from .entity import LektricoEntity + + +@dataclass(frozen=True, kw_only=True) +class LektricoButtonEntityDescription(ButtonEntityDescription): + """Describes Lektrico button entity.""" + + press_fn: Callable[[Device], Coroutine[Any, Any, dict[Any, Any]]] + + +BUTTONS_FOR_CHARGERS: tuple[LektricoButtonEntityDescription, ...] = ( + LektricoButtonEntityDescription( + key="charge_start", + translation_key="charge_start", + entity_category=EntityCategory.CONFIG, + press_fn=lambda device: device.send_charge_start(), + ), + LektricoButtonEntityDescription( + key="charge_stop", + translation_key="charge_stop", + entity_category=EntityCategory.CONFIG, + press_fn=lambda device: device.send_charge_stop(), + ), + LektricoButtonEntityDescription( + key="reboot", + device_class=ButtonDeviceClass.RESTART, + entity_category=EntityCategory.CONFIG, + press_fn=lambda device: device.send_reset(), + ), +) + +BUTTONS_FOR_LB_DEVICES: tuple[LektricoButtonEntityDescription, ...] = ( + LektricoButtonEntityDescription( + key="reboot", + device_class=ButtonDeviceClass.RESTART, + entity_category=EntityCategory.CONFIG, + press_fn=lambda device: device.send_reset(), + ), +) + + +async def async_setup_entry( + hass: HomeAssistant, + entry: LektricoConfigEntry, + async_add_entities: AddEntitiesCallback, +) -> None: + """Set up Lektrico charger based on a config entry.""" + coordinator = entry.runtime_data + + buttons_to_be_used: tuple[LektricoButtonEntityDescription, ...] + if coordinator.device_type in (Device.TYPE_1P7K, Device.TYPE_3P22K): + buttons_to_be_used = BUTTONS_FOR_CHARGERS + else: + buttons_to_be_used = BUTTONS_FOR_LB_DEVICES + + async_add_entities( + LektricoButton( + description, + coordinator, + f"{entry.data[CONF_TYPE]}_{entry.data[ATTR_SERIAL_NUMBER]}", + ) + for description in buttons_to_be_used + ) + + +class LektricoButton(LektricoEntity, ButtonEntity): + """Defines an Lektrico button.""" + + entity_description: LektricoButtonEntityDescription + + def __init__( + self, + description: LektricoButtonEntityDescription, + coordinator: LektricoDeviceDataUpdateCoordinator, + device_name: str, + ) -> None: + """Initialize Lektrico button.""" + super().__init__(coordinator, device_name) + self.entity_description = description + self._attr_unique_id = f"{coordinator.serial_number}-{description.key}" + + async def async_press(self) -> None: + """Press the button.""" + await self.entity_description.press_fn(self.coordinator.device) diff --git a/homeassistant/components/lektrico/strings.json b/homeassistant/components/lektrico/strings.json index 767987e7e64..2470c0865d5 100644 --- a/homeassistant/components/lektrico/strings.json +++ b/homeassistant/components/lektrico/strings.json @@ -22,6 +22,14 @@ } }, "entity": { + "button": { + "charge_start": { + "name": "Charge start" + }, + "charge_stop": { + "name": "Charge stop" + } + }, "sensor": { "state": { "name": "State", diff --git a/tests/components/lektrico/snapshots/test_button.ambr b/tests/components/lektrico/snapshots/test_button.ambr new file mode 100644 index 00000000000..5070cd484c4 --- /dev/null +++ b/tests/components/lektrico/snapshots/test_button.ambr @@ -0,0 +1,140 @@ +# serializer version: 1 +# name: test_all_entities[button.1p7k_500006_charge_start-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'button', + 'entity_category': , + 'entity_id': 'button.1p7k_500006_charge_start', + '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': 'Charge start', + 'platform': 'lektrico', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'charge_start', + 'unique_id': '500006-charge_start', + 'unit_of_measurement': None, + }) +# --- +# name: test_all_entities[button.1p7k_500006_charge_start-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': '1p7k_500006 Charge start', + }), + 'context': , + 'entity_id': 'button.1p7k_500006_charge_start', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'unknown', + }) +# --- +# name: test_all_entities[button.1p7k_500006_charge_stop-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'button', + 'entity_category': , + 'entity_id': 'button.1p7k_500006_charge_stop', + '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': 'Charge stop', + 'platform': 'lektrico', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'charge_stop', + 'unique_id': '500006-charge_stop', + 'unit_of_measurement': None, + }) +# --- +# name: test_all_entities[button.1p7k_500006_charge_stop-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': '1p7k_500006 Charge stop', + }), + 'context': , + 'entity_id': 'button.1p7k_500006_charge_stop', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'unknown', + }) +# --- +# name: test_all_entities[button.1p7k_500006_restart-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'button', + 'entity_category': , + 'entity_id': 'button.1p7k_500006_restart', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Restart', + 'platform': 'lektrico', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': '500006-reboot', + 'unit_of_measurement': None, + }) +# --- +# name: test_all_entities[button.1p7k_500006_restart-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'restart', + 'friendly_name': '1p7k_500006 Restart', + }), + 'context': , + 'entity_id': 'button.1p7k_500006_restart', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'unknown', + }) +# --- diff --git a/tests/components/lektrico/test_button.py b/tests/components/lektrico/test_button.py new file mode 100644 index 00000000000..7bd77848d21 --- /dev/null +++ b/tests/components/lektrico/test_button.py @@ -0,0 +1,32 @@ +"""Tests for the Lektrico button platform.""" + +from unittest.mock import AsyncMock, patch + +from syrupy import SnapshotAssertion + +from homeassistant.const import Platform +from homeassistant.core import HomeAssistant +from homeassistant.helpers import entity_registry as er + +from . import setup_integration + +from tests.common import MockConfigEntry, snapshot_platform + + +async def test_all_entities( + hass: HomeAssistant, + snapshot: SnapshotAssertion, + mock_device: AsyncMock, + mock_config_entry: MockConfigEntry, + entity_registry: er.EntityRegistry, +) -> None: + """Test all entities.""" + + with patch.multiple( + "homeassistant.components.lektrico", + CHARGERS_PLATFORMS=[Platform.BUTTON], + LB_DEVICES_PLATFORMS=[Platform.BUTTON], + ): + await setup_integration(hass, mock_config_entry) + + await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id) diff --git a/tests/components/lektrico/test_sensor.py b/tests/components/lektrico/test_sensor.py index 756f149d3ad..27be7ff1c11 100644 --- a/tests/components/lektrico/test_sensor.py +++ b/tests/components/lektrico/test_sensor.py @@ -23,8 +23,10 @@ async def test_all_entities( entity_registry: er.EntityRegistry, ) -> None: """Test all entities.""" - with patch( - "homeassistant.components.lektrico.CHARGERS_PLATFORMS", [Platform.SENSOR] + with patch.multiple( + "homeassistant.components.lektrico", + CHARGERS_PLATFORMS=[Platform.SENSOR], + LB_DEVICES_PLATFORMS=[Platform.SENSOR], ): await setup_integration(hass, mock_config_entry)