1515# along with this program. If not, see <http://www.gnu.org/licenses/>.
1616
1717__author__ = "Tobias Kraft"
18- __version__ = "1.97 "
18+ __version__ = "1.98 "
1919
2020import time
2121from requests .sessions import Session
@@ -110,6 +110,7 @@ def SetLimitWithPriority(pLimit):
110110
111111 if (SetLimitWithPriority .LastLimit == CastToInt (pLimit )) and SetLimitWithPriority .LastLimitAck :
112112 logger .info ("Inverterlimit was already accepted at %s Watt" ,CastToInt (pLimit ))
113+ CrossCheckLimit ()
113114 return
114115 if (SetLimitWithPriority .LastLimit == CastToInt (pLimit )) and not SetLimitWithPriority .LastLimitAck :
115116 logger .info ("Inverterlimit %s Watt was previously not accepted by at least one inverter, trying again..." ,CastToInt (pLimit ))
@@ -170,6 +171,7 @@ def SetLimitMixedModeWithPriority(pLimit):
170171
171172 if (SetLimitMixedModeWithPriority .LastLimit == CastToInt (pLimit )) and SetLimitMixedModeWithPriority .LastLimitAck :
172173 logger .info ("Inverterlimit was already accepted at %s Watt" ,CastToInt (pLimit ))
174+ CrossCheckLimit ()
173175 return
174176 if (SetLimitMixedModeWithPriority .LastLimit == CastToInt (pLimit )) and not SetLimitMixedModeWithPriority .LastLimitAck :
175177 logger .info ("Inverterlimit %s Watt was previously not accepted by at least one inverter, trying again..." ,CastToInt (pLimit ))
@@ -309,6 +311,7 @@ def SetLimit(pLimit):
309311
310312 if (SetLimit .LastLimit == CastToInt (pLimit )) and SetLimit .LastLimitAck :
311313 logger .info ("Inverterlimit was already accepted at %s Watt" ,CastToInt (pLimit ))
314+ CrossCheckLimit ()
312315 return
313316 if (SetLimit .LastLimit == CastToInt (pLimit )) and not SetLimit .LastLimitAck :
314317 logger .info ("Inverterlimit %s Watt was previously not accepted by at least one inverter, trying again..." ,CastToInt (pLimit ))
@@ -570,6 +573,20 @@ def ApplyLimitsToMaxInverterLimits(pInverter, pSetpoint):
570573 pSetpoint = GetMinWatt (pInverter )
571574 return pSetpoint
572575
576+ def CrossCheckLimit ():
577+ try :
578+ for i in range (INVERTER_COUNT ):
579+ if AVAILABLE [i ]:
580+ DTULimitInW = DTU .GetActualLimitInW (i )
581+ LimitMax = float (CURRENT_LIMIT [i ] + HOY_INVERTER_WATT [i ] * 0.05 )
582+ LimitMin = float (CURRENT_LIMIT [i ] - HOY_INVERTER_WATT [i ] * 0.05 )
583+ if not (min (LimitMax , LimitMin ) < DTULimitInW < max (LimitMax , LimitMin )):
584+ logger .info ("CrossCheckLimit: DTU ({DTULimitInW:.1f}) <> SetLimit ({CURRENT_LIMIT[i]:.1f}). Resend limit to DTU" )
585+ DTU .SetLimit (i , CURRENT_LIMIT [i ])
586+ except :
587+ logger .error ("Exception at CrossCheckLimit" )
588+ raise
589+
573590# Max possible Watts, can be reduced on battery mode
574591def GetMaxWattFromAllInverters ():
575592 maxWatt = 0
@@ -886,7 +903,10 @@ def CheckMinVersion(self):
886903
887904 def GetAvailable (self , pInverterId : int ):
888905 raise NotImplementedError ()
889-
906+
907+ def GetActualLimitInW (self , pInverterId : int ):
908+ raise NotImplementedError ()
909+
890910 def GetInfo (self , pInverterId : int ):
891911 raise NotImplementedError ()
892912
@@ -921,7 +941,7 @@ def GetJson(self, path):
921941 data = session .get (url , timeout = 10 ).json ()
922942 retry_count -= 1
923943 return data
924-
944+
925945 def GetResponseJson (self , path , obj ):
926946 url = f'http://{ self .ip } { path } '
927947 return session .post (url , json = obj , timeout = 10 ).json ()
@@ -931,11 +951,14 @@ def GetACPower(self, pInverterId):
931951 ActualPower_index = ParsedData ["ch0_fld_names" ].index ("P_AC" )
932952 ParsedData = self .GetJson (f'/api/inverter/id/{ pInverterId } ' )
933953 return CastToInt (ParsedData ["ch" ][0 ][ActualPower_index ])
934-
954+
935955 def CheckMinVersion (self ):
936956 MinVersion = '0.8.80'
937957 ParsedData = self .GetJson ('/api/system' )
938- AhoyVersion = str ((ParsedData ["version" ]))
958+ try :
959+ AhoyVersion = str ((ParsedData ["version" ]))
960+ except :
961+ AhoyVersion = str ((ParsedData ["generic" ]["version" ]))
939962 logger .info ('Ahoy: Current Version: %s' ,AhoyVersion )
940963 if version .parse (AhoyVersion ) < version .parse (MinVersion ):
941964 logger .error ('Error: Your AHOY Version is too old! Please update at least to Version %s - you can find the newest dev-releases here: https://github.com/lumapu/ahoy/actions' ,MinVersion )
@@ -946,7 +969,13 @@ def GetAvailable(self, pInverterId: int):
946969 Available = bool (ParsedData ["inverter" ][pInverterId ]["is_avail" ])
947970 logger .info ('Ahoy: Inverter "%s" Available: %s' ,NAME [pInverterId ], Available )
948971 return Available
949-
972+
973+ def GetActualLimitInW (self , pInverterId : int ):
974+ ParsedData = self .GetJson (f'/api/inverter/id/{ pInverterId } ' )
975+ LimitInPercent = float (ParsedData ['power_limit_read' ])
976+ LimitInW = HOY_INVERTER_WATT [pInverterId ] * LimitInPercent / 100
977+ return LimitInW
978+
950979 def GetInfo (self , pInverterId : int ):
951980 ParsedData = self .GetJson ('/api/live' )
952981 temp_index = ParsedData ["ch0_fld_names" ].index ("Temp" )
@@ -1083,6 +1112,12 @@ def GetAvailable(self, pInverterId: int):
10831112 logger .info ('OpenDTU: Inverter "%s" reachable: %s' ,NAME [pInverterId ],Reachable )
10841113 return Reachable
10851114
1115+ def GetActualLimitInW (self , pInverterId : int ):
1116+ ParsedData = self .GetJson ('/api/limit/status' )
1117+ limit_relative = float (ParsedData [SERIAL_NUMBER [pInverterId ]]['limit_relative' ])
1118+ LimitInW = HOY_INVERTER_WATT [pInverterId ] * limit_relative / 100
1119+ return LimitInW
1120+
10861121 def GetInfo (self , pInverterId : int ):
10871122 if SERIAL_NUMBER [pInverterId ] == '' :
10881123 ParsedData = self .GetJson ('/api/livedata/status' )
0 commit comments