Refactor Plugwise select and add regulation_mode selector (#69210)

Co-authored-by: Franck Nijhof <frenck@frenck.nl>
This commit is contained in:
Bouwe Westerdijk 2022-05-11 10:48:13 +02:00 committed by GitHub
parent fb6cdb5a38
commit 2d5a82d10e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,64 +1,113 @@
"""Plugwise Select component for Home Assistant.""" """Plugwise Select component for Home Assistant."""
from __future__ import annotations from __future__ import annotations
from homeassistant.components.select import SelectEntity from collections.abc import Awaitable, Callable
from dataclasses import dataclass
from typing import Any
from plugwise import Smile
from homeassistant.components.select import SelectEntity, SelectEntityDescription
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import STATE_ON from homeassistant.const import STATE_ON
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers.entity import EntityCategory
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DOMAIN, THERMOSTAT_CLASSES from .const import DOMAIN
from .coordinator import PlugwiseDataUpdateCoordinator from .coordinator import PlugwiseDataUpdateCoordinator
from .entity import PlugwiseEntity from .entity import PlugwiseEntity
@dataclass
class PlugwiseSelectDescriptionMixin:
"""Mixin values for Plugwise Select entities."""
command: Callable[[Smile, str, str], Awaitable[Any]]
current_option: str
options: str
@dataclass
class PlugwiseSelectEntityDescription(
SelectEntityDescription, PlugwiseSelectDescriptionMixin
):
"""Class describing Plugwise Number entities."""
SELECT_TYPES = (
PlugwiseSelectEntityDescription(
key="select_schedule",
name="Thermostat Schedule",
icon="mdi:calendar-clock",
command=lambda api, loc, opt: api.set_schedule_state(loc, opt, STATE_ON),
current_option="selected_schedule",
options="available_schedules",
),
PlugwiseSelectEntityDescription(
key="select_regulation_mode",
name="Regulation Mode",
icon="mdi:hvac",
entity_category=EntityCategory.CONFIG,
command=lambda api, loc, opt: api.set_regulation_mode(opt),
current_option="regulation_mode",
options="regulation_modes",
),
)
async def async_setup_entry( async def async_setup_entry(
hass: HomeAssistant, hass: HomeAssistant,
config_entry: ConfigEntry, config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback, async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up the Smile selector from a config entry.""" """Set up the Smile selector from a config entry."""
coordinator = hass.data[DOMAIN][config_entry.entry_id] coordinator: PlugwiseDataUpdateCoordinator = hass.data[DOMAIN][
async_add_entities( config_entry.entry_id
PlugwiseSelectEntity(coordinator, device_id) ]
for device_id, device in coordinator.data.devices.items()
if device["class"] in THERMOSTAT_CLASSES entities: list[PlugwiseSelectEntity] = []
and len(device.get("available_schedules")) > 1 for device_id, device in coordinator.data.devices.items():
) for description in SELECT_TYPES:
if description.options in device and len(device[description.options]) > 1:
entities.append(
PlugwiseSelectEntity(coordinator, device_id, description)
)
async_add_entities(entities)
class PlugwiseSelectEntity(PlugwiseEntity, SelectEntity): class PlugwiseSelectEntity(PlugwiseEntity, SelectEntity):
"""Represent Smile selector.""" """Represent Smile selector."""
entity_description: PlugwiseSelectEntityDescription
def __init__( def __init__(
self, self,
coordinator: PlugwiseDataUpdateCoordinator, coordinator: PlugwiseDataUpdateCoordinator,
device_id: str, device_id: str,
entity_description: PlugwiseSelectEntityDescription,
) -> None: ) -> None:
"""Initialise the selector.""" """Initialise the selector."""
super().__init__(coordinator, device_id) super().__init__(coordinator, device_id)
self._attr_unique_id = f"{device_id}-select_schedule" self.entity_description = entity_description
self._attr_name = (f"{self.device.get('name', '')} Select Schedule").lstrip() self._attr_unique_id = f"{device_id}-{entity_description.key}"
self._attr_name = (f"{self.device['name']} {entity_description.name}").lstrip()
@property @property
def current_option(self) -> str | None: def current_option(self) -> str:
"""Return the selected entity option to represent the entity state.""" """Return the selected entity option to represent the entity state."""
return self.device.get("selected_schedule") return self.device[self.entity_description.current_option]
@property @property
def options(self) -> list[str]: def options(self) -> list[str]:
"""Return a set of selectable options.""" """Return the selectable entity options."""
return self.device.get("available_schedules", []) return self.device[self.entity_description.options]
async def async_select_option(self, option: str) -> None: async def async_select_option(self, option: str) -> None:
"""Change the selected option.""" """Change to the selected entity option."""
if not ( await self.entity_description.command(
await self.coordinator.api.set_schedule_state( self.coordinator.api, self.device["location"], option
self.device.get("location"), )
option,
STATE_ON,
)
):
raise HomeAssistantError(f"Failed to change to schedule {option}")
await self.coordinator.async_request_refresh() await self.coordinator.async_request_refresh()