Reduce the load on met.no servers, yr.no sensor (#12435)

* Spread the load more for the yr.no sensor

* Spread the load more for the yr.no sensor

* Spread the load more for the yr.no sensor

* Spread the load more for the yr.no sensor

* Spread the load more for the yr.no sensor

* Spread the load more for the yr.no sensor

* Spread the load more for the yr.no sensor

* Spread the load more for the yr.no sensor

* Spread the load more for the yr.no sensor

* fix comment

* Spread the load more for the yr.no sensor

* Spread the load more for the yr.no sensor

* Spread the load more for the yr.no sensor

* Update yr.py
This commit is contained in:
Daniel Høyer Iversen 2018-02-17 22:33:41 +01:00 committed by Paulus Schoutsen
parent 4837254146
commit eaba3b315c

View file

@ -7,7 +7,6 @@ https://home-assistant.io/components/sensor.yr/
import asyncio
import logging
from datetime import timedelta
from random import randrange
from xml.parsers.expat import ExpatError
@ -22,16 +21,17 @@ from homeassistant.const import (
ATTR_ATTRIBUTION, CONF_NAME)
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.event import (
async_track_point_in_utc_time, async_track_utc_time_change)
from homeassistant.helpers.event import (async_track_utc_time_change,
async_call_later)
from homeassistant.util import dt as dt_util
REQUIREMENTS = ['xmltodict==0.11.0']
_LOGGER = logging.getLogger(__name__)
CONF_ATTRIBUTION = "Weather forecast from yr.no, delivered by the Norwegian " \
"Meteorological Institute and the NRK."
CONF_ATTRIBUTION = "Weather forecast from met.no, delivered " \
"by the Norwegian Meteorological Institute."
# https://api.met.no/license_data.html
SENSOR_TYPES = {
'symbol': ['Symbol', None],
@ -91,11 +91,8 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
async_add_devices(dev)
weather = YrData(hass, coordinates, forecast, dev)
# Update weather on the hour, spread seconds
async_track_utc_time_change(
hass, weather.async_update, minute=randrange(1, 10),
second=randrange(0, 59))
yield from weather.async_update()
async_track_utc_time_change(hass, weather.updating_devices, minute=31)
yield from weather.fetching_data()
class YrSensor(Entity):
@ -153,27 +150,21 @@ class YrData(object):
self._url = 'https://aa015h6buqvih86i1.api.met.no/'\
'weatherapi/locationforecast/1.9/'
self._urlparams = coordinates
self._nextrun = None
self._forecast = forecast
self.devices = devices
self.data = {}
self.hass = hass
@asyncio.coroutine
def async_update(self, *_):
def fetching_data(self, *_):
"""Get the latest data from yr.no."""
import xmltodict
def try_again(err: str):
"""Retry in 15 minutes."""
_LOGGER.warning("Retrying in 15 minutes: %s", err)
self._nextrun = None
nxt = dt_util.utcnow() + timedelta(minutes=15)
if nxt.minute >= 15:
async_track_point_in_utc_time(self.hass, self.async_update,
nxt)
if self._nextrun is None or dt_util.utcnow() >= self._nextrun:
"""Retry in 15 to 20 minutes."""
minutes = 15 + randrange(6)
_LOGGER.error("Retrying in %i minutes: %s", minutes, err)
async_call_later(self.hass, minutes*60, self.fetching_data)
try:
websession = async_get_clientsession(self.hass)
with async_timeout.timeout(10, loop=self.hass.loop):
@ -190,14 +181,19 @@ class YrData(object):
try:
self.data = xmltodict.parse(text)['weatherdata']
model = self.data['meta']['model']
if '@nextrun' not in model:
model = model[0]
self._nextrun = dt_util.parse_datetime(model['@nextrun'])
except (ExpatError, IndexError) as err:
try_again(err)
return
yield from self.updating_devices()
async_call_later(self.hass, 60*60, self.fetching_data)
@asyncio.coroutine
def updating_devices(self, *_):
"""Find the current data from self.data."""
if not self.data:
return
now = dt_util.utcnow()
forecast_time = now + dt_util.dt.timedelta(hours=self._forecast)