mirror of
https://github.com/home-assistant/core.git
synced 2025-07-09 14:27:07 +00:00
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:
parent
4837254146
commit
eaba3b315c
@ -7,7 +7,6 @@ https://home-assistant.io/components/sensor.yr/
|
|||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from datetime import timedelta
|
|
||||||
from random import randrange
|
from random import randrange
|
||||||
from xml.parsers.expat import ExpatError
|
from xml.parsers.expat import ExpatError
|
||||||
|
|
||||||
@ -22,16 +21,17 @@ from homeassistant.const import (
|
|||||||
ATTR_ATTRIBUTION, CONF_NAME)
|
ATTR_ATTRIBUTION, CONF_NAME)
|
||||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
from homeassistant.helpers.event import (
|
from homeassistant.helpers.event import (async_track_utc_time_change,
|
||||||
async_track_point_in_utc_time, async_track_utc_time_change)
|
async_call_later)
|
||||||
from homeassistant.util import dt as dt_util
|
from homeassistant.util import dt as dt_util
|
||||||
|
|
||||||
REQUIREMENTS = ['xmltodict==0.11.0']
|
REQUIREMENTS = ['xmltodict==0.11.0']
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
CONF_ATTRIBUTION = "Weather forecast from yr.no, delivered by the Norwegian " \
|
CONF_ATTRIBUTION = "Weather forecast from met.no, delivered " \
|
||||||
"Meteorological Institute and the NRK."
|
"by the Norwegian Meteorological Institute."
|
||||||
|
# https://api.met.no/license_data.html
|
||||||
|
|
||||||
SENSOR_TYPES = {
|
SENSOR_TYPES = {
|
||||||
'symbol': ['Symbol', None],
|
'symbol': ['Symbol', None],
|
||||||
@ -91,11 +91,8 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
async_add_devices(dev)
|
async_add_devices(dev)
|
||||||
|
|
||||||
weather = YrData(hass, coordinates, forecast, dev)
|
weather = YrData(hass, coordinates, forecast, dev)
|
||||||
# Update weather on the hour, spread seconds
|
async_track_utc_time_change(hass, weather.updating_devices, minute=31)
|
||||||
async_track_utc_time_change(
|
yield from weather.fetching_data()
|
||||||
hass, weather.async_update, minute=randrange(1, 10),
|
|
||||||
second=randrange(0, 59))
|
|
||||||
yield from weather.async_update()
|
|
||||||
|
|
||||||
|
|
||||||
class YrSensor(Entity):
|
class YrSensor(Entity):
|
||||||
@ -153,50 +150,49 @@ class YrData(object):
|
|||||||
self._url = 'https://aa015h6buqvih86i1.api.met.no/'\
|
self._url = 'https://aa015h6buqvih86i1.api.met.no/'\
|
||||||
'weatherapi/locationforecast/1.9/'
|
'weatherapi/locationforecast/1.9/'
|
||||||
self._urlparams = coordinates
|
self._urlparams = coordinates
|
||||||
self._nextrun = None
|
|
||||||
self._forecast = forecast
|
self._forecast = forecast
|
||||||
self.devices = devices
|
self.devices = devices
|
||||||
self.data = {}
|
self.data = {}
|
||||||
self.hass = hass
|
self.hass = hass
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def async_update(self, *_):
|
def fetching_data(self, *_):
|
||||||
"""Get the latest data from yr.no."""
|
"""Get the latest data from yr.no."""
|
||||||
import xmltodict
|
import xmltodict
|
||||||
|
|
||||||
def try_again(err: str):
|
def try_again(err: str):
|
||||||
"""Retry in 15 minutes."""
|
"""Retry in 15 to 20 minutes."""
|
||||||
_LOGGER.warning("Retrying in 15 minutes: %s", err)
|
minutes = 15 + randrange(6)
|
||||||
self._nextrun = None
|
_LOGGER.error("Retrying in %i minutes: %s", minutes, err)
|
||||||
nxt = dt_util.utcnow() + timedelta(minutes=15)
|
async_call_later(self.hass, minutes*60, self.fetching_data)
|
||||||
if nxt.minute >= 15:
|
try:
|
||||||
async_track_point_in_utc_time(self.hass, self.async_update,
|
websession = async_get_clientsession(self.hass)
|
||||||
nxt)
|
with async_timeout.timeout(10, loop=self.hass.loop):
|
||||||
|
resp = yield from websession.get(
|
||||||
if self._nextrun is None or dt_util.utcnow() >= self._nextrun:
|
self._url, params=self._urlparams)
|
||||||
try:
|
if resp.status != 200:
|
||||||
websession = async_get_clientsession(self.hass)
|
try_again('{} returned {}'.format(resp.url, resp.status))
|
||||||
with async_timeout.timeout(10, loop=self.hass.loop):
|
|
||||||
resp = yield from websession.get(
|
|
||||||
self._url, params=self._urlparams)
|
|
||||||
if resp.status != 200:
|
|
||||||
try_again('{} returned {}'.format(resp.url, resp.status))
|
|
||||||
return
|
|
||||||
text = yield from resp.text()
|
|
||||||
|
|
||||||
except (asyncio.TimeoutError, aiohttp.ClientError) as err:
|
|
||||||
try_again(err)
|
|
||||||
return
|
return
|
||||||
|
text = yield from resp.text()
|
||||||
|
|
||||||
try:
|
except (asyncio.TimeoutError, aiohttp.ClientError) as err:
|
||||||
self.data = xmltodict.parse(text)['weatherdata']
|
try_again(err)
|
||||||
model = self.data['meta']['model']
|
return
|
||||||
if '@nextrun' not in model:
|
|
||||||
model = model[0]
|
try:
|
||||||
self._nextrun = dt_util.parse_datetime(model['@nextrun'])
|
self.data = xmltodict.parse(text)['weatherdata']
|
||||||
except (ExpatError, IndexError) as err:
|
except (ExpatError, IndexError) as err:
|
||||||
try_again(err)
|
try_again(err)
|
||||||
return
|
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()
|
now = dt_util.utcnow()
|
||||||
forecast_time = now + dt_util.dt.timedelta(hours=self._forecast)
|
forecast_time = now + dt_util.dt.timedelta(hours=self._forecast)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user