Пример #1
0
    def test_get_significant_states_only(self):
        """Test significant states when significant_states_only is set."""
        self.test_setup()
        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]
Пример #2
0
    def test_get_significant_states_with_initial(self):
        """Test that only significant states are returned.

        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).
        """
        zero, four, states = self.record_states()
        one = zero + timedelta(seconds=1)
        one_and_half = zero + timedelta(seconds=1.5)
        for entity_id in states:
            if entity_id == "media_player.test":
                states[entity_id] = states[entity_id][1:]
            for state in states[entity_id]:
                if state.last_changed == one:
                    state.last_changed = one_and_half

        hist = history.get_significant_states(
            self.hass,
            one_and_half,
            four,
            filters=history.Filters(),
            include_start_time_state=True,
        )
        assert states == hist
Пример #3
0
    def test_get_significant_states(self):
        """test that only significant states are returned with
        get_significant_states.

        We inject a bunch of state updates from media player 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).

        """
        self.init_recorder()
        mp = 'media_player.test'
        therm = 'thermostat.test'

        def set_state(entity_id, state, **kwargs):
            self.hass.states.set(entity_id, state, **kwargs)
            self.wait_recording_done()
            return self.hass.states.get(entity_id)

        zero = dt_util.utcnow()
        one = zero + timedelta(seconds=1)
        two = one + timedelta(seconds=1)
        three = two + timedelta(seconds=1)
        four = three + timedelta(seconds=1)

        states = {therm: [], mp: []}
        with patch('homeassistant.components.recorder.dt_util.utcnow',
                   return_value=one):
            states[mp].append(
                set_state(mp,
                          'idle',
                          attributes={'media_title': str(sentinel.mt1)}))
            states[mp].append(
                set_state(mp,
                          'YouTube',
                          attributes={'media_title': str(sentinel.mt2)}))
            states[therm].append(
                set_state(therm, 20, attributes={'current_temperature': 19.5}))

        with patch('homeassistant.components.recorder.dt_util.utcnow',
                   return_value=two):
            # this state will be skipped only different in time
            set_state(mp,
                      'YouTube',
                      attributes={'media_title': str(sentinel.mt3)})
            states[therm].append(
                set_state(therm, 21, attributes={'current_temperature': 19.8}))

        with patch('homeassistant.components.recorder.dt_util.utcnow',
                   return_value=three):
            states[mp].append(
                set_state(mp,
                          'Netflix',
                          attributes={'media_title': str(sentinel.mt4)}))
            # attributes changed even though state is the same
            states[therm].append(
                set_state(therm, 21, attributes={'current_temperature': 20}))

        hist = history.get_significant_states(zero, four)
        self.assertEqual(states, hist)
Пример #4
0
    def test_get_significant_states_minimal_response(self):
        """Test that only significant states are returned.

        When minimal responses is set only the first and
        last states return a complete state.

        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).
        """
        zero, four, states = self.record_states()
        hist = history.get_significant_states(self.hass,
                                              zero,
                                              four,
                                              filters=history.Filters(),
                                              minimal_response=True)

        # The second media_player.test state is reduced
        # down to last_changed and state when minimal_response
        # is set.  We use JSONEncoder to make sure that are
        # pre-encoded last_changed is always the same as what
        # will happen with encoding a native state
        input_state = states["media_player.test"][1]
        orig_last_changed = json.dumps(
            process_timestamp(input_state.last_changed),
            cls=JSONEncoder,
        ).replace('"', "")
        orig_state = input_state.state
        states["media_player.test"][1] = {
            "last_changed": orig_last_changed,
            "state": orig_state,
        }

        assert states == hist
Пример #5
0
def test_get_significant_states_without_initial(hass_history):
    """Test that only significant states are returned.

    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).
    """
    hass = hass_history
    zero, four, states = record_states(hass)
    one = zero + timedelta(seconds=1)
    one_and_half = zero + timedelta(seconds=1.5)
    for entity_id in states:
        states[entity_id] = list(
            filter(lambda s: s.last_changed != one, states[entity_id])
        )
    del states["media_player.test2"]

    hist = history.get_significant_states(
        hass,
        one_and_half,
        four,
        filters=history.Filters(),
        include_start_time_state=False,
    )
    assert states == hist
