diff --git a/homeassistant/components/statistics/sensor.py b/homeassistant/components/statistics/sensor.py index 7b2951a1ab6..5b0ad3765b1 100644 --- a/homeassistant/components/statistics/sensor.py +++ b/homeassistant/components/statistics/sensor.py @@ -126,6 +126,7 @@ class StatisticsSensor(SensorEntity): self._entity_id = entity_id self.is_binary = self._entity_id.split(".")[0] == "binary_sensor" self._name = name + self._available = False self._sampling_size = sampling_size self._max_age = max_age self._precision = precision @@ -176,6 +177,7 @@ class StatisticsSensor(SensorEntity): def _add_state_to_queue(self, new_state): """Add the state to the queue.""" + self._available = new_state.state != STATE_UNAVAILABLE if new_state.state in (STATE_UNKNOWN, STATE_UNAVAILABLE, None): return @@ -184,7 +186,6 @@ class StatisticsSensor(SensorEntity): self.states.append(new_state.state) else: self.states.append(float(new_state.state)) - self.ages.append(new_state.last_updated) except ValueError: _LOGGER.error( @@ -216,6 +217,11 @@ class StatisticsSensor(SensorEntity): """Return the unit the value is expressed in.""" return self._unit_of_measurement if not self.is_binary else None + @property + def available(self): + """Return the availability of the sensor linked to the source sensor.""" + return self._available + @property def should_poll(self): """No polling needed.""" diff --git a/tests/components/statistics/test_sensor.py b/tests/components/statistics/test_sensor.py index c3b14ba360d..0aa1c116991 100644 --- a/tests/components/statistics/test_sensor.py +++ b/tests/components/statistics/test_sensor.py @@ -12,6 +12,7 @@ from homeassistant.components.statistics.sensor import DOMAIN, StatisticsSensor from homeassistant.const import ( ATTR_UNIT_OF_MEASUREMENT, SERVICE_RELOAD, + STATE_UNAVAILABLE, STATE_UNKNOWN, TEMP_CELSIUS, ) @@ -110,7 +111,6 @@ class TestStatisticsSensor(unittest.TestCase): self.hass.block_till_done() state = self.hass.states.get("sensor.test") - assert str(self.mean) == state.state assert self.min == state.attributes.get("min_value") assert self.max == state.attributes.get("max_value") @@ -125,13 +125,29 @@ class TestStatisticsSensor(unittest.TestCase): assert self.change == state.attributes.get("change") assert self.average_change == state.attributes.get("average_change") - # Source sensor is unavailable, unit and state should not change - self.hass.states.set("sensor.test_monitored", "unavailable", {}) + # Source sensor turns unavailable, then available with valid value, + # statistics sensor should follow + state = self.hass.states.get("sensor.test") + self.hass.states.set( + "sensor.test_monitored", + STATE_UNAVAILABLE, + {ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS}, + ) self.hass.block_till_done() new_state = self.hass.states.get("sensor.test") - assert state == new_state + assert new_state.state == STATE_UNAVAILABLE + self.hass.states.set( + "sensor.test_monitored", + 0, + {ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS}, + ) + self.hass.block_till_done() + new_state = self.hass.states.get("sensor.test") + assert new_state.state != STATE_UNAVAILABLE + assert new_state.attributes.get("count") == state.attributes.get("count") + 1 - # Source sensor has a non float state, unit and state should not change + # Source sensor has a non-float state, unit and state should not change + state = self.hass.states.get("sensor.test") self.hass.states.set("sensor.test_monitored", "beer", {}) self.hass.block_till_done() new_state = self.hass.states.get("sensor.test")