mirror of
https://github.com/home-assistant/core.git
synced 2026-08-28 02:24:46 -05:00
snoo: add button entity for calling start_snoo (#151052)
Co-authored-by: Joostlek <joostlek@outlook.com>
This commit is contained in:
@@ -19,6 +19,7 @@ _LOGGER = logging.getLogger(__name__)
|
||||
|
||||
PLATFORMS: list[Platform] = [
|
||||
Platform.BINARY_SENSOR,
|
||||
Platform.BUTTON,
|
||||
Platform.EVENT,
|
||||
Platform.SELECT,
|
||||
Platform.SENSOR,
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
"""Support for Snoo Buttons."""
|
||||
|
||||
from collections.abc import Awaitable, Callable
|
||||
from dataclasses import dataclass
|
||||
|
||||
from python_snoo.containers import SnooDevice
|
||||
from python_snoo.exceptions import SnooCommandException
|
||||
from python_snoo.snoo import Snoo
|
||||
|
||||
from homeassistant.components.button import ButtonEntity, ButtonEntityDescription
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||
|
||||
from .const import DOMAIN
|
||||
from .coordinator import SnooConfigEntry
|
||||
from .entity import SnooDescriptionEntity
|
||||
|
||||
|
||||
@dataclass(kw_only=True, frozen=True)
|
||||
class SnooButtonEntityDescription(ButtonEntityDescription):
|
||||
"""Description for Snoo button entities."""
|
||||
|
||||
press_fn: Callable[[Snoo, SnooDevice], Awaitable[None]]
|
||||
|
||||
|
||||
BUTTON_DESCRIPTIONS: list[SnooButtonEntityDescription] = [
|
||||
SnooButtonEntityDescription(
|
||||
key="start_snoo",
|
||||
translation_key="start_snoo",
|
||||
press_fn=lambda snoo, device: snoo.start_snoo(
|
||||
device,
|
||||
),
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
entry: SnooConfigEntry,
|
||||
async_add_entities: AddConfigEntryEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up buttons for Snoo device."""
|
||||
coordinators = entry.runtime_data
|
||||
async_add_entities(
|
||||
SnooButton(coordinator, description)
|
||||
for coordinator in coordinators.values()
|
||||
for description in BUTTON_DESCRIPTIONS
|
||||
)
|
||||
|
||||
|
||||
class SnooButton(SnooDescriptionEntity, ButtonEntity):
|
||||
"""Representation of a Snoo button."""
|
||||
|
||||
entity_description: SnooButtonEntityDescription
|
||||
|
||||
async def async_press(self) -> None:
|
||||
"""Handle the button press."""
|
||||
try:
|
||||
await self.entity_description.press_fn(
|
||||
self.coordinator.snoo,
|
||||
self.coordinator.device,
|
||||
)
|
||||
except SnooCommandException as err:
|
||||
raise HomeAssistantError(
|
||||
translation_domain=DOMAIN,
|
||||
translation_key=f"{self.entity_description.key}_failed",
|
||||
translation_placeholders={"name": str(self.name)},
|
||||
) from err
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"entity": {
|
||||
"button": {
|
||||
"start_snoo": {
|
||||
"default": "mdi:play"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,9 @@
|
||||
"select_failed": {
|
||||
"message": "Error while updating {name} to {option}"
|
||||
},
|
||||
"start_snoo_failed": {
|
||||
"message": "Starting {name} failed"
|
||||
},
|
||||
"switch_on_failed": {
|
||||
"message": "Turning {name} on failed"
|
||||
},
|
||||
@@ -41,6 +44,11 @@
|
||||
"name": "Right safety clip"
|
||||
}
|
||||
},
|
||||
"button": {
|
||||
"start_snoo": {
|
||||
"name": "Start"
|
||||
}
|
||||
},
|
||||
"event": {
|
||||
"event": {
|
||||
"name": "Snoo event",
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
# serializer version: 1
|
||||
# name: test_entities[button.test_snoo_start-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': None,
|
||||
'config_entry_id': <ANY>,
|
||||
'config_subentry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'button',
|
||||
'entity_category': None,
|
||||
'entity_id': 'button.test_snoo_start',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': None,
|
||||
'original_icon': None,
|
||||
'original_name': 'Start',
|
||||
'platform': 'snoo',
|
||||
'previous_unique_id': None,
|
||||
'suggested_object_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'start_snoo',
|
||||
'unique_id': 'random_num_start_snoo',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_entities[button.test_snoo_start-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'friendly_name': 'Test Snoo Start',
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'button.test_snoo_start',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'unavailable',
|
||||
})
|
||||
# ---
|
||||
@@ -0,0 +1,41 @@
|
||||
"""Test Snoo Buttons."""
|
||||
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
from syrupy.assertion import SnapshotAssertion
|
||||
|
||||
from homeassistant.components.button import DOMAIN as BUTTON_DOMAIN, SERVICE_PRESS
|
||||
from homeassistant.const import ATTR_ENTITY_ID, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
|
||||
from . import async_init_integration
|
||||
|
||||
from tests.common import snapshot_platform
|
||||
|
||||
|
||||
async def test_entities(
|
||||
hass: HomeAssistant,
|
||||
bypass_api: AsyncMock,
|
||||
snapshot: SnapshotAssertion,
|
||||
entity_registry: er.EntityRegistry,
|
||||
) -> None:
|
||||
"""Test buttons."""
|
||||
with patch("homeassistant.components.snoo.PLATFORMS", [Platform.BUTTON]):
|
||||
entry = await async_init_integration(hass)
|
||||
|
||||
await snapshot_platform(hass, entity_registry, snapshot, entry.entry_id)
|
||||
|
||||
|
||||
async def test_button_starts_snoo(hass: HomeAssistant, bypass_api: AsyncMock) -> None:
|
||||
"""Test start_snoo button works correctly."""
|
||||
await async_init_integration(hass)
|
||||
|
||||
await hass.services.async_call(
|
||||
BUTTON_DOMAIN,
|
||||
SERVICE_PRESS,
|
||||
{ATTR_ENTITY_ID: "button.test_snoo_start"},
|
||||
blocking=True,
|
||||
)
|
||||
|
||||
assert bypass_api.start_snoo.assert_called_once
|
||||
Reference in New Issue
Block a user