Coverage went from 54 of 107 upload parameters to all 107, adding roughly 34
entities. New families: Type5 lightning, Type6 water leak (CH1-7), Type8
particulate matter, Type10 CO2 and Type11 CO, plus the parameters missing from
existing families - absolute pressure, feels-like temperature, the 10-minute
average wind speed, and the per-channel probe type.
Device classes follow Home Assistant's own list (PM25, PM10, AQI, CO2, CO,
DISTANCE, ATMOSPHERIC_PRESSURE, WIND_SPEED, and binary MOISTURE for leaks), so
the readings work with statistics and unit conversion without template helpers.
Batteries were the trap. The API annotates two incompatible conventions -
"(Normal=1, Low battery=0)" and "(0~5) remark: 5 is full" - and mixing them up is
silent, because a level battery read as a flag reports "not low" for every level
above empty. Eight new binary batteries (t5lsbat, t6c1-7bat) and three new level
batteries (t8bat, t10bat, t11bat) are classified from the document, and
tests/test_wslink_api_coverage.py pins each one to the wording it came from.
Water leak and battery use opposite conventions in the same family (leak 1 means
wet, battery 0 means low), so `on_value` moved into the description and one
entity class now serves both instead of two that differ by a comparison.
`t1cn` was in the API but wired to nothing, so a disconnected outdoor probe kept
publishing its last readings. Gating it required fixing the gate first: an absent
connection flag was treated as "disconnected", which would have blanked
temperature, wind and rain outright on any firmware that omits `t1cn`. Absence is
now treated as no information, and only an explicit non-1 drops the readings.
The probe type (`t234cXtp`) decides whether a channel's humidity reading is air
humidity or soil moisture, which are different device classes. It is resolved
once, when the entity is created, because Home Assistant records the device class
in the entity registry; swapping the physical probe means reinstalling.
Two parameters are handled with a documented caveat: `inbat` is the only battery
whose scale the API does not state and stays a 0/1 flag, and `t5lst` has no unit
(the vendor example uses 9999) so it is read as minutes with 9999 meaning
"nothing recorded".
Also replaces the now-stale TODO block in const.py - it listed exactly these
sensors as unimplemented - and documents the complete coverage in the README.
The WU/PWS platform derives both indices from temperature, humidity and wind
(value_from_data_fn=heat_index / chill_index), but the WSLink descriptions only
read the station's own t1heat / t1chill via value_fn=to_float. Stations that do
not report those fields still got both entities, because
_auto_enable_derived_sensors creates them as soon as the raw inputs arrive, so
they stayed Unavailable forever.
Add wslink_heat_index / wslink_chill_index: prefer the station's reading, compute
it otherwise. The conversions are the subtle part. The WSLink payload is metric
and both entities are declared in Celsius, while the NWS formulas are defined for
Fahrenheit, and chill_index converts the temperature but not the wind speed even
though its formula needs mph. So the temperature goes C -> F in, the wind m/s ->
mph, and the result F -> C back out. For the reported payload (6.2 C, 40 %,
30.6 m/s) that is -1.94 C; leaving the wind in m/s would have reported 0.34 C.
The native unit stays Celsius on purpose: switching it to Fahrenheit to match the
WU platform would misread the values of stations that do send t1heat / t1chill.
Also guard on missing temperature/humidity/wind before delegating, so a payload
without those fields no longer logs an error on every push.
- wind_dir_to_text: treat 0/missing direction as None (calm) so a missing
wind direction no longer renders as North; azimut lambdas pass None too.
- windy: log response status (was logging an un-awaited coroutine method);
count "unexpected response" toward the disable threshold even when logging
is off.
- pocasi: disable threshold >3 -> >=3 to match Windy's 3-strike behavior.
- ecowitt: always attach device_info to native sensors, including unknown
sensor types (previously left orphaned without a device).
- const: stop remapping WSLink connection flags (t1cn/t234cXcn) into the
payload; they had no entity and leaked ghost *_connection keys into data
and persisted SENSORS_TO_LOAD. Gating uses the raw keys and is unaffected.
- config_flow: fix WSLink port fallback typo 433 -> 443; drop mutable default
argument on async_step_init.
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
Updated config flow's initial setup.
Ecowitt stations does not require `API_ID` and `API_KEY`, so we need to
separate Ecowitt setup from PWS/WSLink setup.
- Introduce `to_int`/`to_float` helpers to safely handle None/blank payload values.
- Use the converters across weather/wslink sensor descriptions and simplify wind direction handling.
- Add low-battery binary sensor entities and definitions.
- Extend constants and WSLink key remapping for channels 3–8 (temp, humidity, battery and connection)
- Add new WSLink sensor entity descriptions for the extra channel readings
- Update English translations for the newly added channel sensors and battery states
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
Updates the wind direction sensor to use `MEASUREMENT_ANGLE` state class for proper representation in Home Assistant.
This ensures correct interpretation of wind direction as an angle.
Adds the Wet Bulb Globe Temperature (WBGT) sensor to the integration, pulling data via the WSLink API.
Corrects the state class for rain and wind direction.
Adds support for displaying indoor console and channel 2 battery levels as sensors.
Updates sensor logic to use a common list to determine icon representation
Fixes#74
Adds an outside battery sensor to the integration, providing information about the battery level of the outdoor sensor.
This includes:
- Mapping the `t1bat` WSLink item to the `OUTSIDE_BATTERY` sensor.
- Implementing logic to convert the battery level to a human-readable text representation and a corresponding icon.
- Updates precipitation to intensity and fixes data type of battery level
Updates the outside battery sensor to display an icon
reflecting the battery level, enhancing the user experience
by providing a visual indication of the battery status.
Adds hourly, weekly, monthly, and yearly rain sensors to the integration for WSLink connection.
The units of measurement are corrected for the rain sensor, now displaying millimeters per hour as the station is sending data in mm/h for 'rain' sensor. And cumulative precipitation is in millimeters.
Also includes translations for the new sensors.
Fixes#62
Fixes rainfall unit inconsistency
Updates daily rain sensor to use consistent measurement units and corrects device class and suggested unit.
Fixes#62
Adds database path constant and data migration function
Defines DATABASE_PATH constant for database file location
Introduces migrate_data function to update unit of measurement in long statistics.
Adds sensor migration feature
Introduces a migration step for sensor statistics
Updates schema and translations to support migration
Fixes data migration from mm/d to mm
Includes new sensor connection status constants and mappings
Updates WeatherSensor to handle null data values
Switches temperature unit to Celsius for WSLink sensors
Refines heat and chill index calculations with unit conversions