Skip to content

Commit

Permalink
Merge pull request #169 from tomquist/add-retry
Browse files Browse the repository at this point in the history
Auto-retry failed requests
  • Loading branch information
reserve85 authored Mar 23, 2024
2 parents c3592b0 + 7c5f63d commit 0e7718a
Showing 1 changed file with 35 additions and 13 deletions.
48 changes: 35 additions & 13 deletions HoymilesZeroExport.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,11 @@

import requests
import time
from requests.sessions import Session
from requests.auth import HTTPBasicAuth
from requests.auth import HTTPDigestAuth
from requests.adapters import HTTPAdapter
from urllib3.util import Retry
import os
import logging
from logging.handlers import TimedRotatingFileHandler
Expand All @@ -32,6 +35,7 @@
import subprocess
from config_provider import ConfigFileConfigProvider, MqttConfigProvider, ConfigProviderChain

session = Session()
logging.basicConfig(
format='%(asctime)s %(levelname)-8s %(message)s',
level=logging.INFO,
Expand Down Expand Up @@ -639,7 +643,7 @@ def __init__(self, ip: str, json_status: str, json_payload_mqtt_prefix: str, jso

def GetJson(self, path):
url = f'http://{self.ip}{path}'
return requests.get(url, timeout=10).json()
return session.get(url, timeout=10).json()

def GetPowermeterWatts(self):
ParsedData = self.GetJson('/cm?cmnd=status%2010')
Expand All @@ -659,12 +663,12 @@ def __init__(self, ip: str, user: str, password: str):
def GetJson(self, path):
url = f'http://{self.ip}{path}'
headers = {"content-type": "application/json"}
return requests.get(url, headers=headers, auth=(self.user, self.password), timeout=10).json()
return session.get(url, headers=headers, auth=(self.user, self.password), timeout=10).json()

def GetRpcJson(self, path):
url = f'http://{self.ip}/rpc{path}'
headers = {"content-type": "application/json"}
return requests.get(url, headers=headers, auth=HTTPDigestAuth(self.user, self.password), timeout=10).json()
return session.get(url, headers=headers, auth=HTTPDigestAuth(self.user, self.password), timeout=10).json()

def GetPowermeterWatts(self) -> int:
raise NotImplementedError()
Expand Down Expand Up @@ -698,7 +702,7 @@ def __init__(self, ip: str, port: str, domain: str, id: str):

def GetJson(self, path):
url = f'http://{self.ip}:{self.port}{path}'
return requests.get(url, timeout=10).json()
return session.get(url, timeout=10).json()

def GetPowermeterWatts(self):
ParsedData = self.GetJson(f'/{self.domain}/{self.id}')
Expand All @@ -712,7 +716,7 @@ def __init__(self, ip: str, user: str, password: str):

def GetJson(self, path):
url = f'http://{self.ip}{path}'
return requests.get(url, timeout=10).json()
return session.get(url, timeout=10).json()

def GetPowermeterWatts(self):
ParsedData = self.GetJson(f'/getLastData?user={self.user}&password={self.password}')
Expand All @@ -726,7 +730,7 @@ def __init__(self, ip: str, meterindex: str, json_power_calculate: bool):

def GetJson(self, path):
url = f'http://{self.ip}{path}'
return requests.get(url, timeout=10).json()
return session.get(url, timeout=10).json()

def GetPowermeterWatts(self):
ParsedData = self.GetJson(f'/pages/getinformation.php?heute&meterindex={self.meterindex}')
Expand All @@ -748,7 +752,7 @@ def __init__(self, ip: str, port: str, current_power_alias: str, power_calculate

def GetJson(self, path):
url = f'http://{self.ip}:{self.port}{path}'
return requests.get(url, timeout=10).json()
return session.get(url, timeout=10).json()

def GetPowermeterWatts(self):
if not self.power_calculate:
Expand Down Expand Up @@ -778,7 +782,7 @@ def __init__(self, ip: str, port: str, access_token: str, current_power_entity:
def GetJson(self, path):
url = f"http://{self.ip}:{self.port}{path}"
headers = {"Authorization": "Bearer " + self.access_token, "content-type": "application/json"}
return requests.get(url, headers=headers, timeout=10).json()
return session.get(url, headers=headers, timeout=10).json()

def GetPowermeterWatts(self):
if not self.power_calculate:
Expand All @@ -799,7 +803,7 @@ def __init__(self, ip: str, port: str, uuid: str):

def GetJson(self):
url = f"http://{self.ip}:{self.port}/{self.uuid}"
return requests.get(url, timeout=10).json()
return session.get(url, timeout=10).json()

def GetPowermeterWatts(self):
return CastToInt(self.GetJson()['data'][0]['tuples'][0][1])
Expand Down Expand Up @@ -847,11 +851,17 @@ def __init__(self, inverter_count: int, ip: str, password: str):

def GetJson(self, path):
url = f'http://{self.ip}{path}'
return requests.get(url, timeout=10).json()
# AhoyDTU sometimes returns literal 'null' instead of a valid json, so we retry a few times
data = None
retry_count = 3
while retry_count > 0 and data is None:
data = session.get(url, timeout=10).json()
retry_count -= 1
return data

def GetResponseJson(self, path, obj):
url = f'http://{self.ip}{path}'
return requests.post(url, json = obj, timeout=10).json()
return session.post(url, json = obj, timeout=10).json()

def GetACPower(self, pInverterId):
ParsedData = self.GetJson('/api/live')
Expand Down Expand Up @@ -984,12 +994,12 @@ def __init__(self, inverter_count: int, ip: str, user: str, password: str):

def GetJson(self, path):
url = f'http://{self.ip}{path}'
return requests.get(url, auth=HTTPBasicAuth(self.user, self.password), timeout=10).json()
return session.get(url, auth=HTTPBasicAuth(self.user, self.password), timeout=10).json()

def GetResponseJson(self, path, sendStr):
url = f'http://{self.ip}{path}'
headers = {'Content-Type': 'application/x-www-form-urlencoded'}
return requests.post(url=url, headers=headers, data=sendStr, auth=HTTPBasicAuth(self.user, self.password), timeout=10).json()
return session.post(url=url, headers=headers, data=sendStr, auth=HTTPBasicAuth(self.user, self.password), timeout=10).json()

def GetACPower(self, pInverterId):
ParsedData = self.GetJson(f'/api/livedata/status?inv={SERIAL_NUMBER[pInverterId]}')
Expand Down Expand Up @@ -1267,6 +1277,18 @@ def CreateDTU() -> DTU:

VERSION = config.get('VERSION', 'VERSION')
logger.info("Config file V %s", VERSION)

MAX_RETRIES = config.getint('COMMON', 'MAX_RETRIES', fallback=3)
RETRY_STATUS_CODES = config.get('COMMON', 'RETRY_STATUS_CODES', fallback='500,502,503,504')
RETRY_BACKOFF_FACTOR = config.getfloat('COMMON', 'RETRY_BACKOFF_FACTOR', fallback=0.1)
retry = Retry(total=MAX_RETRIES,
backoff_factor=RETRY_BACKOFF_FACTOR,
status_forcelist=[int(status_code) for status_code in RETRY_STATUS_CODES.split(',')],
allowed_methods={"GET", "POST"})
adapter = HTTPAdapter(max_retries=retry)
session.mount('http://', adapter)
session.mount('https://', adapter)

USE_AHOY = config.getboolean('SELECT_DTU', 'USE_AHOY')
USE_OPENDTU = config.getboolean('SELECT_DTU', 'USE_OPENDTU')
AHOY_IP = config.get('AHOY_DTU', 'AHOY_IP')
Expand Down

0 comments on commit 0e7718a

Please sign in to comment.