Detect reached API rate limit in Tankerkoenig (#110432)
parent
2a12369e31
commit
f13052f9aa
|
@ -12,6 +12,7 @@ from aiotankerkoenig import (
|
||||||
TankerkoenigConnectionError,
|
TankerkoenigConnectionError,
|
||||||
TankerkoenigError,
|
TankerkoenigError,
|
||||||
TankerkoenigInvalidKeyError,
|
TankerkoenigInvalidKeyError,
|
||||||
|
TankerkoenigRateLimitError,
|
||||||
)
|
)
|
||||||
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
@ -19,7 +20,7 @@ from homeassistant.const import CONF_API_KEY, CONF_SHOW_ON_MAP
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
|
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
|
||||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||||
|
|
||||||
from .const import CONF_FUEL_TYPES, CONF_STATIONS
|
from .const import CONF_FUEL_TYPES, CONF_STATIONS
|
||||||
|
|
||||||
|
@ -78,13 +79,22 @@ class TankerkoenigDataUpdateCoordinator(DataUpdateCoordinator):
|
||||||
station_ids = list(self.stations)
|
station_ids = list(self.stations)
|
||||||
|
|
||||||
prices = {}
|
prices = {}
|
||||||
|
|
||||||
# The API seems to only return at most 10 results, so split the list in chunks of 10
|
# The API seems to only return at most 10 results, so split the list in chunks of 10
|
||||||
# and merge it together.
|
# and merge it together.
|
||||||
for index in range(ceil(len(station_ids) / 10)):
|
for index in range(ceil(len(station_ids) / 10)):
|
||||||
|
try:
|
||||||
data = await self._tankerkoenig.prices(
|
data = await self._tankerkoenig.prices(
|
||||||
station_ids[index * 10 : (index + 1) * 10]
|
station_ids[index * 10 : (index + 1) * 10]
|
||||||
)
|
)
|
||||||
|
except TankerkoenigInvalidKeyError as err:
|
||||||
|
raise ConfigEntryAuthFailed(err) from err
|
||||||
|
except (TankerkoenigError, TankerkoenigConnectionError) as err:
|
||||||
|
if isinstance(err, TankerkoenigRateLimitError):
|
||||||
|
_LOGGER.warning(
|
||||||
|
"API rate limit reached, consider to increase polling interval"
|
||||||
|
)
|
||||||
|
raise UpdateFailed(err) from err
|
||||||
|
|
||||||
prices.update(data)
|
prices.update(data)
|
||||||
|
|
||||||
return prices
|
return prices
|
||||||
|
|
|
@ -6,5 +6,5 @@
|
||||||
"documentation": "https://www.home-assistant.io/integrations/tankerkoenig",
|
"documentation": "https://www.home-assistant.io/integrations/tankerkoenig",
|
||||||
"iot_class": "cloud_polling",
|
"iot_class": "cloud_polling",
|
||||||
"loggers": ["aiotankerkoenig"],
|
"loggers": ["aiotankerkoenig"],
|
||||||
"requirements": ["aiotankerkoenig==0.3.0"]
|
"requirements": ["aiotankerkoenig==0.4.0"]
|
||||||
}
|
}
|
||||||
|
|
|
@ -377,7 +377,7 @@ aioswitcher==3.4.1
|
||||||
aiosyncthing==0.5.1
|
aiosyncthing==0.5.1
|
||||||
|
|
||||||
# homeassistant.components.tankerkoenig
|
# homeassistant.components.tankerkoenig
|
||||||
aiotankerkoenig==0.3.0
|
aiotankerkoenig==0.4.0
|
||||||
|
|
||||||
# homeassistant.components.tractive
|
# homeassistant.components.tractive
|
||||||
aiotractive==0.5.6
|
aiotractive==0.5.6
|
||||||
|
|
|
@ -350,7 +350,7 @@ aioswitcher==3.4.1
|
||||||
aiosyncthing==0.5.1
|
aiosyncthing==0.5.1
|
||||||
|
|
||||||
# homeassistant.components.tankerkoenig
|
# homeassistant.components.tankerkoenig
|
||||||
aiotankerkoenig==0.3.0
|
aiotankerkoenig==0.4.0
|
||||||
|
|
||||||
# homeassistant.components.tractive
|
# homeassistant.components.tractive
|
||||||
aiotractive==0.5.6
|
aiotractive==0.5.6
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
"""Tests for the Tankerkoening integration."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from datetime import timedelta
|
||||||
|
from unittest.mock import AsyncMock
|
||||||
|
|
||||||
|
from aiotankerkoenig.exceptions import TankerkoenigRateLimitError
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from homeassistant.components.tankerkoenig.const import DEFAULT_SCAN_INTERVAL
|
||||||
|
from homeassistant.config_entries import ConfigEntryState
|
||||||
|
from homeassistant.const import STATE_UNAVAILABLE
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
import homeassistant.util.dt as dt_util
|
||||||
|
|
||||||
|
from tests.common import MockConfigEntry, async_fire_time_changed
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures("setup_integration")
|
||||||
|
async def test_rate_limit(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
config_entry: MockConfigEntry,
|
||||||
|
tankerkoenig: AsyncMock,
|
||||||
|
caplog: pytest.LogCaptureFixture,
|
||||||
|
) -> None:
|
||||||
|
"""Test detection of API rate limit."""
|
||||||
|
assert config_entry.state == ConfigEntryState.LOADED
|
||||||
|
state = hass.states.get("binary_sensor.station_somewhere_street_1_status")
|
||||||
|
assert state
|
||||||
|
assert state.state == "on"
|
||||||
|
|
||||||
|
tankerkoenig.prices.side_effect = TankerkoenigRateLimitError
|
||||||
|
async_fire_time_changed(
|
||||||
|
hass, dt_util.utcnow() + timedelta(minutes=DEFAULT_SCAN_INTERVAL)
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert (
|
||||||
|
"API rate limit reached, consider to increase polling interval" in caplog.text
|
||||||
|
)
|
||||||
|
state = hass.states.get("binary_sensor.station_somewhere_street_1_status")
|
||||||
|
assert state
|
||||||
|
assert state.state == STATE_UNAVAILABLE
|
||||||
|
|
||||||
|
tankerkoenig.prices.side_effect = None
|
||||||
|
async_fire_time_changed(
|
||||||
|
hass, dt_util.utcnow() + timedelta(minutes=DEFAULT_SCAN_INTERVAL * 2)
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
state = hass.states.get("binary_sensor.station_somewhere_street_1_status")
|
||||||
|
assert state
|
||||||
|
assert state.state == "on"
|
Loading…
Reference in New Issue