Event Bus
User-facing pub/sub façade over Home Assistant's WebSocket event stream. Subscriptions automatically survive reconnects — see Reconnect handling. For typical per-entity reactions prefer the listener decorators described in State and value listeners.
events
EventBus — typed event subscriptions over a WebSocketPort.
The bus tracks per-event-type subscriptions and dispatches each incoming
event to every registered handler. It also exposes a buffering mode used
by StateStore during initial state priming to fix the race between the
REST snapshot and the first incoming event.
Lifecycle
- Constructed with a
WebSocketPort. - After the WS connects, call
startto subscribe to all desired event types in a single batch. - While priming, call
enable_buffering(event_type)to capture matching events into an in-memory queue. Drain withdrain_buffer(event_type). - Reconnect re-subscriptions are handled automatically by the underlying
WebSocketPort.on_reconnecthook installed bystart.
EventBus
Pub/sub facade over a WebSocketPort.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ws
|
WebSocketPort
|
The transport used to subscribe to Home Assistant events. |
required |
Notes
Subscriptions can fail at the transport layer. The bus exposes two APIs to handle this:
subscribe/unsubscribe— fire-and-forget; failures are logged and recorded on the bus so callers can inspect them viasubscription_failureandpending_subscription.subscribe_async/unsubscribe_async— awaitable; transport errors are raised to the caller. Prefer these whenever the caller needs confirmation that Home Assistant actually accepted the subscription.
Source code in src/haclient/core/events.py
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 | |
subscribe
subscribe(event_type: str, handler: EventHandler) -> EventHandler
Register handler for the given event_type.
Subscriptions registered before start are batched; those added
afterwards trigger an immediate WebSocket subscribe if it is the
first handler for the type. The scheduled task is tracked so
callers can await it (pending_subscription) or inspect its
outcome (subscription_failure).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event_type
|
str
|
The Home Assistant event type. |
required |
handler
|
callable
|
Sync or async callable receiving the event dict. |
required |
Returns:
| Type | Description |
|---|---|
callable
|
The same handler, for use as a decorator. |
Notes
This method does not raise transport errors. Use
subscribe_async when the caller needs to know whether Home
Assistant accepted the subscription.
Source code in src/haclient/core/events.py
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | |
subscribe_async
async
subscribe_async(event_type: str, handler: EventHandler) -> EventHandler
Register handler and await the underlying WebSocket subscribe.
Like subscribe, but transport failures propagate to the caller
and the handler is rolled back if the first subscribe for an
event type fails — so callers can rely on the returned handler
being live.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event_type
|
str
|
The Home Assistant event type. |
required |
handler
|
callable
|
Sync or async callable receiving the event dict. |
required |
Returns:
| Type | Description |
|---|---|
callable
|
The registered handler. |
Raises:
| Type | Description |
|---|---|
Exception
|
Any exception raised by the underlying |
Source code in src/haclient/core/events.py
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | |
unsubscribe
unsubscribe(event_type: str, handler: EventHandler) -> None
Remove a previously registered handler.
If the last handler for event_type is removed the WebSocket subscription is also cancelled in the background.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event_type
|
str
|
The Home Assistant event type to unsubscribe from. |
required |
handler
|
callable
|
The exact handler previously passed to |
required |
Source code in src/haclient/core/events.py
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 | |
unsubscribe_async
async
unsubscribe_async(event_type: str, handler: EventHandler) -> None
Remove a handler and await any resulting WebSocket unsubscribe.
Unlike unsubscribe, transport errors raised while telling Home
Assistant to stop sending events propagate to the caller.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event_type
|
str
|
The Home Assistant event type to unsubscribe from. |
required |
handler
|
callable
|
The exact handler previously passed to |
required |
Raises:
| Type | Description |
|---|---|
Exception
|
Any exception raised by |
Source code in src/haclient/core/events.py
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 | |
subscription_failure
subscription_failure(event_type: str) -> BaseException | None
Return the last fire-and-forget subscribe failure, if any.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event_type
|
str
|
The event type to inspect. |
required |
Returns:
| Type | Description |
|---|---|
BaseException or None
|
The exception raised by the most recent fire-and-forget
subscribe attempt, or |
Source code in src/haclient/core/events.py
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 | |
pending_subscription
pending_subscription(event_type: str) -> asyncio.Task[None] | None
Return the in-flight subscribe task for event_type, if any.
Awaiting the returned task lets callers convert a fire-and-forget
subscribe into a confirmed registration without changing the
original call site.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event_type
|
str
|
The event type whose pending subscribe task to return. |
required |
Returns:
| Type | Description |
|---|---|
Task or None
|
The scheduled task, or |
Source code in src/haclient/core/events.py
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 | |
start
async
start() -> None
Subscribe to every registered event type and arm reconnect.
Safe to call multiple times.
Notes
Transport failures during the initial batch are recorded on the
bus (see subscription_failure) but not raised, so a single
flaky event type does not abort startup. Use subscribe_async
afterwards if you need confirmation that a specific subscription
is live.
Source code in src/haclient/core/events.py
274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 | |
enable_buffering
enable_buffering(event_type: str) -> None
Begin buffering events of event_type instead of dispatching them.
Used by StateStore while the initial REST snapshot is being
applied. Idempotent.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event_type
|
str
|
Event type whose incoming frames should be queued in memory
until |
required |
Source code in src/haclient/core/events.py
347 348 349 350 351 352 353 354 355 356 357 358 359 | |
drain_buffer
async
drain_buffer(event_type: str) -> None
Stop buffering and dispatch any accumulated events.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
event_type
|
str
|
The event type whose buffer should be drained. |
required |
Source code in src/haclient/core/events.py
361 362 363 364 365 366 367 368 369 370 371 372 373 374 | |
discard_buffer
discard_buffer(event_type: str) -> None
Drop any buffered events for event_type without dispatching.
Source code in src/haclient/core/events.py
376 377 378 | |
install_reconnect_hook
install_reconnect_hook(on_reconnect: EventHandler | None = None) -> None
Wire the bus into the WebSocket reconnect lifecycle.
After a reconnect, the underlying WS adapter re-subscribes for us
(it stores the original handlers). All we need to do is invoke the
optional on_reconnect callback (e.g. StateStore.refresh_all).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
on_reconnect
|
callable or None
|
Sync or async callable invoked once the WebSocket reconnects.
Receives an empty event dict for compatibility with the
generic event-handler signature. |
None
|
Source code in src/haclient/core/events.py
380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 | |