mirror of
https://github.com/home-assistant/core.git
synced 2025-07-24 21:57:51 +00:00
Add Home Assistant Started event (#34657)
This commit is contained in:
parent
b741199ed3
commit
77443b3d09
@ -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
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -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}})
|
||||||
)
|
)
|
||||||
|
@ -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)
|
||||||
|
@ -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"
|
||||||
|
@ -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.
|
||||||
|
@ -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"):
|
||||||
|
@ -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")
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user