From 18bf0762b551d2469ba63aaa0e2c2aa6f1dbc2db Mon Sep 17 00:00:00 2001 From: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Date: Tue, 27 Jul 2021 21:45:04 +1200 Subject: [PATCH] Add select entities to ESPHome (#53526) Co-authored-by: Otto Winter --- .coveragerc | 1 + .../components/esphome/entry_data.py | 2 + .../components/esphome/manifest.json | 2 +- homeassistant/components/esphome/select.py | 65 +++++++++++++++++++ requirements_all.txt | 2 +- requirements_test_all.txt | 2 +- 6 files changed, 71 insertions(+), 3 deletions(-) create mode 100644 homeassistant/components/esphome/select.py diff --git a/.coveragerc b/.coveragerc index 759e2251988..9a89bf842c6 100644 --- a/.coveragerc +++ b/.coveragerc @@ -279,6 +279,7 @@ omit = homeassistant/components/esphome/fan.py homeassistant/components/esphome/light.py homeassistant/components/esphome/number.py + homeassistant/components/esphome/select.py homeassistant/components/esphome/sensor.py homeassistant/components/esphome/switch.py homeassistant/components/essent/sensor.py diff --git a/homeassistant/components/esphome/entry_data.py b/homeassistant/components/esphome/entry_data.py index 3ab933f75f9..2b926b9b270 100644 --- a/homeassistant/components/esphome/entry_data.py +++ b/homeassistant/components/esphome/entry_data.py @@ -19,6 +19,7 @@ from aioesphomeapi import ( FanInfo, LightInfo, NumberInfo, + SelectInfo, SensorInfo, SwitchInfo, TextSensorInfo, @@ -41,6 +42,7 @@ INFO_TYPE_TO_PLATFORM: dict[type[EntityInfo], str] = { FanInfo: "fan", LightInfo: "light", NumberInfo: "number", + SelectInfo: "select", SensorInfo: "sensor", SwitchInfo: "switch", TextSensorInfo: "sensor", diff --git a/homeassistant/components/esphome/manifest.json b/homeassistant/components/esphome/manifest.json index d8a22534001..218c349e5a8 100644 --- a/homeassistant/components/esphome/manifest.json +++ b/homeassistant/components/esphome/manifest.json @@ -3,7 +3,7 @@ "name": "ESPHome", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/esphome", - "requirements": ["aioesphomeapi==5.0.1"], + "requirements": ["aioesphomeapi==5.1.1"], "zeroconf": ["_esphomelib._tcp.local."], "codeowners": ["@OttoWinter", "@jesserockz"], "after_dependencies": ["zeroconf", "tag"], diff --git a/homeassistant/components/esphome/select.py b/homeassistant/components/esphome/select.py new file mode 100644 index 00000000000..6ba6ba4c594 --- /dev/null +++ b/homeassistant/components/esphome/select.py @@ -0,0 +1,65 @@ +"""Support for esphome selects.""" +from __future__ import annotations + +from typing import cast + +from aioesphomeapi import SelectInfo, SelectState +import voluptuous as vol + +from homeassistant.components.select import SelectEntity +from homeassistant.config_entries import ConfigEntry +from homeassistant.core import HomeAssistant +import homeassistant.helpers.config_validation as cv +from homeassistant.helpers.entity_platform import AddEntitiesCallback + +from . import EsphomeEntity, esphome_state_property, platform_async_setup_entry + +ICON_SCHEMA = vol.Schema(cv.icon) + + +async def async_setup_entry( + hass: HomeAssistant, + entry: ConfigEntry, + async_add_entities: AddEntitiesCallback, +) -> None: + """Set up esphome selects based on a config entry.""" + await platform_async_setup_entry( + hass, + entry, + async_add_entities, + component_key="select", + info_type=SelectInfo, + entity_type=EsphomeSelect, + state_type=SelectState, + ) + + +# https://github.com/PyCQA/pylint/issues/3150 for all @esphome_state_property +# pylint: disable=invalid-overridden-method + + +class EsphomeSelect(EsphomeEntity[SelectInfo, SelectState], SelectEntity): + """A select implementation for esphome.""" + + @property + def icon(self) -> str | None: + """Return the icon.""" + if not self._static_info.icon: + return None + return cast(str, ICON_SCHEMA(self._static_info.icon)) + + @property + def options(self) -> list[str]: + """Return a set of selectable options.""" + return self._static_info.options + + @esphome_state_property + def current_option(self) -> str | None: + """Return the state of the entity.""" + if self._state.missing_state: + return None + return self._state.state + + async def async_select_option(self, option: str) -> None: + """Change the selected option.""" + await self._client.select_command(self._static_info.key, option) diff --git a/requirements_all.txt b/requirements_all.txt index 71e2da64aa2..7ee67487da6 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -163,7 +163,7 @@ aioeafm==0.1.2 aioemonitor==1.0.5 # homeassistant.components.esphome -aioesphomeapi==5.0.1 +aioesphomeapi==5.1.1 # homeassistant.components.flo aioflo==0.4.1 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 5f3042643ce..9569a63d0c3 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -103,7 +103,7 @@ aioeafm==0.1.2 aioemonitor==1.0.5 # homeassistant.components.esphome -aioesphomeapi==5.0.1 +aioesphomeapi==5.1.1 # homeassistant.components.flo aioflo==0.4.1