Skip to content
Merged
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
30 changes: 14 additions & 16 deletions homeassistant/components/sensor/tibber.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def __init__(self, tibber_home):
"""Initialize the sensor."""
self._tibber_home = tibber_home
self._last_updated = None
self._newest_data_timestamp = None
self._last_data_timestamp = None
self._state = None
self._is_available = False
self._device_state_attributes = {}
Expand All @@ -70,13 +70,13 @@ def __init__(self, tibber_home):

async def async_update(self):
"""Get the latest data and updates the states."""
now = dt_util.utcnow()
now = dt_util.now()
if self._tibber_home.current_price_total and self._last_updated and \
self._last_updated.hour == now.hour and self._newest_data_timestamp:
self._last_updated.hour == now.hour and self._last_data_timestamp:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why shouldn't we let the scan interval decide on the update frequency?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The data change every hour, but we want to retry if no data are available.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the data hasn't changed since last update, making a state update will not write a new state to the state machine. So you could just try to do that without making the check here. Are there any downsides, you think? It would make the code cleaner.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure I understood your last comment.
But if I do not return here, the _update_current_price will be called every minute

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, and if all values including state and state attributes remain the same a call to do a state update, will not write a new state to the state machine, so will not clog the database.

The only thing that seems to change, while fetched data is the same, is the time_diff variable that is computed from the current time of the call. What will happen there?

Copy link
Copy Markdown
Member Author

@Danielhiversen Danielhiversen Apr 26, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, there will be no state change and no new state to the state machine.
But I though it would be good avoid calling _update_current_price each minute, and then also avoid iterate over all prices each minute.
So the return here is only to avoid unnecessary cpu load.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👌

return

if (not self._newest_data_timestamp or
(self._newest_data_timestamp - now).total_seconds()/3600 < 12
if (not self._last_data_timestamp or
(self._last_data_timestamp - now).total_seconds()/3600 < 12
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is the check < 12? That looks like the opposite of what I would expect.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The data change every hour, but is available 12-36 hours ahead. So when we have less then 12 hours of future data available new data should be available. We do not know exactly when the new is available, so we might need to retry.

or not self._is_available):
_LOGGER.debug("Asking for new data.")
await self._fetch_data()
Expand Down Expand Up @@ -135,24 +135,22 @@ async def _fetch_data(self):

def _update_current_price(self):
state = None
max_price = None
min_price = None
now = dt_util.utcnow()
max_price = 0
min_price = 10000
now = dt_util.now()
for key, price_total in self._tibber_home.price_total.items():
price_time = dt_util.as_utc(dt_util.parse_datetime(key))
price_time = dt_util.as_local(dt_util.parse_datetime(key))
price_total = round(price_total, 3)
time_diff = (now - price_time).total_seconds()/60
if (not self._newest_data_timestamp or
price_time > self._newest_data_timestamp):
self._newest_data_timestamp = price_time
if (not self._last_data_timestamp or
price_time > self._last_data_timestamp):
self._last_data_timestamp = price_time
if 0 <= time_diff < 60:
state = price_total
self._last_updated = price_time
if now.date() == price_time.date():
if max_price is None or price_total > max_price:
max_price = price_total
if min_price is None or price_total < min_price:
min_price = price_total
max_price = max(max_price, price_total)
min_price = min(min_price, price_total)
self._state = state
self._device_state_attributes['max_price'] = max_price
self._device_state_attributes['min_price'] = min_price
Expand Down