diff --git a/homeassistant/components/anglian_water/sensor.py b/homeassistant/components/anglian_water/sensor.py index c12dd45212e1..52cd629f8bbb 100644 --- a/homeassistant/components/anglian_water/sensor.py +++ b/homeassistant/components/anglian_water/sensor.py @@ -4,6 +4,7 @@ from __future__ import annotations from collections.abc import Callable from dataclasses import dataclass +from datetime import datetime from enum import StrEnum from pyanglianwater.meter import SmartMeter @@ -32,13 +33,14 @@ class AnglianWaterSensor(StrEnum): YESTERDAY_WATER_COST = "yesterday_water_cost" YESTERDAY_SEWERAGE_COST = "yesterday_sewerage_cost" LATEST_READING = "latest_reading" + LAST_UPDATED = "last_updated" @dataclass(frozen=True, kw_only=True) class AnglianWaterSensorEntityDescription(SensorEntityDescription): """Describes AnglianWater sensor entity.""" - value_fn: Callable[[SmartMeter], float] + value_fn: Callable[[SmartMeter], float | datetime | None] ENTITY_DESCRIPTIONS: tuple[AnglianWaterSensorEntityDescription, ...] = ( @@ -76,6 +78,13 @@ ENTITY_DESCRIPTIONS: tuple[AnglianWaterSensorEntityDescription, ...] = ( translation_key=AnglianWaterSensor.YESTERDAY_SEWERAGE_COST, entity_category=EntityCategory.DIAGNOSTIC, ), + AnglianWaterSensorEntityDescription( + key=AnglianWaterSensor.LAST_UPDATED, + device_class=SensorDeviceClass.TIMESTAMP, + value_fn=lambda entity: entity.last_updated, + translation_key=AnglianWaterSensor.LAST_UPDATED, + entity_category=EntityCategory.DIAGNOSTIC, + ), ) @@ -112,6 +121,6 @@ class AnglianWaterSensorEntity(AnglianWaterEntity, SensorEntity): self.entity_description = description @property - def native_value(self) -> float | None: + def native_value(self) -> float | datetime | None: """Return the state of the sensor.""" return self.entity_description.value_fn(self.smart_meter) diff --git a/homeassistant/components/anglian_water/strings.json b/homeassistant/components/anglian_water/strings.json index 6db91b3b9b02..ae6895b98c88 100644 --- a/homeassistant/components/anglian_water/strings.json +++ b/homeassistant/components/anglian_water/strings.json @@ -34,6 +34,9 @@ }, "entity": { "sensor": { + "last_updated": { + "name": "Last meter reading processed" + }, "latest_reading": { "name": "Latest reading" }, diff --git a/tests/components/anglian_water/conftest.py b/tests/components/anglian_water/conftest.py index a5106f47791d..a482a7894555 100644 --- a/tests/components/anglian_water/conftest.py +++ b/tests/components/anglian_water/conftest.py @@ -3,6 +3,7 @@ from collections.abc import AsyncGenerator, Generator from unittest.mock import AsyncMock, MagicMock, patch +from freezegun.api import FrozenDateTimeFactory from pyanglianwater.api import API from pyanglianwater.meter import SmartMeter import pytest @@ -32,20 +33,20 @@ def mock_config_entry() -> MockConfigEntry: @pytest.fixture -def mock_smart_meter() -> SmartMeter: - """Return a mocked Smart Meter.""" - mock = AsyncMock(spec=SmartMeter) - mock.serial_number = "TESTSN" - mock.get_yesterday_consumption = 50 - mock.latest_read = 50 - mock.yesterday_water_cost = 0.5 - mock.yesterday_sewerage_cost = 0.5 - mock.readings = [ +def mock_smart_meter(freezer: FrozenDateTimeFactory) -> SmartMeter: + """Return a Smart Meter for testing.""" + # Freeze time to June 2, 2024 so "yesterday" is June 1, matching our test readings + freezer.move_to("2024-06-02T00:00:00Z") + + meter = SmartMeter("TESTSN") + meter.readings = [ {"read_at": "2024-06-01T12:00:00Z", "consumption": 10, "read": 10}, {"read_at": "2024-06-01T13:00:00Z", "consumption": 15, "read": 25}, {"read_at": "2024-06-01T14:00:00Z", "consumption": 25, "read": 50}, ] - return mock + meter.yesterday_water_cost = 0.5 + meter.yesterday_sewerage_cost = 0.5 + return meter @pytest.fixture diff --git a/tests/components/anglian_water/snapshots/test_sensor.ambr b/tests/components/anglian_water/snapshots/test_sensor.ambr index 377509fb2e67..d75d7dd16785 100644 --- a/tests/components/anglian_water/snapshots/test_sensor.ambr +++ b/tests/components/anglian_water/snapshots/test_sensor.ambr @@ -1,4 +1,54 @@ # serializer version: 1 +# name: test_sensor[sensor.testsn_last_meter_reading_processed-entry] + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'sensor', + 'entity_category': , + 'entity_id': 'sensor.testsn_last_meter_reading_processed', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Last meter reading processed', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Last meter reading processed', + 'platform': 'anglian_water', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': , + 'unique_id': 'TESTSN_last_updated', + 'unit_of_measurement': None, + }) +# --- +# name: test_sensor[sensor.testsn_last_meter_reading_processed-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + 'device_class': 'timestamp', + 'friendly_name': 'TESTSN Last meter reading processed', + }), + 'context': , + 'entity_id': 'sensor.testsn_last_meter_reading_processed', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': '2024-06-01T14:00:00+00:00', + }) +# --- # name: test_sensor[sensor.testsn_latest_reading-entry] EntityRegistryEntrySnapshot({ 'aliases': set({ @@ -53,7 +103,7 @@ 'last_changed': , 'last_reported': , 'last_updated': , - 'state': '50', + 'state': '50.0', }) # --- # name: test_sensor[sensor.testsn_yesterday_s_sewerage_cost-entry] @@ -161,7 +211,7 @@ 'last_changed': , 'last_reported': , 'last_updated': , - 'state': '50', + 'state': '50.0', }) # --- # name: test_sensor[sensor.testsn_yesterday_s_water_cost-entry]