From 2827eac15856af4d68739a853c257f7c1048b291 Mon Sep 17 00:00:00 2001 From: SchiZzA Date: Sun, 26 Jul 2026 00:01:15 +0200 Subject: [PATCH] fix(document): Refresh runtime route docs --- custom_components/sws12500/__init__.py | 15 +++++++-------- custom_components/sws12500/health_coordinator.py | 8 ++++---- custom_components/sws12500/routes.py | 8 ++++---- tests/test_init.py | 4 ++-- 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/custom_components/sws12500/__init__.py b/custom_components/sws12500/__init__.py index 5760d39..1756a5f 100644 --- a/custom_components/sws12500/__init__.py +++ b/custom_components/sws12500/__init__.py @@ -3,16 +3,15 @@ Architecture overview --------------------- 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: - `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` sensors get notified and update their states. -- `hass.data[DOMAIN][entry_id]` is a per-entry *dict* that stores runtime state - (coordinator instance, options snapshot, and sensor platform callbacks). Keeping this - structure consistent is critical; mixing different value types under the same key can - break listener wiring and make the UI appear "frozen". +- `entry.runtime_data` stores per-entry runtime state (coordinator instance, options + snapshot, and sensor platform callbacks). Shared aiohttp route registrations stay + under `hass.data[DOMAIN]["routes"]` because they must survive a config-entry reload. Auto-discovery -------------- @@ -99,9 +98,9 @@ def register_path( ) -> bool: """Register webhook paths. - We register both possible endpoints and use an internal dispatcher (`Routes`) to - enable exactly one of them. This lets us toggle WSLink mode without re-registering - routes on the aiohttp router. + We register the supported station endpoints and use an internal dispatcher + (`Routes`) to enable only the configured ingress path. This lets us toggle + protocols without re-registering routes on the aiohttp router. """ hass.data.setdefault(DOMAIN, {}) diff --git a/custom_components/sws12500/health_coordinator.py b/custom_components/sws12500/health_coordinator.py index cfbeba9..16cb1c7 100644 --- a/custom_components/sws12500/health_coordinator.py +++ b/custom_components/sws12500/health_coordinator.py @@ -71,8 +71,8 @@ def _configured_protocol(config: SWSConfigEntry) -> str: """Return the primary configured protocol (wu / wslink / ecowitt). The legacy PWS/WSLink endpoint takes precedence when enabled; otherwise an - Ecowitt-only setup reports "ecowitt". (Legacy and Ecowitt can be enabled at the - same time; this just labels the primary protocol for the summary.) + Ecowitt-only setup reports "ecowitt". If an old or externally edited config + has both flags enabled, legacy still wins because that is the effective route. """ if checked_or(config.options.get(LEGACY_ENABLED), bool, True): return "wslink" if checked_or(config.options.get(WSLINK), bool, False) else "wu" @@ -235,8 +235,8 @@ class HealthCoordinator(DataUpdateCoordinator): reason = ingress.get("reason") # 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 - # mismatch - it is a valid protocol whenever a payload arrives on its route. + # endpoint. Ecowitt has its own route and is considered valid only when an + # accepted Ecowitt payload arrives there. legacy_mismatch = ( last_protocol in _LEGACY_PROTOCOLS and configured_protocol in _LEGACY_PROTOCOLS diff --git a/custom_components/sws12500/routes.py b/custom_components/sws12500/routes.py index 7c8b964..6d53886 100644 --- a/custom_components/sws12500/routes.py +++ b/custom_components/sws12500/routes.py @@ -3,10 +3,10 @@ Why this dispatcher exists -------------------------- 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 -different push endpoints (legacy WU-style vs WSLink). To allow switching between them without -touching the aiohttp router, we register both routes once and use this in-process dispatcher to -decide which one is currently enabled. +is awkward and error-prone (and can raise if routes already exist). This integration supports +multiple station push endpoints. To allow switching between them without touching the aiohttp +router, we register routes once and use this in-process dispatcher to decide which one is +currently enabled. Important note: - Each route stores a *bound method* handler (e.g. `coordinator.received_data`). That means the diff --git a/tests/test_init.py b/tests/test_init.py index 56b9861..bb14661 100644 --- a/tests/test_init.py +++ b/tests/test_init.py @@ -5,7 +5,7 @@ These tests rely on `pytest-homeassistant-custom-component` to provide: - `MockConfigEntry` helper for config entries 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: 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( 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) # `async_setup_entry` calls `register_path`, which needs `hass.http`.