v2.4.12
v2.4.12 - SolarEdge Optimizers – Changes Summary
This document summarizes changes made to the integration, including recent work on constants, status handling, aggregation, debug logging, CodeFactor-related fixes, documentation, and resource cleanup.
1. Constants and configuration
- Centralized constants in
const.py: Cache TTLs (PANELS_CACHE_TTL_ONE,PANELS_CACHE_TTL_LEGACY,LIFETIME_ENERGY_CACHE_TTL,TEMPERATURE_CACHE_TTL), light-check intervals (LIGHT_CHECK_DESIRED_INTERVAL_FRESH,LIGHT_CHECK_DESIRED_INTERVAL_STALE), API URLs, OAuth client ID, locale-dependent measurement keys (MEASUREMENT_KEYS), and API source labels (OBTAINED_FROM_ONE,OBTAINED_FROM_LEGACY). - Module docstring in
const.pydocuments each constant and shared helpers. - Status helpers in
const.py:is_status_active(status),status_display_value(raw),status_icon(display_value)for consistent handling of blank, Active, Inactive, and other statuses across the integration.
2. Status handling
- Blank (empty) status is treated as active everywhere: aggregation, sorting, display, and icons.
- Display: Blank → shown as "blank" with active icon; "Active" / "Inactive" in proper case; any other value shown as-is with unknown (help-circle) icon.
- Icons: check-circle for Active/blank, alert-circle for Inactive, help-circle for unknown.
- Child counts (Optimizer count, String count, Inverter count) count only active devices (status blank or "Active").
- Duplicate resolution (suffixes a, b, c…): active (including blank) items are ordered first, then others.
3. Aggregation behaviour
- Aggregated values (power, current average, voltage average, lifetime energy) at string, inverter, and site level include data from all devices (any status) that have recent measurements. Averages use the count of devices that contributed data; totals sum all contributing devices.
- Child counts (Optimizer count per string, String count per inverter, Inverter count per site) count only active devices (status blank or "Active") and are always integers.
- Coordinator uses
optimizer_count/string_count/inverter_countfor average divisors andactive_optimizers/active_strings/active_invertersfor child_count sensors.
4. Debug logging
- Cache messages now include TTL where relevant:
- SolarEdge One: Panels, lifetime energy, and temperature cache hit/miss logs include TTL (e.g. "Panels cache miss (TTL=%s)", "Using cached panels (age=%s, TTL=%s)").
- Legacy: Panels and lifetime energy cache messages include TTL and consistent "(legacy)" prefix.
- Coordinator:
_log_update_cycle_debuglogsinterval_kind("fresh" or "stale") and splits the long format string across lines so it stays within line-length limits. - Temperature (One API): Added cache-miss debug before fetching when the temperature cache is expired.
- All debug calls remain guarded with
_LOGGER.isEnabledFor(logging.DEBUG).
5. CodeFactor-related fixes
- config_flow.py: Replaced
except Exception:withexcept Exception as e:in the user step and reauth step; log messages now include the exception (e.g._LOGGER.exception("Unexpected exception: %s", e)). - coordinator.py: Long debug format string in
_log_update_cycle_debugsplit across two lines with implicit string concatenation. - solaredgeoptimizers.py:
requestSystemData: Long URL split intobase+params+url.requestItemHistory: Long chartData URL split intobase+q+url; long dict comprehension rewritten as a multi-line dict comprehension.
- Custom exception:
SolarEdgeAPIErrorinexceptions.pyis used for API/processing errors instead of genericExceptionwhere appropriate. - Legacy client: Replaced
assertwith explicitValueErrorwhere parameter validation is required; replaced genericraise Exception(...)withraise SolarEdgeAPIError(...).
6. File descriptor and resource cleanup
- config_flow.py –
validate_input: API client is closed in afinallyblock after credential validation so temporary sessions are released. - config_flow.py –
async_remove_entry: When the integration is removed, the coordinator is popped fromhass.dataand the API client is closed (if present) before callingremove_entities_and_devices_for_entry, so file descriptors are released even if unload did not run or did not close the API. - init.py: On setup failure (before the coordinator is stored), the temporary API instance is closed in a
finallyblock. - api_dual.py:
close()closes both One and Legacy clients with explicit logging; exceptions from one client do not prevent closing the other. - Legacy client:
close()docstring clarifies thatSession.close()releases file descriptors and thread-local session is cleared.
7. Documentation updates
- README.md: Temperature refresh described as using the temperature cache expiry (30 minutes,
TEMPERATURE_CACHE_TTL). Inactive devices section updated: aggregation uses all devices (any status) with recent data; child counts use only active devices. - info.md: Inactive devices / aggregation paragraph updated to match (aggregation = all devices; child counts = active only).
- docs/Wiki-Home.md:
- Aggregation behaviour (Section 9) rewritten: aggregation values from all devices with recent data; child counts from active only; note on inactive devices contributing to aggregates when they have data.
- Temperature references updated from "15 min" to "30 min" /
TEMPERATURE_CACHE_TTL(data flow note, Section 7 table, Section 12 caching). - Removal cleanup:
async_remove_entrynow documented as closing the API client (releasing file descriptors) when the coordinator is still inhass.data, then calling the shared helper. Config flow table row updated similarly.
- coordinator.py module docstring: Polling interval described as coordinator tick every 5 minutes; minimum interval between full refreshes set to 5 minutes (
LIGHT_CHECK_MIN_INTERVAL). Data aggregation summary updated: power/current/voltage/lifetime from all devices with recent data; child counts from active only.
8. Timing and cache constants (reference)
| Constant | Value | Purpose |
|---|---|---|
UPDATE_DELAY |
5 min | Coordinator tick interval |
LIGHT_CHECK_MIN_INTERVAL |
5 min | Min time between a light-check-triggered full refresh and the next |
LIGHT_CHECK_DESIRED_INTERVAL_FRESH |
5 min | Desired light-check interval when data is fresh |
LIGHT_CHECK_DESIRED_INTERVAL_STALE |
30 min | Desired light-check interval when data is stale or missing |
PANELS_CACHE_TTL_ONE |
2 h | Layout cache (SolarEdge One) |
PANELS_CACHE_TTL_LEGACY |
1 h | Layout cache (legacy API) |
LIFETIME_ENERGY_CACHE_TTL |
1 h | Lifetime energy cache |
TEMPERATURE_CACHE_TTL |
30 min | Optimizer temperatures cache (One API only) |
9. File structure (relevant files)
const.py– Constants, status helpers,resolve_duplicate_indices, display-name parsers.exceptions.py–SolarEdgeAPIError.config_flow.py– Validation (dual API), API close after validation and on entry removal.__init__.py– Setup with API cleanup on failure;remove_entities_and_devices_for_entry.coordinator.py– Adaptive polling, aggregation (all statuses for values, active only for child counts), device registration.solaredgeoptimizers.py– Legacy API;SolarEdgeAPIError; cache TTLs from const.solaredge_one_api.py– One API; cache TTLs and status check from const.api_dual.py– Dual API;OBTAINED_FROM_*from const; robustclose().
This summary reflects the state of the integration after the documented changes. For installation and user-facing features, see the main README and Wiki-Home.
What's Changed
- Dev by @AndrewTapp in #34
New Contributors
- @AndrewTapp made their first contribution in #34
Full Changelog: 2.4.11...2.4.12