From 4d5705c0fe927b2a2be4c32fa0b236609d8b98f3 Mon Sep 17 00:00:00 2001 From: Eddy G Date: Thu, 28 Oct 2021 17:00:31 -0700 Subject: [PATCH] Add 'delta_values' option to utility_meter (#54964) --- .../components/utility_meter/__init__.py | 2 + .../components/utility_meter/const.py | 1 + .../components/utility_meter/sensor.py | 16 +++++- tests/components/utility_meter/test_sensor.py | 57 +++++++++++++++++++ 4 files changed, 73 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/utility_meter/__init__.py b/homeassistant/components/utility_meter/__init__.py index c91bbcb7e57..bdb88d05240 100644 --- a/homeassistant/components/utility_meter/__init__.py +++ b/homeassistant/components/utility_meter/__init__.py @@ -17,6 +17,7 @@ from .const import ( ATTR_TARIFF, CONF_CRON_PATTERN, CONF_METER, + CONF_METER_DELTA_VALUES, CONF_METER_NET_CONSUMPTION, CONF_METER_OFFSET, CONF_METER_TYPE, @@ -84,6 +85,7 @@ METER_CONFIG_SCHEMA = vol.Schema( vol.Optional(CONF_METER_OFFSET, default=DEFAULT_OFFSET): vol.All( cv.time_period, cv.positive_timedelta, max_28_days ), + vol.Optional(CONF_METER_DELTA_VALUES, default=False): cv.boolean, vol.Optional(CONF_METER_NET_CONSUMPTION, default=False): cv.boolean, vol.Optional(CONF_TARIFFS, default=[]): vol.All( cv.ensure_list, [cv.string] diff --git a/homeassistant/components/utility_meter/const.py b/homeassistant/components/utility_meter/const.py index 3e127e4a643..097496e231d 100644 --- a/homeassistant/components/utility_meter/const.py +++ b/homeassistant/components/utility_meter/const.py @@ -28,6 +28,7 @@ CONF_METER = "meter" CONF_SOURCE_SENSOR = "source" CONF_METER_TYPE = "cycle" CONF_METER_OFFSET = "offset" +CONF_METER_DELTA_VALUES = "delta_values" CONF_METER_NET_CONSUMPTION = "net_consumption" CONF_PAUSED = "paused" CONF_TARIFFS = "tariffs" diff --git a/homeassistant/components/utility_meter/sensor.py b/homeassistant/components/utility_meter/sensor.py index ec553cce58a..64cde15aa4f 100644 --- a/homeassistant/components/utility_meter/sensor.py +++ b/homeassistant/components/utility_meter/sensor.py @@ -38,6 +38,7 @@ from .const import ( BIMONTHLY, CONF_CRON_PATTERN, CONF_METER, + CONF_METER_DELTA_VALUES, CONF_METER_NET_CONSUMPTION, CONF_METER_OFFSET, CONF_METER_TYPE, @@ -100,6 +101,9 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= conf_meter_source = hass.data[DATA_UTILITY][meter][CONF_SOURCE_SENSOR] conf_meter_type = hass.data[DATA_UTILITY][meter].get(CONF_METER_TYPE) conf_meter_offset = hass.data[DATA_UTILITY][meter][CONF_METER_OFFSET] + conf_meter_delta_values = hass.data[DATA_UTILITY][meter][ + CONF_METER_DELTA_VALUES + ] conf_meter_net_consumption = hass.data[DATA_UTILITY][meter][ CONF_METER_NET_CONSUMPTION ] @@ -113,6 +117,7 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= conf.get(CONF_NAME), conf_meter_type, conf_meter_offset, + conf_meter_delta_values, conf_meter_net_consumption, conf.get(CONF_TARIFF), conf_meter_tariff_entity, @@ -143,6 +148,7 @@ class UtilityMeterSensor(RestoreEntity, SensorEntity): name, meter_type, meter_offset, + delta_values, net_consumption, tariff=None, tariff_entity=None, @@ -171,6 +177,7 @@ class UtilityMeterSensor(RestoreEntity, SensorEntity): _LOGGER.debug("CRON pattern: %s", self._cron_pattern) else: self._cron_pattern = cron_pattern + self._sensor_delta_values = delta_values self._sensor_net_consumption = net_consumption self._tariff = tariff self._tariff_entity = tariff_entity @@ -206,12 +213,15 @@ class UtilityMeterSensor(RestoreEntity, SensorEntity): self._unit_of_measurement = new_state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) try: - diff = Decimal(new_state.state) - Decimal(old_state.state) + if self._sensor_delta_values: + adjustment = Decimal(new_state.state) + else: + adjustment = Decimal(new_state.state) - Decimal(old_state.state) - if (not self._sensor_net_consumption) and diff < 0: + if (not self._sensor_net_consumption) and adjustment < 0: # Source sensor just rolled over for unknown reasons, return - self._state += diff + self._state += adjustment except ValueError as err: _LOGGER.warning("While processing state changes: %s", err) diff --git a/tests/components/utility_meter/test_sensor.py b/tests/components/utility_meter/test_sensor.py index a41ddcfa9fc..8d9b819f610 100644 --- a/tests/components/utility_meter/test_sensor.py +++ b/tests/components/utility_meter/test_sensor.py @@ -414,6 +414,63 @@ async def test_non_net_consumption(hass): assert state.state == "0" +async def test_delta_values(hass): + """Test utility meter "delta_values" mode.""" + config = { + "utility_meter": { + "energy_bill": {"source": "sensor.energy", "delta_values": True} + } + } + + now = dt_util.utcnow() + with alter_time(now): + assert await async_setup_component(hass, DOMAIN, config) + await hass.async_block_till_done() + + hass.bus.async_fire(EVENT_HOMEASSISTANT_START) + entity_id = config[DOMAIN]["energy_bill"]["source"] + + async_fire_time_changed(hass, now) + hass.states.async_set( + entity_id, 1, {ATTR_UNIT_OF_MEASUREMENT: ENERGY_KILO_WATT_HOUR} + ) + await hass.async_block_till_done() + + state = hass.states.get("sensor.energy_bill") + assert state.attributes.get("status") == PAUSED + + now += timedelta(seconds=30) + with alter_time(now): + async_fire_time_changed(hass, now) + hass.states.async_set( + entity_id, + 3, + {ATTR_UNIT_OF_MEASUREMENT: ENERGY_KILO_WATT_HOUR}, + force_update=True, + ) + await hass.async_block_till_done() + + state = hass.states.get("sensor.energy_bill") + assert state.attributes.get("status") == COLLECTING + + now += timedelta(seconds=30) + with alter_time(now): + async_fire_time_changed(hass, now) + await hass.async_block_till_done() + hass.states.async_set( + entity_id, + 6, + {ATTR_UNIT_OF_MEASUREMENT: ENERGY_KILO_WATT_HOUR}, + force_update=True, + ) + await hass.async_block_till_done() + + state = hass.states.get("sensor.energy_bill") + assert state is not None + + assert state.state == "9" + + def gen_config(cycle, offset=None): """Generate configuration.""" config = {