Skip to content

Cleaned PR#1920 - Fix Session Energy bug for chargers that send phase-specific readings#1925

Open
ric866 wants to merge 4 commits intolbbrhzn:mainfrom
ric866:fix-session-energy-multiphased-chargers-clean
Open

Cleaned PR#1920 - Fix Session Energy bug for chargers that send phase-specific readings#1925
ric866 wants to merge 4 commits intolbbrhzn:mainfrom
ric866:fix-session-energy-multiphased-chargers-clean

Conversation

@ric866
Copy link
Contributor

@ric866 ric866 commented Mar 20, 2026

PR #1920 has got into a mess. This is the cleaned up version.

This PR fixes a bug where the Session Energy sensor fails to update during an active charging session for chargers that send phase-specific energy readings (e.g., Energy.Active.Import.Register.L1).

For these chargers, the Session Energy sensor currently remains at 0 for the duration of the charge and only populates with the final value when the StopTransaction payload is received.

Root Cause :
In on_meter_values, the real-time session energy math (Current - Start) is currently trapped inside the if phase is None: block.

If a charger sends a phase-tagged main energy register, it bypasses this block and gets passed to process_phases() via the unprocessed list. While process_phases() correctly aggregates the phases and updates the main lifetime energy sensor, it lacked the logic to simultaneously update the active Session Energy sensor.

Fix :
Added the standard session energy calculation directly to the end of process_phases().

Refactored the final unit assignment to use a final_value variable.
Added a check to verify an active transaction.
If active, it derives the real-time session energy (final_value - meter_start) and updates the metric so the HA dashboard graph updates continuously during the charge.
Testing :

Verified that single-phase chargers sending L1 energy registers now correctly increment the Session Energy sensor in real-time upon receiving periodic MeterValues.
Verified this does not interfere with chargers that natively report session energy (_charger_reports_session_energy).

Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • Improved session energy tracking by deriving values from incoming energy readings when direct reporting is unavailable
    • Enhanced phase-specific energy metric normalization and aggregation
  • Tests

    • Added test coverage for session energy calculations and phase metric aggregation

PR lbbrhzn#1920 has got into a mess. This is the cleaned up version.
@ric866 ric866 temporarily deployed to continuous-integration March 20, 2026 10:36 — with GitHub Actions Inactive
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 20, 2026

📝 Walkthrough

Walkthrough

The pull request refactors metric normalization in the chargepoint module's phase aggregation logic and introduces session energy derivation when the charger doesn't report session energy directly. Changes include normalizing per-phase metrics through intermediate values, deriving session energy from incoming energy register readings, and updating baseline meter start initialization. Corresponding test cases validate phase processing and session energy calculations.

Changes

Cohort / File(s) Summary
Chargepoint Session Energy Logic
custom_components/ocpp/chargepoint.py
Refactored _sum_l123 metric normalization using intermediate final_value/final_unit variables. Added session energy derivation logic that calculates csess.session_energy = current_reading - meter_start when charger lacks native session energy reporting and an active transaction exists. Updated meter_start baseline initialization when missing. Changed process_measurands to construct new MeasurandValue objects for unphased samples with normalized fields instead of appending original values.
Phase Processing & Session Energy Tests
tests/test_charge_point_core.py
Added three test functions: test_process_phases_voltage_and_current_branches (phase-tagged aggregation for energy readings), test_process_phases_calculates_session_energy (validates session energy derivation during active transactions), and test_process_phases_initializes_session_energy_baseline (validates meter start initialization when absent).

Sequence Diagram

sequenceDiagram
    participant Charger as Charger
    participant CP as ChargePoint<br/>process_measurands
    participant Agg as _sum_l123<br/>(Phase Aggregation)
    participant Session as csess<br/>(Session Tracker)

    Charger->>CP: Energy.Active.Import.Register<br/>(L1, L2, L3 readings)
    activate CP
    
    CP->>Agg: Phase-tagged measurand values
    activate Agg
    
    Agg->>Agg: Normalize per-phase<br/>to final_value/final_unit
    Agg->>Agg: Sum phase values<br/>L1+L2+L3
    
    alt charger_reports_session_energy == false
        Agg->>Session: Check transaction_id active?
        activate Session
        Session-->>Agg: transaction_id exists
        
        Agg->>Session: Get/Initialize meter_start
        alt meter_start missing
            Agg->>Session: Set meter_start = current_reading
            Agg->>Session: Set session_energy = 0.0
        else meter_start exists
            Agg->>Session: Derive session_energy<br/>= current_reading - meter_start
        end
        deactivate Session
    end
    
    Agg->>Agg: Store normalized<br/>metric value/unit
    deactivate Agg
    
    CP->>CP: Construct MeasurandValue<br/>with normalized fields
    deactivate CP
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • drc38

