Skip to content

Add current limit fallback for OCPP 1.6 chargers#1959

Open
lkiw wants to merge 1 commit into
lbbrhzn:mainfrom
lkiw:main
Open

Add current limit fallback for OCPP 1.6 chargers#1959
lkiw wants to merge 1 commit into
lbbrhzn:mainfrom
lkiw:main

Conversation

@lkiw

@lkiw lkiw commented May 14, 2026

Copy link
Copy Markdown

This PR adds a small OCPP 1.6 current limit fallback for chargers that do not expose or accept standard smart charging profiles.

The existing SetChargingProfile flow remains the primary path. If smart charging is unavailable or all standard profile attempts are rejected, the integration now tries an optional charger configuration key for current limiting when supported by the device.

Changes

  • Keep standard OCPP smart charging profiles as the preferred current limit mechanism
  • Add a defensive OCPP 1.6 configuration-key fallback for current limiting
  • Add tests for the fallback behavior
  • Add Opticharge 11 setup notes

Summary by CodeRabbit

  • New Features

    • Enhanced charge rate management with improved fallback mechanism—system now attempts configuration-based current limiting when smart charging is unavailable.
  • Documentation

    • Added BRC Opticharge 11 setup guide with OCPP configuration instructions and measurand selection details.

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 14, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

This PR extends OCPP v1.6 charge rate control by introducing a configuration-based fallback mechanism. When Smart Charging profiles are unavailable or rejected, the system now attempts to set a ChargeRate configuration key instead of failing. A new helper method validates and applies this configuration, tests verify the behavior across multiple scenarios, and documentation describes setup for a supported BRC device.

Changes

Configuration-based charge rate fallback

Layer / File(s) Summary
Configuration fallback infrastructure
custom_components/ocpp/ocppv16.py
Adds CURRENT_LIMIT_CONFIGURATION_KEY constant and new _set_charge_rate_via_configuration helper that validates the current limit, reads the existing configuration value from the charger, avoids redundant calls when values match, and returns success for accepted/reboot-required/unknown outcomes.
set_charge_rate fallback integration
custom_components/ocpp/ocppv16.py
Updates set_charge_rate to invoke the configuration fallback when Smart Charging is not supported, and modifies post-profile handling to return success when either TxProfile or TxDefaultProfile is accepted; otherwise falls back to configuration-based method.
Test coverage for fallback behavior
tests/test_set_charge_rate_v16.py
Imports SetVariableResult, reworks the "SMART not supported" test to verify ChargeRate handling when unavailable (returns False), adds tests for when configuration is present (calls configure and returns True), and adds a test verifying profile rejection falls back to ChargeRate configuration.
BRC Opticharge 11 device documentation
docs/supported-devices.md
Documents OCPP 1.6-J WebSocket URL configuration with charge point identity, measurand selection guidance, and notes on dynamic current control with smart-charging-first and fallback behavior.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • lbbrhzn/ocpp#1722: Modifies set_charge_rate control flow including TxProfile/TxDefault handling and fallback logic with corresponding test adjustments.
  • lbbrhzn/ocpp#1708: Modifies set_charge_rate logic and fallback/acceptance behavior with profile clearing and test coverage.
  • lbbrhzn/ocpp#1718: Modifies set_charge_rate profile-based charging-rate attempt and fallback behavior.

Suggested reviewers

  • lbbrhzn

Poem

A charger once stubborn and slow,
Now flexes with config flow,
When profiles decline,
The fallback's divine—
⚡ Configuration makes current go! 🐰

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 39.13% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add current limit fallback for OCPP 1.6 chargers' directly and clearly describes the main feature being added: a fallback mechanism for setting current limits on OCPP 1.6 chargers.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
tests/test_set_charge_rate_v16.py (1)

151-175: ⚡ Quick win

Duplicate test detected.

The test test_smart_charging_not_supported_charge_rate_unknown_returns_false (lines 151-175) appears to duplicate the behavior of the modified test test_smart_charging_not_supported_returns_false_no_notify (lines 90-120). Both tests verify the same scenario: SMART not supported, ChargeRate returns "Unknown", configure not called, returns False.

Consider removing one of these tests to reduce maintenance burden.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/test_set_charge_rate_v16.py` around lines 151 - 175, Remove the
duplicate test by deleting either
test_smart_charging_not_supported_charge_rate_unknown_returns_false or
test_smart_charging_not_supported_returns_false_no_notify so only one remains;
both cover the same scenario (SMART not supported, cp_v16.get_configuration
returns "Unknown", configure and call must not be invoked and set_charge_rate
returns False). Keep the clearer or more fully named test (referenced by the
test function names above) and ensure the remaining test still sets
cp_v16._attr_supported_features = prof.NONE and monkeypatches get_configuration,
configure, and call as in the diff so behavior is preserved.
custom_components/ocpp/ocppv16.py (1)

589-592: 💤 Low value

Consider simplifying type conversion.

The conversion int(float(limit_amps)) is redundant when limit_amps is already an int per the function signature. If this is defensive programming for unexpected input types, consider adding a docstring note. Otherwise, int(limit_amps) should suffice.

♻️ Simplified conversion
     try:
-        amps = int(float(limit_amps))
+        amps = int(limit_amps)
     except (TypeError, ValueError):
         return False
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@custom_components/ocpp/ocppv16.py` around lines 589 - 592, The
int(float(limit_amps)) conversion is redundant; replace it with amps =
int(limit_amps) to avoid unnecessary float casting (keep the existing except
(TypeError, ValueError): return False behavior). If the code must defensively
accept non-int inputs, instead add a brief docstring or inline comment on the
function handling limit_amps to explain why non-int strings might be passed and
why the try/except is needed; reference the variable limit_amps and the amps
assignment in the current try/except block when making the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@custom_components/ocpp/ocppv16.py`:
- Around line 589-592: The int(float(limit_amps)) conversion is redundant;
replace it with amps = int(limit_amps) to avoid unnecessary float casting (keep
the existing except (TypeError, ValueError): return False behavior). If the code
must defensively accept non-int inputs, instead add a brief docstring or inline
comment on the function handling limit_amps to explain why non-int strings might
be passed and why the try/except is needed; reference the variable limit_amps
and the amps assignment in the current try/except block when making the change.

In `@tests/test_set_charge_rate_v16.py`:
- Around line 151-175: Remove the duplicate test by deleting either
test_smart_charging_not_supported_charge_rate_unknown_returns_false or
test_smart_charging_not_supported_returns_false_no_notify so only one remains;
both cover the same scenario (SMART not supported, cp_v16.get_configuration
returns "Unknown", configure and call must not be invoked and set_charge_rate
returns False). Keep the clearer or more fully named test (referenced by the
test function names above) and ensure the remaining test still sets
cp_v16._attr_supported_features = prof.NONE and monkeypatches get_configuration,
configure, and call as in the diff so behavior is preserved.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2d09d8a8-e68d-4cc3-b8fd-000e2d880132

📥 Commits

Reviewing files that changed from the base of the PR and between 6eb2cfc and 2a22e42.

📒 Files selected for processing (3)
  • custom_components/ocpp/ocppv16.py
  • docs/supported-devices.md
  • tests/test_set_charge_rate_v16.py

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