Remove event entities for unsupported AQM devices for Alexa Devices (#174449)

This commit is contained in:
jameson_uk
2026-09-24 21:31:26 +02:00
committed by GitHub
parent adbdf45aad
commit ef9dea8a74
4 changed files with 85 additions and 18 deletions
@@ -2,8 +2,6 @@
from typing import Final, override
from aioamazondevices.const.devices import SPEAKER_GROUP_FAMILY
from homeassistant.components.event import (
DOMAIN as EVENT_DOMAIN,
EventEntity,
@@ -15,11 +13,12 @@ from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from .const import LOGGER
from .coordinator import AmazonConfigEntry, AmazonDevicesCoordinator
from .entity import AmazonEntity
from .utils import async_remove_entity_from_virtual_group
from .utils import async_remove_entities
# Coordinator is used to centralize the data updates
PARALLEL_UPDATES = 0
EVENTS: Final = {
EventEntityDescription(
key="voice_event",
@@ -38,9 +37,13 @@ async def async_setup_entry(
"""Set up Alexa Devices events based on a config entry."""
coordinator = entry.runtime_data
# Remove voice event from virtual groups
await async_remove_entity_from_virtual_group(
hass, coordinator, EVENT_DOMAIN, "voice_event"
# Remove voice event from virtual groups and AQM devices
await async_remove_entities(
hass,
coordinator,
EVENT_DOMAIN,
"voice_event",
remove_fn=lambda device: not device.voice_control_supported,
)
known_devices: set[str] = set()
@@ -55,7 +58,7 @@ async def async_setup_entry(
AlexaVoiceEvent(coordinator, serial_num, event_desc)
for event_desc in EVENTS
for serial_num in new_devices
if coordinator.data[serial_num].device_family != SPEAKER_GROUP_FAMILY
if coordinator.data[serial_num].voice_control_supported
)
_check_device()
@@ -4,6 +4,7 @@ from collections.abc import Callable
from dataclasses import dataclass
from typing import TYPE_CHECKING, Any, Final, override
from aioamazondevices.const.devices import SPEAKER_GROUP_FAMILY
from aioamazondevices.structures import AmazonDevice
from homeassistant.components.switch import (
@@ -17,7 +18,7 @@ from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from .coordinator import AmazonConfigEntry, alexa_api_call
from .entity import AmazonEntity
from .utils import async_remove_entity_from_virtual_group, async_update_unique_id
from .utils import async_remove_entities, async_update_unique_id
PARALLEL_UPDATES = 1
@@ -90,8 +91,12 @@ async def async_setup_entry(
new_key = "dnd"
# Remove old DND switch from virtual groups
await async_remove_entity_from_virtual_group(
hass, coordinator, SWITCH_DOMAIN, old_key
await async_remove_entities(
hass,
coordinator,
SWITCH_DOMAIN,
old_key,
remove_fn=lambda device: device.device_family == SPEAKER_GROUP_FAMILY,
)
# Replace unique id for DND switch
@@ -1,11 +1,13 @@
"""Utils for Alexa Devices."""
from aioamazondevices.const.devices import SPEAKER_GROUP_FAMILY
from collections.abc import Callable
from aioamazondevices.const.schedules import (
NOTIFICATION_ALARM,
NOTIFICATION_REMINDER,
NOTIFICATION_TIMER,
)
from aioamazondevices.structures import AmazonDevice
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
@@ -37,22 +39,24 @@ async def async_update_unique_id(
entity_registry.async_update_entity(entity_id, new_unique_id=new_unique_id)
async def async_remove_entity_from_virtual_group(
async def async_remove_entities(
hass: HomeAssistant,
coordinator: AmazonDevicesCoordinator,
platform: str,
key: str,
remove_fn: Callable[[AmazonDevice], bool],
) -> None:
"""Remove entity from virtual group."""
"""Remove entities matching remove_fn from the registry."""
entity_registry = er.async_get(hass)
for serial_num in coordinator.data:
for serial_num, device in coordinator.data.items():
if not remove_fn(device):
continue
unique_id = f"{serial_num}-{key}"
entity_id = entity_registry.async_get_entity_id(platform, DOMAIN, unique_id)
is_group = coordinator.data[serial_num].device_family == SPEAKER_GROUP_FAMILY
if entity_id and is_group:
if entity_id:
entity_registry.async_remove(entity_id)
LOGGER.debug("Removed entity '%s' from virtual group", entity_id)
LOGGER.debug("Removed entity '%s'", entity_id)
async def async_remove_unsupported_notification_sensors(
+56 -1
View File
@@ -6,9 +6,10 @@ from freezegun.api import FrozenDateTimeFactory
import pytest
from syrupy.assertion import SnapshotAssertion
from homeassistant.components.alexa_devices.const import DOMAIN
from homeassistant.const import STATE_UNKNOWN, Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from homeassistant.helpers import device_registry as dr, entity_registry as er
from . import assert_device_removed_and_readded, setup_integration
from .const import (
@@ -94,3 +95,57 @@ async def test_device_removed_and_readded(
devices_with={TEST_DEVICE_1_SN: TEST_DEVICE_1, TEST_DEVICE_2_SN: TEST_DEVICE_2},
devices_without={TEST_DEVICE_1_SN: TEST_DEVICE_1},
)
async def test_voice_event_not_created_for_unsupported_device(
hass: HomeAssistant,
mock_amazon_devices_client: AsyncMock,
mock_config_entry: MockConfigEntry,
) -> None:
"""Test voice event entity is not created for devices without voice control support."""
mock_amazon_devices_client.get_devices_data.return_value[
TEST_DEVICE_1_SN
].voice_control_supported = False
with patch("homeassistant.components.alexa_devices.PLATFORMS", [Platform.EVENT]):
await setup_integration(hass, mock_config_entry)
assert not hass.states.get(ENTITY_ID)
async def test_voice_event_removed_for_unsupported_device(
hass: HomeAssistant,
mock_amazon_devices_client: AsyncMock,
mock_config_entry: MockConfigEntry,
device_registry: dr.DeviceRegistry,
entity_registry: er.EntityRegistry,
) -> None:
"""Test voice event entity is removed for devices without voice control support."""
mock_config_entry.add_to_hass(hass)
device = device_registry.async_get_or_create(
config_entry_id=mock_config_entry.entry_id,
identifiers={(DOMAIN, TEST_DEVICE_1_SN)},
name="Echo Test",
manufacturer="Amazon",
model="Echo Dot",
)
entity = entity_registry.async_get_or_create(
Platform.EVENT,
DOMAIN,
unique_id=f"{TEST_DEVICE_1_SN}-voice_event",
device_id=device.id,
config_entry=mock_config_entry,
has_entity_name=True,
)
mock_amazon_devices_client.get_devices_data.return_value[
TEST_DEVICE_1_SN
].voice_control_supported = False
await hass.config_entries.async_setup(mock_config_entry.entry_id)
await hass.async_block_till_done()
assert not hass.states.get(entity.entity_id)
assert entity_registry.async_get(entity.entity_id) is None