From 0186ce78968ba95fc83c0ccf9630134cc1120367 Mon Sep 17 00:00:00 2001 From: Santobert Date: Mon, 30 Mar 2020 17:13:22 +0200 Subject: [PATCH] Filter the history of device_tracker by location attributes (#33356) * Add include_location_attributes * Add check for different state * Fix things * Drop filter * significant changes only * Change default behavior * Remove trailing commas --- homeassistant/components/history/__init__.py | 22 +++++--- tests/components/history/test_init.py | 56 ++++++++++++++++++++ 2 files changed, 71 insertions(+), 7 deletions(-) diff --git a/homeassistant/components/history/__init__.py b/homeassistant/components/history/__init__.py index 7fcbf519bf34..7540740a7370 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 51f1e3cb2aca..64b438a29fce 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()