Exemplo n.º 1
0
def get_states(utc_point_in_time, entity_ids=None, run=None, filters=None):
    """Return the states at a specific point in time."""
    if run is None:
        run = recorder.run_information(utc_point_in_time)

        # History did not run before utc_point_in_time
        if run is None:
            return []

    from sqlalchemy import and_, func

    states = recorder.get_model('States')
    most_recent_state_ids = recorder.query(
        func.max(states.state_id).label('max_state_id')
    ).filter(
        (states.created >= run.start) &
        (states.created < utc_point_in_time) &
        (~states.domain.in_(IGNORE_DOMAINS)))
    if filters:
        most_recent_state_ids = filters.apply(most_recent_state_ids,
                                              entity_ids)

    most_recent_state_ids = most_recent_state_ids.group_by(
        states.entity_id).subquery()

    query = recorder.query('States').join(most_recent_state_ids, and_(
        states.state_id == most_recent_state_ids.c.max_state_id))

    for state in recorder.execute(query):
        if not state.attributes.get(ATTR_HIDDEN, False):
            yield state
Exemplo n.º 2
0
def get_states(utc_point_in_time, entity_ids=None, run=None):
    """Return the states at a specific point in time."""
    if run is None:
        run = recorder.run_information(utc_point_in_time)

        # History did not run before utc_point_in_time
        if run is None:
            return []

    from sqlalchemy import and_, func

    states = recorder.get_model("States")
    most_recent_state_ids = recorder.query(func.max(states.state_id).label("max_state_id")).filter(
        (states.created >= run.start) & (states.created < utc_point_in_time)
    )

    if entity_ids is not None:
        most_recent_state_ids = most_recent_state_ids.filter(states.entity_id.in_(entity_ids))

    most_recent_state_ids = most_recent_state_ids.group_by(states.entity_id).subquery()

    query = recorder.query("States").join(
        most_recent_state_ids, and_(states.state_id == most_recent_state_ids.c.max_state_id)
    )

    return recorder.execute(query)
Exemplo n.º 3
0
def get_significant_states(start_time,
                           end_time=None,
                           entity_id=None,
                           filters=None):
    """
    Return states changes during UTC period start_time - end_time.

    Significant states are all states where there is a state change,
    as well as all states from certain domains (for instance
    thermostat so that we get current temperature in our graphs).
    """
    entity_ids = (entity_id.lower(), ) if entity_id is not None else None
    states = recorder.get_model('States')
    query = recorder.query(
        states).filter((states.domain.in_(SIGNIFICANT_DOMAINS)
                        | (states.last_changed == states.last_updated))
                       & (states.last_updated > start_time))
    if filters:
        query = filters.apply(query, entity_ids)

    if end_time is not None:
        query = query.filter(states.last_updated < end_time)

    states = (state for state in recorder.execute(
        query.order_by(states.entity_id, states.last_updated))
              if (_is_significant(state)
                  and not state.attributes.get(ATTR_HIDDEN, False)))

    return states_to_json(states, start_time, entity_id, filters)
Exemplo n.º 4
0
def get_significant_states(start_time, end_time=None, entity_id=None):
    """
    Return states changes during UTC period start_time - end_time.

    Significant states are all states where there is a state change,
    as well as all states from certain domains (for instance
    thermostat so that we get current temperature in our graphs).
    """
    states = recorder.get_model("States")
    query = recorder.query("States").filter(
        (states.domain.in_(SIGNIFICANT_DOMAINS) | (states.last_changed == states.last_updated))
        & ((~states.domain.in_(IGNORE_DOMAINS)) & (states.last_updated > start_time))
    )

    if end_time is not None:
        query = query.filter(states.last_updated < end_time)

    if entity_id is not None:
        query = query.filter_by(entity_id=entity_id.lower())

    states = (
        state
        for state in recorder.execute(query.order_by(states.entity_id, states.last_updated))
        if _is_significant(state)
    )

    return states_to_json(states, start_time, entity_id)
