1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
| """Select platform for DeWarmte integration."""
from __future__ import annotations
from dataclasses import dataclass
from typing import Any, cast
from enum import Enum
from homeassistant.components.select import (
SelectEntity,
SelectEntityDescription,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from . import DeWarmteDataUpdateCoordinator
from .const import DOMAIN
from .api.models.settings import SETTING_GROUPS
class HeatCurveMode(str, Enum):
"""Heat curve mode settings."""
WEATHER = "weather"
FIXED = "fixed"
class HeatingKind(str, Enum):
"""Heating kind settings."""
CUSTOM = "custom"
FLOOR = "floor"
RADIATOR = "radiator"
BOTH = "both"
class HeatingPerformanceMode(str, Enum):
"""Heating performance mode settings."""
AUTO = "auto"
POMP_AO_ONLY = "pomp_ao_only"
POMP_AO_AND_BACKUP = "pomp_ao_and_backup"
BACKUP_ONLY = "backup_only"
class SoundMode(str, Enum):
"""Sound mode settings."""
NORMAL = "normal"
SILENT = "silent"
class PowerLevel(str, Enum):
"""Power level settings."""
MIN = "min"
MED = "med"
MAX = "max"
class ThermostatDelay(str, Enum):
"""Thermostat delay settings."""
MIN = "min"
MED = "med"
MAX = "max"
class BackupHeatingMode(str, Enum):
"""Backup heating mode settings."""
AUTO = "auto"
ECO = "eco"
COMFORT = "comfort"
class CoolingThermostatType(str, Enum):
"""Cooling thermostat type settings."""
HEATING_ONLY = "heating_only"
HEATING_AND_COOLING = "heating_and_cooling"
class CoolingControlMode(str, Enum):
"""Cooling control mode settings."""
THERMOSTAT = "thermostat"
COOLING_ONLY = "cooling_only"
HEATING_ONLY = "heating_only"
FORCED = "forced"
@dataclass(frozen=True)
class DeWarmteSelectEntityDescription(SelectEntityDescription):
"""Class describing DeWarmte select entities."""
options_enum: type[Enum] | None = None
MODE_SELECTS = {
"heat_curve_mode": DeWarmteSelectEntityDescription(
key="heat_curve_mode",
name="Heat Curve Mode",
options_enum=HeatCurveMode,
options=[mode.value for mode in HeatCurveMode],
),
"heating_kind": DeWarmteSelectEntityDescription(
key="heating_kind",
name="Heating Kind",
options_enum=HeatingKind,
options=[kind.value for kind in HeatingKind],
),
"heating_performance_mode": DeWarmteSelectEntityDescription(
key="heating_performance_mode",
name="Heating Performance Mode",
options_enum=HeatingPerformanceMode,
options=[mode.value for mode in HeatingPerformanceMode],
),
"sound_mode": DeWarmteSelectEntityDescription(
key="sound_mode",
name="Sound Mode",
options_enum=SoundMode,
options=[mode.value for mode in SoundMode],
),
"sound_compressor_power": DeWarmteSelectEntityDescription(
key="sound_compressor_power",
name="Sound Compressor Power",
options_enum=PowerLevel,
options=[level.value for level in PowerLevel],
),
"sound_fan_speed": DeWarmteSelectEntityDescription(
key="sound_fan_speed",
name="Sound Fan Speed",
options_enum=PowerLevel,
options=[level.value for level in PowerLevel],
),
"advanced_thermostat_delay": DeWarmteSelectEntityDescription(
key="advanced_thermostat_delay",
name="Advanced Thermostat Delay",
options_enum=ThermostatDelay,
options=[delay.value for delay in ThermostatDelay],
),
"backup_heating_mode": DeWarmteSelectEntityDescription(
key="backup_heating_mode",
name="Backup Heating Mode",
options_enum=BackupHeatingMode,
options=[mode.value for mode in BackupHeatingMode],
),
"cooling_thermostat_type": DeWarmteSelectEntityDescription(
key="cooling_thermostat_type",
name="Cooling Thermostat Type",
options_enum=CoolingThermostatType,
options=[type.value for type in CoolingThermostatType],
),
"cooling_control_mode": DeWarmteSelectEntityDescription(
key="cooling_control_mode",
name="Cooling Control Mode",
options_enum=CoolingControlMode,
options=[mode.value for mode in CoolingControlMode],
),
}
async def async_setup_entry(
hass: HomeAssistant,
entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up the DeWarmte select entities."""
coordinators = hass.data[DOMAIN][entry.entry_id]
if not isinstance(coordinators, list):
coordinators = [coordinators]
for coordinator in coordinators:
# Only create select entities for AO and MP devices (T devices have no settings)
if not coordinator.device.product_id.startswith(("AO ", "MP ")):
continue
# Filter out cooling entities if cooling is not supported
entities = []
for description in MODE_SELECTS.values():
# Skip cooling entities if cooling is not supported
if description.key in SETTING_GROUPS["cooling"].keys:
assert coordinator.device is not None, "Coordinator device must not be None"
if not coordinator.device.supports_cooling:
continue
entities.append(DeWarmteSelectEntity(coordinator, description))
async_add_entities(entities)
class DeWarmteSelectEntity(CoordinatorEntity[DeWarmteDataUpdateCoordinator], SelectEntity): # type: ignore[override]
"""Representation of a DeWarmte select entity."""
_attr_has_entity_name = True
def __init__(
self,
coordinator: DeWarmteDataUpdateCoordinator,
description: DeWarmteSelectEntityDescription,
) -> None:
"""Initialize the select entity."""
super().__init__(coordinator)
assert coordinator.device is not None, "Coordinator device must not be None"
assert description.options is not None, "Select entity must have options"
self.entity_description = description
self._attr_unique_id = f"{coordinator.device.device_id}_{description.key}"
self._attr_device_info = coordinator.device_info
self._attr_options = description.options
@property
def dewarmte_description(self) -> DeWarmteSelectEntityDescription:
"""Get the DeWarmte specific entity description."""
return cast(DeWarmteSelectEntityDescription, self.entity_description)
@property
def current_option(self) -> str | None: # type: ignore[override]
"""Return the current selected option."""
# Settings are cached in coordinator, read from there
if not hasattr(self.coordinator, '_cached_settings') or not self.coordinator._cached_settings:
return None
settings = self.coordinator._cached_settings
key = self.dewarmte_description.key
# All settings are now at the root level
return getattr(settings, key, None)
async def async_select_option(self, option: str) -> None:
"""Change the selected option."""
await self.coordinator.api.async_update_operation_settings(self.coordinator.device, self.dewarmte_description.key, option)
await self.coordinator.async_request_refresh() |