Migrate cloud settings for all Alexa entities (#92413)

* Migrate cloud settings for all Alexa entities

* Also set settings for unknown entities
pull/92421/head
Erik Montnemery 2023-05-03 18:39:27 +02:00 committed by GitHub
parent 4abf0ddeb9
commit 51be90d87e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 70 additions and 23 deletions

View File

@ -22,7 +22,9 @@ from homeassistant.components.alexa import (
) )
from homeassistant.components.binary_sensor import BinarySensorDeviceClass from homeassistant.components.binary_sensor import BinarySensorDeviceClass
from homeassistant.components.homeassistant.exposed_entities import ( from homeassistant.components.homeassistant.exposed_entities import (
async_expose_entity,
async_get_assistant_settings, async_get_assistant_settings,
async_get_entity_settings,
async_listen_entity_updates, async_listen_entity_updates,
async_should_expose, async_should_expose,
) )
@ -198,35 +200,52 @@ class CloudAlexaConfig(alexa_config.AbstractConfig):
# Don't migrate if there's a YAML config # Don't migrate if there's a YAML config
return return
entity_registry = er.async_get(self.hass) for state in self.hass.states.async_all():
with suppress(HomeAssistantError):
for entity_id, entry in entity_registry.entities.items(): entity_settings = async_get_entity_settings(self.hass, state.entity_id)
if CLOUD_ALEXA in entry.options: if CLOUD_ALEXA in entity_settings:
continue continue
options = {"should_expose": self._should_expose_legacy(entity_id)} async_expose_entity(
entity_registry.async_update_entity_options(entity_id, CLOUD_ALEXA, options) self.hass,
CLOUD_ALEXA,
state.entity_id,
self._should_expose_legacy(state.entity_id),
)
for entity_id in self._prefs.alexa_entity_configs:
with suppress(HomeAssistantError):
entity_settings = async_get_entity_settings(self.hass, entity_id)
if CLOUD_ALEXA in entity_settings:
continue
async_expose_entity(
self.hass,
CLOUD_ALEXA,
entity_id,
self._should_expose_legacy(entity_id),
)
async def async_initialize(self): async def async_initialize(self):
"""Initialize the Alexa config.""" """Initialize the Alexa config."""
await super().async_initialize() await super().async_initialize()
if self._prefs.alexa_settings_version != ALEXA_SETTINGS_VERSION: async def on_hass_started(hass):
if self._prefs.alexa_settings_version < 2: if self._prefs.alexa_settings_version != ALEXA_SETTINGS_VERSION:
self._migrate_alexa_entity_settings_v1() if self._prefs.alexa_settings_version < 2:
await self._prefs.async_update( self._migrate_alexa_entity_settings_v1()
alexa_settings_version=ALEXA_SETTINGS_VERSION await self._prefs.async_update(
alexa_settings_version=ALEXA_SETTINGS_VERSION
)
async_listen_entity_updates(
self.hass, CLOUD_ALEXA, self._async_exposed_entities_updated
) )
async def hass_started(hass): async def on_hass_start(hass):
if self.enabled and ALEXA_DOMAIN not in self.hass.config.components: if self.enabled and ALEXA_DOMAIN not in self.hass.config.components:
await async_setup_component(self.hass, ALEXA_DOMAIN, {}) await async_setup_component(self.hass, ALEXA_DOMAIN, {})
start.async_at_start(self.hass, hass_started) start.async_at_start(self.hass, on_hass_start)
start.async_at_started(self.hass, on_hass_started)
self._prefs.async_listen_updates(self._async_prefs_updated) self._prefs.async_listen_updates(self._async_prefs_updated)
async_listen_entity_updates(
self.hass, CLOUD_ALEXA, self._async_exposed_entities_updated
)
self.hass.bus.async_listen( self.hass.bus.async_listen(
er.EVENT_ENTITY_REGISTRY_UPDATED, er.EVENT_ENTITY_REGISTRY_UPDATED,
self._handle_entity_registry_updated, self._handle_entity_registry_updated,

View File

@ -18,9 +18,12 @@ from homeassistant.components.homeassistant.exposed_entities import (
async_expose_entity, async_expose_entity,
async_get_entity_settings, async_get_entity_settings,
) )
from homeassistant.const import EntityCategory from homeassistant.const import (
from homeassistant.core import HomeAssistant EVENT_HOMEASSISTANT_START,
from homeassistant.exceptions import HomeAssistantError EVENT_HOMEASSISTANT_STARTED,
EntityCategory,
)
from homeassistant.core import CoreState, HomeAssistant
from homeassistant.helpers import entity_registry as er from homeassistant.helpers import entity_registry as er
from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
@ -368,6 +371,8 @@ async def test_alexa_update_expose_trigger_sync(
hass, ALEXA_SCHEMA({}), "mock-user-id", cloud_prefs, cloud_stub hass, ALEXA_SCHEMA({}), "mock-user-id", cloud_prefs, cloud_stub
) )
await conf.async_initialize() await conf.async_initialize()
hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
await hass.async_block_till_done()
with patch_sync_helper() as (to_update, to_remove): with patch_sync_helper() as (to_update, to_remove):
expose_entity(hass, light_entry.entity_id, True) expose_entity(hass, light_entry.entity_id, True)
@ -544,8 +549,10 @@ async def test_alexa_config_migrate_expose_entity_prefs(
entity_registry: er.EntityRegistry, entity_registry: er.EntityRegistry,
) -> None: ) -> None:
"""Test migrating Alexa entity config.""" """Test migrating Alexa entity config."""
hass.state = CoreState.starting
assert await async_setup_component(hass, "homeassistant", {}) assert await async_setup_component(hass, "homeassistant", {})
hass.states.async_set("light.state_only", "on")
entity_exposed = entity_registry.async_get_or_create( entity_exposed = entity_registry.async_get_or_create(
"light", "light",
"test", "test",
@ -593,6 +600,9 @@ async def test_alexa_config_migrate_expose_entity_prefs(
cloud_prefs._prefs[PREF_ALEXA_ENTITY_CONFIGS]["light.unknown"] = { cloud_prefs._prefs[PREF_ALEXA_ENTITY_CONFIGS]["light.unknown"] = {
PREF_SHOULD_EXPOSE: True PREF_SHOULD_EXPOSE: True
} }
cloud_prefs._prefs[PREF_ALEXA_ENTITY_CONFIGS]["light.state_only"] = {
PREF_SHOULD_EXPOSE: False
}
cloud_prefs._prefs[PREF_ALEXA_ENTITY_CONFIGS][entity_exposed.entity_id] = { cloud_prefs._prefs[PREF_ALEXA_ENTITY_CONFIGS][entity_exposed.entity_id] = {
PREF_SHOULD_EXPOSE: True PREF_SHOULD_EXPOSE: True
} }
@ -603,12 +613,20 @@ async def test_alexa_config_migrate_expose_entity_prefs(
hass, ALEXA_SCHEMA({}), "mock-user-id", cloud_prefs, cloud_stub hass, ALEXA_SCHEMA({}), "mock-user-id", cloud_prefs, cloud_stub
) )
await conf.async_initialize() await conf.async_initialize()
hass.bus.async_fire(EVENT_HOMEASSISTANT_START)
await hass.async_block_till_done()
hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
await hass.async_block_till_done()
with pytest.raises(HomeAssistantError): assert async_get_entity_settings(hass, "light.unknown") == {
async_get_entity_settings(hass, "light.unknown") "cloud.alexa": {"should_expose": True}
assert async_get_entity_settings(hass, entity_migrated.entity_id) == { }
assert async_get_entity_settings(hass, "light.state_only") == {
"cloud.alexa": {"should_expose": False} "cloud.alexa": {"should_expose": False}
} }
assert async_get_entity_settings(hass, entity_exposed.entity_id) == {
"cloud.alexa": {"should_expose": True}
}
assert async_get_entity_settings(hass, entity_migrated.entity_id) == { assert async_get_entity_settings(hass, entity_migrated.entity_id) == {
"cloud.alexa": {"should_expose": False} "cloud.alexa": {"should_expose": False}
} }
@ -630,6 +648,7 @@ async def test_alexa_config_migrate_expose_entity_prefs_default_none(
entity_registry: er.EntityRegistry, entity_registry: er.EntityRegistry,
) -> None: ) -> None:
"""Test migrating Alexa entity config.""" """Test migrating Alexa entity config."""
hass.state = CoreState.starting
assert await async_setup_component(hass, "homeassistant", {}) assert await async_setup_component(hass, "homeassistant", {})
entity_default = entity_registry.async_get_or_create( entity_default = entity_registry.async_get_or_create(
@ -650,6 +669,10 @@ async def test_alexa_config_migrate_expose_entity_prefs_default_none(
hass, ALEXA_SCHEMA({}), "mock-user-id", cloud_prefs, cloud_stub hass, ALEXA_SCHEMA({}), "mock-user-id", cloud_prefs, cloud_stub
) )
await conf.async_initialize() await conf.async_initialize()
hass.bus.async_fire(EVENT_HOMEASSISTANT_START)
await hass.async_block_till_done()
hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
await hass.async_block_till_done()
assert async_get_entity_settings(hass, entity_default.entity_id) == { assert async_get_entity_settings(hass, entity_default.entity_id) == {
"cloud.alexa": {"should_expose": True} "cloud.alexa": {"should_expose": True}
@ -663,6 +686,7 @@ async def test_alexa_config_migrate_expose_entity_prefs_default(
entity_registry: er.EntityRegistry, entity_registry: er.EntityRegistry,
) -> None: ) -> None:
"""Test migrating Alexa entity config.""" """Test migrating Alexa entity config."""
hass.state = CoreState.starting
assert await async_setup_component(hass, "homeassistant", {}) assert await async_setup_component(hass, "homeassistant", {})
@ -728,6 +752,10 @@ async def test_alexa_config_migrate_expose_entity_prefs_default(
hass, ALEXA_SCHEMA({}), "mock-user-id", cloud_prefs, cloud_stub hass, ALEXA_SCHEMA({}), "mock-user-id", cloud_prefs, cloud_stub
) )
await conf.async_initialize() await conf.async_initialize()
hass.bus.async_fire(EVENT_HOMEASSISTANT_START)
await hass.async_block_till_done()
hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
await hass.async_block_till_done()
assert async_get_entity_settings(hass, binary_sensor_supported.entity_id) == { assert async_get_entity_settings(hass, binary_sensor_supported.entity_id) == {
"cloud.alexa": {"should_expose": True} "cloud.alexa": {"should_expose": True}