Exemplo n.º 5
0
 def update(self):
     """Get the latest data and update the states."""
     data = self.speedtest_client.data
     if data is None:
         entity_id = 'sensor.speedtest_' + self._name.lower()
         states = recorder.get_model('States')
         try:
             last_state = recorder.execute(
                 recorder.query('States').filter(
                     (states.entity_id == entity_id)
                     & (states.last_changed == states.last_updated)
                     & (states.state != 'unknown')).order_by(
                         states.state_id.desc()).limit(1))
         except TypeError:
             return
         except RuntimeError:
             return
         if not last_state:
             return
         self._state = last_state[0].state
     elif self.type == 'ping':
         self._state = data['ping']
     elif self.type == 'download':
         self._state = data['download']
     elif self.type == 'upload':
         self._state = data['upload']
Exemplo n.º 6
0
def get_significant_states(start_time, end_time=None, entity_id=None,
                           filters=None):
    """
    Return states changes during UTC period start_time - end_time.

    Significant states are all states where there is a state change,
    as well as all states from certain domains (for instance
    thermostat so that we get current temperature in our graphs).
    """
    entity_ids = (entity_id.lower(), ) if entity_id is not None else None
    states = recorder.get_model('States')
    query = recorder.query('States').filter(
        (states.domain.in_(SIGNIFICANT_DOMAINS) |
         (states.last_changed == states.last_updated)) &
        (states.last_updated > start_time))
    if filters:
        query = filters.apply(query, entity_ids)

    if end_time is not None:
        query = query.filter(states.last_updated < end_time)

    states = (
        state for state in recorder.execute(
            query.order_by(states.entity_id, states.last_updated))
        if (_is_significant(state) and
            not state.attributes.get(ATTR_HIDDEN, False)))

    return states_to_json(states, start_time, entity_id, filters)
Exemplo n.º 7
0
 def update(self):
     """Get the latest data and update the states."""
     data = self.speedtest_client.data
     if data is None:
         entity_id = 'sensor.speedtest_' + self._name.lower()
         states = recorder.get_model('States')
         try:
             last_state = recorder.execute(
                 recorder.query('States').filter(
                     (states.entity_id == entity_id) &
                     (states.last_changed == states.last_updated) &
                     (states.state != 'unknown')
                 ).order_by(states.state_id.desc()).limit(1))
         except TypeError:
             return
         except RuntimeError:
             return
         if not last_state:
             return
         self._state = last_state[0].state
     elif self.type == 'ping':
         self._state = data['ping']
     elif self.type == 'download':
         self._state = data['download']
     elif self.type == 'upload':
         self._state = data['upload']
Exemplo n.º 8
0
    def test_saving_event(self):
        """Test saving and restoring an event."""
        event_type = 'EVENT_TEST'
        event_data = {'test_attr': 5, 'test_attr_10': 'nice'}

        events = []

        def event_listener(event):
            """Record events from eventbus."""
            if event.event_type == event_type:
                events.append(event)

        self.hass.bus.listen(MATCH_ALL, event_listener)

        self.hass.bus.fire(event_type, event_data)

        self.hass.block_till_done()
        recorder._INSTANCE.block_till_done()

        db_events = recorder.execute(
            recorder.query('Events').filter_by(event_type=event_type))

        assert len(events) == 1
        assert len(db_events) == 1

        event = events[0]
        db_event = db_events[0]

        assert event.event_type == db_event.event_type
        assert event.data == db_event.data
        assert event.origin == db_event.origin

        # Recorder uses SQLite and stores datetimes as integer unix timestamps
        assert event.time_fired.replace(microsecond=0) == \
            db_event.time_fired.replace(microsecond=0)
Exemplo n.º 9
0
def get_significant_states(start_time, end_time=None, entity_id=None):
    """
    Return states changes during UTC period start_time - end_time.

    Significant states are all states where there is a state change,
    as well as all states from certain domains (for instance
    thermostat so that we get current temperature in our graphs).
    """
    states = recorder.get_model('States')
    query = recorder.query(
        'States').filter((states.domain.in_(SIGNIFICANT_DOMAINS)
                          | (states.last_changed == states.last_updated))
                         & ((~states.domain.in_(IGNORE_DOMAINS))
                            & (states.last_updated > start_time)))

    if end_time is not None:
        query = query.filter(states.last_updated < end_time)

    if entity_id is not None:
        query = query.filter_by(entity_id=entity_id.lower())

    states = (state for state in recorder.execute(
        query.order_by(states.entity_id, states.last_updated))
              if _is_significant(state))

    return states_to_json(states, start_time, entity_id)
Exemplo n.º 10
0
 def get_results():
     """Query DB for results."""
     events = recorder.get_model('Events')
     query = recorder.query('Events').filter(
         (events.time_fired > start_day) &
         (events.time_fired < end_day))
     events = recorder.execute(query)
     return _exclude_events(events, self.config)
Exemplo n.º 11
0
 def get_results():
     """Query DB for results."""
     events = recorder.get_model('Events')
     query = recorder.query('Events').order_by(
         events.time_fired).filter((events.time_fired > start_day)
                                   & (events.time_fired < end_day))
     events = recorder.execute(query)
     return _exclude_events(events, self.config)
Exemplo n.º 12
0
    def test_purge_disabled(self):
        """Test leaving purge_days disabled."""
        self._add_test_states()
        self._add_test_events()
        # make sure we start with 5 states and events
        states = recorder.query('States')
        events = recorder.query('Events').filter(
            recorder.get_model('Events').event_type.like("EVENT_TEST%"))
        self.assertEqual(states.count(), 5)
        self.assertEqual(events.count(), 5)

        # run purge_old_data()
        recorder._INSTANCE.purge_days = None
        recorder._INSTANCE._purge_old_data()

        # we should have all of our states still
        self.assertEqual(states.count(), 5)
        self.assertEqual(events.count(), 5)
Exemplo n.º 13
0
def last_5_states(entity_id):
    """Return the last 5 states for entity_id."""
    entity_id = entity_id.lower()

    states = recorder.get_model('States')
    return recorder.execute(
        recorder.query('States').filter((states.entity_id == entity_id) & (
            states.last_changed == states.last_updated)).order_by(
                states.state_id.desc()).limit(5))
Exemplo n.º 14
0
    def test_purge_disabled(self):
        """Test leaving purge_days disabled."""
        self._add_test_states()
        self._add_test_events()
        # make sure we start with 5 states and events
        states = recorder.query('States')
        events = recorder.query('Events').filter(
            recorder.get_model('Events').event_type.like("EVENT_TEST%"))
        self.assertEqual(states.count(), 5)
        self.assertEqual(events.count(), 5)

        # run purge_old_data()
        recorder._INSTANCE.purge_days = None
        recorder._INSTANCE._purge_old_data()

        # we should have all of our states still
        self.assertEqual(states.count(), 5)
        self.assertEqual(events.count(), 5)
Exemplo n.º 15
0
def last_5_states(entity_id):
    """Return the last 5 states for entity_id."""
    entity_id = entity_id.lower()

    states = recorder.get_model('States')
    return recorder.execute(
        recorder.query('States').filter(
            (states.entity_id == entity_id) &
            (states.last_changed == states.last_updated)
        ).order_by(states.state_id.desc()).limit(5))
Exemplo n.º 16
0
def last_recorder_run():
    """Retireve the last closed recorder run from the DB."""
    recorder.get_instance()
    rec_runs = recorder.get_model('RecorderRuns')
    with recorder.session_scope() as session:
        res = recorder.query(rec_runs).order_by(rec_runs.end.desc()).first()
        if res is None:
            return None
        session.expunge(res)
        return res
Exemplo n.º 17
0
def last_recorder_run():
    """Retireve the last closed recorder run from the DB."""
    recorder.get_instance()
    rec_runs = recorder.get_model('RecorderRuns')
    with recorder.session_scope() as session:
        res = recorder.query(rec_runs).order_by(rec_runs.end.desc()).first()
        if res is None:
            return None
        session.expunge(res)
        return res
Exemplo n.º 18
0
def _add_entities(hass, entity_ids):
    """Add entities."""
    attributes = {'test_attr': 5, 'test_attr_10': 'nice'}
    for idx, entity_id in enumerate(entity_ids):
        hass.states.set(entity_id, 'state{}'.format(idx), attributes)
        hass.block_till_done()
    recorder._INSTANCE.block_till_done()
    db_states = recorder.query('States')
    states = recorder.execute(db_states)
    assert db_states[0].event_id is not None
    return states
Exemplo n.º 19
0
def _add_entities(hass, entity_ids):
    """Add entities."""
    attributes = {'test_attr': 5, 'test_attr_10': 'nice'}
    for idx, entity_id in enumerate(entity_ids):
        hass.states.set(entity_id, 'state{}'.format(idx), attributes)
        hass.block_till_done()
    recorder._INSTANCE.block_till_done()
    db_states = recorder.query('States')
    states = recorder.execute(db_states)
    assert db_states[0].event_id is not None
    return states
Exemplo n.º 20
0
    def get(self, request, datetime=None):
        """Retrieve logbook entries."""
        start_day = dt_util.as_utc(datetime or dt_util.start_of_local_day())
        end_day = start_day + timedelta(days=1)

        events = recorder.get_model('Events')
        query = recorder.query('Events').filter(
            (events.time_fired > start_day) &
            (events.time_fired < end_day))
        events = recorder.execute(query)

        return self.json(humanify(events))
Exemplo n.º 21
0
    def _add_test_events(self):
        """Add a few events for testing."""
        now = int(time.time())
        five_days_ago = now - (60*60*24*5)
        event_data = {'test_attr': 5, 'test_attr_10': 'nice'}

        self.hass.pool.block_till_done()
        recorder._INSTANCE.block_till_done()
        for event_id in range(5):
            if event_id < 2:
                timestamp = five_days_ago
                event_type = 'EVENT_TEST_PURGE'
            else:
                timestamp = now
                event_type = 'EVENT_TEST'
            recorder.query("INSERT INTO events"
                           "(event_type, event_data, origin, created,"
                           "time_fired, utc_offset)"
                           "VALUES (?, ?, ?, ?, ?, ?)",
                           (event_type, json.dumps(event_data), 'LOCAL',
                            timestamp, timestamp, -18000))
Exemplo n.º 22
0
    def get(self, request, datetime=None):
        """Retrieve logbook entries."""
        start_day = dt_util.as_utc(datetime or dt_util.start_of_local_day())
        end_day = start_day + timedelta(days=1)

        events = recorder.get_model('Events')
        query = recorder.query('Events').filter(
            (events.time_fired > start_day) &
            (events.time_fired < end_day))
        events = recorder.execute(query)

        return self.json(humanify(events))
Exemplo n.º 23
0
    def test_purge_old_events(self):
        """Test deleting old events."""
        self._add_test_events()
        events = recorder.query('Events').filter(
            recorder.get_model('Events').event_type.like("EVENT_TEST%"))
        self.assertEqual(events.count(), 5)

        # run purge_old_data()
        recorder._INSTANCE.purge_days = 4
        recorder._INSTANCE._purge_old_data()

        # now we should only have 3 events left
        self.assertEqual(events.count(), 3)
Exemplo n.º 24
0
    def test_purge_old_states(self):
        """Test deleting old states."""
        self._add_test_states()
        # make sure we start with 5 states
        states = recorder.query('States')
        self.assertEqual(states.count(), 5)

        # run purge_old_data()
        recorder._INSTANCE.purge_days = 4
        recorder._INSTANCE._purge_old_data()

        # we should only have 2 states left after purging
        self.assertEqual(states.count(), 2)
Exemplo n.º 25
0
    def test_purge_old_events(self):
        """Test deleting old events."""
        self._add_test_events()
        events = recorder.query('Events').filter(
            recorder.get_model('Events').event_type.like("EVENT_TEST%"))
        self.assertEqual(events.count(), 5)

        # run purge_old_data()
        recorder._INSTANCE.purge_days = 4
        recorder._INSTANCE._purge_old_data()

        # now we should only have 3 events left
        self.assertEqual(events.count(), 3)
Exemplo n.º 26
0
    def test_purge_old_states(self):
        """Test deleting old states."""
        self._add_test_states()
        # make sure we start with 5 states
        states = recorder.query('States')
        self.assertEqual(states.count(), 5)

        # run purge_old_data()
        recorder._INSTANCE.purge_days = 4
        recorder._INSTANCE._purge_old_data()

        # we should only have 2 states left after purging
        self.assertEqual(states.count(), 2)
Exemplo n.º 27
0
    def _add_test_states(self):
        """Add multiple states to the db for testing."""
        now = int(time.time())
        five_days_ago = now - (60*60*24*5)
        attributes = {'test_attr': 5, 'test_attr_10': 'nice'}

        self.hass.pool.block_till_done()
        recorder._INSTANCE.block_till_done()
        for event_id in range(5):
            if event_id < 3:
                timestamp = five_days_ago
                state = 'purgeme'
            else:
                timestamp = now
                state = 'dontpurgeme'
            recorder.query("INSERT INTO states ("
                           "entity_id, domain, state, attributes,"
                           "last_changed, last_updated, created,"
                           "utc_offset, event_id)"
                           "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)",
                           ('test.recorder2', 'sensor', state,
                            json.dumps(attributes), timestamp, timestamp,
                            timestamp, -18000, event_id + 1000))
Exemplo n.º 28
0
def state_changes_during_period(start_time, end_time=None, entity_id=None):
    """Return states changes during UTC period start_time - end_time."""
    states = recorder.get_model("States")
    query = recorder.query("States").filter(
        (states.last_changed == states.last_updated) & (states.last_changed > start_time)
    )

    if end_time is not None:
        query = query.filter(states.last_updated < end_time)

    if entity_id is not None:
        query = query.filter_by(entity_id=entity_id.lower())

    states = recorder.execute(query.order_by(states.entity_id, states.last_updated))

    return states_to_json(states, start_time, entity_id)
Exemplo n.º 29
0
def state_changes_during_period(start_time, end_time=None, entity_id=None):
    """Return states changes during UTC period start_time - end_time."""
    states = recorder.get_model('States')
    query = recorder.query('States').filter(
        (states.last_changed == states.last_updated) &
        (states.last_changed > start_time))

    if end_time is not None:
        query = query.filter(states.last_updated < end_time)

    if entity_id is not None:
        query = query.filter_by(entity_id=entity_id.lower())

    states = recorder.execute(
        query.order_by(states.entity_id, states.last_updated))

    return states_to_json(states, start_time, entity_id)
Exemplo n.º 30
0
    def test_saving_state(self):
        """Test saving and restoring a state."""
        entity_id = 'test.recorder'
        state = 'restoring_from_db'
        attributes = {'test_attr': 5, 'test_attr_10': 'nice'}

        self.hass.states.set(entity_id, state, attributes)

        self.hass.block_till_done()
        recorder._INSTANCE.block_till_done()

        db_states = recorder.query('States')
        states = recorder.execute(db_states)

        assert db_states[0].event_id is not None

        self.assertEqual(1, len(states))
        self.assertEqual(self.hass.states.get(entity_id), states[0])
