mirror of
https://github.com/home-assistant/core.git
synced 2025-04-26 18:27:51 +00:00
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
@ -11,7 +11,7 @@ from homeassistant.exceptions import ConfigEntryNotReady
|
|||||||
|
|
||||||
from .const import DOMAIN
|
from .const import DOMAIN
|
||||||
|
|
||||||
PLATFORMS: list[Platform] = [Platform.CLIMATE]
|
PLATFORMS: list[Platform] = [Platform.CLIMATE, Platform.COVER]
|
||||||
|
|
||||||
type Airtouch5ConfigEntry = ConfigEntry[Airtouch5SimpleClient]
|
type Airtouch5ConfigEntry = ConfigEntry[Airtouch5SimpleClient]
|
||||||
|
|
||||||
|
@ -121,6 +121,7 @@ class Airtouch5ClimateEntity(ClimateEntity, Airtouch5Entity):
|
|||||||
"""Base class for Airtouch5 Climate Entities."""
|
"""Base class for Airtouch5 Climate Entities."""
|
||||||
|
|
||||||
_attr_temperature_unit = UnitOfTemperature.CELSIUS
|
_attr_temperature_unit = UnitOfTemperature.CELSIUS
|
||||||
|
_attr_translation_key = DOMAIN
|
||||||
_attr_target_temperature_step = 1
|
_attr_target_temperature_step = 1
|
||||||
_attr_name = None
|
_attr_name = None
|
||||||
_enable_turn_on_off_backwards_compatibility = False
|
_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.core import callback
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
|
|
||||||
from .const import DOMAIN
|
|
||||||
|
|
||||||
|
|
||||||
class Airtouch5Entity(Entity):
|
class Airtouch5Entity(Entity):
|
||||||
"""Base class for Airtouch5 entities."""
|
"""Base class for Airtouch5 entities."""
|
||||||
|
|
||||||
_attr_should_poll = False
|
_attr_should_poll = False
|
||||||
_attr_has_entity_name = True
|
_attr_has_entity_name = True
|
||||||
_attr_translation_key = DOMAIN
|
|
||||||
|
|
||||||
def __init__(self, client: Airtouch5SimpleClient) -> None:
|
def __init__(self, client: Airtouch5SimpleClient) -> None:
|
||||||
"""Initialise the Entity."""
|
"""Initialise the Entity."""
|
||||||
|
@ -27,6 +27,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"cover": {
|
||||||
|
"damper": {
|
||||||
|
"name": "[%key:component::cover::entity_component::damper::name%]"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user