Files
core/homeassistant/components/velux/binary_sensor.py
T

81 lines
2.8 KiB
Python

"""Support for rain sensors built into some Velux windows."""
from typing import override
from pyvlx import Window
from homeassistant.components.binary_sensor import (
BinarySensorDeviceClass,
BinarySensorEntity,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from . import VeluxConfigEntry
from .coordinator import VeluxLimitationCoordinator
from .entity import velux_device_info, velux_unique_id
PARALLEL_UPDATES = 1
async def async_setup_entry(
hass: HomeAssistant,
config_entry: VeluxConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up rain sensor(s) for Velux platform."""
pyvlx = config_entry.runtime_data.pyvlx
limitation_coordinators = config_entry.runtime_data.limitation_coordinators
async_add_entities(
VeluxRainSensor(limitation_coordinators[node.node_id], config_entry.entry_id)
for node in pyvlx.nodes
if isinstance(node, Window) and node.rain_sensor
)
class VeluxRainSensor(
CoordinatorEntity[VeluxLimitationCoordinator], BinarySensorEntity
):
"""Representation of a Velux rain sensor."""
_attr_entity_registry_enabled_default = False
_attr_device_class = BinarySensorDeviceClass.MOISTURE
_attr_translation_key = "rain_sensor"
_attr_has_entity_name = True
def __init__(
self, coordinator: VeluxLimitationCoordinator, config_entry_id: str
) -> None:
"""Initialize VeluxRainSensor."""
super().__init__(coordinator)
node = coordinator.node
unique_id = velux_unique_id(node, config_entry_id)
self._attr_unique_id = f"{unique_id}_rain_sensor"
self._attr_device_info = velux_device_info(
self.coordinator.hass, node, config_entry_id
)
@override
async def async_added_to_hass(self) -> None:
"""Called when the entity is added to Home Assistant."""
await super().async_added_to_hass()
# Get initial state as we didn't do it on coordinator initialization to avoid doing it for disabled entities
if self.coordinator.data is None:
await self.coordinator.async_request_refresh()
@property
@override
def is_on(self) -> bool | None:
"""Return true if rain is detected."""
# 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.
if self.coordinator.data is None:
return None
return self.coordinator.data.limitation_min.position_percent >= 89