Skip to content

Wallbox-Steckdose - #4172

Open
LKuemmel wants to merge 20 commits into
masterfrom
feature_local_socket
Open

LKuemmel wants to merge 20 commits into
masterfrom
feature_local_socket

Conversation

@LKuemmel

@LKuemmel LKuemmel commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Summary by Sourcery

Integrate automatic Wallbox-Steckdose detection and control into the consumer, MQTT, RFID, fault handling, and internal chargepoint subsystems.

New Features:

  • Add support for automatically detecting and operating a Modbus-based Wallbox-Steckdose as a configurable consumer, including measurements, switching, RFID handling, and fault reporting.
  • Expose Wallbox-Steckdose data and commands through dedicated MQTT topics and integrate them with broker security, validation, subscriptions, and component routing.

Bug Fixes:

  • Prevent deletion of chargepoints assigned to a Wallbox-Steckdose and switch the socket off before removing its consumer configuration.

Enhancements:

  • Extend RFID authorization to Wallbox-Steckdose consumers and increase the default RFID timeout.
  • Refactor internal chargepoint hardware checks and shared Modbus client definitions to support the additional socket hardware.

Tests:

  • Add coverage for Wallbox-Steckdose consumer behavior, RFID handling, measurement publishing, removal safety, and MQTT topic permissions.

Chores:

  • Centralize readable vendor-group names for device and consumer configuration generation.

@LKuemmel
LKuemmel added this pull request to stack #4171 October 22, 2026 10:42
@LKuemmel
LKuemmel force-pushed the feature_local_socket branch from 2f28bda to 5fccd3d Compare October 22, 2026 10:42
@LKuemmel
LKuemmel force-pushed the feature_local_socket branch 4 times, most recently from 7dc9400 to 8d50535 Compare October 23, 2026 14:06
@LKuemmel
LKuemmel force-pushed the feature_local_socket branch from 8d50535 to 360b460 Compare October 23, 2026 14:13
@LKuemmel
LKuemmel requested a lite review from Copilot October 23, 2026 14:13

Copilot AI 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.

🟡 Changes recommended

Unresolved hardware-detection, runtime, validation, import, and GPIO conflicts affect correctness and approval readiness.

4 open issues
What changed in this PR

Adds support for automatically detected openWB wall sockets, including SDM120 metering, GPIO control, MQTT integration, RFID handling, and consumer configuration.

Changes:

  • Adds internal socket detection, measurement, state control, fault handling, and MQTT publication.
  • Adds internal-socket consumer configuration, host selection, RFID support, and assignment validation.
  • Refactors shared hardware checks and updates vendor metadata, topic handling, bridge configuration, and tests.
File Description
packages/​modules/​internal_chargepoint_handler/​rfid.py Publishes scanned RFID tags for the internal socket.
packages/​modules/​internal_chargepoint_handler/​internal_socket.py Implements socket measurements and GPIO state control.
packages/​modules/​internal_chargepoint_handler/​internal_socket_test.py Tests socket MQTT handling, heartbeat behavior, and RFID flow.
packages/​modules/​internal_chargepoint_handler/​internal_socket_module_test.py Tests socket measurements and RFID publication.
packages/​modules/​internal_chargepoint_handler/​internal_socket_config.py Defines internal socket data structures.
packages/​modules/​internal_chargepoint_handler/​internal_hardware_check.py Provides shared EVSE, meter, and socket hardware checks.
packages/​modules/​internal_chargepoint_handler/​internal_chargepoint_handler.py Integrates socket detection and runtime handling.
packages/​modules/​internal_chargepoint_handler/​hardware_definition.py Defines meter and EVSE hardware mappings.
packages/​modules/​internal_chargepoint_handler/​clients.py Adds socket meter discovery and GPIO access.
packages/​modules/​devices/​vendors.py Adds readable vendor-group names.
packages/​modules/​consumers/​openwb/​vendor.py Registers the openWB consumer vendor.
packages/​modules/​consumers/​openwb/​internal_socket/​selection.py Resolves socket hosts and validates assignments.
packages/​modules/​consumers/​openwb/​internal_socket/​consumer.py Implements the internal socket consumer.
packages/​modules/​consumers/​openwb/​internal_socket/​consumer_test.py Tests local and remote socket consumer behavior.
packages/​modules/​consumers/​openwb/​internal_socket/​config.py Defines internal socket consumer configuration.
packages/​modules/​consumers/​openwb/​internal_socket/​__init__.py Initializes the internal socket consumer package.
packages/​modules/​consumers/​openwb/​__init__.py Initializes the openWB consumer package.
packages/​modules/​configuration.py Uses centralized vendor-group labels.
packages/​modules/​common/​store/​_socket_internal.py Publishes internal socket measurements.
packages/​modules/​common/​store/​__init__.py Exposes the internal socket value store.
packages/​modules/​common/​hardware_check.py Contains shared meter-value validation logic.
packages/​modules/​common/​hardware_check_test.py Tests the refactored hardware checks.
packages/​modules/​common/​fault_state.py Routes internal socket fault topics.
packages/​modules/​common/​component_type.py Adds the internal socket component type.
packages/​main.py Runs socket auto-detection during startup.
packages/​helpermodules/​update_config.py Registers internal socket topics for configuration updates.
packages/​helpermodules/​subdata.py Subscribes to and stores internal socket data.
packages/​helpermodules/​setdata.py Validates and republishes internal socket commands and values.
packages/​helpermodules/​mosquitto_dynsec/​missing_role_topics_test.py Covers internal socket topics in ACL validation.
packages/​helpermodules/​command.py Validates socket creation and handles socket removal.
packages/​helpermodules/​command_test.py Tests socket assignment and removal behavior.
packages/​control/​consumer/​rfid.py Enables RFID support for internal socket consumers.
packages/​control/​consumer/​rfid_test.py Extends RFID tests to internal socket consumers.
data/​config/​mosquitto/​local/​openwb_local.conf Bridges internal socket topics between openWB instances.

