diff --git a/homeassistant/components/aosmith/__init__.py b/homeassistant/components/aosmith/__init__.py index af780e012ae..cac746e189e 100644 --- a/homeassistant/components/aosmith/__init__.py +++ b/homeassistant/components/aosmith/__init__.py @@ -13,7 +13,7 @@ from homeassistant.helpers import aiohttp_client from .const import DOMAIN from .coordinator import AOSmithCoordinator -PLATFORMS: list[Platform] = [Platform.WATER_HEATER] +PLATFORMS: list[Platform] = [Platform.SENSOR, Platform.WATER_HEATER] @dataclass diff --git a/homeassistant/components/aosmith/const.py b/homeassistant/components/aosmith/const.py index 06794582258..e79b993182e 100644 --- a/homeassistant/components/aosmith/const.py +++ b/homeassistant/components/aosmith/const.py @@ -14,3 +14,9 @@ REGULAR_INTERVAL = timedelta(seconds=30) # Update interval to be used while a mode or setpoint change is in progress. FAST_INTERVAL = timedelta(seconds=1) + +HOT_WATER_STATUS_MAP = { + "LOW": "low", + "MEDIUM": "medium", + "HIGH": "high", +} diff --git a/homeassistant/components/aosmith/sensor.py b/homeassistant/components/aosmith/sensor.py new file mode 100644 index 00000000000..c9bd9f1321e --- /dev/null +++ b/homeassistant/components/aosmith/sensor.py @@ -0,0 +1,75 @@ +"""The sensor platform for the A. O. Smith integration.""" + +from collections.abc import Callable +from dataclasses import dataclass +from typing import Any + +from homeassistant.components.sensor import ( + SensorDeviceClass, + SensorEntity, + SensorEntityDescription, +) +from homeassistant.config_entries import ConfigEntry +from homeassistant.core import HomeAssistant +from homeassistant.helpers.entity_platform import AddEntitiesCallback + +from . import AOSmithData +from .const import DOMAIN, HOT_WATER_STATUS_MAP +from .coordinator import AOSmithCoordinator +from .entity import AOSmithEntity + + +@dataclass(kw_only=True) +class AOSmithSensorEntityDescription(SensorEntityDescription): + """Define sensor entity description class.""" + + value_fn: Callable[[dict[str, Any]], str | int | None] + + +ENTITY_DESCRIPTIONS: tuple[AOSmithSensorEntityDescription, ...] = ( + AOSmithSensorEntityDescription( + key="hot_water_availability", + translation_key="hot_water_availability", + icon="mdi:water-thermometer", + device_class=SensorDeviceClass.ENUM, + options=["low", "medium", "high"], + value_fn=lambda device: HOT_WATER_STATUS_MAP.get( + device.get("data", {}).get("hotWaterStatus") + ), + ), +) + + +async def async_setup_entry( + hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback +) -> None: + """Set up A. O. Smith sensor platform.""" + data: AOSmithData = hass.data[DOMAIN][entry.entry_id] + + async_add_entities( + AOSmithSensorEntity(data.coordinator, description, junction_id) + for description in ENTITY_DESCRIPTIONS + for junction_id in data.coordinator.data + ) + + +class AOSmithSensorEntity(AOSmithEntity, SensorEntity): + """The sensor entity for the A. O. Smith integration.""" + + entity_description: AOSmithSensorEntityDescription + + def __init__( + self, + coordinator: AOSmithCoordinator, + description: AOSmithSensorEntityDescription, + junction_id: str, + ) -> None: + """Initialize the entity.""" + super().__init__(coordinator, junction_id) + self.entity_description = description + self._attr_unique_id = f"{description.key}_{junction_id}" + + @property + def native_value(self) -> str | int | None: + """Return the state of the sensor.""" + return self.entity_description.value_fn(self.device) diff --git a/homeassistant/components/aosmith/strings.json b/homeassistant/components/aosmith/strings.json index 26de264bab9..0f1fcfc1744 100644 --- a/homeassistant/components/aosmith/strings.json +++ b/homeassistant/components/aosmith/strings.json @@ -24,5 +24,17 @@ "already_configured": "[%key:common::config_flow::abort::already_configured_account%]", "reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]" } + }, + "entity": { + "sensor": { + "hot_water_availability": { + "name": "Hot water availability", + "state": { + "low": "Low", + "medium": "Medium", + "high": "High" + } + } + } } } diff --git a/tests/components/aosmith/snapshots/test_sensor.ambr b/tests/components/aosmith/snapshots/test_sensor.ambr new file mode 100644 index 00000000000..8499a98c8e5 --- /dev/null +++ b/tests/components/aosmith/snapshots/test_sensor.ambr @@ -0,0 +1,20 @@ +# serializer version: 1 +# name: test_state + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'enum', + 'friendly_name': 'My water heater Hot water availability', + 'icon': 'mdi:water-thermometer', + 'options': list([ + 'low', + 'medium', + 'high', + ]), + }), + 'context': , + 'entity_id': 'sensor.my_water_heater_hot_water_availability', + 'last_changed': , + 'last_updated': , + 'state': 'low', + }) +# --- diff --git a/tests/components/aosmith/test_sensor.py b/tests/components/aosmith/test_sensor.py new file mode 100644 index 00000000000..99626b09e83 --- /dev/null +++ b/tests/components/aosmith/test_sensor.py @@ -0,0 +1,27 @@ +"""Tests for the sensor platform of the A. O. Smith integration.""" + +from syrupy.assertion import SnapshotAssertion + +from homeassistant.core import HomeAssistant +from homeassistant.helpers import entity_registry as er + +from tests.common import MockConfigEntry + + +async def test_setup( + hass: HomeAssistant, + entity_registry: er.EntityRegistry, + init_integration: MockConfigEntry, +) -> None: + """Test the setup of the sensor entity.""" + entry = entity_registry.async_get("sensor.my_water_heater_hot_water_availability") + assert entry + assert entry.unique_id == "hot_water_availability_junctionId" + + +async def test_state( + hass: HomeAssistant, init_integration: MockConfigEntry, snapshot: SnapshotAssertion +) -> None: + """Test the state of the sensor entity.""" + state = hass.states.get("sensor.my_water_heater_hot_water_availability") + assert state == snapshot