Skip to content

Commit 08e821c

Browse files
springfall2008Copilotpre-commit-ci-lite[bot]
authored
FoxAPI - handle errors better (#2800)
* FoxAPI - handle errors better * Update apps/predbat/fox.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update apps/predbat/fox.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * [pre-commit.ci lite] apply automatic fixes --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
1 parent 3d31ecf commit 08e821c

2 files changed

Lines changed: 36 additions & 17 deletions

File tree

‎apps/predbat/fox.py‎

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ async def get_device_setting(self, deviceSN, key):
404404
self.device_settings[deviceSN][key] = result
405405
return result
406406
else:
407-
print("Failed to get device setting for {} key {}".format(deviceSN, key))
407+
self.log(f"Fox: Warn: Failed to get device setting for {deviceSN} key {key}")
408408
return None
409409

410410
async def set_device_setting(self, deviceSN, key, value):
@@ -414,6 +414,10 @@ async def set_device_setting(self, deviceSN, key, value):
414414
SET_DEVICE_SETTING = "/op/v0/device/setting/set"
415415
result = await self.request_get(SET_DEVICE_SETTING, datain={"sn": deviceSN, "key": key, "value": value, "lang": FOX_LANG}, post=True)
416416
if result is None:
417+
if self.device_settings.get(deviceSN, {}).get(key, None) is None:
418+
# Failed to write setting after failure to read, assume it doesn't exist
419+
self.log(f"Fox: Warn: Failed to set device setting for {deviceSN} key {key} value {value}, assuming not supported")
420+
return True
417421
return False
418422
return True
419423

@@ -779,9 +783,11 @@ async def request_get(self, path, post=False, datain=None):
779783
retries = 0
780784
self.log("Fox: API Requesting {} {}".format("POST" if post else "GET", path))
781785
while retries < FOX_RETRIES:
782-
result = await self.request_get_func(path, post=post, datain=datain)
786+
result, allow_retry = await self.request_get_func(path, post=post, datain=datain)
783787
if result is not None:
784788
return result
789+
if not allow_retry:
790+
break
785791
retries += 1
786792
await asyncio.sleep(retries * random.random())
787793
return result
@@ -799,15 +805,15 @@ async def request_get_func(self, path, post=False, datain=None):
799805
else:
800806
response = await asyncio.to_thread(requests.get, url, headers=headers, params=datain, timeout=TIMEOUT)
801807
except requests.exceptions.RequestException as e:
802-
self.log(f"Warn: GECloud: Exception during request to {url}: {e}")
808+
self.log(f"Warn: Fox: Exception during request to {url}: {e}")
803809
self.failures_total += 1
804-
return None
810+
return None, False
805811

806812
status_code = response.status_code
807813
if status_code in [400, 401, 402, 403]:
808814
self.log("Warn: Fox: Authentication error with status code {} from {}".format(status_code, url))
809815
self.failures_total += 1
810-
return None
816+
return None, False
811817

812818
try:
813819
data = response.json()
@@ -816,10 +822,10 @@ async def request_get_func(self, path, post=False, datain=None):
816822
data = None
817823
except (requests.Timeout, requests.exceptions.ReadTimeout):
818824
self.log("Warn: Fox: Timeout from {}".format(url))
819-
data = None
825+
return None, True
820826
except (requests.exceptions.RequestException, requests.exceptions.ConnectionError) as e:
821827
self.log("Warn: Fox: Could not connect to {}".format(url))
822-
data = None
828+
return None, True
823829

824830
if response.status_code in [200, 201]:
825831
if data is None:
@@ -830,29 +836,41 @@ async def request_get_func(self, path, post=False, datain=None):
830836
self.failures_total += 1
831837
if errno in [40400, 41200, 41203, 41935]:
832838
# Rate limiting so wait up to 10 seconds
833-
self.log("Fox: Rate limiting detected, waiting...")
834-
await asyncio.sleep(random.random() * 10 + 1)
839+
self.log("Info: Fox: Rate limiting detected, waiting...")
840+
await asyncio.sleep(random.random() * 30 + 1)
841+
return None, True
835842
elif errno in [40402]:
836-
self.log("Fox: Has run out of API calls for today, sleeping...")
843+
# Out of API calls for today
844+
self.log("Warn: Fox: Has run out of API calls for today, sleeping...")
837845
await asyncio.sleep(5 * 60)
838-
return None
846+
return None, False
847+
elif errno in [44096]:
848+
# Unsupported function code
849+
self.log("Warn: Fox: Unsupported function code {} from {}".format(errno, url))
850+
return None, False
851+
elif errno in [40257]:
852+
# Invalid parameter
853+
self.log("Warn: Fox: Invalid parameter {} from {} message {}".format(errno, url, msg))
854+
return None, False
839855
else:
840856
self.log("Warn: Fox: Error {} from {} message {}".format(errno, url, msg))
841-
return None
857+
return None, False
842858

843859
if "result" in data:
844860
data = data["result"]
845861
if data is None:
846862
data = {}
847863

848864
self.last_success_timestamp = datetime.now(timezone.utc)
849-
return data
865+
return data, False
850866
else:
851867
self.failures_total += 1
852868
if response.status_code == 429:
853869
# Rate limiting so wait up to 30 seconds
854-
await asyncio.sleep(random.random() * 30)
855-
return None
870+
self.log("Info: Fox: Rate limiting detected, waiting...")
871+
await asyncio.sleep(random.random() * 30 + 1)
872+
return None, True
873+
return None, False
856874

857875
async def publish_data(self):
858876
"""
@@ -1254,9 +1272,10 @@ async def test_fox_api(api_key):
12541272
# await fox_api.start()
12551273
# res = await fox_api.get_device_settings(sn)
12561274
# res = await fox_api.get_battery_charging_time(sn)
1257-
res = await fox_api.get_scheduler(sn)
1275+
# res = await fox_api.get_scheduler(sn)
12581276
# res = await fox_api.compute_schedule(sn)
12591277
# res = await fox_api.publish_data()
1278+
res = await fox_api.set_device_setting(sn, "dummy", 42)
12601279
print(res)
12611280

12621281
"""

‎apps/predbat/predbat.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
import requests
2626
import asyncio
2727

28-
THIS_VERSION = "v8.26.1"
28+
THIS_VERSION = "v8.26.2"
2929

3030
# fmt: off
3131
PREDBAT_FILES = ["predbat.py", "config.py", "prediction.py", "gecloud.py","utils.py", "inverter.py", "ha.py", "download.py", "unit_test.py", "web.py", "web_helper.py", "predheat.py", "futurerate.py", "octopus.py", "solcast.py","execute.py", "plan.py", "fetch.py", "output.py", "userinterface.py", "energydataservice.py", "alertfeed.py", "compare.py", "db_manager.py", "db_engine.py", "plugin_system.py", "ohme.py", "components.py", "fox.py"]

0 commit comments

Comments
 (0)