Review effort: Lite

Comment thread packages/helpermodules/command.py Outdated
Comment on lines +1209 to +1210
try:
validate_selection(socket_configuration)

Copilot AI 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.

🟡 Changes recommended

Meter failures can leave the socket powered on, and switch-state reporting and broker configuration rollout also need correction.

2 open issues
2 previously missed issues

In code that hasn't changed since last review

Medium severity Bump openwb-version header to 22 for bridge rule updates

data/​config/​mosquitto/​local/​openwb_local.conf:41

Increment the openwb-version header from 21 to 22 along with this bridge rule. runs/setup_mosquitto.sh:201–205 copies this configuration only when its version differs from the installed file. Existing version-21 installations therefore skip the update, leaving socket measurements, status and RFID data unavailable to remote consumers through the public broker.

Medium severity Include socket switch state in ConsumerState

packages/​modules/​consumers/​openwb/​internal_socket/​consumer.py:59

Include the received socket switch state in ConsumerState. The handler publishes openWB/internal_socket/get/state, but this constructor omits it, so ConsumerState.state defaults to False. ConsumerValueStoreBroker then publishes False to the consumer's get/state topic on every successful update, even when the socket is on.

3 resolved since last review

Review effort: Balanced

Comment on lines +295 to +297
self.module.get_values(data.last_tag)
heartbeat_expired = self._check_heartbeat_expired(global_data.heartbeat)
self.update_state.update_state(data, heartbeat_expired)
@LKuemmel
LKuemmel force-pushed the feature_local_socket branch 3 times, most recently from d453df5 to 38a0046 Compare October 27, 2026 10:26
@LKuemmel LKuemmel changed the title wall socket Wallbox-Steckdose Oct 27, 2026
@LKuemmel
LKuemmel force-pushed the feature_local_socket branch from 9868e73 to 8cc51bb Compare October 27, 2026 10:46
@LKuemmel
LKuemmel requested a review from ndrsnhs October 27, 2026 10:49
@LKuemmel
LKuemmel force-pushed the feature_local_socket branch 2 times, most recently from 8e3b1e5 to be6dd88 Compare October 29, 2026 08:25
@LKuemmel
LKuemmel force-pushed the feature_local_socket branch from be6dd88 to 52e647e Compare October 29, 2026 08:31
@LKuemmel
LKuemmel removed this pull request from stack #4171 October 29, 2026 08:53
@LKuemmel
LKuemmel force-pushed the feature_local_socket branch from 7bc3e8f to 5de473d Compare October 29, 2026 08:57
@LKuemmel
LKuemmel added this pull request to stack #4212 October 29, 2026 08:57

Copilot AI 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.

🟡 Changes recommended

Critical shutdown failures can leave sockets powered after consumer deletion or persistent meter errors, while additional state-reporting and permission-migration issues remain unresolved.

6 open issues

Review effort: Balanced

Comment thread packages/helpermodules/command.py Outdated
Comment on lines +1265 to +1266
if consumer is not None and getattr(consumer.data.module, "type", None) == "wallbox_socket":
consumer.module.switch_off()
Comment on lines +287 to +289
self.module.get_values(data.last_tag)
heartbeat_expired = self._check_heartbeat_expired(global_data.heartbeat)
self.update_state.update_state(data, heartbeat_expired)
@sourcery-ai

sourcery-ai Bot commented Nov 10, 2026 •

Copy link
Copy Markdown

Reviewer's Guide

Data structures

