Skip to content

v2.4.14#36

Merged
AndrewTapp merged 43 commits intomainfrom
dev
Mar 14, 2026
Merged

v2.4.14#36
AndrewTapp merged 43 commits intomainfrom
dev

Conversation

@AndrewTapp
Copy link
Owner

v2.4.14 Summary of Changes (SolarEdge Optimizers Integration)

This document summarizes the main changes made to the integration, including new features, lifetime energy logic, reliability improvements, code quality, and documentation updates.


1. New site-level sensors (SolarEdge One only)

  • Installation date

    • Entity: sensor.[prefix]installation_date_[site] (or sensor.[prefix]installation_date when site ID is not in entity IDs).
    • Source: Portal layout/information/site/{siteId}installationDate.
    • Cached for 2 hours (SITE_INFO_CACHE_TTL), same as layout.
  • Peak power

    • Entity: sensor.[prefix]peak_power_[site] (or sensor.[prefix]peak_power when site ID is not in entity IDs).
    • Source: Portal layout/information/site/{siteId}peakPower (kW).
    • Same cache as above.

Both values are fetched via get_site_info_cached() in the SolarEdge One API and stored on the site aggregated data; the sensor platform exposes them only when using the One API.


2. Lifetime energy: portal overrides and removal of threshold

Previous behaviour

  • Site lifetime could use a “portal total” when aggregated data was considered unreliable (below RELIABLE_THRESHOLD_KWH).

Current behaviour

  • Site lifetime

    • Uses the portal’s dashboard production (Wh) from
      dashboard/energy/sites/{siteId}?start-date={installation_date}&end-date=...
      when that value is greater than the aggregated site total.
    • Start date for the request is the site installation date from site info.
  • Inverter and string lifetime

    • Use the portal’s layout/energy by-inverter data (Wh) from
      layout/energy/site/{siteId}/by-inverter?start-date={installation_date}&...
      when the portal value is greater than the aggregated inverter or string total.
  • Removed

    • The constant RELIABLE_THRESHOLD_KWH and all logic based on it.
    • Override rule is now simply: if portal value > aggregated value, use portal value (with start date = installation date).

Implementation details

  • const.py

    • Added SITE_INFO_CACHE_TTL (2 h).
    • Added SENSOR_TYPE_INSTALLATION_DATE, SENSOR_TYPE_PEAK_POWER and included them in SENSOR_TYPE_AGGREGATED_SITE.
    • Removed RELIABLE_THRESHOLD_KWH.
  • solaredge_one_api.py

    • get_site_info_cached(): layout/information/site → installationDate, peakPower (kW).
    • get_dashboard_site_production_cached(installation_date): dashboard/energy/sites → summary.production (Wh).
    • get_layout_energy_by_inverter_cached(installation_date): layout/energy by-inverter → per-inverter and per-string energy (Wh).
    • Caches keyed/used by installation date and date range where relevant.
  • api_dual.py

    • Wraps the above three methods; when not using SolarEdge One, they return empty/None.
  • coordinator.py

    • Fetches site info and installation date; uses it for dashboard production and by-inverter calls.
    • Passes site_info and portal_by_inverter into aggregation.
    • Applies portal overrides for site, inverter, and string lifetime when portal value > aggregated (values from portal are in Wh; converted to kWh for entity state).
  • sensor.py

    • New site-level sensor types for Installation date and Peak power (attributes, units, device classes, translation keys).

3. Reliability and resource handling

  • Unload / file descriptors

    • On integration unload, the coordinator is always retrieved, its API client is closed (my_api.close()), and the coordinator is removed from hass.data, even if async_unload_platforms() fails.
    • Ensures sessions and connections are released and avoids file descriptor leaks (especially for the legacy API’s requests.Session pool).
  • SolarEdge One API close()

    • Made explicitly idempotent: if already closed, returns immediately.
  • Dual API close()

    • Closes both One and legacy clients; tracks and logs if any client fails to close while still attempting to close the other.

4. Debug logging

  • Coordinator: site info fetch result (installation_date, peak_power), dashboard production usage (Wh→kWh), by-inverter fetch and inverter count, and when portal overrides are applied for site, inverter, and string. When creating inverter aggregated data, debug log includes max_active_power (kW).
  • SolarEdge One API: cache miss logs for site info, dashboard production, and by-inverter energy; building inverter node logs maxActivePower (kW) when present.
  • All debug output remains guarded with isEnabledFor(logging.DEBUG) so there is no extra cost at info level.

5. Code quality (CodeFactor / Pylint / pycodestyle)

  • Project root

    • .pylintrc: design limits relaxed (e.g. max-args=10, max-module-lines=2000) so coordinator/sensor and HA callback signatures are not flagged.
    • setup.cfg: [pycodestyle] max-line-length = 159 to align with Pylint.
  • Inline disables

    • # pylint: disable=too-many-arguments added where the design requires more than five parameters (e.g. _calculate_aggregated_data, _register_inverter_and_string_devices, _process_single_string, sensor builder functions, api_dual.__init__, config_flow async_show_form).

