1 """Support for AirGradient select entities."""
3 from collections.abc
import Awaitable, Callable
4 from dataclasses
import dataclass
6 from airgradient
import AirGradientClient, Config
7 from airgradient.models
import ConfigurationControl, LedBarMode, TemperatureUnit
10 DOMAIN
as SELECT_DOMAIN,
12 SelectEntityDescription,
19 from .
import AirGradientConfigEntry
20 from .const
import DOMAIN, PM_STANDARD, PM_STANDARD_REVERSE
21 from .coordinator
import AirGradientCoordinator
22 from .entity
import AirGradientEntity
25 @dataclass(frozen=True, kw_only=True)
27 """Describes AirGradient select entity."""
29 value_fn: Callable[[Config], str |
None]
30 set_value_fn: Callable[[AirGradientClient, str], Awaitable[
None]]
34 key=
"configuration_control",
35 translation_key=
"configuration_control",
36 options=[ConfigurationControl.CLOUD.value, ConfigurationControl.LOCAL.value],
37 entity_category=EntityCategory.CONFIG,
38 value_fn=
lambda config: (
39 config.configuration_control
40 if config.configuration_control
is not ConfigurationControl.NOT_INITIALIZED
43 set_value_fn=
lambda client, value: client.set_configuration_control(
44 ConfigurationControl(value)
48 DISPLAY_SELECT_TYPES: tuple[AirGradientSelectEntityDescription, ...] = (
50 key=
"display_temperature_unit",
51 translation_key=
"display_temperature_unit",
52 options=[x.value
for x
in TemperatureUnit],
53 entity_category=EntityCategory.CONFIG,
54 value_fn=
lambda config: config.temperature_unit,
55 set_value_fn=
lambda client, value: client.set_temperature_unit(
56 TemperatureUnit(value)
60 key=
"display_pm_standard",
61 translation_key=
"display_pm_standard",
62 options=
list(PM_STANDARD_REVERSE),
63 entity_category=EntityCategory.CONFIG,
64 value_fn=
lambda config: PM_STANDARD.get(config.pm_standard),
65 set_value_fn=
lambda client, value: client.set_pm_standard(
66 PM_STANDARD_REVERSE[value]
71 LED_BAR_ENTITIES: tuple[AirGradientSelectEntityDescription, ...] = (
74 translation_key=
"led_bar_mode",
75 options=[x.value
for x
in LedBarMode],
76 entity_category=EntityCategory.CONFIG,
77 value_fn=
lambda config: config.led_bar_mode,
78 set_value_fn=
lambda client, value: client.set_led_bar_mode(LedBarMode(value)),
82 LEARNING_TIME_OFFSET_OPTIONS = [
101 str_value =
str(value)
102 return str_value
if str_value
in values
else None
105 CONTROL_ENTITIES: tuple[AirGradientSelectEntityDescription, ...] = (
107 key=
"nox_index_learning_time_offset",
108 translation_key=
"nox_index_learning_time_offset",
109 options=LEARNING_TIME_OFFSET_OPTIONS,
110 entity_category=EntityCategory.CONFIG,
112 config.nox_learning_offset, LEARNING_TIME_OFFSET_OPTIONS
114 set_value_fn=
lambda client, value: client.set_nox_learning_offset(
int(value)),
117 key=
"voc_index_learning_time_offset",
118 translation_key=
"voc_index_learning_time_offset",
119 options=LEARNING_TIME_OFFSET_OPTIONS,
120 entity_category=EntityCategory.CONFIG,
122 config.tvoc_learning_offset, LEARNING_TIME_OFFSET_OPTIONS
124 set_value_fn=
lambda client, value: client.set_tvoc_learning_offset(
int(value)),
127 key=
"co2_automatic_baseline_calibration",
128 translation_key=
"co2_automatic_baseline_calibration",
130 entity_category=EntityCategory.CONFIG,
132 config.co2_automatic_baseline_calibration_days, ABC_DAYS
134 set_value_fn=
lambda client,
135 value: client.set_co2_automatic_baseline_calibration(
int(value)),
142 entry: AirGradientConfigEntry,
143 async_add_entities: AddEntitiesCallback,
145 """Set up AirGradient select entities based on a config entry."""
147 coordinator = entry.runtime_data
148 model = coordinator.data.measures.model
152 added_entities =
False
155 def _async_check_entities() -> None:
156 nonlocal added_entities
159 coordinator.data.config.configuration_control
is ConfigurationControl.LOCAL
160 and not added_entities
162 entities: list[AirGradientSelect] = [
164 for description
in CONTROL_ENTITIES
169 for description
in DISPLAY_SELECT_TYPES
174 for description
in LED_BAR_ENTITIES
178 added_entities =
True
180 coordinator.data.config.configuration_control
181 is not ConfigurationControl.LOCAL
184 entity_registry = er.async_get(hass)
185 for entity_description
in (
186 DISPLAY_SELECT_TYPES + LED_BAR_ENTITIES + CONTROL_ENTITIES
188 unique_id = f
"{coordinator.serial_number}-{entity_description.key}"
189 if entity_id := entity_registry.async_get_entity_id(
190 SELECT_DOMAIN, DOMAIN, unique_id
192 entity_registry.async_remove(entity_id)
193 added_entities =
False
195 coordinator.async_add_listener(_async_check_entities)
196 _async_check_entities()
200 """Defines an AirGradient select entity."""
202 entity_description: AirGradientSelectEntityDescription
206 coordinator: AirGradientCoordinator,
207 description: AirGradientSelectEntityDescription,
209 """Initialize AirGradient select."""
212 self.
_attr_unique_id_attr_unique_id = f
"{coordinator.serial_number}-{description.key}"
216 """Return the state of the select."""
220 """Change the selected option."""
221 await self.
entity_descriptionentity_description.set_value_fn(self.coordinator.client, option)
None async_select_option(self, str option)
None __init__(self, AirGradientCoordinator coordinator, AirGradientSelectEntityDescription description)
str|None current_option(self)
None async_request_refresh(self)
None async_setup_entry(HomeAssistant hass, AirGradientConfigEntry entry, AddEntitiesCallback async_add_entities)
str|None _get_value(int value, list[str] values)