From df7386e5efd61130e7bdd618e107a3548b9171e4 Mon Sep 17 00:00:00 2001 From: Mark Ferry Date: Fri, 8 Dec 2017 19:26:36 +0000 Subject: [PATCH 1/3] Add 'last' type to min/max sensor Now supports types: min, max, mean, last 'last' is the most recently received value from all tracked entities. --- homeassistant/components/sensor/min_max.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/sensor/min_max.py b/homeassistant/components/sensor/min_max.py index 59a89fa0e3ea86..912bf7b750010b 100644 --- a/homeassistant/components/sensor/min_max.py +++ b/homeassistant/components/sensor/min_max.py @@ -23,12 +23,14 @@ ATTR_MAX_VALUE = 'max_value' ATTR_COUNT_SENSORS = 'count_sensors' ATTR_MEAN = 'mean' +ATTR_LAST = 'last' ATTR_TO_PROPERTY = [ ATTR_COUNT_SENSORS, ATTR_MAX_VALUE, ATTR_MEAN, ATTR_MIN_VALUE, + ATTR_LAST, ] CONF_ENTITY_IDS = 'entity_ids' @@ -40,6 +42,7 @@ ATTR_MIN_VALUE: 'min', ATTR_MAX_VALUE: 'max', ATTR_MEAN: 'mean', + ATTR_LAST: 'last', } PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ @@ -116,7 +119,7 @@ def __init__(self, hass, entity_ids, name, sensor_type, round_digits): if self._sensor_type == v)).capitalize() self._unit_of_measurement = None self._unit_of_measurement_mismatch = False - self.min_value = self.max_value = self.mean = STATE_UNKNOWN + self.min_value = self.max_value = self.mean = self.last = STATE_UNKNOWN self.count_sensors = len(self._entity_ids) self.states = {} @@ -142,6 +145,7 @@ def async_min_max_sensor_state_listener(entity, old_state, new_state): try: self.states[entity] = float(new_state.state) + self.last = float(new_state.state) except ValueError: _LOGGER.warning("Unable to store state. " "Only numerical states are supported") From 721e7ce638796204e3a8df32049eeaadf1700dbd Mon Sep 17 00:00:00 2001 From: Mark Ferry Date: Fri, 8 Dec 2017 20:23:44 +0000 Subject: [PATCH 2/3] Min/max sensor 'last' type test --- tests/components/sensor/test_min_max.py | 36 +++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/tests/components/sensor/test_min_max.py b/tests/components/sensor/test_min_max.py index a6d6a5adc68893..ebfb64d363ac2f 100644 --- a/tests/components/sensor/test_min_max.py +++ b/tests/components/sensor/test_min_max.py @@ -20,6 +20,7 @@ def setup_method(self, method): 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) + self.last = self.values[-1] def teardown_method(self, method): """Stop everything that was started.""" @@ -53,6 +54,7 @@ def test_min_sensor(self): self.assertEqual(str(float(self.min)), state.state) self.assertEqual(self.max, state.attributes.get('max_value')) self.assertEqual(self.mean, state.attributes.get('mean')) + self.assertEqual(self.last, state.attributes.get('last')) def test_max_sensor(self): """Test the max sensor.""" @@ -82,6 +84,7 @@ def test_max_sensor(self): self.assertEqual(str(float(self.max)), state.state) self.assertEqual(self.min, state.attributes.get('min_value')) self.assertEqual(self.mean, state.attributes.get('mean')) + self.assertEqual(self.last, state.attributes.get('last')) def test_mean_sensor(self): """Test the mean sensor.""" @@ -111,6 +114,7 @@ def test_mean_sensor(self): 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')) + self.assertEqual(self.last, state.attributes.get('last')) def test_mean_1_digit_sensor(self): """Test the mean with 1-digit precision sensor.""" @@ -141,6 +145,7 @@ def test_mean_1_digit_sensor(self): 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')) + self.assertEqual(self.last, state.attributes.get('last')) def test_mean_4_digit_sensor(self): """Test the mean with 1-digit precision sensor.""" @@ -171,6 +176,7 @@ def test_mean_4_digit_sensor(self): 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')) + self.assertEqual(self.last, state.attributes.get('last')) def test_not_enough_sensor_value(self): """Test that there is nothing done if not enough values available.""" @@ -260,3 +266,33 @@ def test_different_unit_of_measurement(self): self.assertEqual(STATE_UNKNOWN, state.state) self.assertEqual('ERR', state.attributes.get('unit_of_measurement')) + + def test_last_sensor(self): + """Test the last sensor.""" + config = { + 'sensor': { + 'platform': 'min_max', + 'name': 'test_last', + 'type': 'last', + '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_last') + + self.assertEqual(str(float(self.last)), state.state) + self.assertEqual(self.min, state.attributes.get('min_value')) + self.assertEqual(self.max, state.attributes.get('max_value')) + self.assertEqual(self.mean, state.attributes.get('mean')) From 247de640642a22810442375354c8fb95b97147f7 Mon Sep 17 00:00:00 2001 From: Mark Ferry Date: Sat, 16 Dec 2017 21:48:00 +0000 Subject: [PATCH 3/3] Fix min/max sensor 'last' test --- tests/components/sensor/test_min_max.py | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/tests/components/sensor/test_min_max.py b/tests/components/sensor/test_min_max.py index ebfb64d363ac2f..0376c780ee75de 100644 --- a/tests/components/sensor/test_min_max.py +++ b/tests/components/sensor/test_min_max.py @@ -20,7 +20,6 @@ def setup_method(self, method): 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) - self.last = self.values[-1] def teardown_method(self, method): """Stop everything that was started.""" @@ -54,7 +53,6 @@ def test_min_sensor(self): self.assertEqual(str(float(self.min)), state.state) self.assertEqual(self.max, state.attributes.get('max_value')) self.assertEqual(self.mean, state.attributes.get('mean')) - self.assertEqual(self.last, state.attributes.get('last')) def test_max_sensor(self): """Test the max sensor.""" @@ -84,7 +82,6 @@ def test_max_sensor(self): self.assertEqual(str(float(self.max)), state.state) self.assertEqual(self.min, state.attributes.get('min_value')) self.assertEqual(self.mean, state.attributes.get('mean')) - self.assertEqual(self.last, state.attributes.get('last')) def test_mean_sensor(self): """Test the mean sensor.""" @@ -114,7 +111,6 @@ def test_mean_sensor(self): 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')) - self.assertEqual(self.last, state.attributes.get('last')) def test_mean_1_digit_sensor(self): """Test the mean with 1-digit precision sensor.""" @@ -145,7 +141,6 @@ def test_mean_1_digit_sensor(self): 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')) - self.assertEqual(self.last, state.attributes.get('last')) def test_mean_4_digit_sensor(self): """Test the mean with 1-digit precision sensor.""" @@ -176,7 +171,6 @@ def test_mean_4_digit_sensor(self): 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')) - self.assertEqual(self.last, state.attributes.get('last')) def test_not_enough_sensor_value(self): """Test that there is nothing done if not enough values available.""" @@ -285,14 +279,14 @@ def test_last_sensor(self): assert setup_component(self.hass, 'sensor', config) entity_ids = config['sensor']['entity_ids'] + state = self.hass.states.get('sensor.test_last') 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_last') + self.assertEqual(str(float(value)), state.state) - state = self.hass.states.get('sensor.test_last') - - self.assertEqual(str(float(self.last)), state.state) self.assertEqual(self.min, state.attributes.get('min_value')) self.assertEqual(self.max, state.attributes.get('max_value')) self.assertEqual(self.mean, state.attributes.get('mean'))