From 9cdcfae8f368aebec06569c47304423ce9c45a38 Mon Sep 17 00:00:00 2001 From: Malte Franken Date: Wed, 23 Nov 2016 01:36:29 +1100 Subject: [PATCH] New config parameter for min_max sensor to specify number of digits for rounding mean value (#4237) * new config parameter to specify number of digits for rounding average value * fixed two `line too long` errors * added three new tests for the mean sensor including test for precision of mean value --- homeassistant/components/sensor/min_max.py | 12 ++- tests/components/sensor/test_min_max.py | 93 +++++++++++++++++++++- 2 files changed, 101 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/sensor/min_max.py b/homeassistant/components/sensor/min_max.py index b41966ac861..c1eb57170f4 100644 --- a/homeassistant/components/sensor/min_max.py +++ b/homeassistant/components/sensor/min_max.py @@ -32,6 +32,7 @@ ATTR_TO_PROPERTY = [ ] CONF_ENTITY_IDS = 'entity_ids' +CONF_ROUND_DIGITS = 'round_digits' DEFAULT_NAME = 'Min/Max/Avg Sensor' @@ -48,6 +49,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.All(cv.string, vol.In(SENSOR_TYPES.values())), vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, vol.Required(CONF_ENTITY_IDS): cv.entity_ids, + vol.Optional(CONF_ROUND_DIGITS, default=2): vol.Coerce(int), }) @@ -57,20 +59,23 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): entity_ids = config.get(CONF_ENTITY_IDS) name = config.get(CONF_NAME) sensor_type = config.get(CONF_TYPE) + round_digits = config.get(CONF_ROUND_DIGITS) yield from async_add_devices( - [MinMaxSensor(hass, entity_ids, name, sensor_type)], True) + [MinMaxSensor(hass, entity_ids, name, sensor_type, round_digits)], + True) return True class MinMaxSensor(Entity): """Representation of a min/max sensor.""" - def __init__(self, hass, entity_ids, name, sensor_type): + def __init__(self, hass, entity_ids, name, sensor_type, round_digits): """Initialize the min/max sensor.""" self._hass = hass self._entity_ids = entity_ids self._sensor_type = sensor_type + self._round_digits = round_digits self._name = '{} {}'.format( name, next(v for k, v in SENSOR_TYPES.items() if self._sensor_type == v)) @@ -148,6 +153,7 @@ class MinMaxSensor(Entity): if len(sensor_values) == self.count_sensors: self.min_value = min(sensor_values) self.max_value = max(sensor_values) - self.mean = round(sum(sensor_values) / self.count_sensors, 2) + self.mean = round(sum(sensor_values) / self.count_sensors, + self._round_digits) else: self.min_value = self.max_value = self.mean = STATE_UNKNOWN diff --git a/tests/components/sensor/test_min_max.py b/tests/components/sensor/test_min_max.py index bf49d4113c4..11b08575f46 100644 --- a/tests/components/sensor/test_min_max.py +++ b/tests/components/sensor/test_min_max.py @@ -13,11 +13,13 @@ class TestMinMaxSensor(unittest.TestCase): def setup_method(self, method): """Set up things to be run when tests are started.""" self.hass = get_test_home_assistant() - self.values = [17, 20, 15.2] + self.values = [17, 20, 15.3] self.count = len(self.values) self.min = min(self.values) self.max = max(self.values) self.mean = round(sum(self.values) / self.count, 2) + self.mean_1_digit = round(sum(self.values) / self.count, 1) + self.mean_4_digits = round(sum(self.values) / self.count, 4) def teardown_method(self, method): """Stop everything that was started.""" @@ -81,6 +83,95 @@ class TestMinMaxSensor(unittest.TestCase): self.assertEqual(self.min, state.attributes.get('min_value')) self.assertEqual(self.mean, state.attributes.get('mean')) + def test_mean_sensor(self): + """Test the mean sensor.""" + config = { + 'sensor': { + 'platform': 'min_max', + 'name': 'test', + 'type': 'mean', + 'entity_ids': [ + 'sensor.test_1', + 'sensor.test_2', + 'sensor.test_3', + ] + } + } + + assert setup_component(self.hass, 'sensor', config) + + entity_ids = config['sensor']['entity_ids'] + + for entity_id, value in dict(zip(entity_ids, self.values)).items(): + self.hass.states.set(entity_id, value) + self.hass.block_till_done() + + state = self.hass.states.get('sensor.test_mean') + + self.assertEqual(str(float(self.mean)), state.state) + self.assertEqual(self.min, state.attributes.get('min_value')) + self.assertEqual(self.max, state.attributes.get('max_value')) + + def test_mean_1_digit_sensor(self): + """Test the mean with 1-digit precision sensor.""" + config = { + 'sensor': { + 'platform': 'min_max', + 'name': 'test', + 'type': 'mean', + 'round_digits': 1, + 'entity_ids': [ + 'sensor.test_1', + 'sensor.test_2', + 'sensor.test_3', + ] + } + } + + assert setup_component(self.hass, 'sensor', config) + + entity_ids = config['sensor']['entity_ids'] + + for entity_id, value in dict(zip(entity_ids, self.values)).items(): + self.hass.states.set(entity_id, value) + self.hass.block_till_done() + + state = self.hass.states.get('sensor.test_mean') + + self.assertEqual(str(float(self.mean_1_digit)), state.state) + self.assertEqual(self.min, state.attributes.get('min_value')) + self.assertEqual(self.max, state.attributes.get('max_value')) + + def test_mean_4_digit_sensor(self): + """Test the mean with 1-digit precision sensor.""" + config = { + 'sensor': { + 'platform': 'min_max', + 'name': 'test', + 'type': 'mean', + 'round_digits': 4, + 'entity_ids': [ + 'sensor.test_1', + 'sensor.test_2', + 'sensor.test_3', + ] + } + } + + assert setup_component(self.hass, 'sensor', config) + + entity_ids = config['sensor']['entity_ids'] + + for entity_id, value in dict(zip(entity_ids, self.values)).items(): + self.hass.states.set(entity_id, value) + self.hass.block_till_done() + + state = self.hass.states.get('sensor.test_mean') + + self.assertEqual(str(float(self.mean_4_digits)), state.state) + self.assertEqual(self.min, state.attributes.get('min_value')) + self.assertEqual(self.max, state.attributes.get('max_value')) + def test_not_enough_sensor_value(self): """Test that there is nothing done if not enough values available.""" config = {