From 52fe0a5e966aad9b07fed775bee94183b7fd201c Mon Sep 17 00:00:00 2001 From: gibwar Date: Fri, 1 Mar 2024 08:44:24 -0700 Subject: [PATCH] Fix utility meter reset without tarrifs (#102884) * Fix utility meter reset without tarrifs When using a utility_meter helper set up with a "Meter reset cycle" of "No cycle" it is impossible to properly reset the meter to 0 and utilize the "last reset" and "last period" attributes on the helper. With these changes the service call can now directly reset a meter in such a configuration and the UI selector has been updated to include utility meters in the selection list. Fixes #96920 * Undo UI target selection modes As requested to not cause confusion by being able to reset individual meters when using multiple tariffs. * Adjust logic to only reset standalone sensors The original logic would allow resetting meters with multiple tariffs which was an unintended side effect. --- .../components/utility_meter/sensor.py | 2 +- tests/components/utility_meter/test_sensor.py | 92 +++++++++++++++++++ 2 files changed, 93 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/utility_meter/sensor.py b/homeassistant/components/utility_meter/sensor.py index e9ad7a1ba30..d9c5fabd7c8 100644 --- a/homeassistant/components/utility_meter/sensor.py +++ b/homeassistant/components/utility_meter/sensor.py @@ -570,7 +570,7 @@ class UtilityMeterSensor(RestoreSensor): async def async_reset_meter(self, entity_id): """Reset meter.""" - if self._tariff_entity != entity_id: + if self._tariff is not None and self._tariff_entity != entity_id: return _LOGGER.debug("Reset utility meter <%s>", self.entity_id) self._last_reset = dt_util.utcnow() diff --git a/tests/components/utility_meter/test_sensor.py b/tests/components/utility_meter/test_sensor.py index fa1e3aa8785..a4b37271a85 100644 --- a/tests/components/utility_meter/test_sensor.py +++ b/tests/components/utility_meter/test_sensor.py @@ -21,6 +21,7 @@ from homeassistant.components.utility_meter.const import ( HOURLY, QUARTER_HOURLY, SERVICE_CALIBRATE_METER, + SERVICE_RESET, ) from homeassistant.components.utility_meter.sensor import ( ATTR_LAST_RESET, @@ -771,6 +772,97 @@ async def test_restore_state( assert state.attributes.get("status") == PAUSED +@pytest.mark.parametrize( + ("yaml_config", "config_entry_config"), + ( + ( + { + "utility_meter": { + "energy_bill": { + "source": "sensor.energy", + } + } + }, + None, + ), + ( + None, + { + "cycle": "none", + "delta_values": False, + "name": "Energy bill", + "net_consumption": False, + "offset": 0, + "periodically_resetting": True, + "source": "sensor.energy", + "tariffs": [], + }, + ), + ), +) +async def test_service_reset_no_tariffs( + hass: HomeAssistant, yaml_config, config_entry_config +) -> None: + """Test utility sensor service reset for sensor with no tariffs.""" + # Home assistant is not runnit yet + hass.state = CoreState.not_running + last_reset = "2023-10-01T00:00:00+00:00" + + mock_restore_cache_with_extra_data( + hass, + [ + ( + State( + "sensor.energy_bill", + "3", + attributes={ + ATTR_LAST_RESET: last_reset, + }, + ), + {}, + ), + ], + ) + + if yaml_config: + assert await async_setup_component(hass, DOMAIN, yaml_config) + await hass.async_block_till_done() + else: + config_entry = MockConfigEntry( + data={}, + domain=DOMAIN, + options=config_entry_config, + title=config_entry_config["name"], + ) + config_entry.add_to_hass(hass) + assert await hass.config_entries.async_setup(config_entry.entry_id) + await hass.async_block_till_done() + + state = hass.states.get("sensor.energy_bill") + assert state + assert state.state == "3" + assert state.attributes.get("last_reset") == last_reset + assert state.attributes.get("last_period") == "0" + + now = dt_util.utcnow() + with freeze_time(now): + await hass.services.async_call( + domain=DOMAIN, + service=SERVICE_RESET, + service_data={}, + target={"entity_id": "sensor.energy_bill"}, + blocking=True, + ) + + await hass.async_block_till_done() + + state = hass.states.get("sensor.energy_bill") + assert state + assert state.state == "0" + assert state.attributes.get("last_reset") == now.isoformat() + assert state.attributes.get("last_period") == "3" + + @pytest.mark.parametrize( ("yaml_config", "config_entry_config"), (