Skip to content

Commit

Permalink
Add in-home chime switch to ring (#126305)
Browse files Browse the repository at this point in the history
* Add in-home chime switch to ring

* Fix accidental conftest change
  • Loading branch information
sdb9696 committed Sep 20, 2024
1 parent 7787291 commit efdb107
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 10 deletions.
6 changes: 6 additions & 0 deletions homeassistant/components/ring/icons.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@
"switch": {
"siren": {
"default": "mdi:alarm-bell"
},
"in_home_chime": {
"default": "mdi:bell-ring-outline",
"state": {
"on": "mdi:bell-ring"
}
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions homeassistant/components/ring/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@
"switch": {
"siren": {
"name": "[%key:component::siren::title%]"
},
"in_home_chime": {
"name": "In-home chime"
}
}
},
Expand Down
16 changes: 15 additions & 1 deletion homeassistant/components/ring/switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
import logging
from typing import Any, Generic, Self, cast

from ring_doorbell import RingCapability, RingStickUpCam
from ring_doorbell import RingCapability, RingDoorBell, RingStickUpCam
from ring_doorbell.const import DOORBELL_EXISTING_TYPE

from homeassistant.components.switch import SwitchEntity, SwitchEntityDescription
from homeassistant.const import Platform
Expand All @@ -26,6 +27,8 @@

_LOGGER = logging.getLogger(__name__)

IN_HOME_CHIME_IS_PRESENT = {v for k, v in DOORBELL_EXISTING_TYPE.items() if k != 2}


@dataclass(frozen=True, kw_only=True)
class RingSwitchEntityDescription(
Expand Down Expand Up @@ -54,6 +57,17 @@ class RingSwitchEntityDescription(
new_platform=Platform.SIREN, breaks_in_ha_version="2025.4.0"
),
),
RingSwitchEntityDescription[RingDoorBell](
key="in_home_chime",
translation_key="in_home_chime",
exists_fn=lambda device: device.family == "doorbots"
and device.existing_doorbell_type in IN_HOME_CHIME_IS_PRESENT,
is_on_fn=lambda device: device.existing_doorbell_type_enabled or False,
turn_on_fn=lambda device: device.async_set_existing_doorbell_type_enabled(True),
turn_off_fn=lambda device: device.async_set_existing_doorbell_type_enabled(
False
),
),
)


Expand Down
16 changes: 16 additions & 0 deletions tests/components/ring/device_mocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
RingOther,
RingStickUpCam,
)
from ring_doorbell.const import DOORBELL_EXISTING_TYPE

from homeassistant.components.ring.const import DOMAIN
from homeassistant.util import dt as dt_util
Expand Down Expand Up @@ -173,6 +174,21 @@ def update_history_data(fixture):
)
)

if device_family == "doorbots":
mock_device.configure_mock(
existing_doorbell_type=DOORBELL_EXISTING_TYPE[
device_dict["settings"]["chime_settings"].get("type", 2)
]
)
mock_device.configure_mock(
existing_doorbell_type_enabled=device_dict["settings"][
"chime_settings"
].get("enable", False)
)
mock_device.async_set_existing_doorbell_type_enabled.side_effect = (
lambda i: mock_device.configure_mock(existing_doorbell_type_enabled=i)
)

if device_family == "other":
for prop in ("doorbell_volume", "mic_volume", "voice_volume"):
mock_device.configure_mock(
Expand Down
47 changes: 47 additions & 0 deletions tests/components/ring/snapshots/test_switch.ambr
Original file line number Diff line number Diff line change
@@ -1,4 +1,51 @@
# serializer version: 1
# name: test_states[switch.front_door_in_home_chime-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'switch',
'entity_category': None,
'entity_id': 'switch.front_door_in_home_chime',
'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': 'In-home chime',
'platform': 'ring',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'in_home_chime',
'unique_id': '987654-in_home_chime',
'unit_of_measurement': None,
})
# ---
# name: test_states[switch.front_door_in_home_chime-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'attribution': 'Data provided by Ring.com',
'friendly_name': 'Front Door In-home chime',
}),
'context': <ANY>,
'entity_id': 'switch.front_door_in_home_chime',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_states[switch.front_siren-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
Expand Down
27 changes: 18 additions & 9 deletions tests/components/ring/test_switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,35 +103,44 @@ async def test_siren_on_reports_correctly(
assert state.attributes.get("friendly_name") == "Internal Siren"


async def test_siren_can_be_turned_on_and_off(
hass: HomeAssistant, mock_ring_client, create_deprecated_siren_entity
@pytest.mark.parametrize(
("entity_id"),
[
("switch.front_siren"),
("switch.front_door_in_home_chime"),
],
)
async def test_switch_can_be_turned_on_and_off(
hass: HomeAssistant,
mock_ring_client,
create_deprecated_siren_entity,
entity_id,
) -> None:
"""Tests the siren turns on correctly."""
"""Tests the switch turns on and off correctly."""
await setup_platform(hass, Platform.SWITCH)

state = hass.states.get("switch.front_siren")
assert state.state == STATE_OFF
assert hass.states.get(entity_id)

await hass.services.async_call(
SWITCH_DOMAIN,
SERVICE_TURN_ON,
{ATTR_ENTITY_ID: "switch.front_siren"},
{ATTR_ENTITY_ID: entity_id},
blocking=True,
)

await hass.async_block_till_done()
state = hass.states.get("switch.front_siren")
state = hass.states.get(entity_id)
assert state.state == STATE_ON

await hass.services.async_call(
SWITCH_DOMAIN,
SERVICE_TURN_OFF,
{ATTR_ENTITY_ID: "switch.front_siren"},
{ATTR_ENTITY_ID: entity_id},
blocking=True,
)

await hass.async_block_till_done()
state = hass.states.get("switch.front_siren")
state = hass.states.get(entity_id)
assert state.state == STATE_OFF


Expand Down

0 comments on commit efdb107

Please sign in to comment.