Пример #6
0
    def test_get_significant_states_are_ordered(self):
        """Test order of results from get_significant_states.

        When entity ids are given, the results should be returned with the data
        in the same order.
        """
        zero, four, states = self.record_states()
        entity_ids = ["media_player.test", "media_player.test2"]
        hist = history.get_significant_states(
            self.hass, zero, four, entity_ids, filters=history.Filters()
        )
        assert list(hist.keys()) == entity_ids
        entity_ids = ["media_player.test2", "media_player.test"]
        hist = history.get_significant_states(
            self.hass, zero, four, entity_ids, filters=history.Filters()
        )
        assert list(hist.keys()) == entity_ids
Пример #7
0
    def test_get_significant_states(self):
        """test that only significant states are returned with
        get_significant_states.

        We inject a bunch of state updates from media player 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).

        """
        self.init_recorder()
        mp = 'media_player.test'
        therm = 'thermostat.test'

        def set_state(entity_id, state, **kwargs):
            self.hass.states.set(entity_id, state, **kwargs)
            self.wait_recording_done()
            return self.hass.states.get(entity_id)

        zero = dt_util.utcnow()
        one = zero + timedelta(seconds=1)
        two = one + timedelta(seconds=1)
        three = two + timedelta(seconds=1)
        four = three + timedelta(seconds=1)

        states = {therm: [], mp: []}
        with patch('homeassistant.components.recorder.dt_util.utcnow',
                   return_value=one):
            states[mp].append(
                set_state(mp, 'idle',
                          attributes={'media_title': str(sentinel.mt1)}))
            states[mp].append(
                set_state(mp, 'YouTube',
                          attributes={'media_title': str(sentinel.mt2)}))
            states[therm].append(
                set_state(therm, 20, attributes={'current_temperature': 19.5}))

        with patch('homeassistant.components.recorder.dt_util.utcnow',
                   return_value=two):
            # this state will be skipped only different in time
            set_state(mp, 'YouTube',
                      attributes={'media_title': str(sentinel.mt3)})
            states[therm].append(
                set_state(therm, 21, attributes={'current_temperature': 19.8}))

        with patch('homeassistant.components.recorder.dt_util.utcnow',
                   return_value=three):
            states[mp].append(
                set_state(mp, 'Netflix',
                          attributes={'media_title': str(sentinel.mt4)}))
            # attributes changed even though state is the same
            states[therm].append(
                set_state(therm, 21, attributes={'current_temperature': 20}))

        hist = history.get_significant_states(zero, four)
        self.assertEqual(states, hist)
Пример #8
0
    def test_get_significant_states_multiple_entity_ids(self):
        """Test that only significant states are returned for one entity."""
        zero, four, states = self.record_states()
        del states['media_player.test2']
        del states['thermostat.test2']
        del states['script.can_cancel_this_one']

        hist = history.get_significant_states(
            self.hass, zero, four, ['media_player.test', 'thermostat.test'],
            filters=history.Filters())
        assert states == hist
Пример #9
0
    def test_get_significant_states(self):
        """Test that only significant states are returned.

        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).
        """
        zero, four, states = self.record_states()
        hist = history.get_significant_states(
            self.hass, zero, four, filters=history.Filters())
        assert states == hist
Пример #10
0
    def test_get_significant_states(self):
        """Test that only significant states are returned.

        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).
        """
        zero, four, states = self.record_states()
        hist = history.get_significant_states(
            self.hass, zero, four, filters=history.Filters())
        assert states == hist
