|
| 1 | +"""Support for LinkPlay select.""" |
| 2 | + |
| 3 | +from __future__ import annotations |
| 4 | + |
| 5 | +from collections.abc import Awaitable, Callable, Coroutine |
| 6 | +from dataclasses import dataclass |
| 7 | +import logging |
| 8 | +from typing import Any |
| 9 | + |
| 10 | +from linkplay.bridge import LinkPlayBridge, LinkPlayPlayer |
| 11 | +from linkplay.consts import AudioOutputHwMode |
| 12 | +from linkplay.manufacturers import MANUFACTURER_WIIM |
| 13 | + |
| 14 | +from homeassistant.components.select import SelectEntity, SelectEntityDescription |
| 15 | +from homeassistant.core import HomeAssistant |
| 16 | +from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback |
| 17 | + |
| 18 | +from . import LinkPlayConfigEntry |
| 19 | +from .entity import LinkPlayBaseEntity, exception_wrap |
| 20 | + |
| 21 | +_LOGGER = logging.getLogger(__name__) |
| 22 | + |
| 23 | +AUDIO_OUTPUT_HW_MODE_MAP: dict[AudioOutputHwMode, str] = { |
| 24 | + AudioOutputHwMode.OPTICAL: "optical", |
| 25 | + AudioOutputHwMode.LINE_OUT: "line_out", |
| 26 | + AudioOutputHwMode.COAXIAL: "coaxial", |
| 27 | + AudioOutputHwMode.HEADPHONES: "headphones", |
| 28 | +} |
| 29 | + |
| 30 | +AUDIO_OUTPUT_HW_MODE_MAP_INV: dict[str, AudioOutputHwMode] = { |
| 31 | + v: k for k, v in AUDIO_OUTPUT_HW_MODE_MAP.items() |
| 32 | +} |
| 33 | + |
| 34 | + |
| 35 | +async def _get_current_option(bridge: LinkPlayBridge) -> str: |
| 36 | + """Get the current hardware mode.""" |
| 37 | + modes = await bridge.player.get_audio_output_hw_mode() |
| 38 | + return AUDIO_OUTPUT_HW_MODE_MAP[modes.hardware] |
| 39 | + |
| 40 | + |
| 41 | +@dataclass(frozen=True, kw_only=True) |
| 42 | +class LinkPlaySelectEntityDescription(SelectEntityDescription): |
| 43 | + """Class describing LinkPlay select entities.""" |
| 44 | + |
| 45 | + set_option_fn: Callable[[LinkPlayPlayer, str], Coroutine[Any, Any, None]] |
| 46 | + current_option_fn: Callable[[LinkPlayPlayer], Awaitable[str]] |
| 47 | + |
| 48 | + |
| 49 | +SELECT_TYPES_WIIM: tuple[LinkPlaySelectEntityDescription, ...] = ( |
| 50 | + LinkPlaySelectEntityDescription( |
| 51 | + key="audio_output_hardware_mode", |
| 52 | + translation_key="audio_output_hardware_mode", |
| 53 | + current_option_fn=_get_current_option, |
| 54 | + set_option_fn=( |
| 55 | + lambda linkplay_bridge, |
| 56 | + option: linkplay_bridge.player.set_audio_output_hw_mode( |
| 57 | + AUDIO_OUTPUT_HW_MODE_MAP_INV[option] |
| 58 | + ) |
| 59 | + ), |
| 60 | + options=list(AUDIO_OUTPUT_HW_MODE_MAP_INV), |
| 61 | + ), |
| 62 | +) |
| 63 | + |
| 64 | + |
| 65 | +async def async_setup_entry( |
| 66 | + hass: HomeAssistant, |
| 67 | + config_entry: LinkPlayConfigEntry, |
| 68 | + async_add_entities: AddConfigEntryEntitiesCallback, |
| 69 | +) -> None: |
| 70 | + """Set up the LinkPlay select from config entry.""" |
| 71 | + |
| 72 | + # add entities |
| 73 | + if config_entry.runtime_data.bridge.device.manufacturer == MANUFACTURER_WIIM: |
| 74 | + async_add_entities( |
| 75 | + LinkPlaySelect(config_entry.runtime_data.bridge, description) |
| 76 | + for description in SELECT_TYPES_WIIM |
| 77 | + ) |
| 78 | + |
| 79 | + |
| 80 | +class LinkPlaySelect(LinkPlayBaseEntity, SelectEntity): |
| 81 | + """Representation of LinkPlay select.""" |
| 82 | + |
| 83 | + entity_description: LinkPlaySelectEntityDescription |
| 84 | + |
| 85 | + def __init__( |
| 86 | + self, |
| 87 | + bridge: LinkPlayPlayer, |
| 88 | + description: LinkPlaySelectEntityDescription, |
| 89 | + ) -> None: |
| 90 | + """Initialize LinkPlay select.""" |
| 91 | + super().__init__(bridge) |
| 92 | + self.entity_description = description |
| 93 | + self._attr_unique_id = f"{bridge.device.uuid}-{description.key}" |
| 94 | + |
| 95 | + async def async_update(self) -> None: |
| 96 | + """Get the current value from the device.""" |
| 97 | + try: |
| 98 | + # modes = await self.entity_description.current_option_fn(self._bridge) |
| 99 | + self._attr_current_option = await self.entity_description.current_option_fn( |
| 100 | + self._bridge |
| 101 | + ) |
| 102 | + |
| 103 | + except ValueError as ex: |
| 104 | + _LOGGER.debug( |
| 105 | + "Cannot retrieve hardware mode value from device with error:, %s", ex |
| 106 | + ) |
| 107 | + self._attr_current_option = None |
| 108 | + |
| 109 | + @exception_wrap |
| 110 | + async def async_select_option(self, option: str) -> None: |
| 111 | + """Set the option.""" |
| 112 | + await self.entity_description.set_option_fn(self._bridge, option) |
0 commit comments