Skip to content

Commit e308945

Browse files
committed
Added forbidden error handling for API #28
1 parent ebd1619 commit e308945

File tree

3 files changed

+31
-17
lines changed

3 files changed

+31
-17
lines changed

custom_components/wemportal/coordinator.py

+8-7
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
DataUpdateCoordinator,
99
UpdateFailed,
1010
)
11-
from .exceptions import ServerError, WemPortalError
11+
from .exceptions import ForbiddenError, ServerError, WemPortalError
1212
from .const import _LOGGER, DEFAULT_TIMEOUT
1313
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME
1414
from .wemportalapi import WemPortalApi
@@ -41,8 +41,7 @@ async def _async_update_data(self):
4141
try:
4242
return await self.hass.async_add_executor_job(self.api.fetch_data)
4343
except WemPortalError as exc:
44-
45-
if isinstance(exc.__cause__, ServerError):
44+
if isinstance(exc.__cause__, (ServerError, ForbiddenError)):
4645
_LOGGER.error("Creating new wemportal api instance")
4746
# TODO: This is a temporary solution and should be removed when api cause from #28 is resolved
4847
try:
@@ -55,12 +54,14 @@ async def _async_update_data(self):
5554
except Exception as exc2:
5655
raise UpdateFailed from exc2
5756
try:
58-
return await self.hass.async_add_executor_job(self.api.fetch_data)
57+
return await self.hass.async_add_executor_job(
58+
self.api.fetch_data
59+
)
5960
except WemPortalError as exc2:
60-
_LOGGER.error("Error fetching data from wemportal", exc_info=exc)
61+
_LOGGER.error(
62+
"Error fetching data from wemportal", exc_info=exc
63+
)
6164
raise UpdateFailed from exc2
6265
else:
6366
_LOGGER.error("Error fetching data from wemportal", exc_info=exc)
6467
raise UpdateFailed from exc
65-
66-

custom_components/wemportal/exceptions.py

+8
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,29 @@ class WemPortalError(HomeAssistantError):
88
Custom exception for WEM Portal errors
99
"""
1010

11+
1112
class AuthError(WemPortalError):
1213
"""Exception to indicate an authentication error."""
1314

1415

1516
class UnknownAuthError(WemPortalError):
1617
"""Exception to indicate an unknown authentication error."""
1718

19+
1820
class ServerError(WemPortalError):
1921
"""Exception to indicate a server error."""
2022

23+
24+
class ForbiddenError(WemPortalError):
25+
"""Exception to indicate a forbidden error (403)."""
26+
27+
2128
class ExpiredSessionError(WemPortalError):
2229
"""
2330
Custom exception for expired session errors
2431
"""
2532

33+
2634
class ParameterChangeError(WemPortalError):
2735
"""
2836
Custom exception for parameter change errors

custom_components/wemportal/wemportalapi.py

+15-10
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@
1212
import requests as reqs
1313
import scrapyscript
1414
from fuzzywuzzy import fuzz
15-
from homeassistant.const import CONF_PASSWORD, CONF_SCAN_INTERVAL, CONF_USERNAME
15+
from homeassistant.const import CONF_SCAN_INTERVAL
1616
from scrapy import FormRequest, Spider, Request
1717
from .exceptions import (
1818
AuthError,
19+
ForbiddenError,
1920
UnknownAuthError,
2021
WemPortalError,
2122
ExpiredSessionError,
@@ -73,7 +74,7 @@ def __init__(self, username, password, config={}) -> None:
7374
"X-Api-Version": "2.0.0.0",
7475
"Accept": "*/*",
7576
}
76-
self.scrapingMapper = {}
77+
self.scraping_mapper = {}
7778

7879
# Used to keep track of how many update intervals to wait before retrying spider
7980
self.spider_wait_interval = 0
@@ -197,12 +198,16 @@ def api_login(self):
197198
response_status, response_message = self.get_response_details(response)
198199
if response is None:
199200
raise UnknownAuthError(
200-
f"Authentication Error: Encountered an unknown authentication error."
201+
"Authentication Error: Encountered an unknown authentication error."
201202
) from exc
202203
elif response.status_code == 400:
203204
raise AuthError(
204205
f"Authentication Error: Check if your login credentials are correct. Received response code: {response.status_code}, response: {response.content}. Server returned internal status code: {response_status} and message: {response_message}"
205206
) from exc
207+
elif response.status_code == 403:
208+
raise ForbiddenError(
209+
f"WemPortal forbidden error: Server returned internal status code: {response_status} and message: {response_message}"
210+
) from exc
206211
elif response.status_code == 500:
207212
raise ServerError(
208213
f"WemPortal server error: Server returned internal status code: {response_status} and message: {response_message}"
@@ -243,7 +248,7 @@ def make_api_call(
243248
)
244249
response.raise_for_status()
245250
except Exception as exc:
246-
if response and response.status_code == 401 and not login_retry:
251+
if response and response.status_code in (401, 403) and not login_retry:
247252
self.api_login()
248253
headers = headers or self.headers
249254
time.sleep(delay)
@@ -347,7 +352,7 @@ def change_value(
347352
headers=headers,
348353
data=json.dumps(data),
349354
)
350-
if response.status_code == 401 and login:
355+
if response.status_code in (401, 403) and login:
351356
self.api_login()
352357
self.change_value(
353358
device_id,
@@ -516,7 +521,7 @@ def get_data(self):
516521
# Only for single device, don't know how to handle multiple devices with scraping yet
517522
if self.mode == "both" and len(self.data.keys()) < 2:
518523
try:
519-
temp = self.scrapingMapper[value["ParameterID"]]
524+
temp = self.scraping_mapper[value["ParameterID"]]
520525
except KeyError:
521526
for scraped_entity in self.data[device_id].keys():
522527
scraped_entity_id = self.data[device_id][
@@ -530,21 +535,21 @@ def get_data(self):
530535
)
531536
>= 90
532537
):
533-
self.scrapingMapper.setdefault(
538+
self.scraping_mapper.setdefault(
534539
value["ParameterID"], []
535540
).append(scraped_entity_id)
536541
except IndexError:
537542
pass
538543
# Check if empty
539544
try:
540-
temp = self.scrapingMapper[value["ParameterID"]]
545+
temp = self.scraping_mapper[value["ParameterID"]]
541546
except KeyError:
542-
self.scrapingMapper[value["ParameterID"]] = [
547+
self.scraping_mapper[value["ParameterID"]] = [
543548
value["friendlyName"]
544549
]
545550

546551
finally:
547-
for scraped_entity in self.scrapingMapper[
552+
for scraped_entity in self.scraping_mapper[
548553
value["ParameterID"]
549554
]:
550555
sensor_dict = {

0 commit comments

Comments
 (0)