From 3083f059cc4e6f989b978b1222e5edd08e8199a0 Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Tue, 11 Jan 2022 13:58:35 +0100 Subject: [PATCH] Drop last_reset attribute for non 'total' sensors (#63880) * Drop last_reset attribute for non 'total' sensors * Adjust MQTT tests * Add exception for utility_meter * Rewrite exception for utility_meter * Add comment in utility_meter * Tweak comment --- homeassistant/components/sensor/__init__.py | 8 +++++--- .../components/utility_meter/sensor.py | 13 ++++++++----- tests/components/mqtt/test_sensor.py | 5 +++++ tests/components/sensor/test_init.py | 19 ++++++++++++------- 4 files changed, 30 insertions(+), 15 deletions(-) diff --git a/homeassistant/components/sensor/__init__.py b/homeassistant/components/sensor/__init__.py index 3bbbe221fcf..2b879c30a16 100644 --- a/homeassistant/components/sensor/__init__.py +++ b/homeassistant/components/sensor/__init__.py @@ -308,15 +308,16 @@ class SensorEntity(Entity): """Return state attributes.""" if last_reset := self.last_reset: if ( - self.state_class == SensorStateClass.MEASUREMENT + self.state_class != SensorStateClass.TOTAL and not self._last_reset_reported ): self._last_reset_reported = True report_issue = self._suggest_report_issue() + # This should raise in Home Assistant Core 2022.5 _LOGGER.warning( "Entity %s (%s) with state_class %s has set last_reset. Setting " "last_reset for entities with state_class other than 'total' is " - "deprecated and will be removed from Home Assistant Core 2021.11. " + "not supported. " "Please update your configuration if state_class is manually " "configured, otherwise %s", self.entity_id, @@ -325,7 +326,8 @@ class SensorEntity(Entity): report_issue, ) - return {ATTR_LAST_RESET: last_reset.isoformat()} + if self.state_class == SensorStateClass.TOTAL: + return {ATTR_LAST_RESET: last_reset.isoformat()} return None diff --git a/homeassistant/components/utility_meter/sensor.py b/homeassistant/components/utility_meter/sensor.py index fd2d5b90a15..b8bc452028f 100644 --- a/homeassistant/components/utility_meter/sensor.py +++ b/homeassistant/components/utility_meter/sensor.py @@ -398,14 +398,17 @@ class UtilityMeterSensor(RestoreEntity, SensorEntity): state_attr[ATTR_CRON_PATTERN] = self._cron_pattern if self._tariff is not None: state_attr[ATTR_TARIFF] = self._tariff + # last_reset in utility meter was used before last_reset was added for long term + # statistics in base sensor. base sensor only supports last reset + # sensors with state_class set to total. + # To avoid a breaking change we set last_reset directly + # in extra state attributes. + if last_reset := self._last_reset: + state_attr[ATTR_LAST_RESET] = last_reset.isoformat() + return state_attr @property def icon(self): """Return the icon to use in the frontend, if any.""" return ICON - - @property - def last_reset(self): - """Return the time when the sensor was last reset.""" - return self._last_reset diff --git a/tests/components/mqtt/test_sensor.py b/tests/components/mqtt/test_sensor.py index f3541e8d501..a511938f0d1 100644 --- a/tests/components/mqtt/test_sensor.py +++ b/tests/components/mqtt/test_sensor.py @@ -272,6 +272,7 @@ async def test_setting_sensor_last_reset_via_mqtt_message(hass, mqtt_mock, caplo sensor.DOMAIN: { "platform": "mqtt", "name": "test", + "state_class": "total", "state_topic": "test-topic", "unit_of_measurement": "fav unit", "last_reset_topic": "last-reset-topic", @@ -302,6 +303,7 @@ async def test_setting_sensor_bad_last_reset_via_mqtt_message( sensor.DOMAIN: { "platform": "mqtt", "name": "test", + "state_class": "total", "state_topic": "test-topic", "unit_of_measurement": "fav unit", "last_reset_topic": "last-reset-topic", @@ -327,6 +329,7 @@ async def test_setting_sensor_empty_last_reset_via_mqtt_message( sensor.DOMAIN: { "platform": "mqtt", "name": "test", + "state_class": "total", "state_topic": "test-topic", "unit_of_measurement": "fav unit", "last_reset_topic": "last-reset-topic", @@ -350,6 +353,7 @@ async def test_setting_sensor_last_reset_via_mqtt_json_message(hass, mqtt_mock): sensor.DOMAIN: { "platform": "mqtt", "name": "test", + "state_class": "total", "state_topic": "test-topic", "unit_of_measurement": "fav unit", "last_reset_topic": "last-reset-topic", @@ -379,6 +383,7 @@ async def test_setting_sensor_last_reset_via_mqtt_json_message_2( **{ "platform": "mqtt", "name": "test", + "state_class": "total", "state_topic": "test-topic", "unit_of_measurement": "kWh", "value_template": "{{ value_json.value | float / 60000 }}", diff --git a/tests/components/sensor/test_init.py b/tests/components/sensor/test_init.py index 919736fb59e..b49d8894932 100644 --- a/tests/components/sensor/test_init.py +++ b/tests/components/sensor/test_init.py @@ -81,12 +81,15 @@ async def test_deprecated_temperature_conversion( ) in caplog.text -async def test_deprecated_last_reset(hass, caplog, enable_custom_integrations): +@pytest.mark.parametrize("state_class", ("measurement", "total_increasing")) +async def test_deprecated_last_reset( + hass, caplog, enable_custom_integrations, state_class +): """Test warning on deprecated last reset.""" platform = getattr(hass.components, "test.sensor") platform.init(empty=True) platform.ENTITIES["0"] = platform.MockSensor( - name="Test", state_class="measurement", last_reset=dt_util.utc_from_timestamp(0) + name="Test", state_class=state_class, last_reset=dt_util.utc_from_timestamp(0) ) assert await async_setup_component(hass, "sensor", {"sensor": {"platform": "test"}}) @@ -94,13 +97,15 @@ async def test_deprecated_last_reset(hass, caplog, enable_custom_integrations): assert ( "Entity sensor.test () " - "with state_class measurement has set last_reset. Setting last_reset for " - "entities with state_class other than 'total' is deprecated and will be " - "removed from Home Assistant Core 2021.11. Please update your configuration if " - "state_class is manually configured, otherwise report it to the custom " - "component author." + f"with state_class {state_class} has set last_reset. Setting last_reset for " + "entities with state_class other than 'total' is not supported. Please update " + "your configuration if state_class is manually configured, otherwise report it " + "to the custom component author." ) in caplog.text + state = hass.states.get("sensor.test") + assert "last_reset" not in state.attributes + async def test_deprecated_unit_of_measurement(hass, caplog, enable_custom_integrations): """Test warning on deprecated unit_of_measurement."""