Skip to content

Commit 994fb54

Browse files
authored
Various rate-limiting handling (#33)
1 parent 9d9f321 commit 994fb54

File tree

2 files changed

+41
-11
lines changed

2 files changed

+41
-11
lines changed

frigidaire/__init__.py

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
"""Frigidaire 2.0 API client"""
2+
import traceback
23
from enum import Enum
34
from requests import Response
45
from typing import Optional, Dict, Union, List
@@ -428,7 +429,12 @@ def get_appliances_inner():
428429

429430
try:
430431
return get_appliances_inner()
431-
except FrigidaireException:
432+
except FrigidaireException as e:
433+
# Re-authenticating on a 429 makes things worse
434+
if "cas_3403" in traceback.format_exc():
435+
logging.debug("Rate limited - try again later")
436+
raise e
437+
432438
logging.debug('Listing appliances failed - attempting to re-authenticate')
433439
self.re_authenticate()
434440
return get_appliances_inner()
@@ -446,7 +452,12 @@ def get_appliance_details(self, appliance: Appliance) -> Dict:
446452
appliances = self.get_request(self.regional_base_url,
447453
'/appliance/api/v2/appliances?includeMetadata=true',
448454
self.get_headers_frigidaire("GET", include_bearer_token=True))
449-
except FrigidaireException:
455+
except FrigidaireException as e:
456+
# Re-authenticating on a 429 makes things worse
457+
if "cas_3403" in traceback.format_exc():
458+
logging.debug("Rate limited - try again later")
459+
raise e
460+
450461
self.re_authenticate()
451462
appliances = self.get_request(self.regional_base_url,
452463
'/appliance/api/v2/appliances?includeMetadata=true',
@@ -475,7 +486,12 @@ def execute_action(self, appliance: Appliance, action: List[Component]) -> None:
475486
self.put_request(self.regional_base_url,
476487
f'/appliance/api/v2/appliances/{appliance.appliance_id}/command',
477488
self.get_headers_frigidaire("PUT", include_bearer_token=True), data)
478-
except FrigidaireException:
489+
except FrigidaireException as e:
490+
# Re-authenticating on a 429 makes things worse
491+
if "cas_3403" in traceback.format_exc():
492+
logging.debug("Rate limited - try again later")
493+
raise e
494+
479495
self.re_authenticate()
480496
self.put_request(self.regional_base_url,
481497
f'/appliance/api/v2/appliances/{appliance.appliance_id}/command',
@@ -493,28 +509,29 @@ def parse_response(response: Response) -> Dict:
493509

494510
try:
495511
if response.headers.get('Content-Encoding') == 'gzip':
496-
# Hack: Sometimes the server indicates "Content-Encoding: gzip" but does not send gzipped data
512+
# Hack: Often, the server indicates "Content-Encoding: gzip" but does not send gzipped data
497513
try:
498514
data = gzip.decompress(response.content)
499515
response_dict = json.loads(data.decode("utf-8"))
500516
except gzip.BadGzipFile:
501-
logging.debug("Bad gzipped payload-- attempting to parse as plaintext")
502517
response_dict = response.json()
518+
elif response.content == b'':
519+
# The server says it was JSON, but it was not
520+
response_dict = {}
503521
else:
504522
response_dict = response.json()
505523
except Exception as e:
506524
logging.error(e)
507-
raise FrigidaireException(f'Received an unexpected response:\n{response.content}')
525+
raise FrigidaireException(f'Received an unexpected response:\n{response.content}') from e
508526

509527
return response_dict
510528

511529
@staticmethod
512530
def handle_request_exception(e: Exception, method: str, fullpath: str, headers: Dict[str, str], payload: str):
513531
logging.warning(e)
514532
error_str = f'Error processing request:\n{method} {fullpath}\nheaders={headers}\npayload={payload}\n'
515-
'This may be safely ignored when used to test for a good connection in the authentication flow'
516533
logging.warning(error_str)
517-
raise FrigidaireException(error_str)
534+
raise FrigidaireException(error_str) from e
518535

519536
def get_request(self, url: str, path: str, headers: Dict[str, str]) -> Union[Dict, List]:
520537
"""

test.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@
1010
# You can use the following contents as a starting point
1111
"""
1212
[credentials]
13-
Username=email@example.com
14-
Password=password
13+
username=email@example.com
14+
password=password
15+
; session_key=insert_session_key_here
16+
; regional_base_url=https://api.us.ocp.electrolux.one
1517
"""
1618
config = configparser.ConfigParser()
1719
config.read('config.ini')
@@ -20,40 +22,51 @@
2022
username = credentials.get('username')
2123
password = credentials.get('password')
2224
session_key = credentials.get('session_key', fallback=None)
25+
regional_base_url = credentials.get('regional_base_url', fallback=None)
2326

2427
frigidaire = Frigidaire(
2528
username,
2629
password,
27-
# session_key, # uncomment this if testing with an already authenticated session key
30+
session_key=session_key,
31+
regional_base_url=regional_base_url,
2832
# timeout=5, # uncomment this if testing the request timeout
2933
)
3034

3135
# tests connectivity
36+
logging.debug("tests connectivity")
3237
frigidaire.test_connection()
3338

3439
# get appliances
40+
logging.debug("get appliance")
3541
appliances = frigidaire.get_appliances()
3642

3743
# pick one arbitrarily
3844
appliance = appliances[0]
3945

4046
# get some details for it
47+
logging.debug("get details")
4148
appliance_details = frigidaire.get_appliance_details(appliance)
4249

4350
# turn on
51+
logging.debug("turn on")
4452
frigidaire.execute_action(appliance, Action.set_power(Power.ON))
4553

4654
# set to cool
55+
logging.debug("set to cool")
4756
frigidaire.execute_action(appliance, Action.set_mode(Mode.COOL))
4857

4958
# set fan to medium
59+
logging.debug("set fan to medium")
5060
frigidaire.execute_action(appliance, Action.set_fan_speed(FanSpeed.MEDIUM))
5161

5262
# set temperature to 75
63+
logging.debug("set temp to 75")
5364
frigidaire.execute_action(appliance, Action.set_temperature(75))
5465

5566
# re-authenticate the connection to get a new session_key
67+
logging.debug("re-authenticate")
5668
frigidaire.re_authenticate()
5769

5870
# turn off
71+
logging.debug("turn off")
5972
frigidaire.execute_action(appliance, Action.set_power(Power.OFF))

0 commit comments

Comments
 (0)