Skip to content

Make remote id tag configurable and reset on Home Assistant transaction start#1832

Open
mightytry wants to merge 7 commits into
lbbrhzn:mainfrom
mightytry:main
Open

Make remote id tag configurable and reset on Home Assistant transaction start#1832
mightytry wants to merge 7 commits into
lbbrhzn:mainfrom
mightytry:main

Conversation

@mightytry

@mightytry mightytry commented Dec 18, 2025

Copy link
Copy Markdown
  • Added remote_id_tag as configuration option in configuration.yaml
  • Fixed when Id Tag was set by using the wall box RFID, it was not set back to _remote_id_tag when using home assistant to start afterward

Summary by CodeRabbit

  • New Features
    • Add configuration option to specify a remote ID tag for OCPP transactions; if unset, a random tag is generated.
    • Configured tag is validated (non-empty, max length) and falls back to a generated tag with a logged warning if invalid.
  • Bug Fixes / Behavior
    • Ensure connector-level ID tag is reset/synchronized to the configured or generated remote tag when a remote-start transaction is accepted.

Review Change Stack

@coderabbitai

coderabbitai Bot commented Dec 18, 2025

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a configurable ocpp.remote_id_tag, a ChargePoint getter that returns the configured tag (or a generated 20‑char fallback), and updates the connector id_tag metric to that remote id tag when a RemoteStartTransaction is accepted.

Changes

ChargePoint remote id handling

Layer / File(s) Summary
ChargePoint remote_id_tag lookup and initialization
custom_components/ocpp/chargepoint.py
Import CONF_REMOTE_ID_TAG; add ChargePoint.get_remote_id_tag() to read/validate CONF_REMOTE_ID_TAG or generate a 20‑char fallback; __init__ now sets self._remote_id_tag using that method.
Apply remote_id_tag on RemoteStartTransaction accepted
custom_components/ocpp/ocppv16.py
On accepted RemoteStartTransaction in start_transaction, set the connector-level id_tag metric to self._remote_id_tag before returning True.

Sequence Diagram(s)

sequenceDiagram
    participant Config as Configuration (ocpp.remote_id_tag)
    participant CP as ChargePoint
    participant CS as CentralSystem
    participant Metrics as _metrics

    CP->>Config: get CONF_REMOTE_ID_TAG
    Config-->>CP: configured tag or absent
    CP->>CP: validate/strip or generate 20-char fallback
    CP->>CS: RemoteStartTransaction request
    CS-->>CP: RemoteStartTransactionResponse (Accepted)
    CP->>Metrics: set connector[id_tag] = self._remote_id_tag
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • lbbrhzn/ocpp#1777: Modifies per-connector id_tag/transaction_id handling in ocppv16.py, closely related to metric/id_tag lifecycle changes.

Suggested reviewers

  • drc38

Poem

🐰 I fetch a tag from config or hat,
I trim and check — no clumsy spat.
When remote starts come back as "Yes",
I hop to metrics, tidy and blessed.
⚡🥕

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the two main changes: making the remote id tag configurable and fixing it to reset on HA transaction start, which directly matches the PR objectives and file modifications.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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

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.

@mightytry mightytry had a problem deploying to continuous-integration December 18, 2025 20:14 — with GitHub Actions Failure

@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.

Actionable comments posted: 0

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

297-303: Replace unused loop variable with underscore.

The loop variable i on line 302 is unused and should be replaced with _ per Python convention.

🔎 Apply this diff to follow Python conventions:
     def get_remote_id_tag(self) -> str:
         """Get remote id tag from configuration.yaml or generate a random 20 char one."""
         config = self.hass.data[DOMAIN].get(CONFIG, {})
         alphabet = string.ascii_uppercase + string.digits
         return config.get(
-            CONF_REMOTE_ID_TAG, "".join(secrets.choice(alphabet) for i in range(20))
+            CONF_REMOTE_ID_TAG, "".join(secrets.choice(alphabet) for _ in range(20))
         )
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fecf73f and fa69550.

