Add 'delta_values' option to utility_meter (#54964)

This commit is contained in:
Eddy G 2021-10-28 17:00:31 -07:00 committed by GitHub
parent c8cbd0070d
commit 4d5705c0fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 73 additions and 3 deletions

View File

@ -17,6 +17,7 @@ from .const import (
ATTR_TARIFF, ATTR_TARIFF,
CONF_CRON_PATTERN, CONF_CRON_PATTERN,
CONF_METER, CONF_METER,
CONF_METER_DELTA_VALUES,
CONF_METER_NET_CONSUMPTION, CONF_METER_NET_CONSUMPTION,
CONF_METER_OFFSET, CONF_METER_OFFSET,
CONF_METER_TYPE, CONF_METER_TYPE,
@ -84,6 +85,7 @@ METER_CONFIG_SCHEMA = vol.Schema(
vol.Optional(CONF_METER_OFFSET, default=DEFAULT_OFFSET): vol.All( vol.Optional(CONF_METER_OFFSET, default=DEFAULT_OFFSET): vol.All(
cv.time_period, cv.positive_timedelta, max_28_days 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_METER_NET_CONSUMPTION, default=False): cv.boolean,
vol.Optional(CONF_TARIFFS, default=[]): vol.All( vol.Optional(CONF_TARIFFS, default=[]): vol.All(
cv.ensure_list, [cv.string] cv.ensure_list, [cv.string]

View File

@ -28,6 +28,7 @@ CONF_METER = "meter"
CONF_SOURCE_SENSOR = "source" CONF_SOURCE_SENSOR = "source"
CONF_METER_TYPE = "cycle" CONF_METER_TYPE = "cycle"
CONF_METER_OFFSET = "offset" CONF_METER_OFFSET = "offset"
CONF_METER_DELTA_VALUES = "delta_values"
CONF_METER_NET_CONSUMPTION = "net_consumption" CONF_METER_NET_CONSUMPTION = "net_consumption"
CONF_PAUSED = "paused" CONF_PAUSED = "paused"
CONF_TARIFFS = "tariffs" CONF_TARIFFS = "tariffs"

View File

@ -38,6 +38,7 @@ from .const import (
BIMONTHLY, BIMONTHLY,
CONF_CRON_PATTERN, CONF_CRON_PATTERN,
CONF_METER, CONF_METER,
CONF_METER_DELTA_VALUES,
CONF_METER_NET_CONSUMPTION, CONF_METER_NET_CONSUMPTION,
CONF_METER_OFFSET, CONF_METER_OFFSET,
CONF_METER_TYPE, 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_source = hass.data[DATA_UTILITY][meter][CONF_SOURCE_SENSOR]
conf_meter_type = hass.data[DATA_UTILITY][meter].get(CONF_METER_TYPE) 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_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 = hass.data[DATA_UTILITY][meter][
CONF_METER_NET_CONSUMPTION 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.get(CONF_NAME),
conf_meter_type, conf_meter_type,
conf_meter_offset, conf_meter_offset,
conf_meter_delta_values,
conf_meter_net_consumption, conf_meter_net_consumption,
conf.get(CONF_TARIFF), conf.get(CONF_TARIFF),
conf_meter_tariff_entity, conf_meter_tariff_entity,
@ -143,6 +148,7 @@ class UtilityMeterSensor(RestoreEntity, SensorEntity):
name, name,
meter_type, meter_type,
meter_offset, meter_offset,
delta_values,
net_consumption, net_consumption,
tariff=None, tariff=None,
tariff_entity=None, tariff_entity=None,
@ -171,6 +177,7 @@ class UtilityMeterSensor(RestoreEntity, SensorEntity):
_LOGGER.debug("CRON pattern: %s", self._cron_pattern) _LOGGER.debug("CRON pattern: %s", self._cron_pattern)
else: else:
self._cron_pattern = cron_pattern self._cron_pattern = cron_pattern
self._sensor_delta_values = delta_values
self._sensor_net_consumption = net_consumption self._sensor_net_consumption = net_consumption
self._tariff = tariff self._tariff = tariff
self._tariff_entity = tariff_entity 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) self._unit_of_measurement = new_state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
try: 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, # Source sensor just rolled over for unknown reasons,
return return
self._state += diff self._state += adjustment
except ValueError as err: except ValueError as err:
_LOGGER.warning("While processing state changes: %s", err) _LOGGER.warning("While processing state changes: %s", err)

View File

@ -414,6 +414,63 @@ async def test_non_net_consumption(hass):
assert state.state == "0" 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): def gen_config(cycle, offset=None):
"""Generate configuration.""" """Generate configuration."""
config = { config = {