Use this file to discover all available pages before exploring further.
The HomeAssistant class is the heart of the system, coordinating all operations and managing the asyncio event loop. Every integration, automation, and service interacts with this central hub.
@callbackdef async_create_task[_R]( self, target: Coroutine[Any, Any, _R], name: str | None = None, eager_start: bool = True,) -> asyncio.Task[_R]: """Create a task from within the event loop.""" if eager_start: task = create_eager_task(target, name=name, loop=self.loop) if task.done(): return task else: task = self.loop.create_task(target, name=name) self._tasks.add(task) task.add_done_callback(self._tasks.remove) return task
Eager Start: When eager_start=True, the task begins executing immediately rather than waiting for the next event loop iteration. This significantly improves performance for short-running tasks.
Background tasks are designed for long-running operations:
homeassistant/core.py
@callbackdef async_create_background_task[_R]( self, target: Coroutine[Any, Any, _R], name: str, eager_start: bool = True) -> asyncio.Task[_R]: """Create a background task. A background task is different from a normal task: - Will not block startup - Will be automatically cancelled on shutdown - Calls to async_block_till_done will not wait for completion """ if eager_start: task = create_eager_task(target, name=name, loop=self.loop) if task.done(): return task else: task = self.loop.create_task(target, name=name) self._background_tasks.add(task) task.add_done_callback(self._background_tasks.remove) return task
Use background tasks for operations that should not prevent Home Assistant from starting or stopping, such as continuous monitoring loops or periodic sync operations.
The HassJob system provides type-aware job execution:
homeassistant/core.py
class HassJob[**_P, _R_co]: """Represent a job to be run later. We check the callable type in advance so we can avoid checking it every time we run the job. """ def __init__( self, target: Callable[_P, _R_co], name: str | None = None, *, cancel_on_shutdown: bool | None = None, job_type: HassJobType | None = None, ) -> None: self.target = target self.name = name self._cancel_on_shutdown = cancel_on_shutdown if job_type: self._cache["job_type"] = job_type
def verify_event_loop_thread(self, what: str) -> None: """Report and raise if not running in event loop thread.""" if self.loop_thread_id != threading.get_ident(): from .helpers import frame frame.report_non_thread_safe_operation(what)
In contexts where passing hass is impractical, you can retrieve it:
homeassistant/core.py
@callbackdef async_get_hass() -> HomeAssistant: """Return the HomeAssistant instance. Raises HomeAssistantError when called from the wrong thread. """ if not (hass := async_get_hass_or_none()): raise HomeAssistantError( "async_get_hass called from the wrong thread" ) return hass
Use async_get_hass() sparingly. It’s better to pass hass explicitly to maintain clear dependencies and improve testability.
The config object provides access to system configuration:
hass.config.config_dir # Configuration directory pathhass.config.latitude # Home location latitude hass.config.longitude # Home location longitudehass.config.elevation # Home elevationhass.config.time_zone # System timezonehass.config.units # Unit system (metric/imperial)hass.config.safe_mode # Whether running in safe modehass.config.recovery_mode # Whether running in recovery mode
# Store integration-specific datahass.data["my_integration"] = MyIntegrationData()# Use HassKey for type safetyfrom homeassistant.util.hass_dict import HassKeyMY_DATA_KEY: HassKey[MyIntegrationData] = HassKey("my_integration")hass.data[MY_DATA_KEY] = MyIntegrationData()
Use the integration domain as the key to avoid conflicts. For complex data structures, consider using HassKey for type safety.