6. Translations and i18n

  • All translation files (e.g. translations/*.json) include keys for the new site sensors:
    entity.sensor.installation_date.name, entity.sensor.peak_power.name.
  • Documentation (including internationalization.md) updated to list Installation date and Peak power in the entity sensor names and translation structure.

7. Documentation updates

  • README.md

    • New site-level Installation date and Peak power; lifetime energy described as portal override (dashboard production / by-inverter; start date = installation date); code quality section updated to reference .pylintrc and setup.cfg.
  • info.md

    • Same site sensors and lifetime behaviour; RELIABLE_THRESHOLD removed.
  • docs/Wiki-Home.md

    • Overview, device hierarchy, sensor reference, and API section updated for Installation date and Peak power; caching table includes site info (2 h) and layout (2 h for both One and legacy); lifetime energy and portal overrides described; RELIABLE_THRESHOLD removed and replaced with SITE_INFO_CACHE_TTL in constants; file structure no longer references CODEQUALITY.md/pyproject.toml in the integration folder.
  • docs/SolarEdge-One-API-Summary.md

    • Site info, dashboard production, and by-inverter energy; site-level Installation date and Peak power sensors; portal lifetime overrides and installation date as start date.
  • docs/internationalization.md

    • Installation date and Peak power added to the list of sensor entity names and translation keys.

8. New inverter-level sensor: Max active power (SolarEdge One only)

  • Max active power

    • Entity: sensor.[prefix]max_active_power_[site]_[inverter] (or sensor.[prefix]max_active_power_[inverter] when site ID is not in entity IDs).
    • Source: Portal layout logical v2 .../layout/logical/generic/v2/site/{siteId}?include-optimizers=true → per-inverter properties.maxActivePower (watts). Displayed as kW (same as site Peak power).
    • Cached with the layout (2 h); no separate API call.
    • One API only; legacy layout does not provide this field (sensor still created, value unknown until available).
  • Implementation

    • const.py: SENSOR_TYPE_MAX_ACTIVE_POWER, added to SENSOR_TYPE_AGGREGATED_INVERTER.
    • solaredge_one_api.py: _v2_build_inverter_logical_node reads maxActivePower (W) from inverter properties, converts to kW, adds to inverter data dict.
    • solaredgeoptimizers.py: SolarEdgeInverter has maxActivePower (from data.get("maxActivePower")); SolarEdgeAggregatedData has max_active_power.
    • coordinator.py: _create_inverter_aggregated sets inverter_aggregated.max_active_power = getattr(inverter, "maxActivePower", None); debug log includes max_active_power when creating inverter aggregated.
    • sensor.py: New sensor type in aggregated maps (attr, translation key, units kW); value handling same as Peak power (round to 2 decimals).
    • Translations: All locale files updated with entity.sensor.max_active_power.name (e.g. "Max active power", "Max. Wirkleistung").
  • Inactive inverters: Max active power sensor is still created for inactive inverters (fixed inverter property); value may be unknown if layout does not provide it.


9. File descriptor and documentation refresh

  • File descriptor handling

    • api.py: Protocol close() docstring now states "Release resources, close sessions, and release file descriptors".
    • solaredgeoptimizers.py: Module docstring notes that close() closes all tracked sessions to avoid leaking file descriptors on unload/removal.
    • solaredge_one_api.py: Module docstring notes no persistent sessions (context managers), and close() clears tokens.
    • init.py: Docstring states that on unload or removal the API client is closed to release file descriptors.
    • config_flow.py: Cleanup section now says "Closes API (releases file descriptors), then removes entities and devices".
  • Top-of-file / module comments

    • solaredgeoptimizers.py: Data classes (SolarEdgeInverter maxActivePower, SolarEdgeAggregatedData max_active_power), Key Features (close/file descriptors).
    • sensor.py: Aggregated sensors list includes "Inverter-level: Max active power (kW, from portal layout logical v2; One API only)".
    • coordinator.py: Data aggregation includes "Inverter aggregated data includes max_active_power (kW) from layout logical v2 when available (One API)".
    • solaredge_one_api.py: Key Features include inverter maxActivePower (W→kW) and no persistent sessions/close() clears tokens.
  • Documentation

    • README.md, info.md, docs/Wiki-Home.md, docs/SolarEdge-One-API-Summary.md, docs/internationalization.md: All updated for Max active power (inverter, entity ID, cache, One API only), and where relevant for file descriptor release on unload/removal and dual API close().

10. Files touched (overview)

Area Files
Constants & types const.py (SENSOR_TYPE_*, SITE_INFO_CACHE_TTL, SENSOR_TYPE_MAX_ACTIVE_POWER), solaredgeoptimizers.py (SolarEdgeAggregatedData, SolarEdgeInverter.maxActivePower)
One API solaredge_one_api.py (get_site_info_cached, layout inverter maxActivePower→kW, close/docstring)
Dual API api_dual.py
Protocol api.py (close docstring)
Coordinator coordinator.py (site info, portal overrides, inverter max_active_power, debug log, docstring)
Sensors sensor.py (Installation date, Peak power, Max active power; docstrings)
Setup / unload __init__.py (docstring, unload close)
Config flow config_flow.py (docstring, async_remove_entry close)
Config .pylintrc, setup.cfg (project root)
Translations translations/*.json (installation_date, peak_power, max_active_power)
Docs README.md, info.md, docs/Wiki-Home.md, docs/SolarEdge-One-API-Summary.md, docs/internationalization.md

This summary reflects the state of the integration after the above changes, including the post–v2.4.14 additions (inverter Max active power sensor and file-descriptor/documentation refresh). For version-specific release notes, see the repository releases.

@AndrewTapp AndrewTapp merged commit dbc2c74 into main Mar 14, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant