mirror of
https://github.com/home-assistant/core.git
synced 2026-08-19 12:48:57 +01:00
181 lines
6.1 KiB
Python
181 lines
6.1 KiB
Python
"""Support for range-options of slat-cover connected with WMS WebControl pro."""
|
|
|
|
from collections.abc import Callable
|
|
from datetime import timedelta
|
|
from typing import override
|
|
|
|
from wmspro.const import WMS_WebControl_pro_API_actionDescription as ACTION_DESC
|
|
|
|
from homeassistant.components.number import NumberEntity
|
|
from homeassistant.const import EntityCategory
|
|
from homeassistant.core import HomeAssistant
|
|
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
|
|
|
from . import WebControlProConfigEntry
|
|
from .entity import WebControlProGenericEntity
|
|
|
|
SCAN_INTERVAL = timedelta(seconds=15)
|
|
PARALLEL_UPDATES = 1
|
|
|
|
|
|
async def async_setup_entry(
|
|
hass: HomeAssistant,
|
|
config_entry: WebControlProConfigEntry,
|
|
async_add_entities: AddConfigEntryEntitiesCallback,
|
|
) -> None:
|
|
"""Set up the WMS based slat rotation number entities from a config entry."""
|
|
hub = config_entry.runtime_data
|
|
|
|
entities: list[WebControlProGenericEntity] = []
|
|
for dest in hub.dests.values():
|
|
if dest.hasAction(ACTION_DESC.SlatRotate):
|
|
entities.append(
|
|
WebControlProSlatRangeMin(hass, config_entry.entry_id, dest)
|
|
)
|
|
entities.append(
|
|
WebControlProSlatRangeMax(hass, config_entry.entry_id, dest)
|
|
)
|
|
entities.append(
|
|
WebControlProSlatRotationRaw(hass, config_entry.entry_id, dest)
|
|
)
|
|
if not dest.hasAction(ACTION_DESC.SlatDrive):
|
|
# Only add the numeric slat rotation entity if no cover entity exists
|
|
entities.append(
|
|
WebControlProSlatRotation(hass, config_entry.entry_id, dest)
|
|
)
|
|
|
|
async_add_entities(entities)
|
|
|
|
|
|
class WebControlProSlatRange(WebControlProGenericEntity, NumberEntity):
|
|
"""Representation of a WMS based range-option for a slat-based cover."""
|
|
|
|
_attr_entity_category = EntityCategory.CONFIG
|
|
|
|
_value_name: str
|
|
_value_func: Callable[[float, float], float]
|
|
|
|
@override
|
|
async def async_update(self) -> None:
|
|
"""Update the entity and learn current rotation."""
|
|
await super().async_update()
|
|
|
|
# Learn min/max rotation if different from action limits
|
|
action = self._dest.action(ACTION_DESC.SlatRotate)
|
|
rotation = action["rotation"]
|
|
if rotation and action.wms__minValue < rotation < action.wms__maxValue:
|
|
await self.async_set_native_value(
|
|
self._value_func(self.native_value, rotation)
|
|
)
|
|
|
|
@property
|
|
@override
|
|
def native_min_value(self) -> float:
|
|
"""Return the minimum value."""
|
|
action = self._dest.action(ACTION_DESC.SlatRotate)
|
|
# Use wms__ prefix to get the raw value from the hub without overwrite
|
|
return self._value_func(action.wms__minValue, 0)
|
|
|
|
@property
|
|
@override
|
|
def native_max_value(self) -> float:
|
|
"""Return the maximum value."""
|
|
action = self._dest.action(ACTION_DESC.SlatRotate)
|
|
# Use wms__ prefix to get the raw value from the hub without overwrite
|
|
return self._value_func(0, action.wms__maxValue)
|
|
|
|
@property
|
|
@override
|
|
def native_value(self) -> float:
|
|
"""Return the current min/max value."""
|
|
action = self._dest.action(ACTION_DESC.SlatRotate)
|
|
# Pull the current min/max rotation from the custom overwrite if set
|
|
value = action[self._value_name]
|
|
# -75 and 75 are community-provided sane defaults for various devices
|
|
if value is None:
|
|
value = self._value_func(-75, 75)
|
|
return value
|
|
|
|
@override
|
|
async def async_set_native_value(self, value: float) -> None:
|
|
"""Update the current min/max value."""
|
|
action = self._dest.action(ACTION_DESC.SlatRotate)
|
|
# Push the new min/max rotation to the hub as custom overwrite via the action items
|
|
action[self._value_name] = value
|
|
# The library will take care of the update and persistence on the next poll refresh
|
|
|
|
|
|
class WebControlProSlatRangeMin(WebControlProSlatRange):
|
|
"""Representation of the minimum rotation range-option for a slat-based cover."""
|
|
|
|
_attr_translation_key = "rotation-min"
|
|
|
|
_value_name = "minValue"
|
|
_value_func = staticmethod(min)
|
|
|
|
|
|
class WebControlProSlatRangeMax(WebControlProSlatRange):
|
|
"""Representation of the maximum rotation range-option for a slat-based cover."""
|
|
|
|
_attr_translation_key = "rotation-max"
|
|
|
|
_value_name = "maxValue"
|
|
_value_func = staticmethod(max)
|
|
|
|
|
|
class WebControlProSlatRotation(WebControlProGenericEntity, NumberEntity):
|
|
"""Representation of the WMS based slat-rotation for a slat-based cover."""
|
|
|
|
_attr_translation_key = "rotation"
|
|
|
|
@property
|
|
@override
|
|
def native_min_value(self) -> float:
|
|
"""Return the minimum value."""
|
|
action = self._dest.action(ACTION_DESC.SlatRotate)
|
|
return action.minValue
|
|
|
|
@property
|
|
@override
|
|
def native_max_value(self) -> float:
|
|
"""Return the maximum value."""
|
|
action = self._dest.action(ACTION_DESC.SlatRotate)
|
|
return action.maxValue
|
|
|
|
@property
|
|
@override
|
|
def native_value(self) -> float | None:
|
|
"""Return the current value."""
|
|
action = self._dest.action(ACTION_DESC.SlatRotate)
|
|
rotation = action["rotation"]
|
|
if rotation is None:
|
|
return None
|
|
return rotation
|
|
|
|
@override
|
|
async def async_set_native_value(self, value: float) -> None:
|
|
"""Update the current value."""
|
|
action = self._dest.action(ACTION_DESC.SlatRotate)
|
|
await action(rotation=value)
|
|
|
|
|
|
class WebControlProSlatRotationRaw(WebControlProSlatRotation):
|
|
"""Representation of the WMS based raw slat-rotation for a slat-based cover."""
|
|
|
|
_attr_entity_category = EntityCategory.DIAGNOSTIC
|
|
_attr_translation_key = "rotation-raw"
|
|
|
|
@property
|
|
@override
|
|
def native_min_value(self) -> float:
|
|
"""Return the minimum value."""
|
|
action = self._dest.action(ACTION_DESC.SlatRotate)
|
|
return action.wms__minValue
|
|
|
|
@property
|
|
@override
|
|
def native_max_value(self) -> float:
|
|
"""Return the maximum value."""
|
|
action = self._dest.action(ACTION_DESC.SlatRotate)
|
|
return action.wms__maxValue
|