Sync area changes to google (#70936)
Co-authored-by: Martin Hjelmare <marhje52@gmail.com>pull/71174/head
parent
250a2aa260
commit
7b69e20db7
|
@ -9,8 +9,8 @@ from hass_nabucasa.google_report_state import ErrorResponse
|
|||
from homeassistant.components.google_assistant.const import DOMAIN as GOOGLE_DOMAIN
|
||||
from homeassistant.components.google_assistant.helpers import AbstractConfig
|
||||
from homeassistant.const import CLOUD_NEVER_EXPOSED_ENTITIES
|
||||
from homeassistant.core import CoreState, split_entity_id
|
||||
from homeassistant.helpers import entity_registry as er, start
|
||||
from homeassistant.core import CoreState, Event, callback, split_entity_id
|
||||
from homeassistant.helpers import device_registry as dr, entity_registry as er, start
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
from .const import (
|
||||
|
@ -103,6 +103,10 @@ class CloudGoogleConfig(AbstractConfig):
|
|||
er.EVENT_ENTITY_REGISTRY_UPDATED,
|
||||
self._handle_entity_registry_updated,
|
||||
)
|
||||
self.hass.bus.async_listen(
|
||||
dr.EVENT_DEVICE_REGISTRY_UPDATED,
|
||||
self._handle_device_registry_updated,
|
||||
)
|
||||
|
||||
def should_expose(self, state):
|
||||
"""If a state object should be exposed."""
|
||||
|
@ -217,9 +221,14 @@ class CloudGoogleConfig(AbstractConfig):
|
|||
self._cur_entity_prefs = prefs.google_entity_configs
|
||||
self._cur_default_expose = prefs.google_default_expose
|
||||
|
||||
async def _handle_entity_registry_updated(self, event):
|
||||
@callback
|
||||
def _handle_entity_registry_updated(self, event: Event) -> None:
|
||||
"""Handle when entity registry updated."""
|
||||
if not self.enabled or not self._cloud.is_logged_in:
|
||||
if (
|
||||
not self.enabled
|
||||
or not self._cloud.is_logged_in
|
||||
or self.hass.state != CoreState.running
|
||||
):
|
||||
return
|
||||
|
||||
# Only consider entity registry updates if info relevant for Google has changed
|
||||
|
@ -233,7 +242,30 @@ class CloudGoogleConfig(AbstractConfig):
|
|||
if not self._should_expose_entity_id(entity_id):
|
||||
return
|
||||
|
||||
if self.hass.state != CoreState.running:
|
||||
self.async_schedule_google_sync_all()
|
||||
|
||||
@callback
|
||||
def _handle_device_registry_updated(self, event: Event) -> None:
|
||||
"""Handle when device registry updated."""
|
||||
if (
|
||||
not self.enabled
|
||||
or not self._cloud.is_logged_in
|
||||
or self.hass.state != CoreState.running
|
||||
):
|
||||
return
|
||||
|
||||
# Device registry is only used for area changes. All other changes are ignored.
|
||||
if event.data["action"] != "update" or "area_id" not in event.data["changes"]:
|
||||
return
|
||||
|
||||
# Check if any exposed entity uses the device area
|
||||
if not any(
|
||||
entity_entry.area_id is None
|
||||
and self._should_expose_entity_id(entity_entry.entity_id)
|
||||
for entity_entry in er.async_entries_for_device(
|
||||
er.async_get(self.hass), event.data["device_id"]
|
||||
)
|
||||
):
|
||||
return
|
||||
|
||||
self.async_schedule_google_sync_all()
|
||||
|
|
|
@ -10,7 +10,7 @@ from homeassistant.components.cloud.google_config import CloudGoogleConfig
|
|||
from homeassistant.components.google_assistant import helpers as ga_helpers
|
||||
from homeassistant.const import EVENT_HOMEASSISTANT_STARTED
|
||||
from homeassistant.core import CoreState, State
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
||||
from homeassistant.helpers.entity import EntityCategory
|
||||
from homeassistant.util.dt import utcnow
|
||||
|
||||
|
@ -191,6 +191,66 @@ async def test_google_entity_registry_sync(hass, mock_cloud_login, cloud_prefs):
|
|||
assert len(mock_sync.mock_calls) == 3
|
||||
|
||||
|
||||
async def test_google_device_registry_sync(hass, mock_cloud_login, cloud_prefs):
|
||||
"""Test Google config responds to device registry."""
|
||||
config = CloudGoogleConfig(
|
||||
hass, GACTIONS_SCHEMA({}), "mock-user-id", cloud_prefs, hass.data["cloud"]
|
||||
)
|
||||
ent_reg = er.async_get(hass)
|
||||
entity_entry = ent_reg.async_get_or_create(
|
||||
"light", "hue", "1234", device_id="1234", area_id="ABCD"
|
||||
)
|
||||
|
||||
with patch.object(config, "async_sync_entities_all"):
|
||||
await config.async_initialize()
|
||||
await hass.async_block_till_done()
|
||||
await config.async_connect_agent_user("mock-user-id")
|
||||
|
||||
with patch.object(config, "async_schedule_google_sync_all") as mock_sync:
|
||||
# Device registry updated with non-relevant changes
|
||||
hass.bus.async_fire(
|
||||
dr.EVENT_DEVICE_REGISTRY_UPDATED,
|
||||
{
|
||||
"action": "update",
|
||||
"device_id": "1234",
|
||||
"changes": ["manufacturer"],
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(mock_sync.mock_calls) == 0
|
||||
|
||||
# Device registry updated with relevant changes
|
||||
# but entity has area ID so not impacted
|
||||
hass.bus.async_fire(
|
||||
dr.EVENT_DEVICE_REGISTRY_UPDATED,
|
||||
{
|
||||
"action": "update",
|
||||
"device_id": "1234",
|
||||
"changes": ["area_id"],
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(mock_sync.mock_calls) == 0
|
||||
|
||||
ent_reg.async_update_entity(entity_entry.entity_id, area_id=None)
|
||||
|
||||
# Device registry updated with relevant changes
|
||||
# but entity has area ID so not impacted
|
||||
hass.bus.async_fire(
|
||||
dr.EVENT_DEVICE_REGISTRY_UPDATED,
|
||||
{
|
||||
"action": "update",
|
||||
"device_id": "1234",
|
||||
"changes": ["area_id"],
|
||||
},
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert len(mock_sync.mock_calls) == 1
|
||||
|
||||
|
||||
async def test_sync_google_when_started(hass, mock_cloud_login, cloud_prefs):
|
||||
"""Test Google config syncs on init."""
|
||||
config = CloudGoogleConfig(
|
||||
|
|
Loading…
Reference in New Issue