Add entity translations to hunterdouglas powerview (#98232)
parent
9713466817
commit
49a9d0e439
|
@ -7,7 +7,11 @@ from typing import Any, Final
|
|||
|
||||
from aiopvapi.resources.shade import BaseShade, factory as PvShade
|
||||
|
||||
from homeassistant.components.button import ButtonEntity, ButtonEntityDescription
|
||||
from homeassistant.components.button import (
|
||||
ButtonDeviceClass,
|
||||
ButtonEntity,
|
||||
ButtonEntityDescription,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import EntityCategory
|
||||
from homeassistant.core import HomeAssistant
|
||||
|
@ -36,21 +40,20 @@ class PowerviewButtonDescription(
|
|||
BUTTONS: Final = [
|
||||
PowerviewButtonDescription(
|
||||
key="calibrate",
|
||||
name="Calibrate",
|
||||
translation_key="calibrate",
|
||||
icon="mdi:swap-vertical-circle-outline",
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
press_action=lambda shade: shade.calibrate(),
|
||||
),
|
||||
PowerviewButtonDescription(
|
||||
key="identify",
|
||||
name="Identify",
|
||||
icon="mdi:crosshairs-question",
|
||||
device_class=ButtonDeviceClass.IDENTIFY,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
press_action=lambda shade: shade.jog(),
|
||||
),
|
||||
PowerviewButtonDescription(
|
||||
key="favorite",
|
||||
name="Favorite",
|
||||
translation_key="favorite",
|
||||
icon="mdi:heart",
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
press_action=lambda shade: shade.favorite(),
|
||||
|
@ -104,7 +107,6 @@ class PowerviewButton(ShadeEntity, ButtonEntity):
|
|||
"""Initialize the button entity."""
|
||||
super().__init__(coordinator, device_info, room_name, shade, name)
|
||||
self.entity_description: PowerviewButtonDescription = description
|
||||
self._attr_name = f"{self._shade_name} {description.name}"
|
||||
self._attr_unique_id = f"{self._attr_unique_id}_{description.key}"
|
||||
|
||||
async def async_press(self) -> None:
|
||||
|
|
|
@ -118,7 +118,11 @@ class PowerViewShadeBase(ShadeEntity, CoverEntity):
|
|||
"""Representation of a powerview shade."""
|
||||
|
||||
_attr_device_class = CoverDeviceClass.SHADE
|
||||
_attr_supported_features = CoverEntityFeature(0)
|
||||
_attr_supported_features = (
|
||||
CoverEntityFeature.OPEN
|
||||
| CoverEntityFeature.CLOSE
|
||||
| CoverEntityFeature.SET_POSITION
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
|
@ -131,7 +135,6 @@ class PowerViewShadeBase(ShadeEntity, CoverEntity):
|
|||
"""Initialize the shade."""
|
||||
super().__init__(coordinator, device_info, room_name, shade, name)
|
||||
self._shade: BaseShade = shade
|
||||
self._attr_name = self._shade_name
|
||||
self._scheduled_transition_update: CALLBACK_TYPE | None = None
|
||||
if self._device_info.model != LEGACY_DEVICE_MODEL:
|
||||
self._attr_supported_features |= CoverEntityFeature.STOP
|
||||
|
@ -346,26 +349,14 @@ class PowerViewShadeBase(ShadeEntity, CoverEntity):
|
|||
class PowerViewShade(PowerViewShadeBase):
|
||||
"""Represent a standard shade."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: PowerviewShadeUpdateCoordinator,
|
||||
device_info: PowerviewDeviceInfo,
|
||||
room_name: str,
|
||||
shade: BaseShade,
|
||||
name: str,
|
||||
) -> None:
|
||||
"""Initialize the shade."""
|
||||
super().__init__(coordinator, device_info, room_name, shade, name)
|
||||
self._attr_supported_features |= (
|
||||
CoverEntityFeature.OPEN
|
||||
| CoverEntityFeature.CLOSE
|
||||
| CoverEntityFeature.SET_POSITION
|
||||
)
|
||||
_attr_name = None
|
||||
|
||||
|
||||
class PowerViewShadeWithTiltBase(PowerViewShade):
|
||||
class PowerViewShadeWithTiltBase(PowerViewShadeBase):
|
||||
"""Representation for PowerView shades with tilt capabilities."""
|
||||
|
||||
_attr_name = None
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: PowerviewShadeUpdateCoordinator,
|
||||
|
@ -453,9 +444,11 @@ class PowerViewShadeWithTiltOnClosed(PowerViewShadeWithTiltBase):
|
|||
API Class: ShadeBottomUpTiltOnClosed + ShadeBottomUpTiltOnClosed90
|
||||
|
||||
Type 1 - Bottom Up w/ 90° Tilt
|
||||
Shade 44 - a shade thought to have been a firmware issue (type 0 usually dont tilt)
|
||||
Shade 44 - a shade thought to have been a firmware issue (type 0 usually don't tilt)
|
||||
"""
|
||||
|
||||
_attr_name = None
|
||||
|
||||
@property
|
||||
def open_position(self) -> PowerviewShadeMove:
|
||||
"""Return the open position and required additional positions."""
|
||||
|
@ -570,7 +563,7 @@ class PowerViewShadeTiltOnly(PowerViewShadeWithTiltBase):
|
|||
self._max_tilt = self._shade.shade_limits.tilt_max
|
||||
|
||||
|
||||
class PowerViewShadeTopDown(PowerViewShade):
|
||||
class PowerViewShadeTopDown(PowerViewShadeBase):
|
||||
"""Representation of a shade that lowers from the roof to the floor.
|
||||
|
||||
These shades are inverted where MAX_POSITION equates to closed and MIN_POSITION is open
|
||||
|
@ -579,6 +572,8 @@ class PowerViewShadeTopDown(PowerViewShade):
|
|||
Type 6 - Top Down
|
||||
"""
|
||||
|
||||
_attr_name = None
|
||||
|
||||
@property
|
||||
def current_cover_position(self) -> int:
|
||||
"""Return the current position of cover."""
|
||||
|
@ -594,7 +589,7 @@ class PowerViewShadeTopDown(PowerViewShade):
|
|||
await self._async_set_cover_position(100 - kwargs[ATTR_POSITION])
|
||||
|
||||
|
||||
class PowerViewShadeDualRailBase(PowerViewShade):
|
||||
class PowerViewShadeDualRailBase(PowerViewShadeBase):
|
||||
"""Representation of a shade with top/down bottom/up capabilities.
|
||||
|
||||
Base methods shared between the two shades created
|
||||
|
@ -613,11 +608,13 @@ class PowerViewShadeDualRailBase(PowerViewShade):
|
|||
class PowerViewShadeTDBUBottom(PowerViewShadeDualRailBase):
|
||||
"""Representation of the bottom PowerViewShadeDualRailBase shade.
|
||||
|
||||
These shades have top/down bottom up functionality and two entiites.
|
||||
These shades have top/down bottom up functionality and two entities.
|
||||
Sibling Class: PowerViewShadeTDBUTop
|
||||
API Class: ShadeTopDownBottomUp
|
||||
"""
|
||||
|
||||
_attr_translation_key = "bottom"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: PowerviewShadeUpdateCoordinator,
|
||||
|
@ -629,7 +626,6 @@ class PowerViewShadeTDBUBottom(PowerViewShadeDualRailBase):
|
|||
"""Initialize the shade."""
|
||||
super().__init__(coordinator, device_info, room_name, shade, name)
|
||||
self._attr_unique_id = f"{self._shade.id}_bottom"
|
||||
self._attr_name = f"{self._shade_name} Bottom"
|
||||
|
||||
@callback
|
||||
def _clamp_cover_limit(self, target_hass_position: int) -> int:
|
||||
|
@ -655,11 +651,13 @@ class PowerViewShadeTDBUBottom(PowerViewShadeDualRailBase):
|
|||
class PowerViewShadeTDBUTop(PowerViewShadeDualRailBase):
|
||||
"""Representation of the top PowerViewShadeDualRailBase shade.
|
||||
|
||||
These shades have top/down bottom up functionality and two entiites.
|
||||
These shades have top/down bottom up functionality and two entities.
|
||||
Sibling Class: PowerViewShadeTDBUBottom
|
||||
API Class: ShadeTopDownBottomUp
|
||||
"""
|
||||
|
||||
_attr_translation_key = "top"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: PowerviewShadeUpdateCoordinator,
|
||||
|
@ -671,7 +669,6 @@ class PowerViewShadeTDBUTop(PowerViewShadeDualRailBase):
|
|||
"""Initialize the shade."""
|
||||
super().__init__(coordinator, device_info, room_name, shade, name)
|
||||
self._attr_unique_id = f"{self._shade.id}_top"
|
||||
self._attr_name = f"{self._shade_name} Top"
|
||||
|
||||
@property
|
||||
def should_poll(self) -> bool:
|
||||
|
@ -711,7 +708,7 @@ class PowerViewShadeTDBUTop(PowerViewShadeDualRailBase):
|
|||
|
||||
@callback
|
||||
def _clamp_cover_limit(self, target_hass_position: int) -> int:
|
||||
"""Dont allow a cover to go into an impossbile position."""
|
||||
"""Don't allow a cover to go into an impossbile position."""
|
||||
cover_bottom = hd_position_to_hass(self.positions.primary, MAX_POSITION)
|
||||
return min(target_hass_position, (100 - cover_bottom))
|
||||
|
||||
|
@ -730,7 +727,7 @@ class PowerViewShadeTDBUTop(PowerViewShadeDualRailBase):
|
|||
)
|
||||
|
||||
|
||||
class PowerViewShadeDualOverlappedBase(PowerViewShade):
|
||||
class PowerViewShadeDualOverlappedBase(PowerViewShadeBase):
|
||||
"""Represent a shade that has a front sheer and rear opaque panel.
|
||||
|
||||
This equates to two shades being controlled by one motor
|
||||
|
@ -783,6 +780,8 @@ class PowerViewShadeDualOverlappedCombined(PowerViewShadeDualOverlappedBase):
|
|||
Type 8 - Duolite (front and rear shades)
|
||||
"""
|
||||
|
||||
_attr_translation_key = "combined"
|
||||
|
||||
# type
|
||||
def __init__(
|
||||
self,
|
||||
|
@ -795,7 +794,6 @@ class PowerViewShadeDualOverlappedCombined(PowerViewShadeDualOverlappedBase):
|
|||
"""Initialize the shade."""
|
||||
super().__init__(coordinator, device_info, room_name, shade, name)
|
||||
self._attr_unique_id = f"{self._shade.id}_combined"
|
||||
self._attr_name = f"{self._shade_name} Combined"
|
||||
|
||||
@property
|
||||
def is_closed(self) -> bool:
|
||||
|
@ -842,7 +840,7 @@ class PowerViewShadeDualOverlappedCombined(PowerViewShadeDualOverlappedBase):
|
|||
|
||||
|
||||
class PowerViewShadeDualOverlappedFront(PowerViewShadeDualOverlappedBase):
|
||||
"""Represent the shade front panel - These have a opaque panel too.
|
||||
"""Represent the shade front panel - These have an opaque panel too.
|
||||
|
||||
This equates to two shades being controlled by one motor.
|
||||
The front shade must be completely down before the rear shade will move.
|
||||
|
@ -857,6 +855,8 @@ class PowerViewShadeDualOverlappedFront(PowerViewShadeDualOverlappedBase):
|
|||
Type 10 - Duolite with 180° Tilt
|
||||
"""
|
||||
|
||||
_attr_translation_key = "front"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: PowerviewShadeUpdateCoordinator,
|
||||
|
@ -868,7 +868,6 @@ class PowerViewShadeDualOverlappedFront(PowerViewShadeDualOverlappedBase):
|
|||
"""Initialize the shade."""
|
||||
super().__init__(coordinator, device_info, room_name, shade, name)
|
||||
self._attr_unique_id = f"{self._shade.id}_front"
|
||||
self._attr_name = f"{self._shade_name} Front"
|
||||
|
||||
@property
|
||||
def should_poll(self) -> bool:
|
||||
|
@ -906,7 +905,7 @@ class PowerViewShadeDualOverlappedFront(PowerViewShadeDualOverlappedBase):
|
|||
|
||||
|
||||
class PowerViewShadeDualOverlappedRear(PowerViewShadeDualOverlappedBase):
|
||||
"""Represent the shade front panel - These have a opaque panel too.
|
||||
"""Represent the shade front panel - These have an opaque panel too.
|
||||
|
||||
This equates to two shades being controlled by one motor.
|
||||
The front shade must be completely down before the rear shade will move.
|
||||
|
@ -921,6 +920,8 @@ class PowerViewShadeDualOverlappedRear(PowerViewShadeDualOverlappedBase):
|
|||
Type 10 - Duolite with 180° Tilt
|
||||
"""
|
||||
|
||||
_attr_translation_key = "rear"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: PowerviewShadeUpdateCoordinator,
|
||||
|
@ -932,7 +933,6 @@ class PowerViewShadeDualOverlappedRear(PowerViewShadeDualOverlappedBase):
|
|||
"""Initialize the shade."""
|
||||
super().__init__(coordinator, device_info, room_name, shade, name)
|
||||
self._attr_unique_id = f"{self._shade.id}_rear"
|
||||
self._attr_name = f"{self._shade_name} Rear"
|
||||
|
||||
@property
|
||||
def should_poll(self) -> bool:
|
||||
|
|
|
@ -25,6 +25,8 @@ from .shade_data import PowerviewShadeData, PowerviewShadePositions
|
|||
class HDEntity(CoordinatorEntity[PowerviewShadeUpdateCoordinator]):
|
||||
"""Base class for hunter douglas entities."""
|
||||
|
||||
_attr_has_entity_name = True
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: PowerviewShadeUpdateCoordinator,
|
||||
|
|
|
@ -47,7 +47,7 @@ class PowerviewSelectDescription(
|
|||
DROPDOWNS: Final = [
|
||||
PowerviewSelectDescription(
|
||||
key="powersource",
|
||||
name="Power Source",
|
||||
translation_key="power_source",
|
||||
icon="mdi:power-plug-outline",
|
||||
current_fn=lambda shade: POWER_SUPPLY_TYPE_MAP.get(
|
||||
shade.raw_data.get(ATTR_BATTERY_KIND), None
|
||||
|
@ -106,7 +106,6 @@ class PowerViewSelect(ShadeEntity, SelectEntity):
|
|||
"""Initialize the select entity."""
|
||||
super().__init__(coordinator, device_info, room_name, shade, name)
|
||||
self.entity_description: PowerviewSelectDescription = description
|
||||
self._attr_name = f"{self._shade_name} {description.name}"
|
||||
self._attr_unique_id = f"{self._attr_unique_id}_{description.key}"
|
||||
|
||||
@property
|
||||
|
|
|
@ -55,7 +55,6 @@ class PowerviewSensorDescription(
|
|||
SENSORS: Final = [
|
||||
PowerviewSensorDescription(
|
||||
key="charge",
|
||||
name="Battery",
|
||||
device_class=SensorDeviceClass.BATTERY,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
native_value_fn=lambda shade: round(
|
||||
|
@ -69,7 +68,7 @@ SENSORS: Final = [
|
|||
),
|
||||
PowerviewSensorDescription(
|
||||
key="signal",
|
||||
name="Signal",
|
||||
translation_key="signal_strength",
|
||||
icon="mdi:signal",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
native_value_fn=lambda shade: round(
|
||||
|
@ -129,7 +128,6 @@ class PowerViewSensor(ShadeEntity, SensorEntity):
|
|||
"""Initialize the select entity."""
|
||||
super().__init__(coordinator, device_info, room_name, shade, name)
|
||||
self.entity_description = description
|
||||
self._attr_name = f"{self._shade_name} {description.name}"
|
||||
self._attr_unique_id = f"{self._attr_unique_id}_{description.key}"
|
||||
self._attr_native_unit_of_measurement = description.native_unit_of_measurement
|
||||
|
||||
|
|
|
@ -20,5 +20,42 @@
|
|||
"abort": {
|
||||
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]"
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
"button": {
|
||||
"calibrate": {
|
||||
"name": "Calibrate"
|
||||
},
|
||||
"favorite": {
|
||||
"name": "Favorite"
|
||||
}
|
||||
},
|
||||
"cover": {
|
||||
"bottom": {
|
||||
"name": "Bottom"
|
||||
},
|
||||
"top": {
|
||||
"name": "Top"
|
||||
},
|
||||
"combined": {
|
||||
"name": "Combined"
|
||||
},
|
||||
"front": {
|
||||
"name": "Front"
|
||||
},
|
||||
"rear": {
|
||||
"name": "Rear"
|
||||
}
|
||||
},
|
||||
"select": {
|
||||
"power_source": {
|
||||
"name": "Power source"
|
||||
}
|
||||
},
|
||||
"sensor": {
|
||||
"signal_strength": {
|
||||
"name": "[%key:component::sensor::entity_component::signal_strength::name%]"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue