Merge pull request #1482 from balloob/history-significant-states

History: update significant states
This commit is contained in:
Paulus Schoutsen 2016-03-06 21:45:48 -08:00
commit 18f48191d9
2 changed files with 29 additions and 8 deletions

View File

@ -11,7 +11,7 @@ from collections import defaultdict
from datetime import timedelta
from itertools import groupby
import homeassistant.components.recorder as recorder
from homeassistant.components import recorder, script
import homeassistant.util.dt as dt_util
from homeassistant.const import HTTP_BAD_REQUEST
@ -19,6 +19,7 @@ DOMAIN = 'history'
DEPENDENCIES = ['recorder', 'http']
SIGNIFICANT_DOMAINS = ('thermostat',)
IGNORE_DOMAINS = ('zone', 'scene',)
URL_HISTORY_PERIOD = re.compile(
r'/api/history/period(?:/(?P<date>\d{4}-\d{1,2}-\d{1,2})|)')
@ -46,9 +47,10 @@ def get_significant_states(start_time, end_time=None, entity_id=None):
"""
where = """
(domain in ({}) or last_changed=last_updated)
AND last_updated > ?
""".format(",".join(["'%s'" % x for x in SIGNIFICANT_DOMAINS]))
(domain IN ({}) OR last_changed=last_updated)
AND domain NOT IN ({}) AND last_updated > ?
""".format(",".join("'%s'" % x for x in SIGNIFICANT_DOMAINS),
",".join("'%s'" % x for x in IGNORE_DOMAINS))
data = [start_time]
@ -63,7 +65,8 @@ def get_significant_states(start_time, end_time=None, entity_id=None):
query = ("SELECT * FROM states WHERE {} "
"ORDER BY entity_id, last_updated ASC").format(where)
states = recorder.query_states(query, data)
states = (state for state in recorder.query_states(query, data)
if _is_significant(state))
return states_to_json(states, start_time, entity_id)
@ -200,3 +203,13 @@ def _api_history_period(handler, path_match, data):
handler.write_json(
get_significant_states(start_time, end_time, entity_id).values())
def _is_significant(state):
"""Test if state is significant for history charts.
Will only test for things that are not filtered out in SQL.
"""
# scripts that are not cancellable will never change state
return (state.domain != 'script' or
state.attributes.get(script.ATTR_CAN_CANCEL))

View File

@ -148,7 +148,7 @@ class TestComponentHistory(unittest.TestCase):
"""test that only significant states are returned with
get_significant_states.
We inject a bunch of state updates from media player and
We inject a bunch of state updates from media player, zone and
thermostat. We should get back every thermostat change that
includes an attribute change, but only the state updates for
media player (attribute changes are not significant and not returned).
@ -157,6 +157,9 @@ class TestComponentHistory(unittest.TestCase):
self.init_recorder()
mp = 'media_player.test'
therm = 'thermostat.test'
zone = 'zone.home'
script_nc = 'script.cannot_cancel_this_one'
script_c = 'script.can_cancel_this_one'
def set_state(entity_id, state, **kwargs):
self.hass.states.set(entity_id, state, **kwargs)
@ -169,7 +172,7 @@ class TestComponentHistory(unittest.TestCase):
three = two + timedelta(seconds=1)
four = three + timedelta(seconds=1)
states = {therm: [], mp: []}
states = {therm: [], mp: [], script_c: []}
with patch('homeassistant.components.recorder.dt_util.utcnow',
return_value=one):
states[mp].append(
@ -186,6 +189,11 @@ class TestComponentHistory(unittest.TestCase):
# this state will be skipped only different in time
set_state(mp, 'YouTube',
attributes={'media_title': str(sentinel.mt3)})
# this state will be skipped because domain blacklisted
set_state(zone, 'zoning')
set_state(script_nc, 'off')
states[script_c].append(
set_state(script_c, 'off', attributes={'can_cancel': True}))
states[therm].append(
set_state(therm, 21, attributes={'current_temperature': 19.8}))
@ -199,4 +207,4 @@ class TestComponentHistory(unittest.TestCase):
set_state(therm, 21, attributes={'current_temperature': 20}))
hist = history.get_significant_states(zero, four)
self.assertEqual(states, hist)
assert states == hist