Пример #11
0
    def test_get_significant_states_multiple_entity_ids(self):
        """Test that only significant states are returned for one entity."""
        zero, four, states = self.record_states()
        del states['media_player.test2']
        del states['thermostat.test2']
        del states['script.can_cancel_this_one']

        hist = history.get_significant_states(
            self.hass, zero, four, ['media_player.test', 'thermostat.test'],
            filters=history.Filters())
        assert states == hist
Пример #12
0
    def test_get_significant_states_entity_id(self):
        """Test that only significant states are returned for one entity."""
        zero, four, states = self.record_states()
        del states["media_player.test2"]
        del states["thermostat.test"]
        del states["thermostat.test2"]
        del states["script.can_cancel_this_one"]

        hist = history.get_significant_states(
            self.hass, zero, four, ["media_player.test"], filters=history.Filters()
        )
        assert states == hist
Пример #13
0
    def check_significant_states(self, zero, four, states, config):
        """Check if significant states are retrieved."""
        filters = history.Filters()
        exclude = config[history.DOMAIN].get(history.CONF_EXCLUDE)
        if exclude:
            filters.excluded_entities = exclude.get(history.CONF_ENTITIES, [])
            filters.excluded_domains = exclude.get(history.CONF_DOMAINS, [])
        include = config[history.DOMAIN].get(history.CONF_INCLUDE)
        if include:
            filters.included_entities = include.get(history.CONF_ENTITIES, [])
            filters.included_domains = include.get(history.CONF_DOMAINS, [])

        hist = history.get_significant_states(self.hass, zero, four, filters=filters)
        assert states == hist
Пример #14
0
    def check_significant_states(self, zero, four, states, config):
        """Check if significant states are retrieved."""
        filters = history.Filters()
        exclude = config[history.DOMAIN].get(history.CONF_EXCLUDE)
        if exclude:
            filters.excluded_entities = exclude[history.CONF_ENTITIES]
            filters.excluded_domains = exclude[history.CONF_DOMAINS]
        include = config[history.DOMAIN].get(history.CONF_INCLUDE)
        if include:
            filters.included_entities = include[history.CONF_ENTITIES]
            filters.included_domains = include[history.CONF_DOMAINS]

        hist = history.get_significant_states(zero, four, filters=filters)
        assert states == hist
Пример #15
0
    def check_significant_states(self, zero, four, states, config): \
            # pylint: disable=no-self-use
        """Check if significant states are retrieved."""
        filters = history.Filters()
        exclude = config[history.DOMAIN].get(history.CONF_EXCLUDE)
        if exclude:
            filters.excluded_entities = exclude[history.CONF_ENTITIES]
            filters.excluded_domains = exclude[history.CONF_DOMAINS]
        include = config[history.DOMAIN].get(history.CONF_INCLUDE)
        if include:
            filters.included_entities = include[history.CONF_ENTITIES]
            filters.included_domains = include[history.CONF_DOMAINS]

        hist = history.get_significant_states(zero, four, filters=filters)
        assert states == hist
Пример #16
0
    def check_significant_states(self, zero, four, states, config): \
            # pylint: disable=no-self-use
        """Check if significant states are retrieved."""
        filters = history.Filters()
        exclude = config[history.DOMAIN].get(history.CONF_EXCLUDE)
        if exclude:
            filters.excluded_entities = exclude.get(history.CONF_ENTITIES, [])
            filters.excluded_domains = exclude.get(history.CONF_DOMAINS, [])
        include = config[history.DOMAIN].get(history.CONF_INCLUDE)
        if include:
            filters.included_entities = include.get(history.CONF_ENTITIES, [])
            filters.included_domains = include.get(history.CONF_DOMAINS, [])

        hist = history.get_significant_states(
            self.hass, zero, four, filters=filters)
        assert states == hist
Пример #17
0
def test_get_significant_states_multiple_entity_ids(hass_history):
    """Test that only significant states are returned for one entity."""
    hass = hass_history
    zero, four, states = record_states(hass)
    del states["media_player.test2"]
    del states["media_player.test3"]
    del states["thermostat.test2"]
    del states["script.can_cancel_this_one"]

    hist = history.get_significant_states(
        hass,
        zero,
        four,
        ["media_player.test", "thermostat.test"],
        filters=history.Filters(),
    )
    assert states == hist
