def test_get_states(self): """Test getting states at a specific point in time.""" self.test_setup() states = [] now = dt_util.utcnow() with patch( "homeassistant.components.recorder.dt_util.utcnow", return_value=now ): for i in range(5): state = ha.State( "test.point_in_time_{}".format(i % 5), f"State {i}", {"attribute_test": i}, ) mock_state_change_event(self.hass, state) states.append(state) wait_recording_done(self.hass) future = now + timedelta(seconds=1) with patch( "homeassistant.components.recorder.dt_util.utcnow", return_value=future ): for i in range(5): state = ha.State( "test.point_in_time_{}".format(i % 5), f"State {i}", {"attribute_test": i}, ) mock_state_change_event(self.hass, state) wait_recording_done(self.hass) # Get states returns everything before POINT for state1, state2 in zip( states, sorted( history.get_states(self.hass, future), key=lambda state: state.entity_id ), ): assert state1 == state2 # Test get_state here because we have a DB setup assert states[0] == history.get_state(self.hass, future, states[0].entity_id) time_before_recorder_ran = now - timedelta(days=1000) assert history.get_states(self.hass, time_before_recorder_ran) == [] assert history.get_state(self.hass, time_before_recorder_ran, "demo.id") is None
def test_get_states(self): """ Test getting states at a specific point in time. """ self.init_recorder() states = [] for i in range(5): state = ha.State('test.point_in_time_{}'.format(i % 5), "State {}".format(i), {'attribute_test': i}) mock_state_change_event(self.hass, state) self.hass.pool.block_till_done() states.append(state) recorder._INSTANCE.block_till_done() point = dt_util.utcnow() + timedelta(seconds=1) with patch('homeassistant.util.dt.utcnow', return_value=point): for i in range(5): state = ha.State('test.point_in_time_{}'.format(i % 5), "State {}".format(i), {'attribute_test': i}) mock_state_change_event(self.hass, state) self.hass.pool.block_till_done() # Get states returns everything before POINT self.assertEqual( states, sorted(history.get_states(point), key=lambda state: state.entity_id)) # Test get_state here because we have a DB setup self.assertEqual(states[0], history.get_state(point, states[0].entity_id))
def test_get_states(self): """ Test getting states at a specific point in time. """ self.init_recorder() states = [] # Create 10 states for 5 different entities # After the first 5, sleep a second and save the time # history.get_states takes the latest states BEFORE point X for i in range(10): state = ha.State('test.point_in_time_{}'.format(i % 5), "State {}".format(i), {'attribute_test': i}) mock_state_change_event(self.hass, state) self.hass.pool.block_till_done() recorder._INSTANCE.block_till_done() if i < 5: states.append(state) if i == 4: time.sleep(1) point = dt_util.utcnow() self.assertEqual( states, sorted(history.get_states(point), key=lambda state: state.entity_id)) # Test get_state here because we have a DB setup self.assertEqual(states[0], history.get_state(point, states[0].entity_id))
def test_get_states(self): """ Test getting states at a specific point in time. """ self.init_recorder() states = [] # Create 10 states for 5 different entities # After the first 5, sleep a second and save the time # history.get_states takes the latest states BEFORE point X for i in range(10): state = ha.State("test.point_in_time_{}".format(i % 5), "State {}".format(i), {"attribute_test": i}) mock_state_change_event(self.hass, state) self.hass.pool.block_till_done() recorder._INSTANCE.block_till_done() if i < 5: states.append(state) if i == 4: time.sleep(1) point = dt_util.utcnow() self.assertEqual(states, sorted(history.get_states(point), key=lambda state: state.entity_id)) # Test get_state here because we have a DB setup self.assertEqual(states[0], history.get_state(point, states[0].entity_id))
def _get_states(self, entity_ids, timestamp): """Get the current states for entity_ids.""" _LOGGER.debug('%s._get_states()') states = {} for entity_id in entity_ids: state = history.get_state(self._hass, timestamp, entity_id) if state: states[entity_id] = state return states
def update(self): """Get the latest data and updates the states.""" # Parse templates self.update_period() start, end = self._period # Convert to UTC start = dt_util.as_utc(start) end = dt_util.as_utc(end) # Get history between start and end history_list = history.state_changes_during_period( self.hass, start, end, str(self._entity_id)) if self._entity_id not in history_list.keys(): return # Get the first state last_state = history.get_state(self.hass, start, self._entity_id) last_state = (last_state is not None and last_state == self._entity_state) last_time = dt_util.as_timestamp(start) elapsed = 0 count = 0 # Make calculations for item in history_list.get(self._entity_id): current_state = item.state == self._entity_state current_time = item.last_changed.timestamp() if last_state: elapsed += current_time - last_time if current_state and not last_state: count += 1 last_state = current_state last_time = current_time # Count time elapsed between last history state and end of measure if last_state: measure_end = min(dt_util.as_timestamp(end), dt_util.as_timestamp( datetime.datetime.now())) elapsed += measure_end - last_time # Save value in hours self.value = elapsed / 3600 # Save counter self.count = count
def update(self): """Get the latest data and updates the states.""" # Parse templates self.update_period() start, end = self._period # Convert to UTC start = dt_util.as_utc(start) end = dt_util.as_utc(end) # Get history between start and end history_list = history.state_changes_during_period( self.hass, start, end, str(self._entity_id)) if self._entity_id not in history_list.keys(): return # Get the first state last_state = history.get_state(self.hass, start, self._entity_id) last_state = (last_state is not None and last_state == self._entity_state) last_time = dt_util.as_timestamp(start) elapsed = 0 count = 0 # Make calculations for item in history_list.get(self._entity_id): current_state = item.state == self._entity_state current_time = item.last_changed.timestamp() if last_state: elapsed += current_time - last_time if current_state and not last_state: count += 1 last_state = current_state last_time = current_time # Count time elapsed between last history state and end of measure if last_state: measure_end = min(dt_util.as_timestamp(end), dt_util.as_timestamp(datetime.datetime.now())) elapsed += measure_end - last_time # Save value in hours self.value = elapsed / 3600 # Save counter self.count = count
def test_get_states(self): """Test getting states at a specific point in time.""" self.init_recorder() states = [] now = dt_util.utcnow() with patch('homeassistant.components.recorder.dt_util.utcnow', return_value=now): for i in range(5): state = ha.State( 'test.point_in_time_{}'.format(i % 5), "State {}".format(i), {'attribute_test': i}) mock_state_change_event(self.hass, state) states.append(state) self.wait_recording_done() future = now + timedelta(seconds=1) with patch('homeassistant.components.recorder.dt_util.utcnow', return_value=future): for i in range(5): state = ha.State( 'test.point_in_time_{}'.format(i % 5), "State {}".format(i), {'attribute_test': i}) mock_state_change_event(self.hass, state) self.wait_recording_done() # Get states returns everything before POINT for state1, state2 in zip( states, sorted(history.get_states(self.hass, future), key=lambda state: state.entity_id)): assert state1 == state2 # Test get_state here because we have a DB setup self.assertEqual( states[0], history.get_state(self.hass, future, states[0].entity_id))
def _update(self, start, end, now_timestamp, start_timestamp, end_timestamp): # Get history between start and end history_list = history.state_changes_during_period( self.hass, start, end, str(self._entity_id)) if self._entity_id not in history_list: return # Get the first state last_state = history.get_state(self.hass, start, self._entity_id) last_state = last_state is not None and last_state in self._entity_states last_time = start_timestamp elapsed = 0 count = 0 # Make calculations for item in history_list.get(self._entity_id): current_state = item.state in self._entity_states current_time = item.last_changed.timestamp() if last_state: elapsed += current_time - last_time if current_state and not last_state: count += 1 last_state = current_state last_time = current_time # Count time elapsed between last history state and end of measure if last_state: measure_end = min(end_timestamp, now_timestamp) elapsed += measure_end - last_time # Save value in hours self.value = elapsed / 3600 # Save counter self.count = count
def test_get_states(self): """ Test getting states at a specific point in time. """ self.init_recorder() states = [] for i in range(5): state = ha.State( 'test.point_in_time_{}'.format(i % 5), "State {}".format(i), {'attribute_test': i}) mock_state_change_event(self.hass, state) self.hass.pool.block_till_done() states.append(state) recorder._INSTANCE.block_till_done() point = dt_util.utcnow() + timedelta(seconds=1) with patch('homeassistant.util.dt.utcnow', return_value=point): for i in range(5): state = ha.State( 'test.point_in_time_{}'.format(i % 5), "State {}".format(i), {'attribute_test': i}) mock_state_change_event(self.hass, state) self.hass.pool.block_till_done() # Get states returns everything before POINT self.assertEqual(states, sorted(history.get_states(point), key=lambda state: state.entity_id)) # Test get_state here because we have a DB setup self.assertEqual( states[0], history.get_state(point, states[0].entity_id))
def update(self): """Get the latest data and updates the states.""" # Parse templates self.update_period() start, end = self._period # Convert to UTC start = dt_util.as_utc(start) end = dt_util.as_utc(end) # Get history between start and end history_list = history.state_changes_during_period( start, end, str(self._entity_id)) if self._entity_id not in history_list.keys(): return # Get the first state last_state = history.get_state(start, self._entity_id) last_state = (last_state is not None and last_state == self._entity_state) last_time = dt_util.as_timestamp(start) elapsed = 0 # Make calculations for item in history_list.get(self._entity_id): current_state = item.state == self._entity_state current_time = item.last_changed.timestamp() if last_state: elapsed += current_time - last_time last_state = current_state last_time = current_time # Save value in hours self.value = elapsed / 3600
def update(self): """Get the latest data and updates the states.""" # Get previous values of start and end p_start, p_end = self._period # Parse templates self.update_period() start, end = self._period # Convert times to UTC start = dt_util.as_utc(start) end = dt_util.as_utc(end) p_start = dt_util.as_utc(p_start) p_end = dt_util.as_utc(p_end) now = datetime.datetime.now() # Compute integer timestamps start_timestamp = math.floor(dt_util.as_timestamp(start)) end_timestamp = math.floor(dt_util.as_timestamp(end)) p_start_timestamp = math.floor(dt_util.as_timestamp(p_start)) p_end_timestamp = math.floor(dt_util.as_timestamp(p_end)) now_timestamp = math.floor(dt_util.as_timestamp(now)) # If period has not changed and current time after the period end... if start_timestamp == p_start_timestamp and \ end_timestamp == p_end_timestamp and \ end_timestamp <= now_timestamp: # Don't compute anything as the value cannot have changed return # Get history between start and end history_list = history.state_changes_during_period( self.hass, start, end, str(self._entity_id)) if self._entity_id not in history_list.keys(): return # Get the first state last_state = history.get_state(self.hass, start, self._entity_id) last_state = (last_state is not None and last_state == self._entity_state) last_time = start_timestamp elapsed = 0 count = 0 # Make calculations for item in history_list.get(self._entity_id): current_state = item.state == self._entity_state current_time = item.last_changed.timestamp() if last_state: elapsed += current_time - last_time if current_state and not last_state: count += 1 last_state = current_state last_time = current_time # Count time elapsed between last history state and end of measure if last_state: measure_end = min(end_timestamp, now_timestamp) elapsed += measure_end - last_time # Save value in hours self.value = elapsed / 3600 # Save counter self.count = count
def _update_state(self): # pylint: disable=r0914,r0912,r0915 """Update the sensor state.""" _LOGGER.debug('Updating sensor "%s"', self.name) start = end = start_ts = end_ts = None p_period = self._period # Parse templates self._update_period() if self._period is not None: now = datetime.datetime.now() start, end = self._period if p_period is None: p_start = p_end = now else: p_start, p_end = p_period # Convert times to UTC start = dt_util.as_utc(start) end = dt_util.as_utc(end) p_start = dt_util.as_utc(p_start) p_end = dt_util.as_utc(p_end) # Compute integer timestamps now_ts = math.floor(dt_util.as_timestamp(now)) start_ts = math.floor(dt_util.as_timestamp(start)) end_ts = math.floor(dt_util.as_timestamp(end)) p_start_ts = math.floor(dt_util.as_timestamp(p_start)) p_end_ts = math.floor(dt_util.as_timestamp(p_end)) # If period has not changed and current time after the period end.. if start_ts == p_start_ts and end_ts == p_end_ts and end_ts <= now_ts: # Don't compute anything as the value cannot have changed return self.available_sources = 0 values = [] self.count = 0 self.min_value = self.max_value = None # pylint: disable=too-many-nested-blocks for entity_id in self.sources: _LOGGER.debug('Processing entity "%s"', entity_id) state = self._hass.states.get(entity_id) # type: LazyState if state is None: _LOGGER.error('Unable to find an entity "%s"', entity_id) continue if self._temperature_mode is None: domain = split_entity_id(state.entity_id)[0] self._device_class = state.attributes.get(ATTR_DEVICE_CLASS) self._unit_of_measurement = state.attributes.get( ATTR_UNIT_OF_MEASUREMENT) self._temperature_mode = ( self._device_class == DEVICE_CLASS_TEMPERATURE or domain in (WEATHER_DOMAIN, CLIMATE_DOMAIN, WATER_HEATER_DOMAIN) or self._unit_of_measurement in TEMPERATURE_UNITS) if self._temperature_mode: _LOGGER.debug("%s is a temperature entity.", entity_id) self._device_class = DEVICE_CLASS_TEMPERATURE self._unit_of_measurement = self._hass.config.units.temperature_unit else: _LOGGER.debug("%s is NOT a temperature entity.", entity_id) self._icon = state.attributes.get(ATTR_ICON) value = 0 elapsed = 0 if self._period is None: # Get current state value = self._get_state_value(state) _LOGGER.debug("Current state: %s", value) else: # Get history between start and now history_list = history.state_changes_during_period( self.hass, start, end, str(entity_id)) if entity_id not in history_list.keys(): value = self._get_state_value(state) _LOGGER.warning( 'Historical data not found for entity "%s". ' "Current state used: %s", entity_id, value, ) else: # Get the first state item = history.get_state(self.hass, start, entity_id) _LOGGER.debug("Initial historical state: %s", item) last_state = None last_time = start_ts if item is not None and self._has_state(item.state): last_state = self._get_state_value(item) # Get the other states for item in history_list.get(entity_id): _LOGGER.debug("Historical state: %s", item) current_state = self._get_state_value(item) current_time = item.last_changed.timestamp() if last_state is not None: last_elapsed = current_time - last_time value += last_state * last_elapsed elapsed += last_elapsed last_state = current_state last_time = current_time # Count time elapsed between last history state and now if last_state is not None: last_elapsed = end_ts - last_time value += last_state * last_elapsed elapsed += last_elapsed if elapsed: value /= elapsed _LOGGER.debug("Historical average state: %s", value) if isinstance(value, numbers.Number): values.append(value) self.available_sources += 1 if values: self._state = round(sum(values) / len(values), self._precision) else: self._state = None _LOGGER.debug("Total average state: %s", self._state)
def _update_state(self): # pylint: disable=r0914,r0912,r0915 """Update the sensor state.""" _LOGGER.debug('Updating sensor "%s"', self.name) start = end = start_ts = end_ts = None p_period = self._period # Parse templates self._update_period() if self._period is not None: now = datetime.datetime.now() start, end = self._period if p_period is None: p_start = p_end = now else: p_start, p_end = p_period # Convert times to UTC start = dt_util.as_utc(start) end = dt_util.as_utc(end) p_start = dt_util.as_utc(p_start) p_end = dt_util.as_utc(p_end) # Compute integer timestamps now_ts = math.floor(dt_util.as_timestamp(now)) start_ts = math.floor(dt_util.as_timestamp(start)) end_ts = math.floor(dt_util.as_timestamp(end)) p_start_ts = math.floor(dt_util.as_timestamp(p_start)) p_end_ts = math.floor(dt_util.as_timestamp(p_end)) # If period has not changed and current time after the period end.. if ( start_ts == p_start_ts and end_ts == p_end_ts and end_ts <= now_ts ): # Don't compute anything as the value cannot have changed return self.available_sources = 0 values = [] self.count = 0 self.min_value = self.max_value = None for entity_id in self._entity_ids: # pylint: disable=r1702 _LOGGER.debug('Processing entity "%s"', entity_id) entity = self._hass.states.get(entity_id) if entity is None: _LOGGER.error('Unable to find an entity "%s"', entity_id) continue if self._temperature_mode is None: self._temperature_mode = self._is_temperature(entity) if self._temperature_mode: self._unit_of_measurement = \ self._hass.config.units.temperature_unit self._icon = 'mdi:thermometer' else: self._unit_of_measurement = \ entity.attributes.get(ATTR_UNIT_OF_MEASUREMENT) self._icon = \ entity.attributes.get(ATTR_ICON) value = 0 elapsed = 0 if self._period is None: # Get current state value = self._get_entity_state(entity) _LOGGER.debug('Current state: %s', value) else: # Get history between start and now history_list = history.state_changes_during_period( self.hass, start, end, str(entity_id)) if entity_id not in history_list.keys(): value = self._get_entity_state(entity) _LOGGER.warning( 'Historical data not found for entity "%s". ' 'Current state used: %s', entity_id, value) else: # Get the first state item = history.get_state(self.hass, start, entity_id) _LOGGER.debug('Initial historical state: %s', item) last_state = None last_time = start_ts if ( item is not None and self._has_state(item.state) ): last_state = self._get_entity_state(item) # Get the other states for item in history_list.get(entity_id): _LOGGER.debug('Historical state: %s', item) if self._has_state(item.state): current_state = self._get_entity_state(item) current_time = item.last_changed.timestamp() if last_state: last_elapsed = current_time - last_time value += last_state * last_elapsed elapsed += last_elapsed last_state = current_state last_time = current_time # Count time elapsed between last history state and now if last_state: last_elapsed = end_ts - last_time value += last_state * last_elapsed elapsed += last_elapsed if elapsed: value /= elapsed _LOGGER.debug('Historical average state: %s', value) if isinstance(value, numbers.Number): values.append(value) self.available_sources += 1 if values: self._state = round(sum(values) / len(values), self._precision) else: self._state = None _LOGGER.debug('Total average state: %s', self._state)
async def async_update(self): """Update the sensor state.""" start = now = start_timestamp = now_timestamp = None if self._duration is not None: now = dt_util.now() start = dt_util.as_utc(now - self._duration) now = dt_util.as_utc(now) # Compute integer timestamps start_timestamp = math.floor(dt_util.as_timestamp(start)) now_timestamp = math.floor(dt_util.as_timestamp(now)) values = [] for entity_id in self._entities: _LOGGER.debug('Processing entity \'%s\'', entity_id) entity = self._hass.states.get(entity_id) if entity is None: raise HomeAssistantError( 'Unable to find an entity called {}'.format(entity_id)) value = 0 elapsed = 0 if self._duration is None: # Get current state value = self._get_temperature(entity) _LOGGER.debug('Current temperature: %s', value) else: # Get history between start and now history_list = history.state_changes_during_period( self.hass, start, now, str(entity_id)) if entity_id not in history_list.keys(): value = self._get_temperature(entity) _LOGGER.warning( 'Historical data not found for entity \'%s\'.' ' Current temperature used: %s', entity_id, value) else: # Get the first state item = history.get_state(self.hass, start, entity_id) _LOGGER.debug('Initial historical state: %s', item) last_state = None last_time = start_timestamp if item is not None and item.state is not None: last_state = self._get_temperature(item) # Get the other states for item in history_list.get(entity_id): _LOGGER.debug('Historical state: %s', item) if item.state is not None: current_state = self._get_temperature(item) current_time = item.last_changed.timestamp() if last_state: last_elapsed = current_time - last_time value += last_state * last_elapsed elapsed += last_elapsed last_state = current_state last_time = current_time # Count time elapsed between last history state and now if last_state: last_elapsed = now_timestamp - last_time value += last_state * last_elapsed elapsed += last_elapsed value /= elapsed _LOGGER.debug('Historical average temperature: %s', value) values.append(value) if values: self._state = round(sum(values) / len(values), 1) else: self._state = None _LOGGER.debug('Total average temperature: %s', self._state)