Exemplo n.º 31
0
    def test_saving_state(self):
        """Test saving and restoring a state."""
        entity_id = 'test.recorder'
        state = 'restoring_from_db'
        attributes = {'test_attr': 5, 'test_attr_10': 'nice'}

        self.hass.states.set(entity_id, state, attributes)

        self.hass.block_till_done()
        recorder._INSTANCE.block_till_done()

        db_states = recorder.query('States')
        states = recorder.execute(db_states)

        assert db_states[0].event_id is not None

        self.assertEqual(1, len(states))
        self.assertEqual(self.hass.states.get(entity_id), states[0])
Exemplo n.º 32
0
    def test_saving_event(self):
        """Test saving and restoring an event."""
        event_type = 'EVENT_TEST'
        event_data = {'test_attr': 5, 'test_attr_10': 'nice'}

        events = []

        @callback
        def event_listener(event):
            """Record events from eventbus."""
            if event.event_type == event_type:
                events.append(event)

        self.hass.bus.listen(MATCH_ALL, event_listener)

        self.hass.bus.fire(event_type, event_data)

        self.hass.block_till_done()
        recorder._INSTANCE.block_till_done()

        db_events = recorder.execute(
            recorder.query('Events').filter_by(
                event_type=event_type))

        assert len(events) == 1
        assert len(db_events) == 1

        event = events[0]
        db_event = db_events[0]

        assert event.event_type == db_event.event_type
        assert event.data == db_event.data
        assert event.origin == db_event.origin

        # Recorder uses SQLite and stores datetimes as integer unix timestamps
        assert event.time_fired.replace(microsecond=0) == \
            db_event.time_fired.replace(microsecond=0)
Exemplo n.º 33
0
    def _restore_states(service):
        """Restore states."""
        run = recorder.run_information(dt_util.utcnow())
        if run is None:
            return

        from sqlalchemy import and_, func

        states = recorder.get_model('States')
        most_recent_state_ids = recorder.query(
            func.max(states.state_id).label('max_state_id'))

        most_recent_state_ids = most_recent_state_ids.group_by(
            states.entity_id).subquery()

        query = recorder.query('States').join(
            most_recent_state_ids,
            and_(states.state_id == most_recent_state_ids.c.max_state_id))

        states = recorder.execute(query)

        data = {ATTR_ENTITY_ID: 'group.all_automations'}
        hass.services.call('homeassistant', SERVICE_TURN_OFF, data, True)

        last_services = []
        for state in states:
            if state.domain == group.DOMAIN:
                continue
            if state.domain == input_number.DOMAIN:
                data = {
                    ATTR_ENTITY_ID: state.entity_id,
                    input_number.ATTR_VALUE: state.state
                }
                service = input_number.SERVICE_SELECT_VALUE
            elif state.domain == input_select.DOMAIN:
                data = {
                    ATTR_ENTITY_ID: state.entity_id,
                    input_select.ATTR_OPTION: state.state
                }
                service = input_select.SERVICE_SELECT_OPTION
            elif state.domain == climate.DOMAIN:
                data = {
                    ATTR_ENTITY_ID: state.entity_id,
                    climate.ATTR_TEMPERATURE:
                    state.attributes.get('temperature')
                }
                service = climate.SERVICE_SET_TEMPERATURE
            elif (state.domain in [input_boolean.DOMAIN, automation.DOMAIN]):
                #or state.attributes.get('assumed_state')):
                data = {ATTR_ENTITY_ID: state.entity_id}
                if state.state == STATE_OFF:
                    service = SERVICE_TURN_OFF
                if state.state == STATE_ON:
                    service = SERVICE_TURN_ON
                else:
                    continue
                if state.domain == light.DOMAIN:
                    continue
                if state.domain == automation.DOMAIN:
                    last_services.append((state.domain, service, data))
                    continue
            elif (state.domain in [switch.DOMAIN]):
                continue
            else:
                continue
            if hass.states.get(state.entity_id) is None:
                continue
            hass.services.call(state.domain, service, data, True)

        for (domain, service, data) in last_services:
            hass.services.call(domain, service, data, True)