Skip to content

Commit 602380e

Browse files
authored
Detect reached API rate limit in Tankerkoenig (home-assistant#110432)
1 parent 01c3205 commit 602380e

File tree

5 files changed

+69
-8
lines changed

5 files changed

+69
-8
lines changed

homeassistant/components/tankerkoenig/coordinator.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,15 @@
1212
TankerkoenigConnectionError,
1313
TankerkoenigError,
1414
TankerkoenigInvalidKeyError,
15+
TankerkoenigRateLimitError,
1516
)
1617

1718
from homeassistant.config_entries import ConfigEntry
1819
from homeassistant.const import CONF_API_KEY, CONF_SHOW_ON_MAP
1920
from homeassistant.core import HomeAssistant
2021
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
2122
from homeassistant.helpers.aiohttp_client import async_get_clientsession
22-
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
23+
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
2324

2425
from .const import CONF_FUEL_TYPES, CONF_STATIONS
2526

@@ -78,13 +79,22 @@ async def _async_update_data(self) -> dict[str, PriceInfo]:
7879
station_ids = list(self.stations)
7980

8081
prices = {}
81-
8282
# The API seems to only return at most 10 results, so split the list in chunks of 10
8383
# and merge it together.
8484
for index in range(ceil(len(station_ids) / 10)):
85-
data = await self._tankerkoenig.prices(
86-
station_ids[index * 10 : (index + 1) * 10]
87-
)
85+
try:
86+
data = await self._tankerkoenig.prices(
87+
station_ids[index * 10 : (index + 1) * 10]
88+
)
89+
except TankerkoenigInvalidKeyError as err:
90+
raise ConfigEntryAuthFailed(err) from err
91+
except (TankerkoenigError, TankerkoenigConnectionError) as err:
92+
if isinstance(err, TankerkoenigRateLimitError):
93+
_LOGGER.warning(
94+
"API rate limit reached, consider to increase polling interval"
95+
)
96+
raise UpdateFailed(err) from err
97+
8898
prices.update(data)
8999

90100
return prices

homeassistant/components/tankerkoenig/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@
66
"documentation": "https://www.home-assistant.io/integrations/tankerkoenig",
77
"iot_class": "cloud_polling",
88
"loggers": ["aiotankerkoenig"],
9-
"requirements": ["aiotankerkoenig==0.3.0"]
9+
"requirements": ["aiotankerkoenig==0.4.0"]
1010
}

requirements_all.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,7 @@ aioswitcher==3.4.1
383383
aiosyncthing==0.5.1
384384

385385
# homeassistant.components.tankerkoenig
386-
aiotankerkoenig==0.3.0
386+
aiotankerkoenig==0.4.0
387387

388388
# homeassistant.components.tractive
389389
aiotractive==0.5.6

requirements_test_all.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@ aioswitcher==3.4.1
356356
aiosyncthing==0.5.1
357357

358358
# homeassistant.components.tankerkoenig
359-
aiotankerkoenig==0.3.0
359+
aiotankerkoenig==0.4.0
360360

361361
# homeassistant.components.tractive
362362
aiotractive==0.5.6
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
"""Tests for the Tankerkoening integration."""
2+
from __future__ import annotations
3+
4+
from datetime import timedelta
5+
from unittest.mock import AsyncMock
6+
7+
from aiotankerkoenig.exceptions import TankerkoenigRateLimitError
8+
import pytest
9+
10+
from homeassistant.components.tankerkoenig.const import DEFAULT_SCAN_INTERVAL
11+
from homeassistant.config_entries import ConfigEntryState
12+
from homeassistant.const import STATE_UNAVAILABLE
13+
from homeassistant.core import HomeAssistant
14+
import homeassistant.util.dt as dt_util
15+
16+
from tests.common import MockConfigEntry, async_fire_time_changed
17+
18+
19+
@pytest.mark.usefixtures("setup_integration")
20+
async def test_rate_limit(
21+
hass: HomeAssistant,
22+
config_entry: MockConfigEntry,
23+
tankerkoenig: AsyncMock,
24+
caplog: pytest.LogCaptureFixture,
25+
) -> None:
26+
"""Test detection of API rate limit."""
27+
assert config_entry.state == ConfigEntryState.LOADED
28+
state = hass.states.get("binary_sensor.station_somewhere_street_1_status")
29+
assert state
30+
assert state.state == "on"
31+
32+
tankerkoenig.prices.side_effect = TankerkoenigRateLimitError
33+
async_fire_time_changed(
34+
hass, dt_util.utcnow() + timedelta(minutes=DEFAULT_SCAN_INTERVAL)
35+
)
36+
await hass.async_block_till_done()
37+
assert (
38+
"API rate limit reached, consider to increase polling interval" in caplog.text
39+
)
40+
state = hass.states.get("binary_sensor.station_somewhere_street_1_status")
41+
assert state
42+
assert state.state == STATE_UNAVAILABLE
43+
44+
tankerkoenig.prices.side_effect = None
45+
async_fire_time_changed(
46+
hass, dt_util.utcnow() + timedelta(minutes=DEFAULT_SCAN_INTERVAL * 2)
47+
)
48+
await hass.async_block_till_done()
49+
state = hass.states.get("binary_sensor.station_somewhere_street_1_status")
50+
assert state
51+
assert state.state == "on"

0 commit comments

Comments
 (0)