📒 Files selected for processing (4)
  • config/configuration.yaml (1 hunks)
  • custom_components/ocpp/chargepoint.py (3 hunks)
  • custom_components/ocpp/const.py (1 hunks)
  • custom_components/ocpp/ocppv16.py (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
custom_components/ocpp/ocppv16.py (2)
custom_components/ocpp/chargepoint.py (2)
  • value (85-87)
  • value (90-92)
tests/test_charge_point_v16.py (2)
  • value (4252-4258)
  • value (4261-4263)
🔇 Additional comments (5)
config/configuration.yaml (1)

50-50: LGTM!

The new configuration option is properly formatted and demonstrates the feature with a clear test value.

custom_components/ocpp/const.py (1)

31-31: LGTM!

The new constant follows the existing naming convention and is properly positioned in the file.

custom_components/ocpp/chargepoint.py (2)

54-54: LGTM!

The import is correctly added and follows the existing pattern.


284-284: LGTM!

The refactoring to use get_remote_id_tag() improves maintainability and enables configuration-driven behavior.

custom_components/ocpp/ocppv16.py (1)

629-630: Verify connector-specific metric update in remote transaction start.

The start_transaction method (line 621) accepts a connector_id parameter but updates the global metric self._metrics[0][cstat.id_tag.value] rather than connector-specific metrics. However, the on_start_transaction handler (line 1084) uses the connector_id in its metric key: self._metrics[(connector_id, cstat.id_tag.value)].

Clarify the design intent: Is the global metric update at line 630 intentional (tracking the remote_id_tag used globally across all connectors) or should it be changed to self._metrics[(connector_id, cstat.id_tag.value)] to track per-connector remote start operations? This matters especially if the same charge point has multiple connectors and you call start_transaction with different connector IDs.

@mightytry mightytry changed the title Make remote id tag configurable and fix Make remote id tag configurable and reset on Home Assistant transaction start Dec 18, 2025

@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 (1)
custom_components/ocpp/chargepoint.py (1)

296-302: get_remote_id_tag() is non-idempotent when no config value is set.

Each call without CONF_REMOTE_ID_TAG configured generates a new random tag. Today this is safe because _remote_id_tag is assigned once in __init__, but the public method name implies it can be called freely. If it's ever invoked again (e.g., from ocppv16.py or a future refactor), the returned value won't match _remote_id_tag, breaking authorization checks at line 652.

Consider either caching the generated value or generating the fallback lazily only when needed:

Proposed fix
     def get_remote_id_tag(self) -> str:
         """Get remote id tag from configuration.yaml or generate a random 20 char one."""
         config = self.hass.data[DOMAIN].get(CONFIG, {})
-        alphabet = string.ascii_uppercase + string.digits
-        return config.get(
-            CONF_REMOTE_ID_TAG, "".join(secrets.choice(alphabet) for i in range(20))
-        )
+        tag = config.get(CONF_REMOTE_ID_TAG)
+        if tag is None:
+            alphabet = string.ascii_uppercase + string.digits
+            tag = "".join(secrets.choice(alphabet) for _ in range(20))
+        return tag

This also avoids eagerly generating the random string when the config key is present.

Copilot AI review requested due to automatic review settings April 13, 2026 08:24

@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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@custom_components/ocpp/chargepoint.py`:
- Around line 296-302: The get_remote_id_tag method currently eagerly generates
a random tag in the config.get default and returns blank or non-string values
from configuration; update get_remote_id_tag to (1) retrieve the raw value from
self.hass.data[DOMAIN].get(CONFIG, {}) using CONF_REMOTE_ID_TAG, (2) validate
that the retrieved value is a non-empty string (strip and check length), and (3)
only generate and return a 20-character fallback (using secrets.choice over
alphabet) lazily when the configured value is missing, empty, or not a string;
ensure the method always returns a valid str id_tag. Use the existing symbols
get_remote_id_tag, CONF_REMOTE_ID_TAG, DOMAIN, and CONFIG to locate and change
the code.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d6816a52-4cfa-4e3f-a47d-cea2ca06aef3

📥 Commits

Reviewing files that changed from the base of the PR and between 54d322f and eed8180.

📒 Files selected for processing (2)
  • custom_components/ocpp/chargepoint.py
  • custom_components/ocpp/ocppv16.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • custom_components/ocpp/ocppv16.py

Comment thread custom_components/ocpp/chargepoint.py Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR introduces a configurable remote_id_tag for OCPP remote-start transactions and addresses an issue where an RFID-driven Id Tag could persist into subsequent Home Assistant-initiated starts.

Changes:

  • Add remote_id_tag as a YAML configuration option (constant + example config).
  • Initialize the chargepoint’s _remote_id_tag from YAML (or generate a random one if not configured).
  • Reset the charger-level Id Tag metric to _remote_id_tag when an OCPP 1.6 RemoteStartTransaction is accepted.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
custom_components/ocpp/ocppv16.py Resets charger-level Id Tag to the remote tag after accepted remote start (OCPP 1.6).
custom_components/ocpp/const.py Adds CONF_REMOTE_ID_TAG constant for YAML config lookup.
custom_components/ocpp/chargepoint.py Loads _remote_id_tag from YAML (or generates a random default).
config/configuration.yaml Adds an example remote_id_tag entry under the ocpp: YAML config.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread custom_components/ocpp/chargepoint.py Outdated
mightytry and others added 2 commits April 13, 2026 10:32
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

@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 (1)
custom_components/ocpp/chargepoint.py (1)

300-300: ⚡ Quick win

Replace unused loop variable with underscore.

The loop variable i is not used in the comprehension. By convention, use _ for unused variables.

♻️ Proposed fix
-        fallback = "".join(secrets.choice(alphabet) for i in range(20))
+        fallback = "".join(secrets.choice(alphabet) for _ in range(20))
🤖 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/chargepoint.py` at line 300, The list comprehension
that builds the fallback string uses an unused loop variable `i`; change it to
`_` so the expression becomes a comprehension using `_` instead of `i` (locate
the assignment to `fallback` that calls `"".join(secrets.choice(alphabet) for i
in range(20))` and replace `i` with `_`), keeping the rest (alphabet,
secrets.choice, and length 20) unchanged.
🤖 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/chargepoint.py`:
- Line 300: The list comprehension that builds the fallback string uses an
unused loop variable `i`; change it to `_` so the expression becomes a
comprehension using `_` instead of `i` (locate the assignment to `fallback` that
calls `"".join(secrets.choice(alphabet) for i in range(20))` and replace `i`
with `_`), keeping the rest (alphabet, secrets.choice, and length 20) unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1cee8a45-91a1-471d-8aa3-a712ddca65e6

📥 Commits

Reviewing files that changed from the base of the PR and between 3c9f0d8 and 1995c6d.

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

@colleym

colleym commented Jun 26, 2026

Copy link
Copy Markdown

Real-world use-case - this PR is required for myenergi zappi in OCPP Commercial Mode

This PR is currently the only way to do PIN-less authorized charging from Home Assistant on a myenergi zappi running in OCPP Commercial Mode.

In Commercial Mode the zappi rejects any RemoteStartTransaction whose idTag is not a registered Virtual OCPP Tag (generated from a myaccount PIN). The current behaviour - a random 20-char _remote_id_tag, regenerated on every restart — is therefore always rejected, so HA can never start a charge. With this PR I set remote_id_tag to a registered tag and HA-initiated charge_control start works (e.g. door-access automation → release, no PIN at the unit).

Applied on v0.10.15, resolves it cleanly. The PR is small (+26/-2), MERGEABLE, CI green (CodeRabbit + Snyk), and backward-compatible (random fallback if unset).

@lbbrhzn any chance of a review/merge? Happy to help if anything is needed — thanks! 🙏

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.

3 participants