Пример #18
0
    def test_get_significant_states_without_initial(self):
        """Test that only significant states are returned.

        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).
        """
        zero, four, states = self.record_states()
        one = zero + timedelta(seconds=1)
        one_and_half = zero + timedelta(seconds=1.5)
        for entity_id in states:
            states[entity_id] = list(filter(
                lambda s: s.last_changed != one, states[entity_id]))
        del states['media_player.test2']

        hist = history.get_significant_states(
            self.hass, one_and_half, four, filters=history.Filters(),
            include_start_time_state=False)
        assert states == hist
Пример #19
0
    def test_get_significant_states_with_initial(self):
        """Test that only significant states are returned.

        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).
        """
        zero, four, states = self.record_states()
        one = zero + timedelta(seconds=1)
        one_and_half = zero + timedelta(seconds=1.5)
        for entity_id in states:
            if entity_id == 'media_player.test':
                states[entity_id] = states[entity_id][1:]
            for state in states[entity_id]:
                if state.last_changed == one:
                    state.last_changed = one_and_half

        hist = history.get_significant_states(
            self.hass, one_and_half, four, filters=history.Filters(),
            include_start_time_state=True)
        assert states == hist
Пример #20
0
    def test_get_significant_states(self):
        """Test that only significant states are returned.

        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).
        """
        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)
            self.wait_recording_done()
            return self.hass.states.get(entity_id)

        zero = dt_util.utcnow()
        one = zero + timedelta(seconds=1)
        two = one + timedelta(seconds=1)
        three = two + timedelta(seconds=1)
        four = three + timedelta(seconds=1)

        states = {therm: [], mp: [], script_c: []}
        with patch('homeassistant.components.recorder.dt_util.utcnow',
                   return_value=one):
            states[mp].append(
                set_state(mp,
                          'idle',
                          attributes={'media_title': str(sentinel.mt1)}))
            states[mp].append(
                set_state(mp,
                          'YouTube',
                          attributes={'media_title': str(sentinel.mt2)}))
            states[therm].append(
                set_state(therm, 20, attributes={'current_temperature': 19.5}))

        with patch('homeassistant.components.recorder.dt_util.utcnow',
                   return_value=two):
            # 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}))

        with patch('homeassistant.components.recorder.dt_util.utcnow',
                   return_value=three):
            states[mp].append(
                set_state(mp,
                          'Netflix',
                          attributes={'media_title': str(sentinel.mt4)}))
            # Attributes changed even though state is the same
            states[therm].append(
                set_state(therm, 21, attributes={'current_temperature': 20}))

        hist = history.get_significant_states(zero, four)
        assert states == hist
Пример #21
0
    def test_get_significant_states(self):
        """Test that only significant states are returned.

        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).
        """
        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)
            self.wait_recording_done()
            return self.hass.states.get(entity_id)

        zero = dt_util.utcnow()
        one = zero + timedelta(seconds=1)
        two = one + timedelta(seconds=1)
        three = two + timedelta(seconds=1)
        four = three + timedelta(seconds=1)

        states = {therm: [], mp: [], script_c: []}
        with patch('homeassistant.components.recorder.dt_util.utcnow',
                   return_value=one):
            states[mp].append(
                set_state(mp, 'idle',
                          attributes={'media_title': str(sentinel.mt1)}))
            states[mp].append(
                set_state(mp, 'YouTube',
                          attributes={'media_title': str(sentinel.mt2)}))
            states[therm].append(
                set_state(therm, 20, attributes={'current_temperature': 19.5}))

        with patch('homeassistant.components.recorder.dt_util.utcnow',
                   return_value=two):
            # 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}))

        with patch('homeassistant.components.recorder.dt_util.utcnow',
                   return_value=three):
            states[mp].append(
                set_state(mp, 'Netflix',
                          attributes={'media_title': str(sentinel.mt4)}))
            # Attributes changed even though state is the same
            states[therm].append(
                set_state(therm, 21, attributes={'current_temperature': 20}))

        hist = history.get_significant_states(zero, four)
        assert states == hist
