From e3f953b300978ee7690a493913530bc6fc470573 Mon Sep 17 00:00:00 2001
From: reserve85 <111107925+reserve85@users.noreply.github.com>
Date: Wed, 10 Jan 2024 09:53:00 +0100
Subject: [PATCH 1/5] add average MinPanelVoltage
## V1.66
### script
* calculates an average of the "MinPanelVoltage", rel https://github.com/reserve85/HoymilesZeroExport/issues/120
### Config
* add: `INVERTER_x`: `HOY_BATTERY_AVERAGE_CNT`
---
CHANGELOG.md | 6 ++++++
HoymilesZeroExport.py | 22 +++++++++++++++++++---
HoymilesZeroExport_Config.ini | 34 +++++++++++++++++++++++++++++++++-
3 files changed, 58 insertions(+), 4 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b38f2a9..ad12a15 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,11 @@
# Changelog
+## V1.66
+### script
+* calculates an average of the "MinPanelVoltage", rel https://github.com/reserve85/HoymilesZeroExport/issues/120
+### Config
+* add: `INVERTER_x`: `HOY_BATTERY_AVERAGE_CNT`
+
## V1.65
### script
* bugfix set limit retry
diff --git a/HoymilesZeroExport.py b/HoymilesZeroExport.py
index e2d5c5d..2fd14c8 100644
--- a/HoymilesZeroExport.py
+++ b/HoymilesZeroExport.py
@@ -15,7 +15,7 @@
# along with this program. If not, see .
__author__ = "Tobias Kraft"
-__version__ = "1.65"
+__version__ = "1.66"
import requests
import time
@@ -425,15 +425,23 @@ def GetHoymilesPanelMinVoltageOpenDTU(pInverterId):
return max_value
def GetHoymilesPanelMinVoltage(pInverterId):
+ if not hasattr(GetHoymilesPanelMinVoltage, "HoymilesPanelMinVoltageArray"):
+ GetHoymilesPanelMinVoltage.HoymilesPanelMinVoltageArray = []
try:
if not AVAILABLE[pInverterId]:
return 0
if USE_AHOY:
- return GetHoymilesPanelMinVoltageAhoy(pInverterId)
+ HOY_PANEL_MIN_VOLTAGE_HISTORY_LIST[pInverterId].append(GetHoymilesPanelMinVoltageAhoy(pInverterId))
elif USE_OPENDTU:
- return GetHoymilesPanelMinVoltageOpenDTU(pInverterId)
+ HOY_PANEL_MIN_VOLTAGE_HISTORY_LIST[pInverterId].append(GetHoymilesPanelMinVoltageOpenDTU(pInverterId))
else:
raise Exception("Error: DTU Type not defined")
+
+ # calculate mean over last x values
+ if len(HOY_PANEL_MIN_VOLTAGE_HISTORY_LIST[pInverterId]) > 5:
+ HOY_PANEL_MIN_VOLTAGE_HISTORY_LIST[pInverterId].pop(0)
+ from statistics import mean
+ return mean(HOY_PANEL_MIN_VOLTAGE_HISTORY_LIST[pInverterId])
except:
logger.error("Exception at GetHoymilesPanelMinVoltage, Inverter %s not reachable", pInverterId)
raise
@@ -1063,6 +1071,8 @@ def GetPriorityMode():
HOY_BATTERY_IGNORE_PANELS = []
HOY_BATTERY_PRIORITY = []
HOY_PANEL_VOLTAGE_LIST = []
+HOY_PANEL_MIN_VOLTAGE_HISTORY_LIST = []
+HOY_BATTERY_AVERAGE_CNT = []
for i in range(INVERTER_COUNT):
SERIAL_NUMBER.append(str('yet unknown'))
NAME.append(str('yet unknown'))
@@ -1086,11 +1096,17 @@ def GetPriorityMode():
HOY_BATTERY_IGNORE_PANELS.append(config.get('INVERTER_' + str(i + 1), 'HOY_BATTERY_IGNORE_PANELS'))
HOY_BATTERY_PRIORITY.append(config.getint('INVERTER_' + str(i + 1), 'HOY_BATTERY_PRIORITY'))
HOY_PANEL_VOLTAGE_LIST.append([])
+ HOY_PANEL_MIN_VOLTAGE_HISTORY_LIST.append([])
+ HOY_BATTERY_AVERAGE_CNT.append(config.getint('INVERTER_' + str(i + 1), 'HOY_BATTERY_AVERAGE_CNT'))
SLOW_APPROX_LIMIT = CastToInt(GetMaxWattFromAllInverters() * config.getint('COMMON', 'SLOW_APPROX_LIMIT_IN_PERCENT') / 100)
try:
logger.info("---Init---")
newLimitSetpoint = 0
+
+ GetHoymilesPanelMinVoltage(0)
+
+
if USE_AHOY:
CheckAhoyVersion()
AHOY_FACTOR = GetAhoyLimitFactor()
diff --git a/HoymilesZeroExport_Config.ini b/HoymilesZeroExport_Config.ini
index 7b29449..a1ad15c 100644
--- a/HoymilesZeroExport_Config.ini
+++ b/HoymilesZeroExport_Config.ini
@@ -19,7 +19,7 @@
# ---------------------------------------------------------------------
[VERSION]
-VERSION = 1.64
+VERSION = 1.66
[SELECT_DTU]
# --- define your DTU (only one) ---
@@ -261,6 +261,8 @@ HOY_BATTERY_IGNORE_PANELS =
# set limit of 1100W -> inverter 1 is set to 1000W and inverter 2 is set to 100W
# set limit of 300W -> inverter 1 is set to 300W and inverter 2 is powered off
HOY_BATTERY_PRIORITY = 1
+# Number of measured values for the moving average of the min panel voltage
+HOY_BATTERY_AVERAGE_CNT = 1
[INVERTER_2]
# power rating of your inverter
@@ -296,6 +298,8 @@ HOY_BATTERY_IGNORE_PANELS =
# set limit of 1100W -> inverter 1 is set to 1000W and inverter 2 is set to 100W
# set limit of 300W -> inverter 1 is set to 300W and inverter 2 is powered off
HOY_BATTERY_PRIORITY = 1
+# Number of measured values for the moving average of the min panel voltage
+HOY_BATTERY_AVERAGE_CNT = 1
[INVERTER_3]
# power rating of your inverter
@@ -331,6 +335,8 @@ HOY_BATTERY_IGNORE_PANELS =
# set limit of 1100W -> inverter 1 is set to 1000W and inverter 2 is set to 100W
# set limit of 300W -> inverter 1 is set to 300W and inverter 2 is powered off
HOY_BATTERY_PRIORITY = 1
+# Number of measured values for the moving average of the min panel voltage
+HOY_BATTERY_AVERAGE_CNT = 1
[INVERTER_4]
# power rating of your inverter
@@ -366,6 +372,8 @@ HOY_BATTERY_IGNORE_PANELS =
# set limit of 1100W -> inverter 1 is set to 1000W and inverter 2 is set to 100W
# set limit of 300W -> inverter 1 is set to 300W and inverter 2 is powered off
HOY_BATTERY_PRIORITY = 1
+# Number of measured values for the moving average of the min panel voltage
+HOY_BATTERY_AVERAGE_CNT = 1
[INVERTER_5]
# power rating of your inverter
@@ -401,6 +409,8 @@ HOY_BATTERY_IGNORE_PANELS =
# set limit of 1100W -> inverter 1 is set to 1000W and inverter 2 is set to 100W
# set limit of 300W -> inverter 1 is set to 300W and inverter 2 is powered off
HOY_BATTERY_PRIORITY = 1
+# Number of measured values for the moving average of the min panel voltage
+HOY_BATTERY_AVERAGE_CNT = 1
[INVERTER_6]
# power rating of your inverter
@@ -436,6 +446,8 @@ HOY_BATTERY_IGNORE_PANELS =
# set limit of 1100W -> inverter 1 is set to 1000W and inverter 2 is set to 100W
# set limit of 300W -> inverter 1 is set to 300W and inverter 2 is powered off
HOY_BATTERY_PRIORITY = 1
+# Number of measured values for the moving average of the min panel voltage
+HOY_BATTERY_AVERAGE_CNT = 1
[INVERTER_7]
# power rating of your inverter
@@ -471,6 +483,8 @@ HOY_BATTERY_IGNORE_PANELS =
# set limit of 1100W -> inverter 1 is set to 1000W and inverter 2 is set to 100W
# set limit of 300W -> inverter 1 is set to 300W and inverter 2 is powered off
HOY_BATTERY_PRIORITY = 1
+# Number of measured values for the moving average of the min panel voltage
+HOY_BATTERY_AVERAGE_CNT = 1
[INVERTER_8]
# power rating of your inverter
@@ -506,6 +520,8 @@ HOY_BATTERY_IGNORE_PANELS =
# set limit of 1100W -> inverter 1 is set to 1000W and inverter 2 is set to 100W
# set limit of 300W -> inverter 1 is set to 300W and inverter 2 is powered off
HOY_BATTERY_PRIORITY = 1
+# Number of measured values for the moving average of the min panel voltage
+HOY_BATTERY_AVERAGE_CNT = 1
[INVERTER_9]
# power rating of your inverter
@@ -541,6 +557,8 @@ HOY_BATTERY_IGNORE_PANELS =
# set limit of 1100W -> inverter 1 is set to 1000W and inverter 2 is set to 100W
# set limit of 300W -> inverter 1 is set to 300W and inverter 2 is powered off
HOY_BATTERY_PRIORITY = 1
+# Number of measured values for the moving average of the min panel voltage
+HOY_BATTERY_AVERAGE_CNT = 1
[INVERTER_10]
# power rating of your inverter
@@ -576,6 +594,8 @@ HOY_BATTERY_IGNORE_PANELS =
# set limit of 1100W -> inverter 1 is set to 1000W and inverter 2 is set to 100W
# set limit of 300W -> inverter 1 is set to 300W and inverter 2 is powered off
HOY_BATTERY_PRIORITY = 1
+# Number of measured values for the moving average of the min panel voltage
+HOY_BATTERY_AVERAGE_CNT = 1
[INVERTER_11]
# power rating of your inverter
@@ -611,6 +631,8 @@ HOY_BATTERY_IGNORE_PANELS =
# set limit of 1100W -> inverter 1 is set to 1000W and inverter 2 is set to 100W
# set limit of 300W -> inverter 1 is set to 300W and inverter 2 is powered off
HOY_BATTERY_PRIORITY = 1
+# Number of measured values for the moving average of the min panel voltage
+HOY_BATTERY_AVERAGE_CNT = 1
[INVERTER_12]
# power rating of your inverter
@@ -646,6 +668,8 @@ HOY_BATTERY_IGNORE_PANELS =
# set limit of 1100W -> inverter 1 is set to 1000W and inverter 2 is set to 100W
# set limit of 300W -> inverter 1 is set to 300W and inverter 2 is powered off
HOY_BATTERY_PRIORITY = 1
+# Number of measured values for the moving average of the min panel voltage
+HOY_BATTERY_AVERAGE_CNT = 1
[INVERTER_13]
# power rating of your inverter
@@ -681,6 +705,8 @@ HOY_BATTERY_IGNORE_PANELS =
# set limit of 1100W -> inverter 1 is set to 1000W and inverter 2 is set to 100W
# set limit of 300W -> inverter 1 is set to 300W and inverter 2 is powered off
HOY_BATTERY_PRIORITY = 1
+# Number of measured values for the moving average of the min panel voltage
+HOY_BATTERY_AVERAGE_CNT = 1
[INVERTER_14]
# power rating of your inverter
@@ -716,6 +742,8 @@ HOY_BATTERY_IGNORE_PANELS =
# set limit of 1100W -> inverter 1 is set to 1000W and inverter 2 is set to 100W
# set limit of 300W -> inverter 1 is set to 300W and inverter 2 is powered off
HOY_BATTERY_PRIORITY = 1
+# Number of measured values for the moving average of the min panel voltage
+HOY_BATTERY_AVERAGE_CNT = 1
[INVERTER_15]
# power rating of your inverter
@@ -751,6 +779,8 @@ HOY_BATTERY_IGNORE_PANELS =
# set limit of 1100W -> inverter 1 is set to 1000W and inverter 2 is set to 100W
# set limit of 300W -> inverter 1 is set to 300W and inverter 2 is powered off
HOY_BATTERY_PRIORITY = 1
+# Number of measured values for the moving average of the min panel voltage
+HOY_BATTERY_AVERAGE_CNT = 1
[INVERTER_16]
# power rating of your inverter
@@ -786,6 +816,8 @@ HOY_BATTERY_IGNORE_PANELS =
# set limit of 1100W -> inverter 1 is set to 1000W and inverter 2 is set to 100W
# set limit of 300W -> inverter 1 is set to 300W and inverter 2 is powered off
HOY_BATTERY_PRIORITY = 1
+# Number of measured values for the moving average of the min panel voltage
+HOY_BATTERY_AVERAGE_CNT = 1
# grid power
# ...
From 19a19ba82f8d37caa31d884febf00ecda39f788b Mon Sep 17 00:00:00 2001
From: reserve85 <111107925+reserve85@users.noreply.github.com>
Date: Wed, 10 Jan 2024 12:57:47 +0100
Subject: [PATCH 2/5] log average min voltage
log average min voltage
---
HoymilesZeroExport.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/HoymilesZeroExport.py b/HoymilesZeroExport.py
index 2fd14c8..98db88a 100644
--- a/HoymilesZeroExport.py
+++ b/HoymilesZeroExport.py
@@ -421,7 +421,6 @@ def GetHoymilesPanelMinVoltageOpenDTU(pInverterId):
if (max_value is None or num > max_value):
max_value = num
- logger.info('Lowest panel voltage inverter "%s": %s Volt',NAME[pInverterId],max_value)
return max_value
def GetHoymilesPanelMinVoltage(pInverterId):
@@ -441,6 +440,8 @@ def GetHoymilesPanelMinVoltage(pInverterId):
if len(HOY_PANEL_MIN_VOLTAGE_HISTORY_LIST[pInverterId]) > 5:
HOY_PANEL_MIN_VOLTAGE_HISTORY_LIST[pInverterId].pop(0)
from statistics import mean
+
+ logger.info('Average min-panel voltage, inverter "%s": %s Volt',NAME[pInverterId], mean(HOY_PANEL_MIN_VOLTAGE_HISTORY_LIST[pInverterId]))
return mean(HOY_PANEL_MIN_VOLTAGE_HISTORY_LIST[pInverterId])
except:
logger.error("Exception at GetHoymilesPanelMinVoltage, Inverter %s not reachable", pInverterId)
From cbb56b33bd4c9e24f08fbc849f1f0fe70ecbda53 Mon Sep 17 00:00:00 2001
From: reserve85 <111107925+reserve85@users.noreply.github.com>
Date: Mon, 22 Jan 2024 12:19:13 +0100
Subject: [PATCH 3/5] Improved LimitRetry
## V1.67
### script
* Limit-Handling improved (if not acknowledged -> retransmit)
---
CHANGELOG.md | 4 ++
HoymilesZeroExport.py | 137 +++++++++++++++++++++---------------------
2 files changed, 72 insertions(+), 69 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ad12a15..8bc036e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
# Changelog
+## V1.67
+### script
+* Limit-Handling improved (if not acknowledged -> retransmit)
+
## V1.66
### script
* calculates an average of the "MinPanelVoltage", rel https://github.com/reserve85/HoymilesZeroExport/issues/120
diff --git a/HoymilesZeroExport.py b/HoymilesZeroExport.py
index 98db88a..afd5d59 100644
--- a/HoymilesZeroExport.py
+++ b/HoymilesZeroExport.py
@@ -15,7 +15,7 @@
# along with this program. If not, see .
__author__ = "Tobias Kraft"
-__version__ = "1.66"
+__version__ = "1.67"
import requests
import time
@@ -115,59 +115,61 @@ def SetLimitAhoy(pInverterId, pLimit):
CURRENT_LIMIT[pInverterId] = pLimit
def WaitForAckAhoy(pInverterId, pTimeoutInS):
- url = f'http://{AHOY_IP}/api/inverter/id/{pInverterId}'
- timeout = pTimeoutInS
- timeout_start = time.time()
- while time.time() < timeout_start + timeout:
- time.sleep(0.5)
- ParsedData = requests.get(url, timeout=pTimeoutInS).json()
- ack = bool(ParsedData['power_limit_ack'])
+ try:
+ url = f'http://{AHOY_IP}/api/inverter/id/{pInverterId}'
+ timeout = pTimeoutInS
+ timeout_start = time.time()
+ while time.time() < timeout_start + timeout:
+ time.sleep(0.5)
+ ParsedData = requests.get(url, timeout=pTimeoutInS).json()
+ ack = bool(ParsedData['power_limit_ack'])
+ if ack:
+ break
if ack:
- break
- if ack:
- logger.info('Ahoy: Inverter "%s": Limit acknowledged', NAME[pInverterId])
- else:
+ logger.info('Ahoy: Inverter "%s": Limit acknowledged', NAME[pInverterId])
+ else:
+ logger.info('Ahoy: Inverter "%s": Limit timeout!', NAME[pInverterId])
+ return ack
+ except:
logger.info('Ahoy: Inverter "%s": Limit timeout!', NAME[pInverterId])
- return ack
+ return False
def WaitForAckOpenDTU(pInverterId, pTimeoutInS):
- url = f'http://{OPENDTU_IP}/api/limit/status'
- timeout = pTimeoutInS
- timeout_start = time.time()
- while time.time() < timeout_start + timeout:
- time.sleep(0.5)
- ParsedData = requests.get(url, auth=HTTPBasicAuth(OPENDTU_USER, OPENDTU_PASS), timeout=10).json()
- ack = (ParsedData[SERIAL_NUMBER[pInverterId]]['limit_set_status'] == 'Ok')
+ try:
+ url = f'http://{OPENDTU_IP}/api/limit/status'
+ timeout = pTimeoutInS
+ timeout_start = time.time()
+ while time.time() < timeout_start + timeout:
+ time.sleep(0.5)
+ ParsedData = requests.get(url, auth=HTTPBasicAuth(OPENDTU_USER, OPENDTU_PASS), timeout=10).json()
+ ack = (ParsedData[SERIAL_NUMBER[pInverterId]]['limit_set_status'] == 'Ok')
+ if ack:
+ break
if ack:
- break
- if ack:
- logger.info('OpenDTU: Inverter "%s": Limit acknowledged', NAME[pInverterId])
- else:
+ logger.info('OpenDTU: Inverter "%s": Limit acknowledged', NAME[pInverterId])
+ else:
+ logger.info('OpenDTU: Inverter "%s": Limit timeout!', NAME[pInverterId])
+ return ack
+ except:
logger.info('OpenDTU: Inverter "%s": Limit timeout!', NAME[pInverterId])
- return ack
+ return False
def SetLimitWithPriority(pLimit):
try:
- if SET_LIMIT_RETRY != -1:
- if not hasattr(SetLimitWithPriority, "LastLimit"):
- SetLimitWithPriority.LastLimit = CastToInt(0)
- if not hasattr(SetLimitWithPriority, "SameLimitCnt"):
- SetLimitWithPriority.SameLimitCnt = CastToInt(0)
- if not hasattr(SetLimitWithPriority, "LastLimitAck"):
- SetLimitWithPriority.LastLimitAck = bool(False)
- if (SetLimitWithPriority.LastLimit == CastToInt(pLimit)) and SetLimitWithPriority.LastLimitAck:
- logger.info("Inverterlimit already at %s Watt",CastToInt(pLimit))
- return
- if (SetLimitWithPriority.LastLimit == CastToInt(pLimit)):
- SetLimitWithPriority.SameLimitCnt = SetLimitWithPriority.SameLimitCnt + 1
- else:
- SetLimitWithPriority.LastLimit = CastToInt(pLimit)
- SetLimitWithPriority.SameLimitCnt = 0
- if SetLimitWithPriority.SameLimitCnt >= SET_LIMIT_RETRY:
- logger.info("Retry Counter exceeded: Inverterlimit already at %s Watt",CastToInt(pLimit))
- time.sleep(SET_LIMIT_DELAY_IN_SECONDS)
- return
+ if not hasattr(SetLimitWithPriority, "LastLimit"):
+ SetLimitWithPriority.LastLimit = CastToInt(0)
+ if not hasattr(SetLimitWithPriority, "LastLimitAck"):
+ SetLimitWithPriority.LastLimitAck = bool(False)
+
+ if (SetLimitWithPriority.LastLimit == CastToInt(pLimit)) and SetLimitWithPriority.LastLimitAck:
+ logger.info("Inverterlimit was already accepted at %s Watt",CastToInt(pLimit))
+ return
+ if (SetLimitWithPriority.LastLimit == CastToInt(pLimit)) and not SetLimitWithPriority.LastLimitAck:
+ logger.info("Inverterlimit %s Watt was previously not accepted by the inverter, trying again...",CastToInt(pLimit))
+ return
+
logger.info("setting new limit to %s Watt",CastToInt(pLimit))
+ SetLimitWithPriority.LastLimit = CastToInt(pLimit)
SetLimitWithPriority.LastLimitAck = True
if (CastToInt(pLimit) <= GetMinWattFromAllInverters()):
pLimit = 0 # set only minWatt for every inv.
@@ -179,7 +181,7 @@ def SetLimitWithPriority(pLimit):
LimitPrio = GetMaxWattFromAllInvertersSamePrio(j)
else:
LimitPrio = RemainingLimit
- RemainingLimit = RemainingLimit - LimitPrio
+ RemainingLimit = RemainingLimit - LimitPrio
for i in range(INVERTER_COUNT):
if (not AVAILABLE[i]) or (not HOY_BATTERY_GOOD_VOLTAGE[i]):
@@ -215,26 +217,19 @@ def SetLimit(pLimit):
SetLimitWithPriority(CastToInt(pLimit))
return
- if SET_LIMIT_RETRY != -1:
- if not hasattr(SetLimit, "LastLimit"):
- SetLimit.LastLimit = CastToInt(0)
- if not hasattr(SetLimit, "SameLimitCnt"):
- SetLimit.SameLimitCnt = CastToInt(0)
- if not hasattr(SetLimit, "LastLimitAck"):
- SetLimit.LastLimitAck = bool(False)
- if (SetLimit.LastLimit == CastToInt(pLimit)) and SetLimit.LastLimitAck:
- logger.info("Inverterlimit already at %s Watt",CastToInt(pLimit))
- return
- if (SetLimit.LastLimit == CastToInt(pLimit)):
- SetLimit.SameLimitCnt = SetLimit.SameLimitCnt + 1
- else:
- SetLimit.LastLimit = CastToInt(pLimit)
- SetLimit.SameLimitCnt = 0
- if SetLimit.SameLimitCnt >= SET_LIMIT_RETRY:
- logger.info("Retry Counter exceeded: Inverterlimit already at %s Watt",CastToInt(pLimit))
- time.sleep(SET_LIMIT_DELAY_IN_SECONDS)
- return
+ if not hasattr(SetLimit, "LastLimit"):
+ SetLimit.LastLimit = CastToInt(0)
+ if not hasattr(SetLimit, "LastLimitAck"):
+ SetLimit.LastLimitAck = bool(False)
+
+ if (SetLimit.LastLimit == CastToInt(pLimit)) and SetLimit.LastLimitAck:
+ logger.info("Inverterlimit was already accepted at %s Watt",CastToInt(pLimit))
+ return
+ if (SetLimit.LastLimit == CastToInt(pLimit)) and not SetLimit.LastLimitAck:
+ logger.info("Inverterlimit %s Watt was previously not accepted by the inverter, trying again...",CastToInt(pLimit))
+
logger.info("setting new limit to %s Watt",CastToInt(pLimit))
+ SetLimit.LastLimit = CastToInt(pLimit)
SetLimit.LastLimitAck = True
if (CastToInt(pLimit) <= GetMinWattFromAllInverters()):
pLimit = 0 # set only minWatt for every inv.
@@ -292,6 +287,14 @@ def GetHoymilesAvailable():
if AVAILABLE[i]:
GetHoymilesAvailable = True
if not WasAvail:
+ if hasattr(SetLimit, "LastLimit"):
+ SetLimit.LastLimit = CastToInt(0)
+ if hasattr(SetLimit, "LastLimitAck"):
+ SetLimit.LastLimitAck = bool(False)
+ if hasattr(SetLimitWithPriority, "LastLimit"):
+ SetLimitWithPriority.LastLimit = CastToInt(0)
+ if hasattr(SetLimitWithPriority, "LastLimitAck"):
+ SetLimitWithPriority.LastLimitAck = bool(False)
GetHoymilesInfo()
except Exception as e:
AVAILABLE[i] = False
@@ -304,7 +307,7 @@ def GetHoymilesAvailable():
except:
logger.error('Exception at GetHoymilesAvailable')
raise
-
+
def CheckAhoyVersion():
MinVersion = '0.7.29'
url = f'http://{AHOY_IP}/api/system'
@@ -1104,10 +1107,6 @@ def GetPriorityMode():
try:
logger.info("---Init---")
newLimitSetpoint = 0
-
- GetHoymilesPanelMinVoltage(0)
-
-
if USE_AHOY:
CheckAhoyVersion()
AHOY_FACTOR = GetAhoyLimitFactor()
From 9ff64daa915b65795bba05a52dc6dbfba1f97e49 Mon Sep 17 00:00:00 2001
From: reserve85 <111107925+reserve85@users.noreply.github.com>
Date: Tue, 23 Jan 2024 11:31:07 +0100
Subject: [PATCH 4/5] Repeat limit for specific inverter
## V1.67
### script
* Only repeat limit for the specific inverter (where limit was not acknowledged)
### Config
* renamed `SET_LIMIT_RETRY` to `SET_POWERSTATUS_CNT`
---
CHANGELOG.md | 6 ++++++
HoymilesZeroExport.py | 23 ++++++++++++++++++-----
HoymilesZeroExport_Config.ini | 6 +++---
3 files changed, 27 insertions(+), 8 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8bc036e..2e268f5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,11 @@
# Changelog
+## V1.67
+### script
+* Only repeat limit for the specific inverter (where limit was not acknowledged)
+### Config
+* renamed `SET_LIMIT_RETRY` to `SET_POWERSTATUS_CNT`
+
## V1.67
### script
* Limit-Handling improved (if not acknowledged -> retransmit)
diff --git a/HoymilesZeroExport.py b/HoymilesZeroExport.py
index afd5d59..3d8a8ed 100644
--- a/HoymilesZeroExport.py
+++ b/HoymilesZeroExport.py
@@ -15,7 +15,7 @@
# along with this program. If not, see .
__author__ = "Tobias Kraft"
-__version__ = "1.67"
+__version__ = "1.68"
import requests
import time
@@ -226,7 +226,10 @@ def SetLimit(pLimit):
logger.info("Inverterlimit was already accepted at %s Watt",CastToInt(pLimit))
return
if (SetLimit.LastLimit == CastToInt(pLimit)) and not SetLimit.LastLimitAck:
- logger.info("Inverterlimit %s Watt was previously not accepted by the inverter, trying again...",CastToInt(pLimit))
+ logger.info("Inverterlimit %s Watt was previously not accepted by at least one inverter, trying again...",CastToInt(pLimit))
+ lclRepeatLimit = True
+ else:
+ lclRepeatLimit = False
logger.info("setting new limit to %s Watt",CastToInt(pLimit))
SetLimit.LastLimit = CastToInt(pLimit)
@@ -243,14 +246,21 @@ def SetLimit(pLimit):
logger.info('Ahoy: Inverter "%s": compensate Limit from %s Watt to %s Watt', NAME[i], CastToInt(NewLimit), CastToInt(NewLimit*HOY_COMPENSATE_WATT_FACTOR[i]))
NewLimit = CastToInt(NewLimit * HOY_COMPENSATE_WATT_FACTOR[i])
NewLimit = ApplyLimitsToMaxInverterLimits(i, NewLimit)
+
+ if lclRepeatLimit and LASTLIMITACKNOWLEDGED[i]:
+ continue
+
if USE_AHOY:
SetLimitAhoy(i, NewLimit)
+ LASTLIMITACKNOWLEDGED[i] = True
if not WaitForAckAhoy(i, SET_LIMIT_TIMEOUT_SECONDS):
SetLimit.LastLimitAck = False
+ LASTLIMITACKNOWLEDGED[i] = False
elif USE_OPENDTU:
SetLimitOpenDTU(i, NewLimit)
if not WaitForAckOpenDTU(i, SET_LIMIT_TIMEOUT_SECONDS):
SetLimit.LastLimitAck = False
+ LASTLIMITACKNOWLEDGED[i] = False
else:
raise Exception("Error: DTU Type not defined")
except:
@@ -295,6 +305,7 @@ def GetHoymilesAvailable():
SetLimitWithPriority.LastLimit = CastToInt(0)
if hasattr(SetLimitWithPriority, "LastLimitAck"):
SetLimitWithPriority.LastLimitAck = bool(False)
+ LASTLIMITACKNOWLEDGED[i] = False
GetHoymilesInfo()
except Exception as e:
AVAILABLE[i] = False
@@ -474,7 +485,7 @@ def SetHoymilesPowerStatus(pInverterId, pActive):
try:
if not AVAILABLE[pInverterId]:
return
- if SET_LIMIT_RETRY != -1:
+ if SET_POWERSTATUS_CNT > 0:
if not hasattr(SetHoymilesPowerStatus, "LastPowerStatus"):
SetHoymilesPowerStatus.LastPowerStatus = []
SetHoymilesPowerStatus.LastPowerStatus = [False for i in range(INVERTER_COUNT)]
@@ -486,7 +497,7 @@ def SetHoymilesPowerStatus(pInverterId, pActive):
else:
SetHoymilesPowerStatus.LastPowerStatus[pInverterId] = pActive
SetHoymilesPowerStatus.SamePowerStatusCnt[pInverterId] = 0
- if SetHoymilesPowerStatus.SamePowerStatusCnt[pInverterId] >= SET_LIMIT_RETRY:
+ if SetHoymilesPowerStatus.SamePowerStatusCnt[pInverterId] > SET_POWERSTATUS_CNT:
if pActive:
logger.info("Retry Counter exceeded: Inverter PowerStatus already ON")
else:
@@ -1046,7 +1057,7 @@ def GetPriorityMode():
POLL_INTERVAL_IN_SECONDS = config.getint('COMMON', 'POLL_INTERVAL_IN_SECONDS')
ON_GRID_USAGE_JUMP_TO_LIMIT_PERCENT = config.getint('COMMON', 'ON_GRID_USAGE_JUMP_TO_LIMIT_PERCENT')
MAX_DIFFERENCE_BETWEEN_LIMIT_AND_OUTPUTPOWER = config.getint('COMMON', 'MAX_DIFFERENCE_BETWEEN_LIMIT_AND_OUTPUTPOWER')
-SET_LIMIT_RETRY = config.getint('COMMON', 'SET_LIMIT_RETRY')
+SET_POWERSTATUS_CNT = config.getint('COMMON', 'SET_POWERSTATUS_CNT')
SLOW_APPROX_FACTOR_IN_PERCENT = config.getint('COMMON', 'SLOW_APPROX_FACTOR_IN_PERCENT')
LOG_TEMPERATURE = config.getboolean('COMMON', 'LOG_TEMPERATURE')
POWERMETER_TARGET_POINT = config.getint('CONTROL', 'POWERMETER_TARGET_POINT')
@@ -1063,6 +1074,7 @@ def GetPriorityMode():
HOY_MIN_WATT = []
CURRENT_LIMIT = []
AVAILABLE = []
+LASTLIMITACKNOWLEDGED = []
HOY_BATTERY_GOOD_VOLTAGE = []
HOY_COMPENSATE_WATT_FACTOR = []
HOY_BATTERY_MODE = []
@@ -1086,6 +1098,7 @@ def GetPriorityMode():
HOY_MIN_WATT.append(int(HOY_MAX_WATT[i] * config.getint('INVERTER_' + str(i + 1), 'HOY_MIN_WATT_IN_PERCENT') / 100))
CURRENT_LIMIT.append(int(0))
AVAILABLE.append(bool(False))
+ LASTLIMITACKNOWLEDGED.append(bool(False))
HOY_BATTERY_GOOD_VOLTAGE.append(bool(True))
HOY_BATTERY_MODE.append(config.getboolean('INVERTER_' + str(i + 1), 'HOY_BATTERY_MODE'))
HOY_BATTERY_THRESHOLD_OFF_LIMIT_IN_V.append(config.getfloat('INVERTER_' + str(i + 1), 'HOY_BATTERY_THRESHOLD_OFF_LIMIT_IN_V'))
diff --git a/HoymilesZeroExport_Config.ini b/HoymilesZeroExport_Config.ini
index a1ad15c..6f80e06 100644
--- a/HoymilesZeroExport_Config.ini
+++ b/HoymilesZeroExport_Config.ini
@@ -19,7 +19,7 @@
# ---------------------------------------------------------------------
[VERSION]
-VERSION = 1.66
+VERSION = 1.68
[SELECT_DTU]
# --- define your DTU (only one) ---
@@ -208,8 +208,8 @@ MAX_DIFFERENCE_BETWEEN_LIMIT_AND_OUTPUTPOWER = 100
ENABLE_LOG_TO_FILE = false
# how many logfiles you wish to keep
LOG_BACKUP_COUNT = 30
-# defines how often a identical limit will be set, set it to "-1" for disabled (infinite repeat)
-SET_LIMIT_RETRY = 10
+# defines how often the Inverter Power Status will be set, set it to "-1" for disabled (infinite repeat)
+SET_POWERSTATUS_CNT = 10
# log the inverter temperature
LOG_TEMPERATURE = false
# delay time after turning the inverter off or on
From 6f0f941c4dbdb09fc1f9576226591925a654811a Mon Sep 17 00:00:00 2001
From: reserve85 <111107925+reserve85@users.noreply.github.com>
Date: Tue, 23 Jan 2024 14:43:52 +0100
Subject: [PATCH 5/5] fix limit retry
## V1.69
### script
* try to fix: Only repeat limit for the specific inverter (where limit was not acknowledged)
---
CHANGELOG.md | 6 +++++-
HoymilesZeroExport.py | 28 ++++++++++++++++------------
2 files changed, 21 insertions(+), 13 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2e268f5..daaeb25 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,10 @@
# Changelog
-## V1.67
+## V1.69
+### script
+* try to fix: Only repeat limit for the specific inverter (where limit was not acknowledged)
+
+## V1.68
### script
* Only repeat limit for the specific inverter (where limit was not acknowledged)
### Config
diff --git a/HoymilesZeroExport.py b/HoymilesZeroExport.py
index 3d8a8ed..2c0f446 100644
--- a/HoymilesZeroExport.py
+++ b/HoymilesZeroExport.py
@@ -15,7 +15,7 @@
# along with this program. If not, see .
__author__ = "Tobias Kraft"
-__version__ = "1.68"
+__version__ = "1.69"
import requests
import time
@@ -166,7 +166,6 @@ def SetLimitWithPriority(pLimit):
return
if (SetLimitWithPriority.LastLimit == CastToInt(pLimit)) and not SetLimitWithPriority.LastLimitAck:
logger.info("Inverterlimit %s Watt was previously not accepted by the inverter, trying again...",CastToInt(pLimit))
- return
logger.info("setting new limit to %s Watt",CastToInt(pLimit))
SetLimitWithPriority.LastLimit = CastToInt(pLimit)
@@ -182,28 +181,35 @@ def SetLimitWithPriority(pLimit):
else:
LimitPrio = RemainingLimit
RemainingLimit = RemainingLimit - LimitPrio
-
+
for i in range(INVERTER_COUNT):
if (not AVAILABLE[i]) or (not HOY_BATTERY_GOOD_VOLTAGE[i]):
continue
if HOY_BATTERY_PRIORITY[i] != j:
continue
- Factor = HOY_MAX_WATT[i] / GetMaxWattFromAllInvertersSamePrio(j)
-
+ Factor = HOY_MAX_WATT[i] / GetMaxWattFromAllInvertersSamePrio(j)
NewLimit = CastToInt(LimitPrio*Factor)
NewLimit = ApplyLimitsToSetpointInverter(i, NewLimit)
if HOY_COMPENSATE_WATT_FACTOR[i] != 1:
logger.info('Ahoy: Inverter "%s": compensate Limit from %s Watt to %s Watt', NAME[i], CastToInt(NewLimit), CastToInt(NewLimit*HOY_COMPENSATE_WATT_FACTOR[i]))
NewLimit = CastToInt(NewLimit * HOY_COMPENSATE_WATT_FACTOR[i])
NewLimit = ApplyLimitsToMaxInverterLimits(i, NewLimit)
+
+ if (NewLimit == CastToInt(CURRENT_LIMIT[i])) and LASTLIMITACKNOWLEDGED[i]:
+ continue
+
+ LASTLIMITACKNOWLEDGED[i] = True
+
if USE_AHOY:
SetLimitAhoy(i, NewLimit)
if not WaitForAckAhoy(i, SET_LIMIT_TIMEOUT_SECONDS):
SetLimitWithPriority.LastLimitAck = False
+ LASTLIMITACKNOWLEDGED[i] = False
elif USE_OPENDTU:
SetLimitOpenDTU(i, NewLimit)
if not WaitForAckOpenDTU(i, SET_LIMIT_TIMEOUT_SECONDS):
SetLimitWithPriority.LastLimitAck = False
+ LASTLIMITACKNOWLEDGED[i] = False
else:
raise Exception("Error: DTU Type not defined")
except:
@@ -227,9 +233,6 @@ def SetLimit(pLimit):
return
if (SetLimit.LastLimit == CastToInt(pLimit)) and not SetLimit.LastLimitAck:
logger.info("Inverterlimit %s Watt was previously not accepted by at least one inverter, trying again...",CastToInt(pLimit))
- lclRepeatLimit = True
- else:
- lclRepeatLimit = False
logger.info("setting new limit to %s Watt",CastToInt(pLimit))
SetLimit.LastLimit = CastToInt(pLimit)
@@ -246,13 +249,14 @@ def SetLimit(pLimit):
logger.info('Ahoy: Inverter "%s": compensate Limit from %s Watt to %s Watt', NAME[i], CastToInt(NewLimit), CastToInt(NewLimit*HOY_COMPENSATE_WATT_FACTOR[i]))
NewLimit = CastToInt(NewLimit * HOY_COMPENSATE_WATT_FACTOR[i])
NewLimit = ApplyLimitsToMaxInverterLimits(i, NewLimit)
-
- if lclRepeatLimit and LASTLIMITACKNOWLEDGED[i]:
+
+ if (NewLimit == CastToInt(CURRENT_LIMIT[i])) and LASTLIMITACKNOWLEDGED[i]:
continue
-
+
+ LASTLIMITACKNOWLEDGED[i] = True
+
if USE_AHOY:
SetLimitAhoy(i, NewLimit)
- LASTLIMITACKNOWLEDGED[i] = True
if not WaitForAckAhoy(i, SET_LIMIT_TIMEOUT_SECONDS):
SetLimit.LastLimitAck = False
LASTLIMITACKNOWLEDGED[i] = False