diff --git a/homeassistant/components/lyric/__init__.py b/homeassistant/components/lyric/__init__.py index 23ee08457ff807..af610f12737292 100644 --- a/homeassistant/components/lyric/__init__.py +++ b/homeassistant/components/lyric/__init__.py @@ -21,7 +21,7 @@ CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN) -PLATFORMS = [Platform.CLIMATE, Platform.SENSOR] +PLATFORMS = [Platform.CLIMATE, Platform.SELECT, Platform.SENSOR] async def async_setup_entry(hass: HomeAssistant, entry: LyricConfigEntry) -> bool: diff --git a/homeassistant/components/lyric/icons.json b/homeassistant/components/lyric/icons.json index edb61c3f8e2bd3..6203a932e6b5aa 100644 --- a/homeassistant/components/lyric/icons.json +++ b/homeassistant/components/lyric/icons.json @@ -1,5 +1,10 @@ { "entity": { + "select": { + "room_priority": { + "default": "mdi:home-thermometer" + } + }, "sensor": { "setpoint_status": { "default": "mdi:thermostat" diff --git a/homeassistant/components/lyric/select.py b/homeassistant/components/lyric/select.py new file mode 100644 index 00000000000000..683d2c6b2e3816 --- /dev/null +++ b/homeassistant/components/lyric/select.py @@ -0,0 +1,129 @@ +"""Support for Honeywell Lyric select platform.""" + +import logging + +from aiolyric.objects.device import LyricDevice +from aiolyric.objects.location import LyricLocation +from aiolyric.objects.priority import LyricRoom + +from homeassistant.components.select import SelectEntity +from homeassistant.const import EntityCategory +from homeassistant.core import HomeAssistant +from homeassistant.exceptions import HomeAssistantError +from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback + +from .const import LYRIC_EXCEPTIONS +from .coordinator import LyricConfigEntry, LyricDataUpdateCoordinator +from .entity import LyricDeviceEntity + +_LOGGER = logging.getLogger(__name__) + +# Honeywell Lyric API priority types +PRIORITY_TYPE_PICK_A_ROOM = "PickARoom" +PRIORITY_TYPE_FOLLOW_ME = "FollowMe" +PRIORITY_TYPE_WHOLE_HOUSE = "WholeHouse" + +# Option shown in the select for the FollowMe mode +OPTION_FOLLOW_ME = "follow_me" + + +async def async_setup_entry( + hass: HomeAssistant, + entry: LyricConfigEntry, + async_add_entities: AddConfigEntryEntitiesCallback, +) -> None: + """Set up Honeywell Lyric select entities based on a config entry.""" + coordinator = entry.runtime_data + + async_add_entities( + LyricRoomPrioritySelect(coordinator, location, device) + for location in coordinator.data.locations + for device in location.devices + if device.device_class == "Thermostat" + and device.device_id.startswith("LCC") + and coordinator.data.rooms_dict.get(device.mac_id) + ) + + +class LyricRoomPrioritySelect(LyricDeviceEntity, SelectEntity): + """Select entity for Honeywell Lyric thermostat room priority.""" + + _attr_entity_category = EntityCategory.CONFIG + _attr_translation_key = "room_priority" + + def __init__( + self, + coordinator: LyricDataUpdateCoordinator, + location: LyricLocation, + device: LyricDevice, + ) -> None: + """Initialize the room priority select entity.""" + super().__init__( + coordinator, + location, + device, + f"{device.mac_id}_room_priority", + ) + + @property + def _rooms(self) -> dict[int, LyricRoom]: + """Return the rooms for this thermostat.""" + return self.coordinator.data.rooms_dict.get(self._mac_id, {}) + + @property + def options(self) -> list[str]: + """Return the list of available room priority options.""" + room_options = sorted( + room.room_name for room in self._rooms.values() if room.room_name + ) + return [OPTION_FOLLOW_ME, *room_options] + + @property + def current_option(self) -> str | None: + """Return the currently selected room priority.""" + priority = self.coordinator.data.priorities_dict.get(self._mac_id) + if priority is None: + return None + + current = priority.current_priority + if current.priority_type == PRIORITY_TYPE_FOLLOW_ME: + return OPTION_FOLLOW_ME + + if current.priority_type == PRIORITY_TYPE_PICK_A_ROOM: + selected = current.selected_rooms + if selected: + room = self._rooms.get(selected[0]) + if room is not None: + return room.room_name + + return None + + async def async_select_option(self, option: str) -> None: + """Set the room priority.""" + if option == OPTION_FOLLOW_ME: + priority_type = PRIORITY_TYPE_FOLLOW_ME + rooms: list[int] = [] + else: + priority_type = PRIORITY_TYPE_PICK_A_ROOM + room_id = next( + (rid for rid, room in self._rooms.items() if room.room_name == option), + None, + ) + if room_id is None: + _LOGGER.error("Room not found: %s", option) + return + rooms = [room_id] + + _LOGGER.debug("Set room priority: type=%s, rooms=%s", priority_type, rooms) + try: + await self.coordinator.data.update_priority( + self.location, + self.device, + priority_type=priority_type, + rooms=rooms, + ) + except LYRIC_EXCEPTIONS as exception: + raise HomeAssistantError( + f"Failed to set room priority: {exception}" + ) from exception + await self.coordinator.async_refresh() diff --git a/homeassistant/components/lyric/strings.json b/homeassistant/components/lyric/strings.json index 51f1cff5269aca..7ea9cbfeee9562 100644 --- a/homeassistant/components/lyric/strings.json +++ b/homeassistant/components/lyric/strings.json @@ -37,6 +37,14 @@ } }, "entity": { + "select": { + "room_priority": { + "name": "Room priority", + "state": { + "follow_me": "Follow me" + } + } + }, "sensor": { "indoor_humidity": { "name": "Indoor humidity"