mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 21:27:38 +00:00
Avoid exposing unsupported entities to Alexa (#92107)
* Avoid exposing unsupported entities to Alexa * Update homeassistant/components/cloud/alexa_config.py Co-authored-by: epenet <6771947+epenet@users.noreply.github.com> --------- Co-authored-by: epenet <6771947+epenet@users.noreply.github.com>
This commit is contained in:
parent
21d887dd04
commit
7215f6320e
@ -20,14 +20,17 @@ from homeassistant.components.alexa import (
|
||||
errors as alexa_errors,
|
||||
state_report as alexa_state_report,
|
||||
)
|
||||
from homeassistant.components.binary_sensor import BinarySensorDeviceClass
|
||||
from homeassistant.components.homeassistant.exposed_entities import (
|
||||
async_get_assistant_settings,
|
||||
async_listen_entity_updates,
|
||||
async_should_expose,
|
||||
)
|
||||
from homeassistant.components.sensor import SensorDeviceClass
|
||||
from homeassistant.const import CLOUD_NEVER_EXPOSED_ENTITIES
|
||||
from homeassistant.core import HomeAssistant, callback, split_entity_id
|
||||
from homeassistant.helpers import entity_registry as er, start
|
||||
from homeassistant.helpers.entity import get_device_class
|
||||
from homeassistant.helpers.event import async_call_later
|
||||
from homeassistant.setup import async_setup_component
|
||||
from homeassistant.util.dt import utcnow
|
||||
@ -51,6 +54,69 @@ CLOUD_ALEXA = f"{CLOUD_DOMAIN}.{ALEXA_DOMAIN}"
|
||||
SYNC_DELAY = 1
|
||||
|
||||
|
||||
SUPPORTED_DOMAINS = {
|
||||
"alarm_control_panel",
|
||||
"alert",
|
||||
"automation",
|
||||
"button",
|
||||
"camera",
|
||||
"climate",
|
||||
"cover",
|
||||
"fan",
|
||||
"group",
|
||||
"humidifier",
|
||||
"image_processing",
|
||||
"input_boolean",
|
||||
"input_button",
|
||||
"input_number",
|
||||
"light",
|
||||
"lock",
|
||||
"media_player",
|
||||
"number",
|
||||
"scene",
|
||||
"script",
|
||||
"switch",
|
||||
"timer",
|
||||
"vacuum",
|
||||
}
|
||||
|
||||
SUPPORTED_BINARY_SENSOR_DEVICE_CLASSES = {
|
||||
BinarySensorDeviceClass.DOOR,
|
||||
BinarySensorDeviceClass.GARAGE_DOOR,
|
||||
BinarySensorDeviceClass.MOTION,
|
||||
BinarySensorDeviceClass.OPENING,
|
||||
BinarySensorDeviceClass.PRESENCE,
|
||||
BinarySensorDeviceClass.WINDOW,
|
||||
}
|
||||
|
||||
SUPPORTED_SENSOR_DEVICE_CLASSES = {
|
||||
SensorDeviceClass.TEMPERATURE,
|
||||
}
|
||||
|
||||
|
||||
def _supported_legacy(hass: HomeAssistant, entity_id: str) -> bool:
|
||||
"""Return if the entity is supported.
|
||||
|
||||
This is called when migrating from legacy config format to avoid exposing
|
||||
all binary sensors and sensors.
|
||||
"""
|
||||
domain = split_entity_id(entity_id)[0]
|
||||
if domain in SUPPORTED_DOMAINS:
|
||||
return True
|
||||
|
||||
device_class = get_device_class(hass, entity_id)
|
||||
if (
|
||||
domain == "binary_sensor"
|
||||
and device_class in SUPPORTED_BINARY_SENSOR_DEVICE_CLASSES
|
||||
):
|
||||
return True
|
||||
|
||||
if domain == "sensor" and device_class in SUPPORTED_SENSOR_DEVICE_CLASSES:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
class CloudAlexaConfig(alexa_config.AbstractConfig):
|
||||
"""Alexa Configuration."""
|
||||
|
||||
@ -183,9 +249,13 @@ class CloudAlexaConfig(alexa_config.AbstractConfig):
|
||||
|
||||
# Backwards compat
|
||||
if (default_expose := self._prefs.alexa_default_expose) is None:
|
||||
return not auxiliary_entity
|
||||
return not auxiliary_entity and _supported_legacy(self.hass, entity_id)
|
||||
|
||||
return not auxiliary_entity and split_entity_id(entity_id)[0] in default_expose
|
||||
return (
|
||||
not auxiliary_entity
|
||||
and split_entity_id(entity_id)[0] in default_expose
|
||||
and _supported_legacy(self.hass, entity_id)
|
||||
)
|
||||
|
||||
def should_expose(self, entity_id):
|
||||
"""If an entity should be exposed."""
|
||||
|
@ -650,3 +650,101 @@ async def test_alexa_config_migrate_expose_entity_prefs_default_none(
|
||||
|
||||
entity_default = entity_registry.async_get(entity_default.entity_id)
|
||||
assert entity_default.options == {"cloud.alexa": {"should_expose": True}}
|
||||
|
||||
|
||||
async def test_alexa_config_migrate_expose_entity_prefs_default(
|
||||
hass: HomeAssistant,
|
||||
cloud_prefs: CloudPreferences,
|
||||
cloud_stub,
|
||||
entity_registry: er.EntityRegistry,
|
||||
) -> None:
|
||||
"""Test migrating Alexa entity config."""
|
||||
|
||||
assert await async_setup_component(hass, "homeassistant", {})
|
||||
|
||||
binary_sensor_supported = entity_registry.async_get_or_create(
|
||||
"binary_sensor",
|
||||
"test",
|
||||
"binary_sensor_supported",
|
||||
original_device_class="door",
|
||||
suggested_object_id="supported",
|
||||
)
|
||||
|
||||
binary_sensor_unsupported = entity_registry.async_get_or_create(
|
||||
"binary_sensor",
|
||||
"test",
|
||||
"binary_sensor_unsupported",
|
||||
original_device_class="battery",
|
||||
suggested_object_id="unsupported",
|
||||
)
|
||||
|
||||
light = entity_registry.async_get_or_create(
|
||||
"light",
|
||||
"test",
|
||||
"unique",
|
||||
suggested_object_id="light",
|
||||
)
|
||||
|
||||
sensor_supported = entity_registry.async_get_or_create(
|
||||
"sensor",
|
||||
"test",
|
||||
"sensor_supported",
|
||||
original_device_class="temperature",
|
||||
suggested_object_id="supported",
|
||||
)
|
||||
|
||||
sensor_unsupported = entity_registry.async_get_or_create(
|
||||
"sensor",
|
||||
"test",
|
||||
"sensor_unsupported",
|
||||
original_device_class="battery",
|
||||
suggested_object_id="unsupported",
|
||||
)
|
||||
|
||||
water_heater = entity_registry.async_get_or_create(
|
||||
"water_heater",
|
||||
"test",
|
||||
"unique",
|
||||
suggested_object_id="water_heater",
|
||||
)
|
||||
|
||||
await cloud_prefs.async_update(
|
||||
alexa_enabled=True,
|
||||
alexa_report_state=False,
|
||||
alexa_settings_version=1,
|
||||
)
|
||||
|
||||
cloud_prefs._prefs[PREF_ALEXA_DEFAULT_EXPOSE] = [
|
||||
"binary_sensor",
|
||||
"light",
|
||||
"sensor",
|
||||
"water_heater",
|
||||
]
|
||||
conf = alexa_config.CloudAlexaConfig(
|
||||
hass, ALEXA_SCHEMA({}), "mock-user-id", cloud_prefs, cloud_stub
|
||||
)
|
||||
await conf.async_initialize()
|
||||
|
||||
binary_sensor_supported = entity_registry.async_get(
|
||||
binary_sensor_supported.entity_id
|
||||
)
|
||||
assert binary_sensor_supported.options == {"cloud.alexa": {"should_expose": True}}
|
||||
|
||||
binary_sensor_unsupported = entity_registry.async_get(
|
||||
binary_sensor_unsupported.entity_id
|
||||
)
|
||||
assert binary_sensor_unsupported.options == {
|
||||
"cloud.alexa": {"should_expose": False}
|
||||
}
|
||||
|
||||
light = entity_registry.async_get(light.entity_id)
|
||||
assert light.options == {"cloud.alexa": {"should_expose": True}}
|
||||
|
||||
sensor_supported = entity_registry.async_get(sensor_supported.entity_id)
|
||||
assert sensor_supported.options == {"cloud.alexa": {"should_expose": True}}
|
||||
|
||||
sensor_unsupported = entity_registry.async_get(sensor_unsupported.entity_id)
|
||||
assert sensor_unsupported.options == {"cloud.alexa": {"should_expose": False}}
|
||||
|
||||
water_heater = entity_registry.async_get(water_heater.entity_id)
|
||||
assert water_heater.options == {"cloud.alexa": {"should_expose": False}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user