"""Support for hunterdouglass_powerview settings.""" from __future__ import annotations from collections.abc import Callable, Coroutine from dataclasses import dataclass from typing import Any, Final from aiopvapi.resources.shade import BaseShade, factory as PvShade from homeassistant.components.select import SelectEntity, SelectEntityDescription from homeassistant.config_entries import ConfigEntry from homeassistant.const import EntityCategory from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback from .const import ( ATTR_BATTERY_KIND, DOMAIN, POWER_SUPPLY_TYPE_MAP, POWER_SUPPLY_TYPE_REVERSE_MAP, ROOM_ID_IN_SHADE, ROOM_NAME_UNICODE, SHADE_BATTERY_LEVEL, ) from .coordinator import PowerviewShadeUpdateCoordinator from .entity import ShadeEntity from .model import PowerviewDeviceInfo, PowerviewEntryData @dataclass class PowerviewSelectDescriptionMixin: """Mixin to describe a select entity.""" current_fn: Callable[[BaseShade], Any] select_fn: Callable[[BaseShade, str], Coroutine[Any, Any, bool]] @dataclass class PowerviewSelectDescription( SelectEntityDescription, PowerviewSelectDescriptionMixin ): """A class that describes select entities.""" entity_category: EntityCategory = EntityCategory.CONFIG DROPDOWNS: Final = [ PowerviewSelectDescription( key="powersource", name="Power Source", icon="mdi:power-plug-outline", current_fn=lambda shade: POWER_SUPPLY_TYPE_MAP.get( shade.raw_data.get(ATTR_BATTERY_KIND), None ), options=list(POWER_SUPPLY_TYPE_MAP.values()), select_fn=lambda shade, option: shade.set_power_source( POWER_SUPPLY_TYPE_REVERSE_MAP.get(option) ), ), ] async def async_setup_entry( hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback ) -> None: """Set up the hunter douglas select entities.""" pv_entry: PowerviewEntryData = hass.data[DOMAIN][entry.entry_id] entities = [] for raw_shade in pv_entry.shade_data.values(): shade: BaseShade = PvShade(raw_shade, pv_entry.api) if SHADE_BATTERY_LEVEL not in shade.raw_data: continue name_before_refresh = shade.name room_id = shade.raw_data.get(ROOM_ID_IN_SHADE) room_name = pv_entry.room_data.get(room_id, {}).get(ROOM_NAME_UNICODE, "") for description in DROPDOWNS: entities.append( PowerViewSelect( pv_entry.coordinator, pv_entry.device_info, room_name, shade, name_before_refresh, description, ) ) async_add_entities(entities) class PowerViewSelect(ShadeEntity, SelectEntity): """Representation of a select entity.""" def __init__( self, coordinator: PowerviewShadeUpdateCoordinator, device_info: PowerviewDeviceInfo, room_name: str, shade: BaseShade, name: str, description: PowerviewSelectDescription, ) -> None: """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 def current_option(self) -> str | None: """Return the selected entity option to represent the entity state.""" return self.entity_description.current_fn(self._shade) async def async_select_option(self, option: str) -> None: """Change the selected option.""" await self.entity_description.select_fn(self._shade, option) await self._shade.refresh() # force update data to ensure new info is in coordinator self.async_write_ha_state()