fix(document): Refresh runtime route docs
parent
1bb8864426
commit
2827eac158
|
|
@ -3,16 +3,15 @@
|
||||||
Architecture overview
|
Architecture overview
|
||||||
---------------------
|
---------------------
|
||||||
This integration is *push-based*: the weather station calls our HTTP endpoint and we
|
This integration is *push-based*: the weather station calls our HTTP endpoint and we
|
||||||
receive a query payload. We do not poll the station.
|
receive an HTTP payload. We do not poll the station.
|
||||||
|
|
||||||
Key building blocks:
|
Key building blocks:
|
||||||
- `WeatherDataUpdateCoordinator` acts as an in-memory "data bus" for the latest payload.
|
- `WeatherDataUpdateCoordinator` acts as an in-memory "data bus" for the latest payload.
|
||||||
On each webhook request we call `async_set_updated_data(...)` and all `CoordinatorEntity`
|
On each webhook request we call `async_set_updated_data(...)` and all `CoordinatorEntity`
|
||||||
sensors get notified and update their states.
|
sensors get notified and update their states.
|
||||||
- `hass.data[DOMAIN][entry_id]` is a per-entry *dict* that stores runtime state
|
- `entry.runtime_data` stores per-entry runtime state (coordinator instance, options
|
||||||
(coordinator instance, options snapshot, and sensor platform callbacks). Keeping this
|
snapshot, and sensor platform callbacks). Shared aiohttp route registrations stay
|
||||||
structure consistent is critical; mixing different value types under the same key can
|
under `hass.data[DOMAIN]["routes"]` because they must survive a config-entry reload.
|
||||||
break listener wiring and make the UI appear "frozen".
|
|
||||||
|
|
||||||
Auto-discovery
|
Auto-discovery
|
||||||
--------------
|
--------------
|
||||||
|
|
@ -99,9 +98,9 @@ def register_path(
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""Register webhook paths.
|
"""Register webhook paths.
|
||||||
|
|
||||||
We register both possible endpoints and use an internal dispatcher (`Routes`) to
|
We register the supported station endpoints and use an internal dispatcher
|
||||||
enable exactly one of them. This lets us toggle WSLink mode without re-registering
|
(`Routes`) to enable only the configured ingress path. This lets us toggle
|
||||||
routes on the aiohttp router.
|
protocols without re-registering routes on the aiohttp router.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
hass.data.setdefault(DOMAIN, {})
|
hass.data.setdefault(DOMAIN, {})
|
||||||
|
|
|
||||||
|
|
@ -71,8 +71,8 @@ def _configured_protocol(config: SWSConfigEntry) -> str:
|
||||||
"""Return the primary configured protocol (wu / wslink / ecowitt).
|
"""Return the primary configured protocol (wu / wslink / ecowitt).
|
||||||
|
|
||||||
The legacy PWS/WSLink endpoint takes precedence when enabled; otherwise an
|
The legacy PWS/WSLink endpoint takes precedence when enabled; otherwise an
|
||||||
Ecowitt-only setup reports "ecowitt". (Legacy and Ecowitt can be enabled at the
|
Ecowitt-only setup reports "ecowitt". If an old or externally edited config
|
||||||
same time; this just labels the primary protocol for the summary.)
|
has both flags enabled, legacy still wins because that is the effective route.
|
||||||
"""
|
"""
|
||||||
if checked_or(config.options.get(LEGACY_ENABLED), bool, True):
|
if checked_or(config.options.get(LEGACY_ENABLED), bool, True):
|
||||||
return "wslink" if checked_or(config.options.get(WSLINK), bool, False) else "wu"
|
return "wslink" if checked_or(config.options.get(WSLINK), bool, False) else "wu"
|
||||||
|
|
@ -235,8 +235,8 @@ class HealthCoordinator(DataUpdateCoordinator):
|
||||||
reason = ingress.get("reason")
|
reason = ingress.get("reason")
|
||||||
|
|
||||||
# A WU vs WSLink mismatch means the station is misconfigured for the legacy
|
# A WU vs WSLink mismatch means the station is misconfigured for the legacy
|
||||||
# endpoint. Ecowitt coexists with the legacy endpoint, so it never counts as a
|
# endpoint. Ecowitt has its own route and is considered valid only when an
|
||||||
# mismatch - it is a valid protocol whenever a payload arrives on its route.
|
# accepted Ecowitt payload arrives there.
|
||||||
legacy_mismatch = (
|
legacy_mismatch = (
|
||||||
last_protocol in _LEGACY_PROTOCOLS
|
last_protocol in _LEGACY_PROTOCOLS
|
||||||
and configured_protocol in _LEGACY_PROTOCOLS
|
and configured_protocol in _LEGACY_PROTOCOLS
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,10 @@
|
||||||
Why this dispatcher exists
|
Why this dispatcher exists
|
||||||
--------------------------
|
--------------------------
|
||||||
Home Assistant registers aiohttp routes on startup. Re-registering or removing routes at runtime
|
Home Assistant registers aiohttp routes on startup. Re-registering or removing routes at runtime
|
||||||
is awkward and error-prone (and can raise if routes already exist). This integration supports two
|
is awkward and error-prone (and can raise if routes already exist). This integration supports
|
||||||
different push endpoints (legacy WU-style vs WSLink). To allow switching between them without
|
multiple station push endpoints. To allow switching between them without touching the aiohttp
|
||||||
touching the aiohttp router, we register both routes once and use this in-process dispatcher to
|
router, we register routes once and use this in-process dispatcher to decide which one is
|
||||||
decide which one is currently enabled.
|
currently enabled.
|
||||||
|
|
||||||
Important note:
|
Important note:
|
||||||
- Each route stores a *bound method* handler (e.g. `coordinator.received_data`). That means the
|
- Each route stores a *bound method* handler (e.g. `coordinator.received_data`). That means the
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ These tests rely on `pytest-homeassistant-custom-component` to provide:
|
||||||
- `MockConfigEntry` helper for config entries
|
- `MockConfigEntry` helper for config entries
|
||||||
|
|
||||||
They validate that the integration can set up a config entry and that the
|
They validate that the integration can set up a config entry and that the
|
||||||
coordinator is created and stored in `hass.data`.
|
coordinator is stored on `entry.runtime_data`.
|
||||||
|
|
||||||
Note:
|
Note:
|
||||||
This integration registers aiohttp routes via `hass.http.app.router`. In this
|
This integration registers aiohttp routes via `hass.http.app.router`. In this
|
||||||
|
|
@ -46,7 +46,7 @@ def config_entry() -> MockConfigEntry:
|
||||||
async def test_async_setup_entry_creates_runtime_state(
|
async def test_async_setup_entry_creates_runtime_state(
|
||||||
hass, config_entry: MockConfigEntry, monkeypatch
|
hass, config_entry: MockConfigEntry, monkeypatch
|
||||||
):
|
):
|
||||||
"""Setting up a config entry should succeed and populate hass.data."""
|
"""Setting up a config entry should succeed and populate runtime state."""
|
||||||
config_entry.add_to_hass(hass)
|
config_entry.add_to_hass(hass)
|
||||||
|
|
||||||
# `async_setup_entry` calls `register_path`, which needs `hass.http`.
|
# `async_setup_entry` calls `register_path`, which needs `hass.http`.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue