Skip to content

Commit 9f7911a

Browse files
authored
Update solaredgeoptimizers.py
1 parent 2df0496 commit 9f7911a

File tree

1 file changed

+55
-5
lines changed

1 file changed

+55
-5
lines changed

custom_components/solaredgeoptimizers/solaredgeoptimizers.py

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,52 @@
1-
"""Legacy SolarEdge Monitoring Portal API client: authentication, site layout (inverters/strings/optimizers), live optimizer data with locale-aware measurement keys, and lifetime energy."""
1+
"""
2+
SolarEdge Optimizers Integration - Legacy Monitoring API Client (solaredgeoptimizers.py)
3+
4+
This module implements the client for the legacy SolarEdge Monitoring Portal API. It serves
5+
as a fallback when the SolarEdge One API is unavailable or returns no valid data.
6+
7+
Authentication:
8+
- Uses HTTP Basic Authentication with site credentials
9+
- Session-based with CSRF token handling for subsequent requests
10+
- Thread-local sessions for safe concurrent access in ThreadPoolExecutor
11+
12+
API Endpoints (monitoring.solaredge.com/solaredge-apigw/api/...):
13+
14+
1. Login Check:
15+
GET .../sites/{siteId}/layout/logical
16+
Validates credentials and returns HTTP status code
17+
18+
2. Site Structure (Logical Layout):
19+
GET .../sites/{siteId}/layout/logical
20+
Returns JSON with inverters, strings, and optimizers hierarchy
21+
22+
3. Optimizer Live Data (System Data):
23+
GET .../solaredge-web/p/systemData?reporterId={optimizerId}&...
24+
Returns power, voltage, current, optimizer voltage for one optimizer
25+
Locale-aware measurement keys (supports multiple languages)
26+
27+
4. Lifetime Energy:
28+
POST .../sites/{siteId}/layout/energy?timeUnit=ALL
29+
Returns lifetime energy data keyed by optimizer/string ID
30+
31+
5. Historical Data:
32+
GET .../solaredge-web/p/chartData?reporterId={id}&...
33+
Returns time-series data for power, current, voltage, energy
34+
35+
Data Classes Defined:
36+
- SolarEdgeSite: Root container with site ID and list of inverters
37+
- SolarEdgeInverter: Inverter with serial, name, status, and list of strings
38+
- SolarEdgeString: String with ID, name, status, and list of optimizers
39+
- SolarlEdgeOptimizer: Optimizer with ID, serial, name, display name, status
40+
- SolarEdgeOptimizerData: Live measurement data (power, voltage, current, energy, etc.)
41+
- SolarEdgeAggregatedData: Aggregated data for string/inverter/site levels
42+
43+
Key Features:
44+
- Locale-aware measurement key parsing (supports EN, DE, FR, ES, IT, NL, etc.)
45+
- Thread-local session reuse for efficient parallel requests
46+
- Caching for panels (1 hour) and lifetime energy (1 hour)
47+
- Unicode normalization for measurement keys (handles various dash/space variants)
48+
- Timezone-aware date parsing for lastMeasurementDate
49+
"""
250
import time
351
import threading
452
import re
@@ -14,6 +62,8 @@
1462
from datetime import datetime, timedelta
1563
from jsonfinder import jsonfinder
1664

65+
from .const import API_TIMEOUT_SHORT, API_TIMEOUT_LONG, MAX_PARALLEL_WORKERS
66+
1767
# Added logger setup to replace print statements with proper logging
1868
_LOGGER = logging.getLogger(__name__)
1969

@@ -353,7 +403,7 @@ def check_login(self):
353403
kwargs["headers"] = {"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36",
354404
}
355405
# Add timeout to prevent hanging and log request attempt
356-
kwargs["timeout"] = 30 # 30 second timeout
406+
kwargs["timeout"] = API_TIMEOUT_SHORT
357407
if _LOGGER.isEnabledFor(logging.DEBUG):
358408
_LOGGER.debug("SolarEdge Optimizers: Making login check request with 30s timeout")
359409

@@ -416,7 +466,7 @@ def requestLogicalLayout(self):
416466
_LOGGER.debug("SolarEdge Optimizers: Making logical layout request with 60s timeout")
417467
kwargs = {
418468
"auth": requests.auth.HTTPBasicAuth(self.username, self.password),
419-
"timeout": 60,
469+
"timeout": API_TIMEOUT_LONG,
420470
}
421471
try:
422472
return self._fetch_logical_layout(url, kwargs)
@@ -483,7 +533,7 @@ def requestSystemData(self, itemId):
483533

484534
kwargs = {
485535
"auth": requests.auth.HTTPBasicAuth(self.username, self.password),
486-
"timeout": 30, # Prevent hung requests in ThreadPoolExecutor
536+
"timeout": API_TIMEOUT_SHORT,
487537
}
488538
with requests.get(url, **kwargs) as r:
489539
if _LOGGER.isEnabledFor(logging.DEBUG):
@@ -547,7 +597,7 @@ def requestAllData(self):
547597
for optimizer in string.optimizers
548598
]
549599

550-
max_workers = min(os.cpu_count() or 4, len(optimizer_ids), 10)
600+
max_workers = min(os.cpu_count() or 4, len(optimizer_ids), MAX_PARALLEL_WORKERS)
551601
if _LOGGER.isEnabledFor(logging.DEBUG):
552602
_LOGGER.debug(
553603
"SolarEdge Optimizers (legacy): requestAllData fetching %d optimizers with max_workers=%d",

0 commit comments

Comments
 (0)