From d6e7a3e537564c6bfc52580e2271491f4f7dc698 Mon Sep 17 00:00:00 2001 From: kingy444 Date: Thu, 9 Jun 2022 14:46:45 +1000 Subject: [PATCH] Add powerview advanced features (#73061) Co-authored-by: J. Nick Koston --- .coveragerc | 3 +- .../hunterdouglas_powerview/__init__.py | 2 +- .../hunterdouglas_powerview/button.py | 124 ++++++++++++++++++ .../hunterdouglas_powerview/cover.py | 3 +- .../hunterdouglas_powerview/entity.py | 5 + 5 files changed, 133 insertions(+), 4 deletions(-) create mode 100644 homeassistant/components/hunterdouglas_powerview/button.py diff --git a/.coveragerc b/.coveragerc index 3db90953f74..44b205746df 100644 --- a/.coveragerc +++ b/.coveragerc @@ -505,9 +505,10 @@ omit = homeassistant/components/huawei_lte/switch.py homeassistant/components/hue/light.py homeassistant/components/hunterdouglas_powerview/__init__.py + homeassistant/components/hunterdouglas_powerview/button.py homeassistant/components/hunterdouglas_powerview/coordinator.py - homeassistant/components/hunterdouglas_powerview/diagnostics.py homeassistant/components/hunterdouglas_powerview/cover.py + homeassistant/components/hunterdouglas_powerview/diagnostics.py homeassistant/components/hunterdouglas_powerview/entity.py homeassistant/components/hunterdouglas_powerview/scene.py homeassistant/components/hunterdouglas_powerview/sensor.py diff --git a/homeassistant/components/hunterdouglas_powerview/__init__.py b/homeassistant/components/hunterdouglas_powerview/__init__.py index 88aa5214c9b..fe039964e5d 100644 --- a/homeassistant/components/hunterdouglas_powerview/__init__.py +++ b/homeassistant/components/hunterdouglas_powerview/__init__.py @@ -56,7 +56,7 @@ PARALLEL_UPDATES = 1 CONFIG_SCHEMA = cv.removed(DOMAIN, raise_if_present=False) -PLATFORMS = [Platform.COVER, Platform.SCENE, Platform.SENSOR] +PLATFORMS = [Platform.BUTTON, Platform.COVER, Platform.SCENE, Platform.SENSOR] _LOGGER = logging.getLogger(__name__) diff --git a/homeassistant/components/hunterdouglas_powerview/button.py b/homeassistant/components/hunterdouglas_powerview/button.py new file mode 100644 index 00000000000..131ef279a20 --- /dev/null +++ b/homeassistant/components/hunterdouglas_powerview/button.py @@ -0,0 +1,124 @@ +"""Buttons for Hunter Douglas Powerview advanced features.""" +from __future__ import annotations + +from collections.abc import Callable +from dataclasses import dataclass +from typing import Any, Final + +from aiopvapi.resources.shade import BaseShade, factory as PvShade + +from homeassistant.components.button import ( + ButtonDeviceClass, + ButtonEntity, + ButtonEntityDescription, +) +from homeassistant.config_entries import ConfigEntry +from homeassistant.core import HomeAssistant +from homeassistant.helpers.entity import EntityCategory +from homeassistant.helpers.entity_platform import AddEntitiesCallback + +from .const import ( + COORDINATOR, + DEVICE_INFO, + DOMAIN, + PV_API, + PV_ROOM_DATA, + PV_SHADE_DATA, + ROOM_ID_IN_SHADE, + ROOM_NAME_UNICODE, +) +from .coordinator import PowerviewShadeUpdateCoordinator +from .entity import ShadeEntity + + +@dataclass +class PowerviewButtonDescriptionMixin: + """Mixin to describe a Button entity.""" + + press_action: Callable[[BaseShade], Any] + + +@dataclass +class PowerviewButtonDescription( + ButtonEntityDescription, PowerviewButtonDescriptionMixin +): + """Class to describe a Button entity.""" + + +BUTTONS: Final = [ + PowerviewButtonDescription( + key="calibrate", + name="Calibrate", + icon="mdi:swap-vertical-circle-outline", + device_class=ButtonDeviceClass.UPDATE, + entity_category=EntityCategory.DIAGNOSTIC, + press_action=lambda shade: shade.calibrate(), + ), + PowerviewButtonDescription( + key="identify", + name="Identify", + icon="mdi:crosshairs-question", + device_class=ButtonDeviceClass.UPDATE, + entity_category=EntityCategory.DIAGNOSTIC, + press_action=lambda shade: shade.jog(), + ), +] + + +async def async_setup_entry( + hass: HomeAssistant, + entry: ConfigEntry, + async_add_entities: AddEntitiesCallback, +) -> None: + """Set up the hunter douglas advanced feature buttons.""" + + pv_data = hass.data[DOMAIN][entry.entry_id] + room_data: dict[str | int, Any] = pv_data[PV_ROOM_DATA] + shade_data = pv_data[PV_SHADE_DATA] + pv_request = pv_data[PV_API] + coordinator: PowerviewShadeUpdateCoordinator = pv_data[COORDINATOR] + device_info: dict[str, Any] = pv_data[DEVICE_INFO] + + entities: list[ButtonEntity] = [] + for raw_shade in shade_data.values(): + shade: BaseShade = PvShade(raw_shade, pv_request) + name_before_refresh = shade.name + room_id = shade.raw_data.get(ROOM_ID_IN_SHADE) + room_name = room_data.get(room_id, {}).get(ROOM_NAME_UNICODE, "") + + for description in BUTTONS: + entities.append( + PowerviewButton( + coordinator, + device_info, + room_name, + shade, + name_before_refresh, + description, + ) + ) + + async_add_entities(entities) + + +class PowerviewButton(ShadeEntity, ButtonEntity): + """Representation of an advanced feature button.""" + + def __init__( + self, + coordinator: PowerviewShadeUpdateCoordinator, + device_info: dict[str, Any], + room_name: str, + shade: BaseShade, + name: str, + description: PowerviewButtonDescription, + ) -> None: + """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: + """Handle the button press.""" + await self.entity_description.press_action(self._shade) diff --git a/homeassistant/components/hunterdouglas_powerview/cover.py b/homeassistant/components/hunterdouglas_powerview/cover.py index 565bac6a5c8..c3061c75301 100644 --- a/homeassistant/components/hunterdouglas_powerview/cover.py +++ b/homeassistant/components/hunterdouglas_powerview/cover.py @@ -323,8 +323,7 @@ class PowerViewShadeBase(ShadeEntity, CoverEntity): async def _async_force_refresh_state(self) -> None: """Refresh the cover state and force the device cache to be bypassed.""" - await self._shade.refresh() - self._async_update_shade_data(self._shade.raw_data) + await self.async_update() self.async_write_ha_state() async def async_added_to_hass(self) -> None: diff --git a/homeassistant/components/hunterdouglas_powerview/entity.py b/homeassistant/components/hunterdouglas_powerview/entity.py index 04885fa576e..7814ba9cb12 100644 --- a/homeassistant/components/hunterdouglas_powerview/entity.py +++ b/homeassistant/components/hunterdouglas_powerview/entity.py @@ -117,3 +117,8 @@ class ShadeEntity(HDEntity): device_info[ATTR_SW_VERSION] = sw_version return device_info + + async def async_update(self) -> None: + """Refresh shade position.""" + await self._shade.refresh() + self.data.update_shade_positions(self._shade.raw_data)