Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 26 additions & 14 deletions homeassistant/components/sensor/history_stats.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@
}
ICON = 'mdi:chart-line'

ATTR_START = 'from'
ATTR_END = 'to'
ATTR_VALUE = 'value'


Expand Down Expand Up @@ -157,12 +155,9 @@ def should_poll(self):
@property
def device_state_attributes(self):
"""Return the state attributes of the sensor."""
start, end = self._period
hsh = HistoryStatsHelper
return {
ATTR_VALUE: hsh.pretty_duration(self.value),
ATTR_START: start.strftime('%Y-%m-%d %H:%M:%S'),
ATTR_END: end.strftime('%Y-%m-%d %H:%M:%S'),
}

@property
Expand All @@ -172,13 +167,33 @@ def icon(self):

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 to UTC
# 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 = dt_util.as_utc(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(
Expand All @@ -191,7 +206,7 @@ def update(self):
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)
last_time = start_timestamp
elapsed = 0
count = 0

Expand All @@ -210,8 +225,7 @@ def update(self):

# 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()))
measure_end = min(end_timestamp, now_timestamp)
elapsed += measure_end - last_time

# Save value in hours
Expand Down Expand Up @@ -279,13 +293,11 @@ def pretty_duration(hours):
hours, seconds = divmod(seconds, 3600)
minutes, seconds = divmod(seconds, 60)
if days > 0:
return '%dd %dh %dm %ds' % (days, hours, minutes, seconds)
return '%dd %dh %dm' % (days, hours, minutes)
elif hours > 0:
return '%dh %dm %ds' % (hours, minutes, seconds)
elif minutes > 0:
return '%dm %ds' % (minutes, seconds)
return '%dh %dm' % (hours, minutes)
else:
return '%ds' % (seconds,)
return '%dm' % minutes

@staticmethod
def pretty_ratio(value, period):
Expand Down
31 changes: 22 additions & 9 deletions tests/components/sensor/test_history_stats.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,16 +58,29 @@ def test_period_parsing(self):
self.hass, 'test', 'on', None, today, duration, 'time', 'test')

sensor1.update_period()
sensor1_start, sensor1_end = sensor1._period
sensor2.update_period()

self.assertEqual(
sensor1.device_state_attributes['from'][-8:], '00:00:00')
self.assertEqual(
sensor1.device_state_attributes['to'][-8:], '02:01:00')
self.assertEqual(
sensor2.device_state_attributes['from'][-8:], '21:59:00')
self.assertEqual(
sensor2.device_state_attributes['to'][-8:], '00:00:00')
sensor2_start, sensor2_end = sensor2._period

# Start = 00:00:00
self.assertEqual(sensor1_start.hour, 0)
self.assertEqual(sensor1_start.minute, 0)
self.assertEqual(sensor1_start.second, 0)

# End = 02:01:00
self.assertEqual(sensor1_end.hour, 2)
self.assertEqual(sensor1_end.minute, 1)
self.assertEqual(sensor1_end.second, 0)

# Start = 21:59:00
self.assertEqual(sensor2_start.hour, 21)
self.assertEqual(sensor2_start.minute, 59)
self.assertEqual(sensor2_start.second, 0)

# End = 00:00:00
self.assertEqual(sensor2_end.hour, 0)
self.assertEqual(sensor2_end.minute, 0)
self.assertEqual(sensor2_end.second, 0)

def test_measure(self):
"""Test the history statistics sensor measure."""
Expand Down