All entities (weather, battery, health, native Ecowitt) now report through a
single device under the existing {(DOMAIN,)} identifier, removing the separate
"Ecowitt {model}" device that appeared whenever Ecowitt was enabled. This
collapses the previous two-device layout (and the duplicate/untranslated native
Ecowitt sensors living on the second device) into one.
The device model reflects the running station type via _station_model():
"Ecowitt <model>" when Ecowitt is active (model learned from the payload's
`model` field and stored on runtime_data.ecowitt_model), else "WSLink", else
"PWS". Device identity is centralised in data.build_device_info() and reused by
every platform.
No device-registry migration is required: the identifier is unchanged; only the
model/grouping change. Full device unification under a renamed hub is deferred
to the rename round.
Tests: device-info assertions updated to the shared device across the entity
suites; new _station_model/build_device_info branch coverage in test_data.py;
received_ecowitt now asserts the learned model. 320 passed, 100% coverage.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Reuse existing `WeatherDataUpdateCoordinator` instance across reloads instead of
creating a new one; routes keep pointing to the same coordinator, so entities
stay subscribed and updates never silently drop
- `update_listener` now skips full reload when only `SENSORS_TO_LOAD` changes
(auto-discovery); avoids the "frozen UI" window caused by temporary platform unload
- Replaced direct `route._handler` mutation with a proper `Routes` dispatcher;
all aiohttp routes are registered once and an internal dispatcher decides which
handler is active — safe to switch at runtime without touching the router
- Fixed `self.config_entry` / `self.config` inconsistency in coordinator
- `BatteryBinarySensor` now carries correct `device_info` (same identifiers as
`WeatherSensor`) → single device card in UI instead of two
- Translations for binary sensors must live under `entity.binary_sensor.*`,
not `entity.sensor.*`
- Fixed all tests broken by new `register_path(hass, coordinator, coordinator_h, entry)` signature
- Updated `_RouterStub` to accept `name=` kwargs and return objects with `.method`
- Added `async post()` to `_RequestStub` stubs
- Aligned `Routes` tests with new `method:path` dispatch key format and `show_enabled()` output
- Replaced `WindyApiKeyError` with `WindyPasswordMissing` to match actual exceptions
- Updated `_FakeResponse` to use HTTP status codes instead of response text strings
- Patched `persistent_notification.create` in Windy push tests to avoid `SimpleNamespace` errors
Adds the SWSRuntimeData dataclass and SWSConfigEntry type alias so
per-entry state can move from loosely-typed hass.data[DOMAIN][entry_id]
dicts to HA 2025+ typed entry.runtime_data. The legacy ENTRY_* string
keys are kept in place for now so callers can be migrated incrementally.
This commit is not final update. Just preparing for future complete refactor.
integration
- Introduce HealthDiagnosticSensor for device health status reporting
- Add new constants and data keys for health sensor integration
- Wire health_sensor module into sensor platform setup
- Refactor sensor descriptions to improve derived sensor handling
- Implement pytest fixtures and comprehensive tests covering:
- Config flows and options validation
- Data reception and authentication
- Sensor platform setup and dynamic sensor addition
- Push integration with Pocasi.cz and Windy API
- Route dispatching and error handling
- Utilities, conversions, and translation functions
- Add detailed architecture overview in __init__.py
- Introduce shared runtime keys in data.py to avoid key conflicts
- Implement dual route dispatcher for webhook endpoint selection
- Enhance sensor platform for dynamic sensor addition without reloads
- Rename battery level "unknown" to "drained" with updated icons
- Improve utils.py with centralized helpers for remapping and discovery
- Update translations and strings for consistency