Add AirTouch5 cover (#122462)
* AirTouch5 - add cover Each zone has a damper that can be controlled as a cover. * remove unused assignment * remove opinionated feature support * Revert "remove unused assignment" This reverts commit b4205a60a22ae3869436229b4a45547348496d39. * ruff formatting changes * git push translation and refactor
This commit is contained in:
parent
482cf261c0
commit
64f997718a
5 changed files with 141 additions and 4 deletions
|
@ -11,7 +11,7 @@ from homeassistant.exceptions import ConfigEntryNotReady
|
|||
|
||||
from .const import DOMAIN
|
||||
|
||||
PLATFORMS: list[Platform] = [Platform.CLIMATE]
|
||||
PLATFORMS: list[Platform] = [Platform.CLIMATE, Platform.COVER]
|
||||
|
||||
type Airtouch5ConfigEntry = ConfigEntry[Airtouch5SimpleClient]
|
||||
|
||||
|
|
|
@ -121,6 +121,7 @@ class Airtouch5ClimateEntity(ClimateEntity, Airtouch5Entity):
|
|||
"""Base class for Airtouch5 Climate Entities."""
|
||||
|
||||
_attr_temperature_unit = UnitOfTemperature.CELSIUS
|
||||
_attr_translation_key = DOMAIN
|
||||
_attr_target_temperature_step = 1
|
||||
_attr_name = None
|
||||
_enable_turn_on_off_backwards_compatibility = False
|
||||
|
|
134
homeassistant/components/airtouch5/cover.py
Normal file
134
homeassistant/components/airtouch5/cover.py
Normal file
|
@ -0,0 +1,134 @@
|
|||
"""Representation of the Damper for AirTouch 5 Devices."""
|
||||
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
from airtouch5py.airtouch5_simple_client import Airtouch5SimpleClient
|
||||
from airtouch5py.packets.zone_control import (
|
||||
ZoneControlZone,
|
||||
ZoneSettingPower,
|
||||
ZoneSettingValue,
|
||||
)
|
||||
from airtouch5py.packets.zone_name import ZoneName
|
||||
from airtouch5py.packets.zone_status import ZoneStatusZone
|
||||
|
||||
from homeassistant.components.cover import (
|
||||
ATTR_POSITION,
|
||||
CoverDeviceClass,
|
||||
CoverEntity,
|
||||
CoverEntityFeature,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.device_registry import DeviceInfo
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from . import Airtouch5ConfigEntry
|
||||
from .const import DOMAIN
|
||||
from .entity import Airtouch5Entity
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: Airtouch5ConfigEntry,
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up the Airtouch 5 Cover entities."""
|
||||
client = config_entry.runtime_data
|
||||
|
||||
# Each zone has a cover for its open percentage
|
||||
async_add_entities(
|
||||
Airtouch5ZoneOpenPercentage(
|
||||
client, zone, client.latest_zone_status[zone.zone_number].has_sensor
|
||||
)
|
||||
for zone in client.zones
|
||||
)
|
||||
|
||||
|
||||
class Airtouch5ZoneOpenPercentage(CoverEntity, Airtouch5Entity):
|
||||
"""How open the damper is in each zone."""
|
||||
|
||||
_attr_device_class = CoverDeviceClass.DAMPER
|
||||
_attr_translation_key = "damper"
|
||||
|
||||
# Zones with temperature sensors shouldn't be manually controlled.
|
||||
# We allow it but warn the user in the integration documentation.
|
||||
_attr_supported_features = (
|
||||
CoverEntityFeature.SET_POSITION
|
||||
| CoverEntityFeature.OPEN
|
||||
| CoverEntityFeature.CLOSE
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self, client: Airtouch5SimpleClient, zone_name: ZoneName, has_sensor: bool
|
||||
) -> None:
|
||||
"""Initialise the Cover Entity."""
|
||||
super().__init__(client)
|
||||
self._zone_name = zone_name
|
||||
|
||||
self._attr_unique_id = f"zone_{zone_name.zone_number}_open_percentage"
|
||||
self._attr_device_info = DeviceInfo(
|
||||
identifiers={(DOMAIN, f"zone_{zone_name.zone_number}")},
|
||||
name=zone_name.zone_name,
|
||||
manufacturer="Polyaire",
|
||||
model="AirTouch 5",
|
||||
)
|
||||
|
||||
@callback
|
||||
def _async_update_attrs(self, data: dict[int, ZoneStatusZone]) -> None:
|
||||
if self._zone_name.zone_number not in data:
|
||||
return
|
||||
status = data[self._zone_name.zone_number]
|
||||
|
||||
self._attr_current_cover_position = int(status.open_percentage * 100)
|
||||
if status.open_percentage == 0:
|
||||
self._attr_is_closed = True
|
||||
else:
|
||||
self._attr_is_closed = False
|
||||
self.async_write_ha_state()
|
||||
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Add data updated listener after this object has been initialized."""
|
||||
await super().async_added_to_hass()
|
||||
self._client.zone_status_callbacks.append(self._async_update_attrs)
|
||||
self._async_update_attrs(self._client.latest_zone_status)
|
||||
|
||||
async def async_will_remove_from_hass(self) -> None:
|
||||
"""Remove data updated listener after this object has been initialized."""
|
||||
await super().async_will_remove_from_hass()
|
||||
self._client.zone_status_callbacks.remove(self._async_update_attrs)
|
||||
|
||||
async def async_open_cover(self, **kwargs: Any) -> None:
|
||||
"""Open the damper."""
|
||||
await self._set_cover_position(100)
|
||||
|
||||
async def async_close_cover(self, **kwargs: Any) -> None:
|
||||
"""Close damper."""
|
||||
await self._set_cover_position(0)
|
||||
|
||||
async def async_set_cover_position(self, **kwargs: Any) -> None:
|
||||
"""Update the damper to a specific position."""
|
||||
|
||||
if (position := kwargs.get(ATTR_POSITION)) is None:
|
||||
_LOGGER.debug("Argument `position` is missing in set_cover_position")
|
||||
return
|
||||
await self._set_cover_position(position)
|
||||
|
||||
async def _set_cover_position(self, position_percent: float) -> None:
|
||||
power: ZoneSettingPower
|
||||
|
||||
if position_percent == 0:
|
||||
power = ZoneSettingPower.SET_TO_OFF
|
||||
else:
|
||||
power = ZoneSettingPower.SET_TO_ON
|
||||
|
||||
zcz = ZoneControlZone(
|
||||
self._zone_name.zone_number,
|
||||
ZoneSettingValue.SET_OPEN_PERCENTAGE,
|
||||
power,
|
||||
position_percent / 100.0,
|
||||
)
|
||||
|
||||
packet = self._client.data_packet_factory.zone_control([zcz])
|
||||
await self._client.send_packet(packet)
|
|
@ -6,15 +6,12 @@ from airtouch5py.airtouch5_simple_client import Airtouch5SimpleClient
|
|||
from homeassistant.core import callback
|
||||
from homeassistant.helpers.entity import Entity
|
||||
|
||||
from .const import DOMAIN
|
||||
|
||||
|
||||
class Airtouch5Entity(Entity):
|
||||
"""Base class for Airtouch5 entities."""
|
||||
|
||||
_attr_should_poll = False
|
||||
_attr_has_entity_name = True
|
||||
_attr_translation_key = DOMAIN
|
||||
|
||||
def __init__(self, client: Airtouch5SimpleClient) -> None:
|
||||
"""Initialise the Entity."""
|
||||
|
|
|
@ -27,6 +27,11 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"cover": {
|
||||
"damper": {
|
||||
"name": "[%key:component::cover::entity_component::damper::name%]"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue