From 31adfbf51b7091c6783a5b2a5d4995b1846c17a7 Mon Sep 17 00:00:00 2001 From: Diogo Gomes Date: Sun, 10 Feb 2019 00:46:36 +0000 Subject: [PATCH 1/4] change offset from int to Time period dictionary --- .../components/utility_meter/__init__.py | 6 ++- .../components/utility_meter/sensor.py | 19 ++++---- tests/components/utility_meter/test_sensor.py | 47 +++++++++++++++---- 3 files changed, 55 insertions(+), 17 deletions(-) diff --git a/homeassistant/components/utility_meter/__init__.py b/homeassistant/components/utility_meter/__init__.py index 8a8e669ba886b..47d3bc1d2045b 100644 --- a/homeassistant/components/utility_meter/__init__.py +++ b/homeassistant/components/utility_meter/__init__.py @@ -6,6 +6,7 @@ """ import logging +from datetime import timedelta import voluptuous as vol @@ -29,6 +30,8 @@ ATTR_TARIFFS = 'tariffs' +DEFAULT_OFFSET = timedelta(hours=0) + SERVICE_METER_SCHEMA = vol.Schema({ vol.Required(ATTR_ENTITY_ID): cv.entity_ids, }) @@ -41,7 +44,8 @@ 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_TARIFFS, default=[]): vol.All( cv.ensure_list, [cv.string]), }) diff --git a/homeassistant/components/utility_meter/sensor.py b/homeassistant/components/utility_meter/sensor.py index cd86f9c0bd01d..1393cb9c363b8 100644 --- a/homeassistant/components/utility_meter/sensor.py +++ b/homeassistant/components/utility_meter/sensor.py @@ -5,7 +5,7 @@ https://home-assistant.io/components/sensor.utility_meter/ """ import logging - +from datetime import date, timedelta from decimal import Decimal, DecimalException import homeassistant.util.dt as dt_util @@ -133,14 +133,16 @@ def async_tariff_change(self, entity, old_state, new_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: + 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) @@ -160,11 +162,12 @@ async def async_added_to_hass(self): if self._period == HOURLY: async_track_time_change(self.hass, self._async_reset_meter, - minute=self._period_offset, second=0) + minute=self._period_offset.seconds//60, + second=0) elif self._period == DAILY: async_track_time_change(self.hass, self._async_reset_meter, - hour=self._period_offset, minute=0, - second=0) + hour=self._period_offset.seconds//3600, + 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) diff --git a/tests/components/utility_meter/test_sensor.py b/tests/components/utility_meter/test_sensor.py index 23fc8872570cd..ab474e1cfd018 100644 --- a/tests/components/utility_meter/test_sensor.py +++ b/tests/components/utility_meter/test_sensor.py @@ -57,8 +57,8 @@ async def test_state(hass): assert state.state == '1' -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': { @@ -68,6 +68,18 @@ 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 + } + import pprint + pprint.pprint(config) + 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() @@ -107,30 +119,49 @@ 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(31)), + "2018-01-31T23:59: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) From 6495d47481edb5ee32b5a27dce6e34e612c6ea8c Mon Sep 17 00:00:00 2001 From: Diogo Gomes Date: Sun, 10 Feb 2019 01:33:50 +0000 Subject: [PATCH 2/4] track according to offset --- .../components/utility_meter/sensor.py | 20 +++++++++---------- tests/components/utility_meter/test_sensor.py | 5 +++-- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/homeassistant/components/utility_meter/sensor.py b/homeassistant/components/utility_meter/sensor.py index 1393cb9c363b8..305b60e5590ab 100644 --- a/homeassistant/components/utility_meter/sensor.py +++ b/homeassistant/components/utility_meter/sensor.py @@ -161,16 +161,16 @@ async def async_added_to_hass(self): await super().async_added_to_hass() if self._period == HOURLY: - async_track_time_change(self.hass, self._async_reset_meter, - minute=self._period_offset.seconds//60, - second=0) - elif self._period == DAILY: - async_track_time_change(self.hass, self._async_reset_meter, - hour=self._period_offset.seconds//3600, - 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) diff --git a/tests/components/utility_meter/test_sensor.py b/tests/components/utility_meter/test_sensor.py index ab474e1cfd018..dd524ec00dd27 100644 --- a/tests/components/utility_meter/test_sensor.py +++ b/tests/components/utility_meter/test_sensor.py @@ -156,8 +156,9 @@ async def test_self_no_reset_yearly(hass): async def test_reset_yearly_offset(hass): """Test yearly reset of meter.""" - await _test_self_reset(hass, gen_config('yearly', timedelta(31)), - "2018-01-31T23:59:00.000000+00:00") + 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): From 06be42eaff80de0106af12de8fee3da97f569412 Mon Sep 17 00:00:00 2001 From: Diogo Gomes Date: Sun, 10 Feb 2019 21:37:40 +0000 Subject: [PATCH 3/4] left overs... tks @fabaff --- tests/components/utility_meter/test_sensor.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/components/utility_meter/test_sensor.py b/tests/components/utility_meter/test_sensor.py index dd524ec00dd27..e584166829d24 100644 --- a/tests/components/utility_meter/test_sensor.py +++ b/tests/components/utility_meter/test_sensor.py @@ -73,8 +73,6 @@ def gen_config(cycle, offset=None): 'days': offset.days, 'seconds': offset.seconds } - import pprint - pprint.pprint(config) return config From 670ec66ca3c28e30a7fbaa7f27d54fd9e35971d9 Mon Sep 17 00:00:00 2001 From: Diogo Gomes Date: Sun, 24 Feb 2019 12:13:13 +0000 Subject: [PATCH 4/4] typo --- homeassistant/components/utility_meter/sensor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/utility_meter/sensor.py b/homeassistant/components/utility_meter/sensor.py index 121257f8826d8..dd1514f5e4351 100644 --- a/homeassistant/components/utility_meter/sensor.py +++ b/homeassistant/components/utility_meter/sensor.py @@ -128,7 +128,7 @@ def async_tariff_change(self, entity, old_state, new_state): self.async_schedule_update_ha_state() async def _async_reset_meter(self, event): - """Determine cycle - Helper function for larger then daily cycles.""" + """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())\