Parcourir la source

Add retries for fetching the usage data

I keep getting 500 errors causing the entire thing to fail. Including
some retries to account for this and hopefully allow the request to
succeed.
Jason Tarka il y a 11 mois
Parent
commit
44d021b5ae
1 fichiers modifiés avec 35 ajouts et 5 suppressions
  1. 35 5
      main.py

+ 35 - 5
main.py

@@ -11,6 +11,8 @@
 
 import pyemvue
 import json
+import time
+import sys
 
 from pyemvue.enums import Scale, Unit
 from pyemvue import PyEmVue
@@ -20,6 +22,10 @@ from datetime import datetime, timezone, timedelta
 NOW = datetime.now(timezone.utc) - timedelta(minutes=2)
 DAYS_BACK = 14 # Number of days in the past to get per-minute data for.
 MAX_HOURS = 12 # The maxinum number of hours that can be retrieved at once.
+MAX_ATTEMPTS = 5
+
+def eprint(*args, **kwargs):
+    print(*args, file=sys.stderr, **kwargs)
 
 # Get & display minutely data for all devices.
 def allUsageOverTime(vue: PyEmVue):
@@ -38,11 +44,9 @@ def channelUsageOverTime(vue: PyEmVue, c):
 	start_time = NOW - timedelta(days=DAYS_BACK)
 	end_time = start_time + timedelta(hours=MAX_HOURS)
 	while start_time < NOW:
-		usage_over_time, start = vue.get_chart_usage(
-				c,
-				start_time, end_time,
-				scale=Scale.MINUTE.value,
-				unit=Unit.KWH.value
+		usage_over_time, start = getChartUsage(
+				vue, c,
+				start_time, end_time
 			)
 		time = start
 		for kwh in usage_over_time:
@@ -57,6 +61,32 @@ def channelUsageOverTime(vue: PyEmVue, c):
 		start_time = end_time
 		end_time += timedelta(minutes=(MAX_HOURS*60))
 
+def getChartUsage(vue: PyEmVue, channel, start_time, end_time):
+	"""
+	Get per-minute usage for the channel, with up to MAX_ATTEMPTS
+	attempts to account for errors.
+	"""
+	attempt = 0
+	while True:
+		attempt += 1
+		try:
+			return vue.get_chart_usage(
+					channel,
+					start_time, end_time,
+					scale=Scale.MINUTE.value,
+					unit=Unit.KWH.value
+				)
+		except Exception as e:
+			if attempt < MAX_ATTEMPTS:
+				eprint(
+					f'Attempt {attempt} for channel {channel.name}',
+					f'from {start_time} to {end_time}',
+					f'failed:', e)
+				time.sleep(5)
+			else:
+				eprint(f'Failed after {attempt} attempts')
+				raise
+
 if __name__ == '__main__':
 	with open('keys.json') as f:
 		keys = json.load(f)