diff --git a/homeassistant/components/husqvarna_automower/sensor.py b/homeassistant/components/husqvarna_automower/sensor.py index 4cc3bcf5e57..146ef17a6e4 100644 --- a/homeassistant/components/husqvarna_automower/sensor.py +++ b/homeassistant/components/husqvarna_automower/sensor.py @@ -4,6 +4,7 @@ from collections.abc import Callable from dataclasses import dataclass from datetime import datetime import logging +from typing import TYPE_CHECKING from aioautomower.model import MowerAttributes, MowerModes, RestrictedReasons @@ -14,7 +15,7 @@ from homeassistant.components.sensor import ( SensorStateClass, ) from homeassistant.const import PERCENTAGE, EntityCategory, UnitOfLength, UnitOfTime -from homeassistant.core import HomeAssistant +from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.typing import StateType @@ -184,11 +185,31 @@ RESTRICTED_REASONS: list = [ ] +@callback +def _get_work_area_names(data: MowerAttributes) -> list[str]: + """Return a list with all work area names.""" + if TYPE_CHECKING: + # Sensor does not get created if it is None + assert data.work_areas is not None + return [data.work_areas[work_area_id].name for work_area_id in data.work_areas] + + +@callback +def _get_current_work_area_name(data: MowerAttributes) -> str: + """Return the name of the current work area.""" + if TYPE_CHECKING: + # Sensor does not get created if values are None + assert data.work_areas is not None + assert data.mower.work_area_id is not None + return data.work_areas[data.mower.work_area_id].name + + @dataclass(frozen=True, kw_only=True) class AutomowerSensorEntityDescription(SensorEntityDescription): """Describes Automower sensor entity.""" exists_fn: Callable[[MowerAttributes], bool] = lambda _: True + option_fn: Callable[[MowerAttributes], list[str] | None] = lambda _: None value_fn: Callable[[MowerAttributes], StateType | datetime] @@ -204,7 +225,7 @@ SENSOR_TYPES: tuple[AutomowerSensorEntityDescription, ...] = ( key="mode", translation_key="mode", device_class=SensorDeviceClass.ENUM, - options=[option.lower() for option in list(MowerModes)], + option_fn=lambda data: [option.lower() for option in list(MowerModes)], value_fn=( lambda data: data.mower.mode.lower() if data.mower.mode != MowerModes.UNKNOWN @@ -302,18 +323,26 @@ SENSOR_TYPES: tuple[AutomowerSensorEntityDescription, ...] = ( key="error", translation_key="error", device_class=SensorDeviceClass.ENUM, + option_fn=lambda data: ERROR_KEY_LIST, value_fn=lambda data: ( "no_error" if data.mower.error_key is None else data.mower.error_key ), - options=ERROR_KEY_LIST, ), AutomowerSensorEntityDescription( key="restricted_reason", translation_key="restricted_reason", device_class=SensorDeviceClass.ENUM, - options=RESTRICTED_REASONS, + option_fn=lambda data: RESTRICTED_REASONS, value_fn=lambda data: data.planner.restricted_reason.lower(), ), + AutomowerSensorEntityDescription( + key="work_area", + translation_key="work_area", + device_class=SensorDeviceClass.ENUM, + exists_fn=lambda data: data.capabilities.work_areas, + option_fn=_get_work_area_names, + value_fn=_get_current_work_area_name, + ), ) @@ -352,3 +381,8 @@ class AutomowerSensorEntity(AutomowerBaseEntity, SensorEntity): def native_value(self) -> StateType | datetime: """Return the state of the sensor.""" return self.entity_description.value_fn(self.mower_attributes) + + @property + def options(self) -> list[str] | None: + """Return the option of the sensor.""" + return self.entity_description.option_fn(self.mower_attributes) diff --git a/homeassistant/components/husqvarna_automower/strings.json b/homeassistant/components/husqvarna_automower/strings.json index bd2ffe6b012..c94a8d0f6d1 100644 --- a/homeassistant/components/husqvarna_automower/strings.json +++ b/homeassistant/components/husqvarna_automower/strings.json @@ -243,6 +243,12 @@ "home": "Home", "demo": "Demo" } + }, + "work_area": { + "name": "Work area", + "state": { + "my_lawn": "My lawn" + } } }, "switch": { diff --git a/tests/components/husqvarna_automower/snapshots/test_sensor.ambr b/tests/components/husqvarna_automower/snapshots/test_sensor.ambr index c43a7d4841a..6cb74ab8814 100644 --- a/tests/components/husqvarna_automower/snapshots/test_sensor.ambr +++ b/tests/components/husqvarna_automower/snapshots/test_sensor.ambr @@ -991,3 +991,61 @@ 'state': '103.000', }) # --- +# name: test_sensor_snapshot[sensor.test_mower_1_work_area-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'options': list([ + 'Front lawn', + 'Back lawn', + 'my_lawn', + ]), + }), + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': None, + 'entity_id': 'sensor.test_mower_1_work_area', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Work area', + 'platform': 'husqvarna_automower', + 'previous_unique_id': None, + 'supported_features': 0, + 'translation_key': 'work_area', + 'unique_id': 'c7233734-b219-4287-a173-08e3643f89f0_work_area', + 'unit_of_measurement': None, + }) +# --- +# name: test_sensor_snapshot[sensor.test_mower_1_work_area-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'enum', + 'friendly_name': 'Test Mower 1 Work area', + 'options': list([ + 'Front lawn', + 'Back lawn', + 'my_lawn', + ]), + }), + 'context': , + 'entity_id': 'sensor.test_mower_1_work_area', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'Front lawn', + }) +# ---