Add Home Assistant Started event (#34657)

This commit is contained in:
Paulus Schoutsen 2020-04-24 14:13:39 -07:00 committed by GitHub
parent b741199ed3
commit 77443b3d09
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 68 additions and 25 deletions

View File

@ -14,7 +14,7 @@ from homeassistant.const import (
CONF_PLATFORM, CONF_PLATFORM,
CONF_ZONE, CONF_ZONE,
EVENT_AUTOMATION_TRIGGERED, EVENT_AUTOMATION_TRIGGERED,
EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STARTED,
SERVICE_RELOAD, SERVICE_RELOAD,
SERVICE_TOGGLE, SERVICE_TOGGLE,
SERVICE_TURN_OFF, SERVICE_TURN_OFF,
@ -409,7 +409,7 @@ class AutomationEntity(ToggleEntity, RestoreEntity):
# HomeAssistant is starting up # HomeAssistant is starting up
if self.hass.state != CoreState.not_running: if self.hass.state != CoreState.not_running:
self._async_detach_triggers = await self._async_attach_triggers() self._async_detach_triggers = await self._async_attach_triggers(False)
self.async_write_ha_state() self.async_write_ha_state()
return return
@ -419,10 +419,10 @@ class AutomationEntity(ToggleEntity, RestoreEntity):
if not self._is_enabled or self._async_detach_triggers is not None: if not self._is_enabled or self._async_detach_triggers is not None:
return return
self._async_detach_triggers = await self._async_attach_triggers() self._async_detach_triggers = await self._async_attach_triggers(True)
self.hass.bus.async_listen_once( self.hass.bus.async_listen_once(
EVENT_HOMEASSISTANT_START, async_enable_automation EVENT_HOMEASSISTANT_STARTED, async_enable_automation
) )
self.async_write_ha_state() self.async_write_ha_state()
@ -439,15 +439,17 @@ class AutomationEntity(ToggleEntity, RestoreEntity):
self.async_write_ha_state() self.async_write_ha_state()
async def _async_attach_triggers(self): async def _async_attach_triggers(
self, home_assistant_start: bool
) -> Optional[Callable[[], None]]:
"""Set up the triggers.""" """Set up the triggers."""
removes = [] removes = []
info = {"name": self._name} info = {"name": self._name, "home_assistant_start": home_assistant_start}
for conf in self._trigger_config: for conf in self._trigger_config:
platform = importlib.import_module(f".{conf[CONF_PLATFORM]}", __name__) platform = importlib.import_module(f".{conf[CONF_PLATFORM]}", __name__)
remove = await platform.async_attach_trigger( remove = await platform.async_attach_trigger( # type: ignore
self.hass, conf, self.async_trigger, info self.hass, conf, self.async_trigger, info
) )

View File

@ -4,7 +4,7 @@ import logging
import voluptuous as vol import voluptuous as vol
from homeassistant.const import CONF_EVENT, CONF_PLATFORM, EVENT_HOMEASSISTANT_STOP from homeassistant.const import CONF_EVENT, CONF_PLATFORM, EVENT_HOMEASSISTANT_STOP
from homeassistant.core import CoreState, callback from homeassistant.core import callback
# mypy: allow-untyped-defs # mypy: allow-untyped-defs
@ -40,7 +40,7 @@ async def async_attach_trigger(hass, config, action, automation_info):
# Automation are enabled while hass is starting up, fire right away # Automation are enabled while hass is starting up, fire right away
# Check state because a config reload shouldn't trigger it. # Check state because a config reload shouldn't trigger it.
if hass.state == CoreState.starting: if automation_info["home_assistant_start"]:
hass.async_run_job( hass.async_run_job(
action({"trigger": {"platform": "homeassistant", "event": event}}) action({"trigger": {"platform": "homeassistant", "event": event}})
) )

View File

@ -6,7 +6,12 @@ from hass_nabucasa import cloud_api
from hass_nabucasa.google_report_state import ErrorResponse from hass_nabucasa.google_report_state import ErrorResponse
from homeassistant.components.google_assistant.helpers import AbstractConfig from homeassistant.components.google_assistant.helpers import AbstractConfig
from homeassistant.const import CLOUD_NEVER_EXPOSED_ENTITIES, HTTP_OK from homeassistant.const import (
CLOUD_NEVER_EXPOSED_ENTITIES,
EVENT_HOMEASSISTANT_STARTED,
HTTP_OK,
)
from homeassistant.core import CoreState, callback
from homeassistant.helpers import entity_registry from homeassistant.helpers import entity_registry
from .const import ( from .const import (
@ -32,6 +37,7 @@ class CloudGoogleConfig(AbstractConfig):
self._cloud = cloud self._cloud = cloud
self._cur_entity_prefs = self._prefs.google_entity_configs self._cur_entity_prefs = self._prefs.google_entity_configs
self._sync_entities_lock = asyncio.Lock() self._sync_entities_lock = asyncio.Lock()
self._sync_on_started = False
@property @property
def enabled(self): def enabled(self):
@ -169,6 +175,21 @@ class CloudGoogleConfig(AbstractConfig):
entity_id = event.data["entity_id"] entity_id = event.data["entity_id"]
# Schedule a sync if a change was made to an entity that Google knows about if not self._should_expose_entity_id(entity_id):
if self._should_expose_entity_id(entity_id): return
if self.hass.state == CoreState.running:
self.async_schedule_google_sync_all() self.async_schedule_google_sync_all()
return
if self._sync_on_started:
return
self._sync_on_started = True
@callback
async def sync_google(_):
"""Sync entities to Google."""
await self.async_sync_entities_all()
self.hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STARTED, sync_google)

View File

@ -184,6 +184,7 @@ EVENT_COMPONENT_LOADED = "component_loaded"
EVENT_CORE_CONFIG_UPDATE = "core_config_updated" EVENT_CORE_CONFIG_UPDATE = "core_config_updated"
EVENT_HOMEASSISTANT_CLOSE = "homeassistant_close" EVENT_HOMEASSISTANT_CLOSE = "homeassistant_close"
EVENT_HOMEASSISTANT_START = "homeassistant_start" EVENT_HOMEASSISTANT_START = "homeassistant_start"
EVENT_HOMEASSISTANT_STARTED = "homeassistant_started"
EVENT_HOMEASSISTANT_STOP = "homeassistant_stop" EVENT_HOMEASSISTANT_STOP = "homeassistant_stop"
EVENT_HOMEASSISTANT_FINAL_WRITE = "homeassistant_final_write" EVENT_HOMEASSISTANT_FINAL_WRITE = "homeassistant_final_write"
EVENT_LOGBOOK_ENTRY = "logbook_entry" EVENT_LOGBOOK_ENTRY = "logbook_entry"

View File

@ -50,6 +50,7 @@ from homeassistant.const import (
EVENT_HOMEASSISTANT_CLOSE, EVENT_HOMEASSISTANT_CLOSE,
EVENT_HOMEASSISTANT_FINAL_WRITE, EVENT_HOMEASSISTANT_FINAL_WRITE,
EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_START,
EVENT_HOMEASSISTANT_STARTED,
EVENT_HOMEASSISTANT_STOP, EVENT_HOMEASSISTANT_STOP,
EVENT_SERVICE_REGISTERED, EVENT_SERVICE_REGISTERED,
EVENT_SERVICE_REMOVED, EVENT_SERVICE_REMOVED,
@ -279,6 +280,7 @@ class HomeAssistant:
self.state = CoreState.running self.state = CoreState.running
_async_create_timer(self) _async_create_timer(self)
self.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
def add_job(self, target: Callable[..., Any], *args: Any) -> None: def add_job(self, target: Callable[..., Any], *args: Any) -> None:
"""Add job to the executor pool. """Add job to the executor pool.

View File

@ -25,6 +25,7 @@ async def test_if_fires_on_hass_start(hass):
assert len(calls) == 0 assert len(calls) == 0
await hass.async_start() await hass.async_start()
await hass.async_block_till_done()
assert automation.is_on(hass, "automation.hello") assert automation.is_on(hass, "automation.hello")
assert len(calls) == 1 assert len(calls) == 1
@ -61,6 +62,7 @@ async def test_if_fires_on_hass_shutdown(hass):
await hass.async_start() await hass.async_start()
assert automation.is_on(hass, "automation.hello") assert automation.is_on(hass, "automation.hello")
await hass.async_block_till_done()
assert len(calls) == 0 assert len(calls) == 0
with patch.object(hass.loop, "stop"): with patch.object(hass.loop, "stop"):

View File

@ -10,7 +10,7 @@ from homeassistant.const import (
ATTR_ENTITY_ID, ATTR_ENTITY_ID,
ATTR_NAME, ATTR_NAME,
EVENT_AUTOMATION_TRIGGERED, EVENT_AUTOMATION_TRIGGERED,
EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STARTED,
STATE_OFF, STATE_OFF,
STATE_ON, STATE_ON,
) )
@ -700,6 +700,7 @@ async def test_initial_value_on(hass):
assert automation.is_on(hass, "automation.hello") assert automation.is_on(hass, "automation.hello")
await hass.async_start() await hass.async_start()
await hass.async_block_till_done()
hass.bus.async_fire("test_event") hass.bus.async_fire("test_event")
await hass.async_block_till_done() await hass.async_block_till_done()
assert len(calls) == 1 assert len(calls) == 1
@ -822,7 +823,7 @@ async def test_automation_not_trigger_on_bootstrap(hass):
await hass.async_block_till_done() await hass.async_block_till_done()
assert len(calls) == 0 assert len(calls) == 0
hass.bus.async_fire(EVENT_HOMEASSISTANT_START) hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
await hass.async_block_till_done() await hass.async_block_till_done()
assert automation.is_on(hass, "automation.hello") assert automation.is_on(hass, "automation.hello")

View File

@ -6,7 +6,8 @@ from asynctest import patch
from homeassistant.components.cloud import GACTIONS_SCHEMA from homeassistant.components.cloud import GACTIONS_SCHEMA
from homeassistant.components.cloud.google_config import CloudGoogleConfig from homeassistant.components.cloud.google_config import CloudGoogleConfig
from homeassistant.components.google_assistant import helpers as ga_helpers from homeassistant.components.google_assistant import helpers as ga_helpers
from homeassistant.const import HTTP_NOT_FOUND from homeassistant.const import EVENT_HOMEASSISTANT_STARTED, HTTP_NOT_FOUND
from homeassistant.core import CoreState
from homeassistant.helpers.entity_registry import EVENT_ENTITY_REGISTRY_UPDATED from homeassistant.helpers.entity_registry import EVENT_ENTITY_REGISTRY_UPDATED
from homeassistant.util.dt import utcnow from homeassistant.util.dt import utcnow
@ -25,9 +26,7 @@ async def test_google_update_report_state(hass, cloud_prefs):
await config.async_initialize() await config.async_initialize()
await config.async_connect_agent_user("mock-user-id") await config.async_connect_agent_user("mock-user-id")
with patch.object( with patch.object(config, "async_sync_entities") as mock_sync, patch(
config, "async_sync_entities", side_effect=mock_coro
) as mock_sync, patch(
"homeassistant.components.google_assistant.report_state.async_enable_report_state" "homeassistant.components.google_assistant.report_state.async_enable_report_state"
) as mock_report_state: ) as mock_report_state:
await cloud_prefs.async_update(google_report_state=True) await cloud_prefs.async_update(google_report_state=True)
@ -67,9 +66,9 @@ async def test_google_update_expose_trigger_sync(hass, cloud_prefs):
await config.async_initialize() await config.async_initialize()
await config.async_connect_agent_user("mock-user-id") await config.async_connect_agent_user("mock-user-id")
with patch.object( with patch.object(config, "async_sync_entities") as mock_sync, patch.object(
config, "async_sync_entities", side_effect=mock_coro ga_helpers, "SYNC_DELAY", 0
) as mock_sync, patch.object(ga_helpers, "SYNC_DELAY", 0): ):
await cloud_prefs.async_update_google_entity_config( await cloud_prefs.async_update_google_entity_config(
entity_id="light.kitchen", should_expose=True entity_id="light.kitchen", should_expose=True
) )
@ -79,9 +78,9 @@ async def test_google_update_expose_trigger_sync(hass, cloud_prefs):
assert len(mock_sync.mock_calls) == 1 assert len(mock_sync.mock_calls) == 1
with patch.object( with patch.object(config, "async_sync_entities") as mock_sync, patch.object(
config, "async_sync_entities", side_effect=mock_coro ga_helpers, "SYNC_DELAY", 0
) as mock_sync, patch.object(ga_helpers, "SYNC_DELAY", 0): ):
await cloud_prefs.async_update_google_entity_config( await cloud_prefs.async_update_google_entity_config(
entity_id="light.kitchen", should_expose=False entity_id="light.kitchen", should_expose=False
) )
@ -107,7 +106,7 @@ async def test_google_entity_registry_sync(hass, mock_cloud_login, cloud_prefs):
await config.async_connect_agent_user("mock-user-id") await config.async_connect_agent_user("mock-user-id")
with patch.object( with patch.object(
config, "async_schedule_google_sync_all", side_effect=mock_coro config, "async_schedule_google_sync_all"
) as mock_sync, patch.object(ga_helpers, "SYNC_DELAY", 0): ) as mock_sync, patch.object(ga_helpers, "SYNC_DELAY", 0):
# Created entity # Created entity
hass.bus.async_fire( hass.bus.async_fire(
@ -148,3 +147,18 @@ async def test_google_entity_registry_sync(hass, mock_cloud_login, cloud_prefs):
await hass.async_block_till_done() await hass.async_block_till_done()
assert len(mock_sync.mock_calls) == 3 assert len(mock_sync.mock_calls) == 3
# When hass is not started yet we wait till started
hass.state = CoreState.starting
hass.bus.async_fire(
EVENT_ENTITY_REGISTRY_UPDATED,
{"action": "create", "entity_id": "light.kitchen"},
)
await hass.async_block_till_done()
assert len(mock_sync.mock_calls) == 3
with patch.object(config, "async_sync_entities_all") as mock_sync:
hass.bus.async_fire(EVENT_HOMEASSISTANT_STARTED)
await hass.async_block_till_done()
assert len(mock_sync.mock_calls) == 1