"""Support for Tuya select.""" from __future__ import annotations from typing import cast from tuya_iot import TuyaDevice, TuyaDeviceManager from tuya_iot.device import TuyaDeviceStatusRange from homeassistant.components.select import SelectEntity, SelectEntityDescription from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.entity_platform import AddEntitiesCallback from . import HomeAssistantTuyaData from .base import EnumTypeData, TuyaEntity from .const import DOMAIN, TUYA_DISCOVERY_NEW, DPCode # All descriptions can be found here. Mostly the Enum data types in the # default instructions set of each category end up being a select. # https://developer.tuya.com/en/docs/iot/standarddescription?id=K9i5ql6waswzq SELECTS: dict[str, tuple[SelectEntityDescription, ...]] = { # Coffee maker # https://developer.tuya.com/en/docs/iot/categorykfj?id=Kaiuz2p12pc7f "kfj": ( SelectEntityDescription( key=DPCode.CUP_NUMBER, name="Cups", icon="mdi:numeric", ), SelectEntityDescription( key=DPCode.CONCENTRATION_SET, name="Concentration", icon="mdi:altimeter", ), SelectEntityDescription( key=DPCode.MATERIAL, name="Material", ), SelectEntityDescription( key=DPCode.MODE, name="Mode", ), ), } async def async_setup_entry( hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback ) -> None: """Set up Tuya select dynamically through Tuya discovery.""" hass_data: HomeAssistantTuyaData = hass.data[DOMAIN][entry.entry_id] @callback def async_discover_device(device_ids: list[str]) -> None: """Discover and add a discovered Tuya select.""" entities: list[TuyaSelectEntity] = [] for device_id in device_ids: device = hass_data.device_manager.device_map[device_id] if descriptions := SELECTS.get(device.category): for description in descriptions: if ( description.key in device.function or description.key in device.status ): entities.append( TuyaSelectEntity( device, hass_data.device_manager, description ) ) async_add_entities(entities) async_discover_device([*hass_data.device_manager.device_map]) entry.async_on_unload( async_dispatcher_connect(hass, TUYA_DISCOVERY_NEW, async_discover_device) ) class TuyaSelectEntity(TuyaEntity, SelectEntity): """Tuya Select Entity.""" def __init__( self, device: TuyaDevice, device_manager: TuyaDeviceManager, description: SelectEntityDescription, ) -> None: """Init Tuya sensor.""" super().__init__(device, device_manager) self.entity_description = description self._attr_unique_id = f"{super().unique_id}{description.key}" self._attr_opions: list[str] = [] if status_range := device.status_range.get(description.key): self._status_range = cast(TuyaDeviceStatusRange, status_range) # Extract type data from enum status range, if self._status_range.type == "Enum": type_data = EnumTypeData.from_json(self._status_range.values) self._attr_options = type_data.range @property def current_option(self) -> str | None: """Return the selected entity option to represent the entity state.""" # Raw value value = self.tuya_device.status.get(self.entity_description.key) if value is None or value not in self._attr_options: return None return value def select_option(self, option: str) -> None: """Change the selected option.""" self._send_command( [ { "code": self.entity_description.key, "value": option, } ] )