# ADR-0121: Hub + DataUpdateCoordinator Separation (Single Coordinator per Panel)

Status: Accepted

## Context

The E27 Home Assistant integration is event-driven and maintains a single
session per panel (ADR-0118). The library (elke27_lib) owns protocol, session,
bootstrap, and state, while Home Assistant must expose entities that update
reliably and efficiently.

Home Assistant provides DataUpdateCoordinator (DUC) as a standard mechanism to:
- centralize data distribution to many entities
- standardize availability and error propagation
- avoid duplicated refresh work
- integrate cleanly with CoordinatorEntity patterns

To keep responsibilities clear and testable, we want a separation between:
- a Home Assistant “hub” that orchestrates the library client and applies
  integration-level policies, and
- a Home Assistant coordinator that serves as the HA-facing update fan-out
  surface.

## Decision

The integration will use a two-layer HA runtime model:

1. Hub (integration-owned)
   - Owns the Elke27Client instance and its lifecycle.
   - Subscribes to library semantic events.
   - Maintains the canonical snapshot/state view for Home Assistant.
   - Applies HA-side policies and decisions, including:
     - permission-aware preflight prompting (ADR-0110)
     - privilege TTL semantics (ADR-0115)
     - reconnect lifecycle coordination (ADR-0113) as needed at the HA layer
   - Exposes command methods for entities and services.
   - Never allows parallel outbound traffic to bypass library throttling.

2. DataUpdateCoordinator (HA-owned)
   - Serves as the single HA-facing data surface for entities.
   - Receives push-fed updates from the hub via async_set_updated_data.
   - Standardizes availability and error state presentation.
   - May optionally perform low-rate health checks via the hub, but does not
     perform routine polling for state.

There will be exactly one DataUpdateCoordinator per configured panel (per config
entry). The coordinator holds a single unified snapshot tree for that panel.

Entities:
- subclass CoordinatorEntity
- read exclusively from coordinator.data
- call hub command methods for actions
- never call the library directly

## Rationale

This model:
- keeps protocol complexity out of entities and out of HA coordinator plumbing
- aligns with standard Home Assistant patterns (CoordinatorEntity + DUC)
- avoids multiple independent refresh loops per domain
- provides a clean test boundary between orchestration (hub) and HA update
  distribution (coordinator)
- matches the single-session-per-panel constraint

A single coordinator per panel reduces complexity and ensures consistent cross-
domain state updates (areas/zones/outputs/etc.) derived from the same session and
event stream.

## Consequences

- A unified snapshot object must exist for coordinator.data.
- The hub is the only integration component that interacts with Elke27Client.
- Entities become thin views and are simpler to maintain.
- Optional health checks, if used, must route through hub and respect library
  backpressure (ADR-0111).

## Scope / Non-Goals

- Does not define the exact snapshot object shape.
- Does not define specific health check intervals.
- Does not constrain internal library state layout.

## References

- ADR-0109: Home Assistant Integration Adapts to E27 Library Model
- ADR-0111: E27 Request Concurrency and Backpressure
- ADR-0112: E27 Bootstrap and Configuration Download Sequencing
- ADR-0115: Privilege Lifetime and Sliding TTL
- ADR-0118: Multi-Panel Support with Single Session per Panel
- ADR-0120: Throttling and Concurrency Responsibilities (HA vs Library)
