Utility Meter offset defined by a time_period (#20926)

* change offset from int to Time period dictionary

* track according to offset

* left overs... tks @fabaff

* typo
This commit is contained in:
Diogo Gomes 2019-03-06 12:55:24 +00:00 committed by Charles Garwood
parent 54895fcb1e
commit 8e9a496002
3 changed files with 61 additions and 24 deletions

View file

@ -1,5 +1,6 @@
"""Support for tracking consumption over given periods of time."""
import logging
from datetime import timedelta
import voluptuous as vol
@ -23,6 +24,8 @@ TARIFF_ICON = 'mdi:clock-outline'
ATTR_TARIFFS = 'tariffs'
DEFAULT_OFFSET = timedelta(hours=0)
SERVICE_METER_SCHEMA = vol.Schema({
vol.Required(ATTR_ENTITY_ID): cv.entity_ids,
})
@ -35,7 +38,8 @@ METER_CONFIG_SCHEMA = vol.Schema({
vol.Required(CONF_SOURCE_SENSOR): cv.entity_id,
vol.Optional(CONF_NAME): cv.string,
vol.Optional(CONF_METER_TYPE): vol.In(METER_TYPES),
vol.Optional(CONF_METER_OFFSET, default=0): cv.positive_int,
vol.Optional(CONF_METER_OFFSET, default=DEFAULT_OFFSET):
vol.All(cv.time_period, cv.positive_timedelta),
vol.Optional(CONF_METER_NET_CONSUMPTION, default=False): cv.boolean,
vol.Optional(CONF_TARIFFS, default=[]): vol.All(
cv.ensure_list, [cv.string]),

View file

@ -1,6 +1,6 @@
"""Utility meter from sensors providing raw data."""
import logging
from datetime import date, timedelta
from decimal import Decimal, DecimalException
import homeassistant.util.dt as dt_util
@ -128,15 +128,17 @@ class UtilityMeterSensor(RestoreEntity):
self.async_schedule_update_ha_state()
async def _async_reset_meter(self, event):
"""Determine cycle - Helper function for larger then daily cycles."""
now = dt_util.now()
if self._period == WEEKLY and now.weekday() != self._period_offset:
"""Determine cycle - Helper function for larger than daily cycles."""
now = dt_util.now().date()
if self._period == WEEKLY and\
now != now - timedelta(days=now.weekday())\
+ self._period_offset:
return
if self._period == MONTHLY and\
now.day != (1 + self._period_offset):
now != date(now.year, now.month, 1) + self._period_offset:
return
if self._period == YEARLY and\
(now.month != (1 + self._period_offset) or now.day != 1):
now != date(now.year, 1, 1) + self._period_offset:
return
await self.async_reset_meter(self._tariff_entity)
@ -155,15 +157,16 @@ class UtilityMeterSensor(RestoreEntity):
await super().async_added_to_hass()
if self._period == HOURLY:
async_track_time_change(self.hass, self._async_reset_meter,
minute=self._period_offset, second=0)
elif self._period == DAILY:
async_track_time_change(self.hass, self._async_reset_meter,
hour=self._period_offset, minute=0,
second=0)
elif self._period in [WEEKLY, MONTHLY, YEARLY]:
async_track_time_change(self.hass, self._async_reset_meter,
hour=0, minute=0, second=0)
async_track_time_change(
self.hass, self._async_reset_meter,
minute=self._period_offset.seconds // 60,
second=self._period_offset.seconds % 60)
elif self._period in [DAILY, WEEKLY, MONTHLY, YEARLY]:
async_track_time_change(
self.hass, self._async_reset_meter,
hour=self._period_offset.seconds // 3600,
minute=self._period_offset.seconds % 3600 // 60,
second=self._period_offset.seconds % 3600 % 60)
async_dispatcher_connect(
self.hass, SIGNAL_RESET_METER, self.async_reset_meter)

View file

@ -123,8 +123,8 @@ async def test_non_net_consumption(hass):
assert state.state == '0'
async def _test_self_reset(hass, cycle, start_time, expect_reset=True):
"""Test energy sensor self reset."""
def gen_config(cycle, offset=None):
"""Generate configuration."""
config = {
'utility_meter': {
'energy_bill': {
@ -134,6 +134,16 @@ async def _test_self_reset(hass, cycle, start_time, expect_reset=True):
}
}
if offset:
config['utility_meter']['energy_bill']['offset'] = {
'days': offset.days,
'seconds': offset.seconds
}
return config
async def _test_self_reset(hass, config, start_time, expect_reset=True):
"""Test energy sensor self reset."""
assert await async_setup_component(hass, DOMAIN, config)
assert await async_setup_component(hass, SENSOR_DOMAIN, config)
await hass.async_block_till_done()
@ -173,30 +183,50 @@ async def _test_self_reset(hass, cycle, start_time, expect_reset=True):
async def test_self_reset_hourly(hass):
"""Test hourly reset of meter."""
await _test_self_reset(hass, 'hourly', "2017-12-31T23:59:00.000000+00:00")
await _test_self_reset(hass, gen_config('hourly'),
"2017-12-31T23:59:00.000000+00:00")
async def test_self_reset_daily(hass):
"""Test daily reset of meter."""
await _test_self_reset(hass, 'daily', "2017-12-31T23:59:00.000000+00:00")
await _test_self_reset(hass, gen_config('daily'),
"2017-12-31T23:59:00.000000+00:00")
async def test_self_reset_weekly(hass):
"""Test weekly reset of meter."""
await _test_self_reset(hass, 'weekly', "2017-12-31T23:59:00.000000+00:00")
await _test_self_reset(hass, gen_config('weekly'),
"2017-12-31T23:59:00.000000+00:00")
async def test_self_reset_monthly(hass):
"""Test monthly reset of meter."""
await _test_self_reset(hass, 'monthly', "2017-12-31T23:59:00.000000+00:00")
await _test_self_reset(hass, gen_config('monthly'),
"2017-12-31T23:59:00.000000+00:00")
async def test_self_reset_yearly(hass):
"""Test yearly reset of meter."""
await _test_self_reset(hass, 'yearly', "2017-12-31T23:59:00.000000+00:00")
await _test_self_reset(hass, gen_config('yearly'),
"2017-12-31T23:59:00.000000+00:00")
async def test_self_no_reset_yearly(hass):
"""Test yearly reset of meter does not occur after 1st January."""
await _test_self_reset(hass, 'yearly', "2018-01-01T23:59:00.000000+00:00",
await _test_self_reset(hass, gen_config('yearly'),
"2018-01-01T23:59:00.000000+00:00",
expect_reset=False)
async def test_reset_yearly_offset(hass):
"""Test yearly reset of meter."""
await _test_self_reset(hass,
gen_config('yearly', timedelta(days=1, minutes=10)),
"2018-01-02T00:09:00.000000+00:00")
async def test_no_reset_yearly_offset(hass):
"""Test yearly reset of meter."""
await _test_self_reset(hass, gen_config('yearly', timedelta(31)),
"2018-01-30T23:59:00.000000+00:00",
expect_reset=False)