hass-core/homeassistant/components/chacon_dio/cover.py
cnico 092e362f01
Add new integration for Dio Chacon cover devices (#116267)
* Dio Chacon integration addition with config flow and cover entity

* Addition of model information for device

* Addition of light and service to force reloading states

* Logger improvements

* Convert light to switch and usage of v1.0.0 of the api

* 100% for tests coverage

* Invalid credential implementation and rebase on latest ha dev code

* Simplify PR with only one platform

* Ruff correction

* restore original .gitignore content

* Correction of cover state bug when using cover when using actions on cover group.

* Begin of corrections following review.

* unit tests correction

* Refactor with a coordinator as asked by review

* Implemented a post constructor callback init method via dio-chacon-api-1.0.2. Improved typing.

* Corrections for 2nd review

* Reimplemented without coordinator as reviewed with Joostlek

* Review improvement

* generalize callback in entity

* Other review improvements

* Refactored tests for readability

* Test 100% operationals

* Tests review corrections

* Tests review corrections

* Review tests improvements

* simplified tests with snapshots and callback method

* Final fixes

* Final fixes

* Final fixes

* Rename to chacon_dio

---------

Co-authored-by: Joostlek <joostlek@outlook.com>
2024-07-04 16:45:20 +02:00

124 lines
4 KiB
Python

"""Cover Platform for Chacon Dio REV-SHUTTER devices."""
import logging
from typing import Any
from dio_chacon_wifi_api.const import DeviceTypeEnum, ShutterMoveEnum
from homeassistant.components.cover import (
ATTR_POSITION,
CoverDeviceClass,
CoverEntity,
CoverEntityFeature,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import ChaconDioConfigEntry
from .entity import ChaconDioEntity
_LOGGER = logging.getLogger(__name__)
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ChaconDioConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up Chacon Dio cover devices."""
data = config_entry.runtime_data
client = data.client
async_add_entities(
ChaconDioCover(client, device)
for device in data.list_devices
if device["type"] == DeviceTypeEnum.SHUTTER.value
)
class ChaconDioCover(ChaconDioEntity, CoverEntity):
"""Object for controlling a Chacon Dio cover."""
_attr_device_class = CoverDeviceClass.SHUTTER
_attr_name = None
_attr_supported_features = (
CoverEntityFeature.OPEN
| CoverEntityFeature.CLOSE
| CoverEntityFeature.STOP
| CoverEntityFeature.SET_POSITION
)
def _update_attr(self, data: dict[str, Any]) -> None:
"""Recomputes the attributes values either at init or when the device state changes."""
self._attr_available = data["connected"]
self._attr_current_cover_position = data["openlevel"]
self._attr_is_closing = data["movement"] == ShutterMoveEnum.DOWN.value
self._attr_is_opening = data["movement"] == ShutterMoveEnum.UP.value
self._attr_is_closed = self._attr_current_cover_position == 0
async def async_close_cover(self, **kwargs: Any) -> None:
"""Close the cover.
Closed status is effective after the server callback that triggers callback_device_state.
"""
_LOGGER.debug(
"Close cover %s , %s, %s",
self.target_id,
self._attr_name,
self.is_closed,
)
# closes effectively only if cover is not already closing and not fully closed
if not self._attr_is_closing and not self.is_closed:
self._attr_is_closing = True
self.async_write_ha_state()
await self.client.move_shutter_direction(
self.target_id, ShutterMoveEnum.DOWN
)
async def async_open_cover(self, **kwargs: Any) -> None:
"""Open the cover.
Opened status is effective after the server callback that triggers callback_device_state.
"""
_LOGGER.debug(
"Open cover %s , %s, %s",
self.target_id,
self._attr_name,
self.current_cover_position,
)
# opens effectively only if cover is not already opening and not fully opened
if not self._attr_is_opening and self.current_cover_position != 100:
self._attr_is_opening = True
self.async_write_ha_state()
await self.client.move_shutter_direction(self.target_id, ShutterMoveEnum.UP)
async def async_stop_cover(self, **kwargs: Any) -> None:
"""Stop the cover."""
_LOGGER.debug("Stop cover %s , %s", self.target_id, self._attr_name)
self._attr_is_opening = False
self._attr_is_closing = False
self.async_write_ha_state()
await self.client.move_shutter_direction(self.target_id, ShutterMoveEnum.STOP)
async def async_set_cover_position(self, **kwargs: Any) -> None:
"""Set the cover open position in percentage.
Closing or opening status is effective after the server callback that triggers callback_device_state.
"""
position: int = kwargs[ATTR_POSITION]
_LOGGER.debug(
"Set cover position %i, %s , %s", position, self.target_id, self._attr_name
)
await self.client.move_shutter_percentage(self.target_id, position)