From 8a38424c2454520310a2c0aae71f0ce77e82d1fb Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Tue, 18 Jun 2024 22:34:11 +0200 Subject: [PATCH] Add more airgradient configuration entities (#119191) --- .../components/airgradient/select.py | 43 ++++++- .../components/airgradient/strings.json | 15 +++ .../airgradient/snapshots/test_select.ambr | 112 ++++++++++++++++++ 3 files changed, 166 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/airgradient/select.py b/homeassistant/components/airgradient/select.py index 7880e55de19..8fac06917fd 100644 --- a/homeassistant/components/airgradient/select.py +++ b/homeassistant/components/airgradient/select.py @@ -4,7 +4,12 @@ from collections.abc import Awaitable, Callable from dataclasses import dataclass from airgradient import AirGradientClient, Config -from airgradient.models import ConfigurationControl, TemperatureUnit +from airgradient.models import ( + ConfigurationControl, + LedBarMode, + PmStandard, + TemperatureUnit, +) from homeassistant.components.select import SelectEntity, SelectEntityDescription from homeassistant.const import EntityCategory @@ -17,6 +22,12 @@ from .const import DOMAIN from .coordinator import AirGradientConfigCoordinator from .entity import AirGradientEntity +PM_STANDARD = { + PmStandard.UGM3: "ugm3", + PmStandard.USAQI: "us_aqi", +} +PM_STANDARD_REVERSE = {v: k for k, v in PM_STANDARD.items()} + @dataclass(frozen=True, kw_only=True) class AirGradientSelectEntityDescription(SelectEntityDescription): @@ -25,6 +36,7 @@ class AirGradientSelectEntityDescription(SelectEntityDescription): value_fn: Callable[[Config], str | None] set_value_fn: Callable[[AirGradientClient, str], Awaitable[None]] requires_display: bool = False + requires_led_bar: bool = False CONFIG_CONTROL_ENTITY = AirGradientSelectEntityDescription( @@ -32,9 +44,11 @@ CONFIG_CONTROL_ENTITY = AirGradientSelectEntityDescription( translation_key="configuration_control", options=[ConfigurationControl.CLOUD.value, ConfigurationControl.LOCAL.value], entity_category=EntityCategory.CONFIG, - value_fn=lambda config: config.configuration_control - if config.configuration_control is not ConfigurationControl.NOT_INITIALIZED - else None, + value_fn=lambda config: ( + config.configuration_control + if config.configuration_control is not ConfigurationControl.NOT_INITIALIZED + else None + ), set_value_fn=lambda client, value: client.set_configuration_control( ConfigurationControl(value) ), @@ -52,6 +66,26 @@ PROTECTED_SELECT_TYPES: tuple[AirGradientSelectEntityDescription, ...] = ( ), requires_display=True, ), + AirGradientSelectEntityDescription( + key="display_pm_standard", + translation_key="display_pm_standard", + options=list(PM_STANDARD_REVERSE), + entity_category=EntityCategory.CONFIG, + value_fn=lambda config: PM_STANDARD.get(config.pm_standard), + set_value_fn=lambda client, value: client.set_pm_standard( + PM_STANDARD_REVERSE[value] + ), + requires_display=True, + ), + AirGradientSelectEntityDescription( + key="led_bar_mode", + translation_key="led_bar_mode", + options=[x.value for x in LedBarMode], + entity_category=EntityCategory.CONFIG, + value_fn=lambda config: config.led_bar_mode, + set_value_fn=lambda client, value: client.set_led_bar_mode(LedBarMode(value)), + requires_led_bar=True, + ), ) @@ -74,6 +108,7 @@ async def async_setup_entry( description.requires_display and measurement_coordinator.data.model.startswith("I") ) + or (description.requires_led_bar and "L" in measurement_coordinator.data.model) ) async_add_entities(entities) diff --git a/homeassistant/components/airgradient/strings.json b/homeassistant/components/airgradient/strings.json index a0f6af08132..f4b558cf31a 100644 --- a/homeassistant/components/airgradient/strings.json +++ b/homeassistant/components/airgradient/strings.json @@ -38,6 +38,21 @@ "c": "Celsius", "f": "Fahrenheit" } + }, + "display_pm_standard": { + "name": "Display PM standard", + "state": { + "ugm3": "µg/m³", + "us_aqi": "US AQI" + } + }, + "led_bar_mode": { + "name": "LED bar mode", + "state": { + "off": "Off", + "co2": "Carbon dioxide", + "pm": "Particulate matter" + } } }, "sensor": { diff --git a/tests/components/airgradient/snapshots/test_select.ambr b/tests/components/airgradient/snapshots/test_select.ambr index fb201b88204..d29c7d23923 100644 --- a/tests/components/airgradient/snapshots/test_select.ambr +++ b/tests/components/airgradient/snapshots/test_select.ambr @@ -54,6 +54,61 @@ 'state': 'local', }) # --- +# name: test_all_entities[select.airgradient_display_pm_standard-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'options': list([ + 'ugm3', + 'us_aqi', + ]), + }), + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'select', + 'entity_category': , + 'entity_id': 'select.airgradient_display_pm_standard', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'Display PM standard', + 'platform': 'airgradient', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'display_pm_standard', + 'unique_id': '84fce612f5b8-display_pm_standard', + 'unit_of_measurement': None, + }) +# --- +# name: test_all_entities[select.airgradient_display_pm_standard-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Airgradient Display PM standard', + 'options': list([ + 'ugm3', + 'us_aqi', + ]), + }), + 'context': , + 'entity_id': 'select.airgradient_display_pm_standard', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'ugm3', + }) +# --- # name: test_all_entities[select.airgradient_display_temperature_unit-entry] EntityRegistryEntrySnapshot({ 'aliases': set({ @@ -109,6 +164,63 @@ 'state': 'c', }) # --- +# name: test_all_entities[select.airgradient_led_bar_mode-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'options': list([ + 'off', + 'co2', + 'pm', + ]), + }), + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'select', + 'entity_category': , + 'entity_id': 'select.airgradient_led_bar_mode', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'LED bar mode', + 'platform': 'airgradient', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'led_bar_mode', + 'unique_id': '84fce612f5b8-led_bar_mode', + 'unit_of_measurement': None, + }) +# --- +# name: test_all_entities[select.airgradient_led_bar_mode-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'Airgradient LED bar mode', + 'options': list([ + 'off', + 'co2', + 'pm', + ]), + }), + 'context': , + 'entity_id': 'select.airgradient_led_bar_mode', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'co2', + }) +# --- # name: test_all_entities_outdoor[select.airgradient_configuration_source-entry] EntityRegistryEntrySnapshot({ 'aliases': set({