@@ -1317,63 +1317,102 @@ def _read_sparse(addr_list: list, fatal: bool = False) -> bool:
13171317 addrs_3000 = sorted ([addr for addr in addresses if 3000 <= addr < 4000 ])
13181318 max_3000_addr = max (addrs_3000 )
13191319 count_3000 = (max_3000_addr - 3000 ) + 1
1320+ _3000_key = ('3000_block' , count_3000 )
1321+ _3000_RETRY_S = 300
1322+
1323+ # Skip-on-failure: after the first failure, suppress retries for 5 minutes.
1324+ # This prevents log flooding when an inverter simply doesn't support this range
1325+ # (e.g. one model in a two-inverter setup where only one uses 3000-range registers).
1326+ _3000_prev = self ._failed_optional_ranges .get (_3000_key )
1327+ _3000_skip = False
1328+ if _3000_prev :
1329+ _3000_fail_time , _3000_fail_count = _3000_prev
1330+ if time .time () - _3000_fail_time < _3000_RETRY_S :
1331+ logger .debug (
1332+ f"Skipping 3000-range block (failed { _3000_fail_count } x, "
1333+ f"retry in { int (_3000_RETRY_S - (time .time () - _3000_fail_time ))} s)"
1334+ )
1335+ _3000_skip = True
1336+ else :
1337+ logger .debug (f"Retrying previously failed 3000-range block (3000-{ max_3000_addr } )" )
1338+
1339+ if not _3000_skip :
1340+ _3000_any_fail = False
1341+ _3000_any_ok = False
1342+
1343+ # Check if we need to split the read (max 125 registers per read)
1344+ if count_3000 > 125 :
1345+ # Split into contiguous blocks
1346+ logger .debug (f"Splitting 3000 range into blocks (total range: 3000-{ max_3000_addr } , { count_3000 } registers)" )
1347+
1348+ blocks = []
1349+ current_block = [addrs_3000 [0 ]]
1350+ for addr in addrs_3000 [1 :]:
1351+ if addr - current_block [- 1 ] <= 10 : # Group if gap is small
1352+ current_block .append (addr )
1353+ else :
1354+ blocks .append (current_block )
1355+ current_block = [addr ]
1356+ blocks .append (current_block )
13201357
1321- # Check if we need to split the read (max 125 registers per read)
1322- if count_3000 > 125 :
1323- # Split into contiguous blocks
1324- logger .debug (f"Splitting 3000 range into blocks (total range: 3000-{ max_3000_addr } , { count_3000 } registers)" )
1325-
1326- blocks = []
1327- current_block = [addrs_3000 [0 ]]
1328- for addr in addrs_3000 [1 :]:
1329- if addr - current_block [- 1 ] <= 10 : # Group if gap is small
1330- current_block .append (addr )
1331- else :
1332- blocks .append (current_block )
1333- current_block = [addr ]
1334- blocks .append (current_block )
1335-
1336- # Read each block separately
1337- for block in blocks :
1338- min_addr_block = min (block )
1339- max_addr_block = max (block )
1340- count_block = (max_addr_block - min_addr_block ) + 1
1341-
1342- # Further split if block still exceeds 125 registers
1343- if count_block > 125 :
1344- # Read in 125-register chunks
1345- for chunk_start in range (min_addr_block , max_addr_block + 1 , 125 ):
1346- chunk_count = min (125 , max_addr_block - chunk_start + 1 )
1347- logger .debug (f"Reading 3000 sub-chunk ({ chunk_start } -{ chunk_start + chunk_count - 1 } , { chunk_count } registers)" )
1348- registers = self .read_input_registers (chunk_start , chunk_count )
1358+ # Read each block separately
1359+ for block in blocks :
1360+ min_addr_block = min (block )
1361+ max_addr_block = max (block )
1362+ count_block = (max_addr_block - min_addr_block ) + 1
1363+
1364+ # Further split if block still exceeds 125 registers
1365+ if count_block > 125 :
1366+ # Read in 125-register chunks
1367+ for chunk_start in range (min_addr_block , max_addr_block + 1 , 125 ):
1368+ chunk_count = min (125 , max_addr_block - chunk_start + 1 )
1369+ logger .debug (f"Reading 3000 sub-chunk ({ chunk_start } -{ chunk_start + chunk_count - 1 } , { chunk_count } registers)" )
1370+ registers = self .read_input_registers (chunk_start , chunk_count )
1371+ if registers is None :
1372+ _3000_any_fail = True
1373+ logger .debug (f"3000 sub-chunk failed ({ chunk_start } -{ chunk_start + chunk_count - 1 } )" )
1374+ else :
1375+ _3000_any_ok = True
1376+ for i , value in enumerate (registers ):
1377+ self ._register_cache [chunk_start + i ] = value
1378+ else :
1379+ logger .debug (f"Reading 3000 sub-range ({ min_addr_block } -{ max_addr_block } , { count_block } registers)" )
1380+ registers = self .read_input_registers (min_addr_block , count_block )
13491381 if registers is None :
1350- logger .warning (f"Failed to read 3000 chunk ({ chunk_start } -{ chunk_start + chunk_count - 1 } )" )
1382+ _3000_any_fail = True
1383+ logger .debug (f"3000 sub-range failed ({ min_addr_block } -{ max_addr_block } )" )
13511384 else :
1385+ _3000_any_ok = True
13521386 for i , value in enumerate (registers ):
1353- self ._register_cache [chunk_start + i ] = value
1354- else :
1355- logger .debug (f"Reading 3000 sub-range ({ min_addr_block } -{ max_addr_block } , { count_block } registers)" )
1356- registers = self .read_input_registers (min_addr_block , count_block )
1357- if registers is None :
1358- logger .warning (f"Failed to read 3000 block ({ min_addr_block } -{ max_addr_block } )" )
1359- else :
1360- for i , value in enumerate (registers ):
1361- addr = min_addr_block + i
1362- self ._register_cache [addr ] = value
1363- # Log load_energy registers specifically
1364- if addr in [3075 , 3076 , 3077 , 3078 ]:
1365- logger .debug (f"[{ self .register_map ['name' ]} @{ self .connection_id } ] Cached 3000 range: reg { addr } = { value } " )
1366- else :
1367- # Single read is sufficient
1368- logger .debug (f"Reading 3000 range (3000-{ max_3000_addr } , { count_3000 } registers)" )
1369- registers = self .read_input_registers (3000 , count_3000 )
1370- if registers is None :
1371- logger .warning ("Failed to read 3000 register block (extended data may be unavailable)" )
1372- # Don't return None - continue with what we have
1387+ addr = min_addr_block + i
1388+ self ._register_cache [addr ] = value
1389+ if addr in [3075 , 3076 , 3077 , 3078 ]:
1390+ logger .debug (f"[{ self .register_map ['name' ]} @{ self .connection_id } ] Cached 3000 range: reg { addr } = { value } " )
13731391 else :
1374- # Populate cache
1375- for i , value in enumerate (registers ):
1376- self ._register_cache [3000 + i ] = value
1392+ # Single read is sufficient
1393+ logger .debug (f"Reading 3000 range (3000-{ max_3000_addr } , { count_3000 } registers)" )
1394+ registers = self .read_input_registers (3000 , count_3000 )
1395+ if registers is None :
1396+ _3000_any_fail = True
1397+ else :
1398+ _3000_any_ok = True
1399+ for i , value in enumerate (registers ):
1400+ self ._register_cache [3000 + i ] = value
1401+
1402+ # Update failure tracking based on outcome
1403+ if _3000_any_fail and not _3000_any_ok :
1404+ _prev = self ._failed_optional_ranges .get (_3000_key )
1405+ _count = (_prev [1 ] + 1 ) if _prev else 1
1406+ self ._failed_optional_ranges [_3000_key ] = (time .time (), _count )
1407+ if _count == 1 :
1408+ logger .warning (
1409+ f"Failed to read 3000 register block (extended data may be unavailable). "
1410+ f"Will suppress and retry in { _3000_RETRY_S } s."
1411+ )
1412+ else :
1413+ logger .debug (f"3000 register block still failing (attempt { _count } )" )
1414+ elif _3000_any_ok :
1415+ self ._failed_optional_ranges .pop (_3000_key , None )
13771416
13781417 # Read 8000 range if needed - WIT/WIS battery/storage data
13791418 if has_8000_range :
0 commit comments