Add button platform to Opengarage (#103569)
* Add button entity to reboot OpenGarage device * Addressing code review comments * Another code-review fix * Update homeassistant/components/opengarage/button.py Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com> --------- Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>pull/104208/head^2
parent
4fa76801af
commit
53717523e5
|
@ -18,13 +18,11 @@ from .const import CONF_DEVICE_KEY, DOMAIN
|
|||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
PLATFORMS = [Platform.BINARY_SENSOR, Platform.COVER, Platform.SENSOR]
|
||||
PLATFORMS = [Platform.BINARY_SENSOR, Platform.BUTTON, Platform.COVER, Platform.SENSOR]
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
"""Set up OpenGarage from a config entry."""
|
||||
hass.data.setdefault(DOMAIN, {})
|
||||
|
||||
open_garage_connection = opengarage.OpenGarage(
|
||||
f"{entry.data[CONF_HOST]}:{entry.data[CONF_PORT]}",
|
||||
entry.data[CONF_DEVICE_KEY],
|
||||
|
@ -36,7 +34,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||
open_garage_connection=open_garage_connection,
|
||||
)
|
||||
await open_garage_data_coordinator.async_config_entry_first_refresh()
|
||||
hass.data[DOMAIN][entry.entry_id] = open_garage_data_coordinator
|
||||
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = open_garage_data_coordinator
|
||||
|
||||
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
|
||||
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
"""OpenGarage button."""
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable
|
||||
from dataclasses import dataclass
|
||||
from typing import Any, cast
|
||||
|
||||
from opengarage import OpenGarage
|
||||
|
||||
from homeassistant.components.button import (
|
||||
ButtonDeviceClass,
|
||||
ButtonEntity,
|
||||
ButtonEntityDescription,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import EntityCategory
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from . import OpenGarageDataUpdateCoordinator
|
||||
from .const import DOMAIN
|
||||
from .entity import OpenGarageEntity
|
||||
|
||||
|
||||
@dataclass(frozen=True, kw_only=True)
|
||||
class OpenGarageButtonEntityDescription(ButtonEntityDescription):
|
||||
"""OpenGarage Browser button description."""
|
||||
|
||||
press_action: Callable[[OpenGarage], Any]
|
||||
|
||||
|
||||
BUTTONS: tuple[OpenGarageButtonEntityDescription, ...] = (
|
||||
OpenGarageButtonEntityDescription(
|
||||
key="restart",
|
||||
device_class=ButtonDeviceClass.RESTART,
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
press_action=lambda opengarage: opengarage.reboot(),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up the OpenGarage button entities."""
|
||||
coordinator: OpenGarageDataUpdateCoordinator = hass.data[DOMAIN][
|
||||
config_entry.entry_id
|
||||
]
|
||||
|
||||
async_add_entities(
|
||||
OpenGarageButtonEntity(
|
||||
coordinator, cast(str, config_entry.unique_id), description
|
||||
)
|
||||
for description in BUTTONS
|
||||
)
|
||||
|
||||
|
||||
class OpenGarageButtonEntity(OpenGarageEntity, ButtonEntity):
|
||||
"""Representation of an OpenGarage button."""
|
||||
|
||||
entity_description: OpenGarageButtonEntityDescription
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: OpenGarageDataUpdateCoordinator,
|
||||
device_id: str,
|
||||
description: OpenGarageButtonEntityDescription,
|
||||
) -> None:
|
||||
"""Initialize the button."""
|
||||
super().__init__(coordinator, device_id, description)
|
||||
|
||||
async def async_press(self) -> None:
|
||||
"""Press the button."""
|
||||
await self.entity_description.press_action(
|
||||
self.coordinator.open_garage_connection
|
||||
)
|
||||
await self.coordinator.async_refresh()
|
|
@ -0,0 +1,59 @@
|
|||
"""Fixtures for the OpenGarage integration tests."""
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Generator
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.opengarage.const import CONF_DEVICE_KEY, DOMAIN
|
||||
from homeassistant.const import CONF_HOST, CONF_PORT, CONF_VERIFY_SSL
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from tests.common import MockConfigEntry
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_config_entry() -> MockConfigEntry:
|
||||
"""Return the default mocked config entry."""
|
||||
return MockConfigEntry(
|
||||
title="Test device",
|
||||
domain=DOMAIN,
|
||||
data={
|
||||
CONF_HOST: "http://1.1.1.1",
|
||||
CONF_PORT: "80",
|
||||
CONF_DEVICE_KEY: "abc123",
|
||||
CONF_VERIFY_SSL: False,
|
||||
},
|
||||
unique_id="12345",
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_opengarage() -> Generator[MagicMock, None, None]:
|
||||
"""Return a mocked OpenGarage client."""
|
||||
with patch(
|
||||
"homeassistant.components.opengarage.opengarage.OpenGarage",
|
||||
autospec=True,
|
||||
) as client_mock:
|
||||
client = client_mock.return_value
|
||||
client.device_url = "http://1.1.1.1:80"
|
||||
client.update_state.return_value = {
|
||||
"name": "abcdef",
|
||||
"mac": "aa:bb:cc:dd:ee:ff",
|
||||
"fwv": "1.2.0",
|
||||
}
|
||||
yield client
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
async def init_integration(
|
||||
hass: HomeAssistant, mock_config_entry: MockConfigEntry, mock_opengarage: MagicMock
|
||||
) -> MockConfigEntry:
|
||||
"""Set up the OpenGarage integration for testing."""
|
||||
mock_config_entry.add_to_hass(hass)
|
||||
|
||||
await hass.config_entries.async_setup(mock_config_entry.entry_id)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
return mock_config_entry
|
|
@ -0,0 +1,33 @@
|
|||
"""Test the OpenGarage Browser buttons."""
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import homeassistant.components.button as button
|
||||
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 tests.common import MockConfigEntry
|
||||
|
||||
|
||||
async def test_buttons(
|
||||
hass: HomeAssistant,
|
||||
mock_opengarage: MagicMock,
|
||||
init_integration: MockConfigEntry,
|
||||
entity_registry: er.EntityRegistry,
|
||||
device_registry: dr.DeviceRegistry,
|
||||
) -> None:
|
||||
"""Test standard OpenGarage buttons."""
|
||||
entry = entity_registry.async_get("button.abcdef_restart")
|
||||
assert entry
|
||||
assert entry.unique_id == "12345_restart"
|
||||
await hass.services.async_call(
|
||||
button.DOMAIN,
|
||||
button.SERVICE_PRESS,
|
||||
{ATTR_ENTITY_ID: "button.abcdef_restart"},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(mock_opengarage.reboot.mock_calls) == 1
|
||||
|
||||
assert entry.device_id
|
||||
device_entry = device_registry.async_get(entry.device_id)
|
||||
assert device_entry
|
Loading…
Reference in New Issue