From 574f4710aac2643ca616004ab6207290c5c17ec2 Mon Sep 17 00:00:00 2001 From: Tom Date: Mon, 21 Mar 2022 21:13:03 +0100 Subject: [PATCH] Add select platform to Plugwise (#68303) Co-authored-by: Franck Nijhof --- .coveragerc | 1 + homeassistant/components/plugwise/climate.py | 9 +-- homeassistant/components/plugwise/const.py | 8 +++ homeassistant/components/plugwise/select.py | 64 ++++++++++++++++++++ 4 files changed, 74 insertions(+), 8 deletions(-) create mode 100644 homeassistant/components/plugwise/select.py diff --git a/.coveragerc b/.coveragerc index 47b07724421..3b99fac2c3b 100644 --- a/.coveragerc +++ b/.coveragerc @@ -898,6 +898,7 @@ omit = homeassistant/components/plaato/sensor.py homeassistant/components/plex/media_player.py homeassistant/components/plex/view.py + homeassistant/components/plugwise/select.py homeassistant/components/plum_lightpad/light.py homeassistant/components/pocketcasts/sensor.py homeassistant/components/point/__init__.py diff --git a/homeassistant/components/plugwise/climate.py b/homeassistant/components/plugwise/climate.py index e22f12c3526..12a203b6896 100644 --- a/homeassistant/components/plugwise/climate.py +++ b/homeassistant/components/plugwise/climate.py @@ -21,18 +21,11 @@ from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback -from .const import DEFAULT_MAX_TEMP, DEFAULT_MIN_TEMP, DOMAIN +from .const import DEFAULT_MAX_TEMP, DEFAULT_MIN_TEMP, DOMAIN, THERMOSTAT_CLASSES from .coordinator import PlugwiseDataUpdateCoordinator from .entity import PlugwiseEntity from .util import plugwise_command -THERMOSTAT_CLASSES = [ - "thermostat", - "thermostatic_radiator_valve", - "zone_thermometer", - "zone_thermostat", -] - async def async_setup_entry( hass: HomeAssistant, diff --git a/homeassistant/components/plugwise/const.py b/homeassistant/components/plugwise/const.py index adcd68ed50e..3bcad0b88aa 100644 --- a/homeassistant/components/plugwise/const.py +++ b/homeassistant/components/plugwise/const.py @@ -24,6 +24,7 @@ PLATFORMS_GATEWAY = [ Platform.CLIMATE, Platform.SENSOR, Platform.SWITCH, + Platform.SELECT, ] ZEROCONF_MAP = { "smile": "P1", @@ -43,3 +44,10 @@ DEFAULT_SCAN_INTERVAL = { "thermostat": timedelta(seconds=60), } DEFAULT_USERNAME = "smile" + +THERMOSTAT_CLASSES = [ + "thermostat", + "thermostatic_radiator_valve", + "zone_thermometer", + "zone_thermostat", +] diff --git a/homeassistant/components/plugwise/select.py b/homeassistant/components/plugwise/select.py new file mode 100644 index 00000000000..b3cfb366889 --- /dev/null +++ b/homeassistant/components/plugwise/select.py @@ -0,0 +1,64 @@ +"""Plugwise Select component for Home Assistant.""" +from __future__ import annotations + +from homeassistant.components.select import SelectEntity +from homeassistant.config_entries import ConfigEntry +from homeassistant.const import STATE_ON +from homeassistant.core import HomeAssistant +from homeassistant.exceptions import HomeAssistantError +from homeassistant.helpers.entity_platform import AddEntitiesCallback + +from .const import DOMAIN, THERMOSTAT_CLASSES +from .coordinator import PlugwiseDataUpdateCoordinator +from .entity import PlugwiseEntity + + +async def async_setup_entry( + hass: HomeAssistant, + config_entry: ConfigEntry, + async_add_entities: AddEntitiesCallback, +) -> None: + """Set up the Smile selector from a config entry.""" + coordinator = hass.data[DOMAIN][config_entry.entry_id] + async_add_entities( + PlugwiseSelectEntity(coordinator, device_id) + for device_id, device in coordinator.data.devices.items() + if device["class"] in THERMOSTAT_CLASSES + and len(device.get("available_schedules")) > 1 + ) + + +class PlugwiseSelectEntity(PlugwiseEntity, SelectEntity): + """Represent Smile selector.""" + + def __init__( + self, + coordinator: PlugwiseDataUpdateCoordinator, + device_id: str, + ) -> None: + """Initialise the selector.""" + super().__init__(coordinator, device_id) + self._attr_unique_id = f"{device_id}-select_schedule" + self._attr_name = (f"{self.device.get('name', '')} Select Schedule").lstrip() + + @property + def current_option(self) -> str | None: + """Return the selected entity option to represent the entity state.""" + return self.device.get("selected_schedule") + + @property + def options(self) -> list[str]: + """Return a set of selectable options.""" + return self.device.get("available_schedules", []) + + async def async_select_option(self, option: str) -> None: + """Change the selected option.""" + if not ( + await self.coordinator.api.set_schedule_state( + self.device.get("location"), + option, + STATE_ON, + ) + ): + raise HomeAssistantError(f"Failed to change to schedule {option}") + await self.coordinator.async_request_refresh()