mirror of
https://github.com/home-assistant/core.git
synced 2025-07-24 13:47:35 +00:00
Avoid exposing unsupported entities to Google Assistant (#92105)
* Avoid exposing unsupported entities to Google Assistant * Add Google Assistant specific support sets * Add test
This commit is contained in:
parent
a164530a64
commit
65c9d4a4ae
@ -7,12 +7,14 @@ from typing import Any
|
||||
from hass_nabucasa import Cloud, cloud_api
|
||||
from hass_nabucasa.google_report_state import ErrorResponse
|
||||
|
||||
from homeassistant.components.binary_sensor import BinarySensorDeviceClass
|
||||
from homeassistant.components.google_assistant import DOMAIN as GOOGLE_DOMAIN
|
||||
from homeassistant.components.google_assistant.helpers import AbstractConfig
|
||||
from homeassistant.components.homeassistant.exposed_entities import (
|
||||
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 (
|
||||
CoreState,
|
||||
@ -22,6 +24,7 @@ from homeassistant.core import (
|
||||
split_entity_id,
|
||||
)
|
||||
from homeassistant.helpers import device_registry as dr, entity_registry as er, start
|
||||
from homeassistant.helpers.entity import get_device_class
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from .const import (
|
||||
@ -39,6 +42,73 @@ _LOGGER = logging.getLogger(__name__)
|
||||
CLOUD_GOOGLE = f"{CLOUD_DOMAIN}.{GOOGLE_DOMAIN}"
|
||||
|
||||
|
||||
SUPPORTED_DOMAINS = {
|
||||
"alarm_control_panel",
|
||||
"button",
|
||||
"camera",
|
||||
"climate",
|
||||
"cover",
|
||||
"fan",
|
||||
"group",
|
||||
"humidifier",
|
||||
"input_boolean",
|
||||
"input_button",
|
||||
"input_select",
|
||||
"light",
|
||||
"lock",
|
||||
"media_player",
|
||||
"scene",
|
||||
"script",
|
||||
"select",
|
||||
"switch",
|
||||
"vacuum",
|
||||
}
|
||||
|
||||
SUPPORTED_BINARY_SENSOR_DEVICE_CLASSES = {
|
||||
BinarySensorDeviceClass.DOOR,
|
||||
BinarySensorDeviceClass.GARAGE_DOOR,
|
||||
BinarySensorDeviceClass.LOCK,
|
||||
BinarySensorDeviceClass.MOTION,
|
||||
BinarySensorDeviceClass.OPENING,
|
||||
BinarySensorDeviceClass.PRESENCE,
|
||||
BinarySensorDeviceClass.WINDOW,
|
||||
}
|
||||
|
||||
SUPPORTED_SENSOR_DEVICE_CLASSES = {
|
||||
SensorDeviceClass.AQI,
|
||||
SensorDeviceClass.CO,
|
||||
SensorDeviceClass.CO2,
|
||||
SensorDeviceClass.HUMIDITY,
|
||||
SensorDeviceClass.PM10,
|
||||
SensorDeviceClass.PM25,
|
||||
SensorDeviceClass.TEMPERATURE,
|
||||
SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS,
|
||||
}
|
||||
|
||||
|
||||
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 CloudGoogleConfig(AbstractConfig):
|
||||
"""HA Cloud Configuration for Google Assistant."""
|
||||
|
||||
@ -180,9 +250,13 @@ class CloudGoogleConfig(AbstractConfig):
|
||||
|
||||
# Backwards compat
|
||||
if 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_entity_id(self, entity_id):
|
||||
"""If an entity should be exposed."""
|
||||
|
@ -611,3 +611,106 @@ async def test_google_config_migrate_expose_entity_prefs_default_none(
|
||||
|
||||
entity_default = entity_registry.async_get(entity_default.entity_id)
|
||||
assert entity_default.options == {"cloud.google_assistant": {"should_expose": True}}
|
||||
|
||||
|
||||
async def test_google_config_migrate_expose_entity_prefs_default(
|
||||
hass: HomeAssistant,
|
||||
cloud_prefs: CloudPreferences,
|
||||
entity_registry: er.EntityRegistry,
|
||||
) -> None:
|
||||
"""Test migrating Google 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(
|
||||
google_enabled=True,
|
||||
google_report_state=False,
|
||||
google_settings_version=1,
|
||||
)
|
||||
|
||||
cloud_prefs._prefs[PREF_GOOGLE_DEFAULT_EXPOSE] = [
|
||||
"binary_sensor",
|
||||
"light",
|
||||
"sensor",
|
||||
"water_heater",
|
||||
]
|
||||
conf = CloudGoogleConfig(
|
||||
hass, GACTIONS_SCHEMA({}), "mock-user-id", cloud_prefs, Mock(is_logged_in=False)
|
||||
)
|
||||
await conf.async_initialize()
|
||||
|
||||
binary_sensor_supported = entity_registry.async_get(
|
||||
binary_sensor_supported.entity_id
|
||||
)
|
||||
assert binary_sensor_supported.options == {
|
||||
"cloud.google_assistant": {"should_expose": True}
|
||||
}
|
||||
|
||||
binary_sensor_unsupported = entity_registry.async_get(
|
||||
binary_sensor_unsupported.entity_id
|
||||
)
|
||||
assert binary_sensor_unsupported.options == {
|
||||
"cloud.google_assistant": {"should_expose": False}
|
||||
}
|
||||
|
||||
light = entity_registry.async_get(light.entity_id)
|
||||
assert light.options == {"cloud.google_assistant": {"should_expose": True}}
|
||||
|
||||
sensor_supported = entity_registry.async_get(sensor_supported.entity_id)
|
||||
assert sensor_supported.options == {
|
||||
"cloud.google_assistant": {"should_expose": True}
|
||||
}
|
||||
|
||||
sensor_unsupported = entity_registry.async_get(sensor_unsupported.entity_id)
|
||||
assert sensor_unsupported.options == {
|
||||
"cloud.google_assistant": {"should_expose": False}
|
||||
}
|
||||
|
||||
water_heater = entity_registry.async_get(water_heater.entity_id)
|
||||
assert water_heater.options == {"cloud.google_assistant": {"should_expose": False}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user