diff --git a/homeassistant/components/deconz/select.py b/homeassistant/components/deconz/select.py index dad3ba9d78d..7f3f8cca060 100644 --- a/homeassistant/components/deconz/select.py +++ b/homeassistant/components/deconz/select.py @@ -3,6 +3,7 @@ from __future__ import annotations from pydeconz.models.event import EventType +from pydeconz.models.sensor.air_purifier import AirPurifier, AirPurifierFanMode from pydeconz.models.sensor.presence import ( Presence, PresenceConfigDeviceMode, @@ -36,6 +37,17 @@ async def async_setup_entry( hub = DeconzHub.get_hub(hass, config_entry) hub.entities[DOMAIN] = set() + @callback + def async_add_air_purifier_sensor(_: EventType, sensor_id: str) -> None: + """Add air purifier select entity from deCONZ.""" + sensor = hub.api.sensors.air_purifier[sensor_id] + async_add_entities([DeconzAirPurifierFanMode(sensor, hub)]) + + hub.register_platform_add_device_callback( + async_add_air_purifier_sensor, + hub.api.sensors.air_purifier, + ) + @callback def async_add_presence_sensor(_: EventType, sensor_id: str) -> None: """Add presence select entity from deCONZ.""" @@ -55,6 +67,39 @@ async def async_setup_entry( ) +class DeconzAirPurifierFanMode(DeconzDevice[AirPurifier], SelectEntity): + """Representation of a deCONZ air purifier fan mode entity.""" + + _name_suffix = "Fan Mode" + unique_id_suffix = "fan_mode" + _update_key = "mode" + + _attr_entity_category = EntityCategory.CONFIG + _attr_options = [ + AirPurifierFanMode.OFF.value, + AirPurifierFanMode.AUTO.value, + AirPurifierFanMode.SPEED_1.value, + AirPurifierFanMode.SPEED_2.value, + AirPurifierFanMode.SPEED_3.value, + AirPurifierFanMode.SPEED_4.value, + AirPurifierFanMode.SPEED_5.value, + ] + + TYPE = DOMAIN + + @property + def current_option(self) -> str: + """Return the selected entity option to represent the entity state.""" + return self._device.fan_mode.value + + async def async_select_option(self, option: str) -> None: + """Change the selected option.""" + await self.hub.api.sensors.air_purifier.set_config( + id=self._device.resource_id, + fan_mode=AirPurifierFanMode(option), + ) + + class DeconzPresenceDeviceModeSelect(DeconzDevice[Presence], SelectEntity): """Representation of a deCONZ presence device mode entity.""" diff --git a/tests/components/deconz/snapshots/test_select.ambr b/tests/components/deconz/snapshots/test_select.ambr index 12966709947..997eab0901f 100644 --- a/tests/components/deconz/snapshots/test_select.ambr +++ b/tests/components/deconz/snapshots/test_select.ambr @@ -506,3 +506,68 @@ 'state': 'medium', }) # --- +# name: test_select[sensor_payload3-expected3][select.ikea_starkvind_fan_mode-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'options': list([ + 'off', + 'auto', + 'speed_1', + 'speed_2', + 'speed_3', + 'speed_4', + 'speed_5', + ]), + }), + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'select', + 'entity_category': , + 'entity_id': 'select.ikea_starkvind_fan_mode', + 'has_entity_name': False, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': None, + 'original_icon': None, + 'original_name': 'IKEA Starkvind Fan Mode', + 'platform': 'deconz', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': None, + 'unique_id': '0c:43:14:ff:fe:6c:20:12-01-fc7d-fan_mode', + 'unit_of_measurement': None, + }) +# --- +# name: test_select[sensor_payload3-expected3][select.ikea_starkvind_fan_mode-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'friendly_name': 'IKEA Starkvind Fan Mode', + 'options': list([ + 'off', + 'auto', + 'speed_1', + 'speed_2', + 'speed_3', + 'speed_4', + 'speed_5', + ]), + }), + 'context': , + 'entity_id': 'select.ikea_starkvind_fan_mode', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'speed_1', + }) +# --- diff --git a/tests/components/deconz/test_select.py b/tests/components/deconz/test_select.py index 900283d88bb..c677853841c 100644 --- a/tests/components/deconz/test_select.py +++ b/tests/components/deconz/test_select.py @@ -4,6 +4,7 @@ from collections.abc import Callable from typing import Any from unittest.mock import patch +from pydeconz.models.sensor.air_purifier import AirPurifierFanMode from pydeconz.models.sensor.presence import ( PresenceConfigDeviceMode, PresenceConfigTriggerDistance, @@ -119,6 +120,42 @@ TEST_DATA = [ "request_data": {"triggerdistance": "far"}, }, ), + ( # Air Purifier Fan Mode + { + "config": { + "filterlifetime": 259200, + "ledindication": True, + "locked": False, + "mode": "speed_1", + "on": True, + "reachable": True, + }, + "ep": 1, + "etag": "de26d19d9e91b2db3ded6ee7ab6b6a4b", + "lastannounced": None, + "lastseen": "2024-08-07T18:27Z", + "manufacturername": "IKEA of Sweden", + "modelid": "STARKVIND Air purifier", + "name": "IKEA Starkvind", + "productid": "E2007", + "state": { + "deviceruntime": 73405, + "filterruntime": 73405, + "lastupdated": "2024-08-07T18:27:52.543", + "replacefilter": False, + "speed": 20, + }, + "swversion": "1.1.001", + "type": "ZHAAirPurifier", + "uniqueid": "0c:43:14:ff:fe:6c:20:12-01-fc7d", + }, + { + "entity_id": "select.ikea_starkvind_fan_mode", + "option": AirPurifierFanMode.AUTO.value, + "request": "/sensors/0/config", + "request_data": {"mode": "auto"}, + }, + ), ]