Skip to content

Commit

Permalink
Add Ring Intercom open door button (home-assistant#113514)
Browse files Browse the repository at this point in the history
* 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>
  • Loading branch information
cosimomeli and joostlek authored Mar 15, 2024
1 parent a9fb34d commit 4107cd6
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 0 deletions.
57 changes: 57 additions & 0 deletions homeassistant/components/ring/button.py
Original file line number Diff line number Diff line change
@@ -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()
1 change: 1 addition & 0 deletions homeassistant/components/ring/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

PLATFORMS = [
Platform.BINARY_SENSOR,
Platform.BUTTON,
Platform.CAMERA,
Platform.LIGHT,
Platform.SENSOR,
Expand Down
3 changes: 3 additions & 0 deletions homeassistant/components/ring/icons.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
"voice_volume": {
"default": "mdi:account-voice"
},
"open_door": {
"default": "mdi:door-closed-lock"
},
"wifi_signal_category": {
"default": "mdi:wifi"
},
Expand Down
5 changes: 5 additions & 0 deletions homeassistant/components/ring/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@
"name": "Ding"
}
},
"button": {
"open_door": {
"name": "Open door"
}
},
"light": {
"light": {
"name": "[%key:component::light::title%]"
Expand Down
11 changes: 11 additions & 0 deletions tests/components/ring/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
42 changes: 42 additions & 0 deletions tests/components/ring/test_button.py
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 4107cd6

Please sign in to comment.