diff --git a/homeassistant/components/history/__init__.py b/homeassistant/components/history/__init__.py index 7fcbf519bf3..7540740a737 100644 --- a/homeassistant/components/history/__init__.py +++ b/homeassistant/components/history/__init__.py @@ -39,7 +39,7 @@ CONFIG_SCHEMA = vol.Schema( extra=vol.ALLOW_EXTRA, ) -SIGNIFICANT_DOMAINS = ("thermostat", "climate", "water_heater") +SIGNIFICANT_DOMAINS = ("climate", "device_tracker", "thermostat", "water_heater") IGNORE_DOMAINS = ("zone", "scene") @@ -50,6 +50,7 @@ def get_significant_states( entity_ids=None, filters=None, include_start_time_state=True, + significant_changes_only=True, ): """ Return states changes during UTC period start_time - end_time. @@ -61,13 +62,16 @@ def get_significant_states( timer_start = time.perf_counter() with session_scope(hass=hass) as session: - query = session.query(States).filter( - ( - States.domain.in_(SIGNIFICANT_DOMAINS) - | (States.last_changed == States.last_updated) + if significant_changes_only: + query = session.query(States).filter( + ( + States.domain.in_(SIGNIFICANT_DOMAINS) + | (States.last_changed == States.last_updated) + ) + & (States.last_updated > start_time) ) - & (States.last_updated > start_time) - ) + else: + query = session.query(States).filter(States.last_updated > start_time) if filters: query = filters.apply(query, entity_ids) @@ -327,6 +331,9 @@ class HistoryPeriodView(HomeAssistantView): if entity_ids: entity_ids = entity_ids.lower().split(",") include_start_time_state = "skip_initial_state" not in request.query + significant_changes_only = ( + request.query.get("significant_changes_only", "1") != "0" + ) hass = request.app["hass"] @@ -338,6 +345,7 @@ class HistoryPeriodView(HomeAssistantView): entity_ids, self.filters, include_start_time_state, + significant_changes_only, ) result = list(result.values()) if _LOGGER.isEnabledFor(logging.DEBUG): diff --git a/tests/components/history/test_init.py b/tests/components/history/test_init.py index 51f1e3cb2ac..64b438a29fc 100644 --- a/tests/components/history/test_init.py +++ b/tests/components/history/test_init.py @@ -522,6 +522,62 @@ class TestComponentHistory(unittest.TestCase): ) assert list(hist.keys()) == entity_ids + def test_get_significant_states_only(self): + """Test significant states when significant_states_only is set.""" + self.init_recorder() + entity_id = "sensor.test" + + def set_state(state, **kwargs): + """Set the state.""" + self.hass.states.set(entity_id, state, **kwargs) + wait_recording_done(self.hass) + return self.hass.states.get(entity_id) + + start = dt_util.utcnow() - timedelta(minutes=4) + points = [] + for i in range(1, 4): + points.append(start + timedelta(minutes=i)) + + states = [] + with patch( + "homeassistant.components.recorder.dt_util.utcnow", return_value=start + ): + set_state("123", attributes={"attribute": 10.64}) + + with patch( + "homeassistant.components.recorder.dt_util.utcnow", return_value=points[0] + ): + # Attributes are different, state not + states.append(set_state("123", attributes={"attribute": 21.42})) + + with patch( + "homeassistant.components.recorder.dt_util.utcnow", return_value=points[1] + ): + # state is different, attributes not + states.append(set_state("32", attributes={"attribute": 21.42})) + + with patch( + "homeassistant.components.recorder.dt_util.utcnow", return_value=points[2] + ): + # everything is different + states.append(set_state("412", attributes={"attribute": 54.23})) + + hist = history.get_significant_states( + self.hass, start, significant_changes_only=True + ) + + assert len(hist[entity_id]) == 2 + assert states[0] not in hist[entity_id] + assert states[1] in hist[entity_id] + assert states[2] in hist[entity_id] + + hist = history.get_significant_states( + self.hass, start, significant_changes_only=False + ) + + assert len(hist[entity_id]) == 3 + assert states == hist[entity_id] + def check_significant_states(self, zero, four, states, config): """Check if significant states are retrieved.""" filters = history.Filters()