142 lines
4.8 KiB
Python
142 lines
4.8 KiB
Python
|
"""Base class for Overkiz covers, shutters, awnings, etc."""
|
||
|
|
||
|
from __future__ import annotations
|
||
|
|
||
|
from typing import Any, cast
|
||
|
|
||
|
from pyoverkiz.enums import OverkizCommand, OverkizCommandParam, OverkizState
|
||
|
|
||
|
from homeassistant.components.cover import (
|
||
|
ATTR_TILT_POSITION,
|
||
|
CoverEntity,
|
||
|
CoverEntityFeature,
|
||
|
)
|
||
|
|
||
|
from ..entity import OverkizEntity
|
||
|
|
||
|
ATTR_OBSTRUCTION_DETECTED = "obstruction-detected"
|
||
|
|
||
|
COMMANDS_STOP: list[OverkizCommand] = [
|
||
|
OverkizCommand.STOP,
|
||
|
OverkizCommand.MY,
|
||
|
]
|
||
|
COMMANDS_STOP_TILT: list[OverkizCommand] = [
|
||
|
OverkizCommand.STOP,
|
||
|
OverkizCommand.MY,
|
||
|
]
|
||
|
COMMANDS_OPEN: list[OverkizCommand] = [
|
||
|
OverkizCommand.OPEN,
|
||
|
OverkizCommand.UP,
|
||
|
]
|
||
|
COMMANDS_OPEN_TILT: list[OverkizCommand] = [
|
||
|
OverkizCommand.OPEN_SLATS,
|
||
|
OverkizCommand.TILT_DOWN,
|
||
|
]
|
||
|
COMMANDS_CLOSE: list[OverkizCommand] = [
|
||
|
OverkizCommand.CLOSE,
|
||
|
OverkizCommand.DOWN,
|
||
|
]
|
||
|
COMMANDS_CLOSE_TILT: list[OverkizCommand] = [
|
||
|
OverkizCommand.CLOSE_SLATS,
|
||
|
OverkizCommand.TILT_UP,
|
||
|
]
|
||
|
|
||
|
COMMANDS_SET_TILT_POSITION: list[OverkizCommand] = [OverkizCommand.SET_ORIENTATION]
|
||
|
|
||
|
|
||
|
class OverkizGenericCover(OverkizEntity, CoverEntity):
|
||
|
"""Representation of an Overkiz Cover."""
|
||
|
|
||
|
@property
|
||
|
def current_cover_tilt_position(self) -> int | None:
|
||
|
"""Return current position of cover tilt.
|
||
|
|
||
|
None is unknown, 0 is closed, 100 is fully open.
|
||
|
"""
|
||
|
position = self.executor.select_state(
|
||
|
OverkizState.CORE_SLATS_ORIENTATION, OverkizState.CORE_SLATE_ORIENTATION
|
||
|
)
|
||
|
if position is not None:
|
||
|
return 100 - cast(int, position)
|
||
|
|
||
|
return None
|
||
|
|
||
|
async def async_set_cover_tilt_position(self, **kwargs: Any) -> None:
|
||
|
"""Move the cover tilt to a specific position."""
|
||
|
if command := self.executor.select_command(*COMMANDS_SET_TILT_POSITION):
|
||
|
await self.executor.async_execute_command(
|
||
|
command,
|
||
|
100 - kwargs[ATTR_TILT_POSITION],
|
||
|
)
|
||
|
|
||
|
@property
|
||
|
def is_closed(self) -> bool | None:
|
||
|
"""Return if the cover is closed."""
|
||
|
|
||
|
state = self.executor.select_state(
|
||
|
OverkizState.CORE_OPEN_CLOSED,
|
||
|
OverkizState.CORE_SLATS_OPEN_CLOSED,
|
||
|
OverkizState.CORE_OPEN_CLOSED_PARTIAL,
|
||
|
OverkizState.CORE_OPEN_CLOSED_PEDESTRIAN,
|
||
|
OverkizState.CORE_OPEN_CLOSED_UNKNOWN,
|
||
|
OverkizState.MYFOX_SHUTTER_STATUS,
|
||
|
)
|
||
|
if state is not None:
|
||
|
return state == OverkizCommandParam.CLOSED
|
||
|
|
||
|
# Keep this condition after the previous one. Some device like the pedestrian gate, always return 50 as position.
|
||
|
if self.current_cover_position is not None:
|
||
|
return self.current_cover_position == 0
|
||
|
|
||
|
if self.current_cover_tilt_position is not None:
|
||
|
return self.current_cover_tilt_position == 0
|
||
|
|
||
|
return None
|
||
|
|
||
|
async def async_open_cover_tilt(self, **kwargs: Any) -> None:
|
||
|
"""Open the cover tilt."""
|
||
|
if command := self.executor.select_command(*COMMANDS_OPEN_TILT):
|
||
|
await self.executor.async_execute_command(command)
|
||
|
|
||
|
async def async_close_cover_tilt(self, **kwargs: Any) -> None:
|
||
|
"""Close the cover tilt."""
|
||
|
if command := self.executor.select_command(*COMMANDS_CLOSE_TILT):
|
||
|
await self.executor.async_execute_command(command)
|
||
|
|
||
|
async def async_stop_cover(self, **kwargs: Any) -> None:
|
||
|
"""Stop the cover."""
|
||
|
if command := self.executor.select_command(*COMMANDS_STOP):
|
||
|
await self.executor.async_execute_command(command)
|
||
|
|
||
|
async def async_stop_cover_tilt(self, **kwargs: Any) -> None:
|
||
|
"""Stop the cover tilt."""
|
||
|
if command := self.executor.select_command(*COMMANDS_STOP_TILT):
|
||
|
await self.executor.async_execute_command(command)
|
||
|
|
||
|
def is_running(self, commands: list[OverkizCommand]) -> bool:
|
||
|
"""Return if the given commands are currently running."""
|
||
|
return any(
|
||
|
execution.get("device_url") == self.device.device_url
|
||
|
and execution.get("command_name") in commands
|
||
|
for execution in self.coordinator.executions.values()
|
||
|
)
|
||
|
|
||
|
@property
|
||
|
def supported_features(self) -> CoverEntityFeature:
|
||
|
"""Flag supported features."""
|
||
|
supported_features = CoverEntityFeature(0)
|
||
|
|
||
|
if self.executor.has_command(*COMMANDS_OPEN_TILT):
|
||
|
supported_features |= CoverEntityFeature.OPEN_TILT
|
||
|
|
||
|
if self.executor.has_command(*COMMANDS_STOP_TILT):
|
||
|
supported_features |= CoverEntityFeature.STOP_TILT
|
||
|
|
||
|
if self.executor.has_command(*COMMANDS_CLOSE_TILT):
|
||
|
supported_features |= CoverEntityFeature.CLOSE_TILT
|
||
|
|
||
|
if self.executor.has_command(*COMMANDS_SET_TILT_POSITION):
|
||
|
supported_features |= CoverEntityFeature.SET_TILT_POSITION
|
||
|
|
||
|
return supported_features
|