Forwarders (Windy / Pocasi):
- `enabled` becomes a property reading the option live. Toggling it does not
reload the entry, so the cached copy left the diagnostics sensor reporting a
stale value indefinitely for a disabled forwarder.
- Reject empty credentials explicitly: an empty string is still a `str`, so
`checked` alone let an unconfigured forwarder send a request that could only
ever be refused.
- Use `persistent_notification.async_create` instead of the sync variant.
- Use WINDY_MAX_RETRIES consistently; add POCASI_CZ_MAX_RETRIES.
Utils:
- `voc_level_to_text` / `battery_5step_to_pct` go through `to_int` like every
other value_fn. A bare `int()` raised on a garbage payload value, which
`WeatherSensor.native_value` then logged with a full traceback on every push.
Out-of-range battery steps are clamped to a valid percentage.
- Simplify `check_disabled` (drop the redundant camelCase flag).
Config flow:
- `retain_data` re-reads SENSORS_TO_LOAD at submit time. Auto-discovery appends
to it from the webhook handler, so writing back the snapshot taken when the
step opened silently rolled back any sensor discovered meanwhile.
Coordinator:
- Drop the per-push staleness recalculation; the hourly timer already covers it.
Ecowitt:
- Tolerate aioecowitt moving/renaming the internal SENSOR_MAP rather than
failing the whole module import; unit-variant dedup degrades instead.
Translations:
- Battery state key `unknown` -> `drained`: the entity emits UnitOfBat.UNKNOWN,
whose value is "drained", so the old key never matched and the raw state
leaked into the UI. cs.json was already correct.
- Remove the dead `migration` step; `async_step_migration` does not exist.
Also: remove verified-dead constants/helpers and fix ~30 docstring typos.
- 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