Пример #22
0
    async def handle_presence_simulation(call,
                                         restart=False,
                                         entities_after_restart=None,
                                         delta_after_restart=None):
        """Start the presence simulation"""
        if call is not None:  #if we are here, it is a call of the service, or a restart at the end of a cycle
            if isinstance(call.data.get("entity_id", entities), list):
                overridden_entities = call.data.get("entity_id", entities)
            else:
                overridden_entities = [call.data.get("entity_id", entities)]
            overridden_delta = call.data.get("delta", delta)
            overridden_restore = call.data.get("restore_states",
                                               restoreAfterStop)
        else:  #if we are it is a call from the toggle service or from the turn_on action of the switch entity
            # or this is a restart and the simulation was launched after a restart of HA
            if entities_after_restart is not None:
                overridden_entities = entities_after_restart
            else:
                overridden_entities = entities
            if delta_after_restart is not None:
                overridden_delta = delta_after_restart
            else:
                overridden_delta = delta
            overridden_restore = restoreAfterStop

        #get the switch entity
        entity = hass.data[DOMAIN][SWITCH_PLATFORM][SWITCH]
        _LOGGER.debug("Is already running ? %s", entity.state)
        if is_running():
            _LOGGER.warning(
                "Presence simulation already running. Doing nothing")
            return
        running = True
        #turn on the switch. Not calling turn_on() to avoid calling the start service again
        entity.internal_turn_on()
        _LOGGER.debug("setting restore states %s", overridden_restore)
        await entity.set_restore_states(overridden_restore)
        _LOGGER.debug("Presence simulation started")

        current_date = datetime.now(timezone.utc)
        #compute the start date that will be used in the query to get the historic of the entities
        minus_delta = current_date + timedelta(-overridden_delta)
        #expand the entitiies, meaning replace the groups with the entities in it
        try:
            expanded_entities = await async_expand_entities(overridden_entities
                                                            )
        except Exception as e:
            _LOGGER.error("Error during identifing entities")
            running = False
            entity.internal_turn_off()
            return

        if not restart:
            #set attribute on the switch
            try:
                await entity.set_start_datetime(
                    datetime.now(hass.config.time_zone))
            except Exception as e:
                _LOGGER.error(
                    "Start datetime could not be set to HA timezone: ", e)
                await entity.set_start_datetime(datetime.now())
            if overridden_restore:
                service_data = {}
                service_data["scene_id"] = RESTORE_SCENE
                service_data["snapshot_entities"] = expanded_entities
                _LOGGER.debug("Saving scene before launching the simulation")
                try:
                    await hass.services.async_call("scene",
                                                   "create",
                                                   service_data,
                                                   blocking=True)
                except Exception as e:
                    _LOGGER.error(
                        "Scene could not be created, continue without the restore functionality: %s",
                        e)

        await entity.set_entities(expanded_entities)
        await entity.set_delta(overridden_delta)
        _LOGGER.debug("Getting the historic from %s for %s", minus_delta,
                      expanded_entities)
        dic = history.get_significant_states(hass=hass,
                                             start_time=minus_delta,
                                             entity_ids=expanded_entities,
                                             significant_changes_only=False)
        _LOGGER.debug("history: %s", dic)
        for entity_id in dic:
            _LOGGER.debug('Entity %s', entity_id)
            #launch an async task by entity_id
            hass.async_create_task(
                simulate_single_entity(entity_id, dic[entity_id]))

        #launch an async task that will restart the simulation after the delay has passed
        hass.async_create_task(
            restart_presence_simulation(
                call,
                entities_after_restart=entities_after_restart,
                delta_after_restart=delta_after_restart))
        _LOGGER.debug("All async tasks launched")