🐰 Phase by phase, the energy flows,
Sessions track what each meter knows,
Baseline set, the math unfolds,
From L1, L2, L3—stories told!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Title check ✅ Passed The title 'Cleaned PR#1920 - Fix Session Energy bug for chargers that send phase-specific readings' clearly and specifically describes the main change: fixing a session energy bug for phase-specific charger readings. It is concise, directly related to the primary purpose of the PR, and provides sufficient context for understanding the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link

codecov bot commented Mar 20, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.97%. Comparing base (fb6245c) to head (2436a99).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1925      +/-   ##
==========================================
+ Coverage   94.94%   94.97%   +0.02%     
==========================================
  Files          12       12              
  Lines        2946     2963      +17     
==========================================
+ Hits         2797     2814      +17     
  Misses        149      149              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@ric866 ric866 temporarily deployed to continuous-integration March 20, 2026 10:44 — with GitHub Actions Inactive
@ric866 ric866 temporarily deployed to continuous-integration March 20, 2026 11:27 — with GitHub Actions Inactive
@ric866 ric866 marked this pull request as ready for review March 20, 2026 11:32
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
custom_components/ocpp/chargepoint.py (1)

825-864: Session energy derivation logic looks correct for the intended fix.

The implementation properly:

  • Only activates for Energy.Active.Import.Register when charger doesn't report session energy directly
  • Initializes meter_start baseline if missing
  • Computes session energy as (final_value - meter_start) with appropriate rounding

One minor observation: when ms_metric.unit != final_unit (line 860), the session energy is silently not updated. Consider adding a debug log for this mismatch scenario to aid troubleshooting.

💡 Optional: Add debug logging for unit mismatch
                             elif ms_metric.unit == final_unit:
                                 se_metric.value = (
                                     round(1000 * (final_value - ms_metric.value)) / 1000
                                 )
                                 se_metric.unit = final_unit
+                            else:
+                                _LOGGER.debug(
+                                    "Session energy not updated: unit mismatch (meter_start=%s, current=%s)",
+                                    ms_metric.unit,
+                                    final_unit,
+                                )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@custom_components/ocpp/chargepoint.py` around lines 825 - 864, Session energy
isn't updated when ms_metric.unit != final_unit; add a debug log in the branch
handling unit mismatch to aid troubleshooting. Locate the block in
chargepoint.py where DEFAULT_MEASURAND and _charger_reports_session_energy are
checked and the tx_metric/ms_metric/se_metric logic runs, and insert a debug log
(using the component logger used elsewhere in this class) in the else path after
the unit comparison (the branch where currently nothing happens when
ms_metric.unit != final_unit) that includes identifying info such as target_cid,
csess.transaction_id.value, ms_metric.unit and final_unit so operators can see
why session energy wasn't computed.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@custom_components/ocpp/chargepoint.py`:
- Around line 825-864: Session energy isn't updated when ms_metric.unit !=
final_unit; add a debug log in the branch handling unit mismatch to aid
troubleshooting. Locate the block in chargepoint.py where DEFAULT_MEASURAND and
_charger_reports_session_energy are checked and the
tx_metric/ms_metric/se_metric logic runs, and insert a debug log (using the
component logger used elsewhere in this class) in the else path after the unit
comparison (the branch where currently nothing happens when ms_metric.unit !=
final_unit) that includes identifying info such as target_cid,
csess.transaction_id.value, ms_metric.unit and final_unit so operators can see
why session energy wasn't computed.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3046332b-cd24-4d3e-9c1c-b272422937da

📥 Commits

Reviewing files that changed from the base of the PR and between 7ceb78f and 7d34e43.

📒 Files selected for processing (2)
  • custom_components/ocpp/chargepoint.py
  • tests/test_charge_point_core.py

@ric866 ric866 changed the title Cleaned up version of PR#1920 Cleaned PR#1920 - Fix Session Energy bug for chargers that send phase-specific readings Mar 20, 2026
@ric866 ric866 temporarily deployed to continuous-integration March 24, 2026 13:35 — with GitHub Actions Inactive
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