Detect reached API rate limit in Tankerkoenig (#110432)

pull/111133/head
Michael 2024-02-13 14:34:01 +01:00 committed by Franck Nijhof
parent 2a12369e31
commit f13052f9aa
No known key found for this signature in database
GPG Key ID: D62583BA8AB11CA3
5 changed files with 69 additions and 8 deletions

View File

@ -12,6 +12,7 @@ from aiotankerkoenig import (
TankerkoenigConnectionError,
TankerkoenigError,
TankerkoenigInvalidKeyError,
TankerkoenigRateLimitError,
)
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.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
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
@ -78,13 +79,22 @@ class TankerkoenigDataUpdateCoordinator(DataUpdateCoordinator):
station_ids = list(self.stations)
prices = {}
# The API seems to only return at most 10 results, so split the list in chunks of 10
# and merge it together.
for index in range(ceil(len(station_ids) / 10)):
data = await self._tankerkoenig.prices(
station_ids[index * 10 : (index + 1) * 10]
)
try:
data = await self._tankerkoenig.prices(
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)
return prices

View File

@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/tankerkoenig",
"iot_class": "cloud_polling",
"loggers": ["aiotankerkoenig"],
"requirements": ["aiotankerkoenig==0.3.0"]
"requirements": ["aiotankerkoenig==0.4.0"]
}

View File

@ -377,7 +377,7 @@ aioswitcher==3.4.1
aiosyncthing==0.5.1
# homeassistant.components.tankerkoenig
aiotankerkoenig==0.3.0
aiotankerkoenig==0.4.0
# homeassistant.components.tractive
aiotractive==0.5.6

View File

@ -350,7 +350,7 @@ aioswitcher==3.4.1
aiosyncthing==0.5.1
# homeassistant.components.tankerkoenig
aiotankerkoenig==0.3.0
aiotankerkoenig==0.4.0
# homeassistant.components.tractive
aiotractive==0.5.6

View File

@ -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"