From a1edf0a77cd06ee5cf5c20a5e84f752ce6406b46 Mon Sep 17 00:00:00 2001 From: wollew Date: Thu, 8 Jan 2026 12:19:40 +0100 Subject: [PATCH] fix rain sensor for some rare velux windows (#160504) --- .../components/velux/binary_sensor.py | 8 +++++--- tests/components/velux/test_binary_sensor.py | 20 ++++++++++++++++--- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/velux/binary_sensor.py b/homeassistant/components/velux/binary_sensor.py index 2b7d9f71579..22bec674b64 100644 --- a/homeassistant/components/velux/binary_sensor.py +++ b/homeassistant/components/velux/binary_sensor.py @@ -74,6 +74,8 @@ class VeluxRainSensor(VeluxEntity, BinarySensorEntity): self._attr_available = True - # Velux windows with rain sensors report an opening limitation of 93 or 100 (Velux GPU) when rain is detected. - # So far, only 93 and 100 have been observed in practice, documentation on this is non-existent AFAIK. - self._attr_is_on = limitation.min_value in {93, 100} + # Velux windows with rain sensors report an opening limitation when rain is detected. + # So far we've seen 89, 91, 93 (most cases) or 100 (Velux GPU). It probably makes sense to + # assume that any large enough limitation (we use >=89) means rain is detected. + # Documentation on this is non-existent AFAIK. + self._attr_is_on = limitation.min_value >= 89 diff --git a/tests/components/velux/test_binary_sensor.py b/tests/components/velux/test_binary_sensor.py index 776b0301d4b..e289e79855d 100644 --- a/tests/components/velux/test_binary_sensor.py +++ b/tests/components/velux/test_binary_sensor.py @@ -49,15 +49,29 @@ async def test_rain_sensor_state( assert state is not None assert state.state == STATE_ON - # simulate rain detected (other Velux models report 93) + # simulate rain detected (most Velux models report 93) mock_window.get_limitation.return_value.min_value = 93 await update_polled_entities(hass, freezer) state = hass.states.get(test_entity_id) assert state is not None assert state.state == STATE_ON + # simulate rain detected (other Velux models report 89) + mock_window.get_limitation.return_value.min_value = 89 + await update_polled_entities(hass, freezer) + state = hass.states.get(test_entity_id) + assert state is not None + assert state.state == STATE_ON + + # simulate other limits which do not indicate rain detected + mock_window.get_limitation.return_value.min_value = 88 + await update_polled_entities(hass, freezer) + state = hass.states.get(test_entity_id) + assert state is not None + assert state.state == STATE_OFF + # simulate no rain detected again - mock_window.get_limitation.return_value.min_value = 95 + mock_window.get_limitation.return_value.min_value = 0 await update_polled_entities(hass, freezer) state = hass.states.get(test_entity_id) assert state is not None @@ -144,7 +158,7 @@ async def test_rain_sensor_unavailability( # Simulate recovery mock_window.get_limitation.side_effect = None - mock_window.get_limitation.return_value.min_value = 95 + mock_window.get_limitation.return_value.min_value = 0 await update_polled_entities(hass, freezer) # Entity should be available again