Add Ring Intercom open door button (#113514)

* Add button

* Make Ruff happy

* Apply suggestions from code review

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>

* Fix doc string

* Format

* Update tests/components/ring/test_button.py

---------

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
This commit is contained in:
cosimomeli 2024-03-15 15:31:51 +01:00 committed by GitHub
parent a9fb34d9c2
commit 4107cd6ad8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 119 additions and 0 deletions

View file

@ -0,0 +1,57 @@
"""Component providing support for Ring buttons."""
from __future__ import annotations
from homeassistant.components.button import ButtonEntity, ButtonEntityDescription
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DOMAIN, RING_DEVICES, RING_DEVICES_COORDINATOR
from .coordinator import RingDataCoordinator
from .entity import RingEntity, exception_wrap
BUTTON_DESCRIPTION = ButtonEntityDescription(
key="open_door", translation_key="open_door"
)
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Create the buttons for the Ring devices."""
devices = hass.data[DOMAIN][config_entry.entry_id][RING_DEVICES]
devices_coordinator: RingDataCoordinator = hass.data[DOMAIN][config_entry.entry_id][
RING_DEVICES_COORDINATOR
]
async_add_entities(
RingDoorButton(device, devices_coordinator, BUTTON_DESCRIPTION)
for device in devices["other"]
if device.has_capability("open")
)
class RingDoorButton(RingEntity, ButtonEntity):
"""Creates a button to open the ring intercom door."""
def __init__(
self,
device,
coordinator,
description: ButtonEntityDescription,
) -> None:
"""Initialize the button."""
super().__init__(
device,
coordinator,
)
self.entity_description = description
self._attr_unique_id = f"{device.id}-{description.key}"
@exception_wrap
def press(self) -> None:
"""Open the door."""
self._device.open_door()

View file

@ -16,6 +16,7 @@ DEFAULT_ENTITY_NAMESPACE = "ring"
PLATFORMS = [
Platform.BINARY_SENSOR,
Platform.BUTTON,
Platform.CAMERA,
Platform.LIGHT,
Platform.SENSOR,

View file

@ -22,6 +22,9 @@
"voice_volume": {
"default": "mdi:account-voice"
},
"open_door": {
"default": "mdi:door-closed-lock"
},
"wifi_signal_category": {
"default": "mdi:wifi"
},

View file

@ -37,6 +37,11 @@
"name": "Ding"
}
},
"button": {
"open_door": {
"name": "Open door"
}
},
"light": {
"light": {
"name": "[%key:component::light::title%]"

View file

@ -131,4 +131,15 @@ def requests_mock_fixture():
),
text="ok",
)
# Mocks the open door command for intercom devices
mock.put(
"https://api.ring.com/commands/v1/devices/185036587/device_rpc",
status_code=200,
text="{}",
)
# Mocks the response for getting the history of the intercom
mock.get(
"https://api.ring.com/clients_api/doorbots/185036587/history",
text=load_fixture("intercom_history.json", "ring"),
)
yield mock

View file

@ -0,0 +1,42 @@
"""The tests for the Ring button platform."""
import requests_mock
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from .common import setup_platform
async def test_entity_registry(
hass: HomeAssistant,
requests_mock: requests_mock.Mocker,
entity_registry: er.EntityRegistry,
) -> None:
"""Tests that the devices are registered in the entity registry."""
await setup_platform(hass, Platform.BUTTON)
entry = entity_registry.async_get("button.ingress_open_door")
assert entry.unique_id == "185036587-open_door"
async def test_button_opens_door(
hass: HomeAssistant, requests_mock: requests_mock.Mocker
) -> None:
"""Tests the door open button works correctly."""
await setup_platform(hass, Platform.BUTTON)
# Mocks the response for opening door
mock = requests_mock.put(
"https://api.ring.com/commands/v1/devices/185036587/device_rpc",
status_code=200,
text="{}",
)
await hass.services.async_call(
"button", "press", {"entity_id": "button.ingress_open_door"}, blocking=True
)
await hass.async_block_till_done()
assert mock.called_once