Skip to content

Commit c014bc1

Browse files
authored
Merge pull request #75 from jwillemsen/jwi-ratelimitrepair
Rate limitation changes
2 parents 3004a98 + ca4a3b2 commit c014bc1

File tree

4 files changed

+67
-10
lines changed

4 files changed

+67
-10
lines changed

custom_components/daikin_onecta/coordinator.py

+9-3
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def __init__(self, hass: HomeAssistant, config_entry: ConfigEntry) -> None:
2525
"""Initialize."""
2626
self.options = config_entry.options
2727

28-
super().__init__(hass, _LOGGER, name=DOMAIN, update_interval=self.determine_update_interval())
28+
super().__init__(hass, _LOGGER, name=DOMAIN, update_interval=self.determine_update_interval(hass))
2929

3030
_LOGGER.info(
3131
"Daikin coordinator initialized with %s interval.",
@@ -55,7 +55,7 @@ async def _async_update_data(self):
5555
device = Appliance(dev_data, daikin_api)
5656
devices[dev_data["id"]] = device
5757

58-
self.update_interval = self.determine_update_interval()
58+
self.update_interval = self.determine_update_interval(self.hass)
5959

6060
_LOGGER.debug(
6161
"Daikin coordinator finished _async_update_data, interval %s.",
@@ -68,14 +68,20 @@ def update_settings(self, config_entry: ConfigEntry):
6868
self.update_interval = self.determine_update_interval()
6969
_LOGGER.info("Daikin coordinator changed interval to %s", self.update_interval)
7070

71-
def determine_update_interval(self):
71+
def determine_update_interval(self, hass: HomeAssistant):
7272
# Default of low scan minutes interval
7373
scan_interval = self.options.get("low_scan_interval", 30)
7474
hs = datetime.strptime(self.options.get("high_scan_start", "07:00:00"), "%H:%M:%S").time()
7575
ls = datetime.strptime(self.options.get("low_scan_start", "22:00:00"), "%H:%M:%S").time()
7676
if self.in_between(datetime.now().time(), hs, ls):
7777
scan_interval = self.options.get("high_scan_interval", 10)
7878

79+
# When we hit our daily rate limit we skip the next update because any call which results
80+
# again in just a rate limit error back is counted as call for the limit of next day
81+
daikin_api = hass.data[DOMAIN][DAIKIN_API]
82+
if daikin_api.rate_limits["remaining_day"] == 0:
83+
scan_interval *= 2
84+
7985
return timedelta(minutes=scan_interval)
8086

8187
def in_between(self, now, start, end):

custom_components/daikin_onecta/daikin_api.py

+38-7
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from homeassistant import config_entries
1010
from homeassistant import core
1111
from homeassistant.helpers import config_entry_oauth2_flow
12+
from homeassistant.helpers import issue_registry as ir
1213

1314
from .const import DAIKIN_DEVICES
1415
from .const import DOMAIN
@@ -84,10 +85,16 @@ async def doBearerRequest(self, resourceUrl, options=None):
8485
_LOGGER.error("REQUEST FAILED: %s", e)
8586
return []
8687

87-
self.rate_limits["minute"] = res.headers.get("X-RateLimit-Limit-minute", 0)
88-
self.rate_limits["day"] = res.headers.get("X-RateLimit-Limit-day", 0)
89-
self.rate_limits["remaining_minutes"] = res.headers.get("X-RateLimit-Remaining-minute", 0)
90-
self.rate_limits["remaining_day"] = res.headers.get("X-RateLimit-Remaining-day", 0)
88+
self.rate_limits["minute"] = int(res.headers.get("X-RateLimit-Limit-minute", 0))
89+
self.rate_limits["day"] = int(res.headers.get("X-RateLimit-Limit-day", 0))
90+
self.rate_limits["remaining_minutes"] = int(res.headers.get("X-RateLimit-Remaining-minute", 0))
91+
self.rate_limits["remaining_day"] = int(res.headers.get("X-RateLimit-Remaining-day", 0))
92+
93+
if self.rate_limits["remaining_minutes"] > 0:
94+
ir.async_delete_issue(self.hass, DOMAIN, "minute_rate_limit")
95+
96+
if self.rate_limits["remaining_day"] > 0:
97+
ir.async_delete_issue(self.hass, DOMAIN, "day_rate_limit")
9198

9299
_LOGGER.debug("BEARER RESPONSE CODE: %s LIMIT: %s", res.status_code, self.rate_limits)
93100

@@ -98,9 +105,33 @@ async def doBearerRequest(self, resourceUrl, options=None):
98105
_LOGGER.error("RETRIEVE JSON FAILED: %s", res.text)
99106
return False
100107
elif res.status_code == 429:
101-
raise Exception(
102-
"Rate limit: Remaining minute " + str(self.rate_limits["remaining_minutes"]) + " day " + str(self.rate_limits["remaining_day"])
103-
)
108+
if self.rate_limits["remaining_minutes"] == 0:
109+
ir.async_create_issue(
110+
self.hass,
111+
DOMAIN,
112+
"minute_rate_limit",
113+
is_fixable=False,
114+
is_persistent=True,
115+
severity=ir.IssueSeverity.ERROR,
116+
learn_more_url="https://developer.cloud.daikineurope.com/docs/b0dffcaa-7b51-428a-bdff-a7c8a64195c0/rate_limitation",
117+
translation_key="minute_rate_limit",
118+
)
119+
120+
if self.rate_limits["remaining_day"] == 0:
121+
ir.async_create_issue(
122+
self.hass,
123+
DOMAIN,
124+
"day_rate_limit",
125+
is_fixable=False,
126+
is_persistent=True,
127+
severity=ir.IssueSeverity.ERROR,
128+
learn_more_url="https://developer.cloud.daikineurope.com/docs/b0dffcaa-7b51-428a-bdff-a7c8a64195c0/rate_limitation",
129+
translation_key="day_rate_limit",
130+
)
131+
if options is not None and "method" in options and options["method"] == "PATCH":
132+
return False
133+
else:
134+
return []
104135
elif res.status_code == 204:
105136
self._last_patch_call = datetime.now()
106137
return True

custom_components/daikin_onecta/strings.json

+10
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,15 @@
3535
"title": "Daikin Onecta"
3636
}
3737
}
38+
},
39+
"issues": {
40+
"day_rate_limit": {
41+
"title": "The daily rate limit has been reached",
42+
"description": "You have reached your daily rate limit to the Daikin Cloud, check your polling frequency in the Daikin Onecta configuration."
43+
},
44+
"minute_rate_limit": {
45+
"title": "The minute rate limit has been reached",
46+
"description": "You have reached your minute rate limit to the Daikin Cloud, don't make so many calls to your Daikin devices in one minute."
47+
}
3848
}
3949
}

custom_components/daikin_onecta/translations/en.json

+10
Original file line numberDiff line numberDiff line change
@@ -63,5 +63,15 @@
6363
}
6464
}
6565
}
66+
},
67+
"issues": {
68+
"day_rate_limit": {
69+
"title": "The daily rate limit has been reached",
70+
"description": "You have reached your daily rate limit to the Daikin Cloud, check your polling frequency in the Daikin Onecta configuration."
71+
},
72+
"minute_rate_limit": {
73+
"title": "The minute rate limit has been reached",
74+
"description": "You have reached your minute rate limit to the Daikin Cloud, don't make so many calls to your Daikin devices in one minute."
75+
}
6676
}
6777
}

0 commit comments

Comments
 (0)