Define the wallbox socket’s persisted MQTT state and consumer value store, including its measurement and fault fields.

  • packages/helpermodules/subdata.py L1258-1266 (+4 small edits)
  • packages/modules/common/store/__init__.py L7
  • packages/modules/common/store/_wallbox_socket.py L1-23
  • packages/modules/internal_chargepoint_handler/wallbox_socket_config.py L1-33

Add the wallbox socket component type and route it to its internal MQTT topic namespace.

  • packages/modules/common/component_type.py L13, L41-42
  • packages/modules/common/fault_state.py L53-54

Add wallbox socket consumer configuration and its openWB vendor descriptor, defining the selectable chargepoint and supported usage modes.

  • packages/modules/consumers/openwb/vendor.py L1-14
  • packages/modules/consumers/openwb/wallbox_socket/config.py L1-24

Define the socket’s Modbus meter and share the hardware definitions used by the internal chargepoint clients.

  • packages/modules/internal_chargepoint_handler/clients.py L11-14, L105-108 (+7 small edits)
  • packages/modules/internal_chargepoint_handler/hardware_definition.py L1-23

Expose RFID support and update the consumer timeout default for RFID authorization.

  • packages/control/consumer/consumer_data.py L69
  • packages/control/consumer/rfid.py L9-13

API

Add internal socket MQTT topic routing, payload validation, subscriptions, permissions, and topic migration recognition.

  • data/config/mosquitto/local/openwb_local.conf L1, L41
  • data/config/mosquitto/public/default-dynamic-security.json L84, L975-980
  • packages/helpermodules/mosquitto_dynsec/missing_role_topics_test.py L82-95
  • packages/helpermodules/setdata.py L105-106, L1241-1260
  • packages/helpermodules/update_config.py L368-382

Add the wallbox socket consumer adapter that reads socket state, propagates faults, switches the socket, and clears its RFID tag through MQTT.

  • packages/modules/consumers/openwb/wallbox_socket/consumer.py L1-78

Protect assigned chargepoints from deletion and attempt to switch off wallbox socket consumers before removing them.

  • packages/helpermodules/command.py L416-425, L1264-1272

Forward RFID reader input to the socket’s last-tag topic as well as the existing chargepoint topic.

  • packages/modules/internal_chargepoint_handler/rfid.py L132

Make configurable consumer operations suppress unnecessary component updates when state does not change.

  • packages/modules/common/configurable_consumer.py L95-111

Implementation

Extract shared internal chargepoint hardware checks and adapt them to the relocated meter and client definitions.

  • packages/modules/common/hardware_check.py L1-26 (6 small edits)
  • packages/modules/internal_chargepoint_handler/internal_hardware_check.py L1-113

Integrate socket detection, Modbus metering, heartbeat handling, GPIO control, and lifecycle management into the internal chargepoint handler.

  • packages/modules/internal_chargepoint_handler/internal_chargepoint_handler.py L120-140, L275-301, L307-325 (+13 small edits)

Implement socket meter polling, error recovery, measurement publication, and GPIO switching.

  • packages/modules/internal_chargepoint_handler/wallbox_socket.py L1-112

Centralize readable vendor-group labels and use the shared mapping when building consumer and device configuration data.

  • packages/modules/configuration.py L8-490 (5 small edits)
  • packages/modules/devices/vendors.py L8-14

Tests

Extend RFID authorization tests to run against every supported consumer module type and explicitly set the test timeout.

  • packages/control/consumer/rfid_test.py L11, L18-19, L25-27

Test that removing a wallbox socket consumer switches it off before topic removal, while other consumer types are unaffected.

  • packages/helpermodules/command_test.py L170-188

Verify the wallbox socket consumer subscribes to the selected reader, returns its RFID state, and clears tags only on request.

  • packages/modules/consumers/openwb/wallbox_socket/consumer_test.py L1-60

Test wallbox socket measurement publication and RFID tag updates.

  • packages/modules/internal_chargepoint_handler/wallbox_socket_module_test.py L1-40

Update hardware check tests for the extracted internal chargepoint checks and renamed meter validation function.

  • packages/modules/common/hardware_check_test.py L10-15 (+3 small edits)

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copilot AI 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.

🟡 Changes recommended

Persistent meter failures can bypass fail-safe shutdown, while consumer removal continues after switch-off failures, potentially leaving sockets energized without their controlling configuration.

5 open issues
2 resolved since last review

Review effort: Balanced

Comment thread packages/helpermodules/command.py Resolved
Base automatically changed from feature_consumer_rfid to master November 10, 2026 13:32
@LKuemmel
LKuemmel force-pushed the feature_local_socket branch from 841080d to da07078 Compare November 10, 2026 13:49
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.

2 participants