From 5ae8b6bc02581fd70dc7fe8069260a64f9c5d2e9 Mon Sep 17 00:00:00 2001 From: Joost Lekkerkerker Date: Thu, 4 Jan 2024 11:53:04 +0100 Subject: [PATCH] Add entity descriptions to Streamlabs water (#107071) * Add sensor tests to Streamlabs water * Add sensor tests to Streamlabs water * Use entity descriptions in streamlabs water * Use entity descriptions in streamlabs water * Use entity descriptions in streamlabs water * Add translations --- .../components/streamlabswater/sensor.py | 124 +++++++++--------- .../components/streamlabswater/strings.json | 13 ++ .../snapshots/test_sensor.ambr | 48 +++---- 3 files changed, 100 insertions(+), 85 deletions(-) diff --git a/homeassistant/components/streamlabswater/sensor.py b/homeassistant/components/streamlabswater/sensor.py index 6f17c23b4f5..e49668208af 100644 --- a/homeassistant/components/streamlabswater/sensor.py +++ b/homeassistant/components/streamlabswater/sensor.py @@ -1,20 +1,57 @@ """Support for Streamlabs Water Monitor Usage.""" from __future__ import annotations -from homeassistant.components.sensor import SensorDeviceClass, SensorEntity +from collections.abc import Callable +from dataclasses import dataclass + +from homeassistant.components.sensor import ( + SensorDeviceClass, + SensorEntity, + SensorEntityDescription, +) from homeassistant.config_entries import ConfigEntry from homeassistant.const import UnitOfVolume from homeassistant.core import HomeAssistant +from homeassistant.helpers.device_registry import DeviceInfo from homeassistant.helpers.entity_platform import AddEntitiesCallback +from homeassistant.helpers.typing import StateType from homeassistant.helpers.update_coordinator import CoordinatorEntity from . import StreamlabsCoordinator from .const import DOMAIN from .coordinator import StreamlabsData -NAME_DAILY_USAGE = "Daily Water" -NAME_MONTHLY_USAGE = "Monthly Water" -NAME_YEARLY_USAGE = "Yearly Water" + +@dataclass(frozen=True, kw_only=True) +class StreamlabsWaterSensorEntityDescription(SensorEntityDescription): + """Streamlabs sensor entity description.""" + + value_fn: Callable[[StreamlabsData], StateType] + + +SENSORS: tuple[StreamlabsWaterSensorEntityDescription, ...] = ( + StreamlabsWaterSensorEntityDescription( + key="daily_usage", + translation_key="daily_usage", + native_unit_of_measurement=UnitOfVolume.GALLONS, + device_class=SensorDeviceClass.WATER, + value_fn=lambda data: data.daily_usage, + ), + StreamlabsWaterSensorEntityDescription( + key="monthly_usage", + translation_key="monthly_usage", + native_unit_of_measurement=UnitOfVolume.GALLONS, + device_class=SensorDeviceClass.WATER, + value_fn=lambda data: data.monthly_usage, + ), + StreamlabsWaterSensorEntityDescription( + key="yearly_usage", + translation_key="yearly_usage", + native_unit_of_measurement=UnitOfVolume.GALLONS, + device_class=SensorDeviceClass.WATER, + value_fn=lambda data: data.yearly_usage, + ), +) async def async_setup_entry( @@ -25,32 +62,34 @@ async def async_setup_entry( """Set up Streamlabs water sensor from a config entry.""" coordinator = hass.data[DOMAIN][entry.entry_id] - entities = [] - - for location_id in coordinator.data: - entities.extend( - [ - StreamLabsDailyUsage(coordinator, location_id), - StreamLabsMonthlyUsage(coordinator, location_id), - StreamLabsYearlyUsage(coordinator, location_id), - ] - ) - - async_add_entities(entities) + async_add_entities( + StreamLabsSensor(coordinator, location_id, entity_description) + for location_id in coordinator.data + for entity_description in SENSORS + ) -class StreamLabsDailyUsage(CoordinatorEntity[StreamlabsCoordinator], SensorEntity): +class StreamLabsSensor(CoordinatorEntity[StreamlabsCoordinator], SensorEntity): """Monitors the daily water usage.""" - _attr_device_class = SensorDeviceClass.WATER - _attr_native_unit_of_measurement = UnitOfVolume.GALLONS - _key = "daily_usage" + _attr_has_entity_name = True - def __init__(self, coordinator: StreamlabsCoordinator, location_id: str) -> None: + entity_description: StreamlabsWaterSensorEntityDescription + + def __init__( + self, + coordinator: StreamlabsCoordinator, + location_id: str, + entity_description: StreamlabsWaterSensorEntityDescription, + ) -> None: """Initialize the daily water usage device.""" super().__init__(coordinator) self._location_id = location_id - self._attr_unique_id = f"{location_id}-{self._key}" + self._attr_unique_id = f"{location_id}-{entity_description.key}" + self.entity_description = entity_description + self._attr_device_info = DeviceInfo( + identifiers={(DOMAIN, location_id)}, name=self.location_data.name + ) @property def location_data(self) -> StreamlabsData: @@ -58,43 +97,6 @@ class StreamLabsDailyUsage(CoordinatorEntity[StreamlabsCoordinator], SensorEntit return self.coordinator.data[self._location_id] @property - def name(self) -> str: - """Return the name for daily usage.""" - return f"{self.location_data.name} {NAME_DAILY_USAGE}" - - @property - def native_value(self) -> float: + def native_value(self) -> StateType: """Return the current daily usage.""" - return self.location_data.daily_usage - - -class StreamLabsMonthlyUsage(StreamLabsDailyUsage): - """Monitors the monthly water usage.""" - - _key = "monthly_usage" - - @property - def name(self) -> str: - """Return the name for monthly usage.""" - return f"{self.location_data.name} {NAME_MONTHLY_USAGE}" - - @property - def native_value(self) -> float: - """Return the current monthly usage.""" - return self.location_data.monthly_usage - - -class StreamLabsYearlyUsage(StreamLabsDailyUsage): - """Monitors the yearly water usage.""" - - _key = "yearly_usage" - - @property - def name(self) -> str: - """Return the name for yearly usage.""" - return f"{self.location_data.name} {NAME_YEARLY_USAGE}" - - @property - def native_value(self) -> float: - """Return the current yearly usage.""" - return self.location_data.yearly_usage + return self.entity_description.value_fn(self.location_data) diff --git a/homeassistant/components/streamlabswater/strings.json b/homeassistant/components/streamlabswater/strings.json index e6b5dd7465b..393c2119501 100644 --- a/homeassistant/components/streamlabswater/strings.json +++ b/homeassistant/components/streamlabswater/strings.json @@ -31,6 +31,19 @@ } } }, + "entity": { + "sensor": { + "daily_usage": { + "name": "Daily usage" + }, + "monthly_usage": { + "name": "Monthly usage" + }, + "yearly_usage": { + "name": "Yearly usage" + } + } + }, "issues": { "deprecated_yaml_import_issue_cannot_connect": { "title": "The Streamlabs water YAML configuration import failed", diff --git a/tests/components/streamlabswater/snapshots/test_sensor.ambr b/tests/components/streamlabswater/snapshots/test_sensor.ambr index 9a4c1cdc97e..5cd2479903a 100644 --- a/tests/components/streamlabswater/snapshots/test_sensor.ambr +++ b/tests/components/streamlabswater/snapshots/test_sensor.ambr @@ -1,5 +1,5 @@ # serializer version: 1 -# name: test_all_entities[sensor.water_monitor_daily_water-entry] +# name: test_all_entities[sensor.water_monitor_daily_usage-entry] EntityRegistryEntrySnapshot({ 'aliases': set({ }), @@ -11,8 +11,8 @@ 'disabled_by': None, 'domain': 'sensor', 'entity_category': None, - 'entity_id': 'sensor.water_monitor_daily_water', - 'has_entity_name': False, + 'entity_id': 'sensor.water_monitor_daily_usage', + 'has_entity_name': True, 'hidden_by': None, 'icon': None, 'id': , @@ -21,30 +21,30 @@ }), 'original_device_class': , 'original_icon': None, - 'original_name': 'Water Monitor Daily Water', + 'original_name': 'Daily usage', 'platform': 'streamlabswater', 'previous_unique_id': None, 'supported_features': 0, - 'translation_key': None, + 'translation_key': 'daily_usage', 'unique_id': '945e7c52-854a-41e1-8524-50c6993277e1-daily_usage', 'unit_of_measurement': , }) # --- -# name: test_all_entities[sensor.water_monitor_daily_water-state] +# name: test_all_entities[sensor.water_monitor_daily_usage-state] StateSnapshot({ 'attributes': ReadOnlyDict({ 'device_class': 'water', - 'friendly_name': 'Water Monitor Daily Water', + 'friendly_name': 'Water Monitor Daily usage', 'unit_of_measurement': , }), 'context': , - 'entity_id': 'sensor.water_monitor_daily_water', + 'entity_id': 'sensor.water_monitor_daily_usage', 'last_changed': , 'last_updated': , 'state': '200.4', }) # --- -# name: test_all_entities[sensor.water_monitor_monthly_water-entry] +# name: test_all_entities[sensor.water_monitor_monthly_usage-entry] EntityRegistryEntrySnapshot({ 'aliases': set({ }), @@ -56,8 +56,8 @@ 'disabled_by': None, 'domain': 'sensor', 'entity_category': None, - 'entity_id': 'sensor.water_monitor_monthly_water', - 'has_entity_name': False, + 'entity_id': 'sensor.water_monitor_monthly_usage', + 'has_entity_name': True, 'hidden_by': None, 'icon': None, 'id': , @@ -66,30 +66,30 @@ }), 'original_device_class': , 'original_icon': None, - 'original_name': 'Water Monitor Monthly Water', + 'original_name': 'Monthly usage', 'platform': 'streamlabswater', 'previous_unique_id': None, 'supported_features': 0, - 'translation_key': None, + 'translation_key': 'monthly_usage', 'unique_id': '945e7c52-854a-41e1-8524-50c6993277e1-monthly_usage', 'unit_of_measurement': , }) # --- -# name: test_all_entities[sensor.water_monitor_monthly_water-state] +# name: test_all_entities[sensor.water_monitor_monthly_usage-state] StateSnapshot({ 'attributes': ReadOnlyDict({ 'device_class': 'water', - 'friendly_name': 'Water Monitor Monthly Water', + 'friendly_name': 'Water Monitor Monthly usage', 'unit_of_measurement': , }), 'context': , - 'entity_id': 'sensor.water_monitor_monthly_water', + 'entity_id': 'sensor.water_monitor_monthly_usage', 'last_changed': , 'last_updated': , 'state': '420.5', }) # --- -# name: test_all_entities[sensor.water_monitor_yearly_water-entry] +# name: test_all_entities[sensor.water_monitor_yearly_usage-entry] EntityRegistryEntrySnapshot({ 'aliases': set({ }), @@ -101,8 +101,8 @@ 'disabled_by': None, 'domain': 'sensor', 'entity_category': None, - 'entity_id': 'sensor.water_monitor_yearly_water', - 'has_entity_name': False, + 'entity_id': 'sensor.water_monitor_yearly_usage', + 'has_entity_name': True, 'hidden_by': None, 'icon': None, 'id': , @@ -111,24 +111,24 @@ }), 'original_device_class': , 'original_icon': None, - 'original_name': 'Water Monitor Yearly Water', + 'original_name': 'Yearly usage', 'platform': 'streamlabswater', 'previous_unique_id': None, 'supported_features': 0, - 'translation_key': None, + 'translation_key': 'yearly_usage', 'unique_id': '945e7c52-854a-41e1-8524-50c6993277e1-yearly_usage', 'unit_of_measurement': , }) # --- -# name: test_all_entities[sensor.water_monitor_yearly_water-state] +# name: test_all_entities[sensor.water_monitor_yearly_usage-state] StateSnapshot({ 'attributes': ReadOnlyDict({ 'device_class': 'water', - 'friendly_name': 'Water Monitor Yearly Water', + 'friendly_name': 'Water Monitor Yearly usage', 'unit_of_measurement': , }), 'context': , - 'entity_id': 'sensor.water_monitor_yearly_water', + 'entity_id': 'sensor.water_monitor_yearly_usage', 'last_changed': , 'last_updated': , 'state': '65432.4',