diff --git a/zha/event.py b/zha/event.py index bed66632..6a0b7dcf 100644 --- a/zha/event.py +++ b/zha/event.py @@ -19,6 +19,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self._listeners: dict[str, list[Callable]] = {} self._event_tasks: list[asyncio.Task] = [] + self._golbal_listeners: list[Callable] = [] def on_event( # pylint: disable=invalid-name self, event_name: str, callback: Callable @@ -34,6 +35,19 @@ def unsubscribe() -> None: return unsubscribe + def on_all_events( # pylint: disable=invalid-name + self, callback: Callable + ) -> Callable: + """Register a callback for all events.""" + self._golbal_listeners.append(callback) + + def unsubscribe() -> None: + """Unsubscribe listeners.""" + if callback in self._golbal_listeners: + self._golbal_listeners.remove(callback) + + return unsubscribe + def once(self, event_name: str, callback: Callable) -> Callable: """Listen for an event exactly once.""" @@ -47,7 +61,7 @@ def event_listener(data: dict) -> None: def emit(self, event_name: str, data=None) -> None: """Run all callbacks for an event.""" - for listener in self._listeners.get(event_name, []): + for listener in [*self._listeners.get(event_name, []), *self._golbal_listeners]: if inspect.iscoroutinefunction(listener): if data is None: task = asyncio.create_task(listener())