Skip to content

fix: EVSE-Ruecklesen vor Phasenumschaltung#3326

Open
s0170071 wants to merge 2 commits intoopenWB:masterfrom
s0170071:fix/phase-switch-evse-readback
Open

fix: EVSE-Ruecklesen vor Phasenumschaltung#3326
s0170071 wants to merge 2 commits intoopenWB:masterfrom
s0170071:fix/phase-switch-evse-readback

Conversation

@s0170071
Copy link
Copy Markdown

@s0170071 s0170071 commented Apr 25, 2026

Problem

Beim Phasenwechsel wird aktuell set_current(0) an die EVSE gesendet und dann blind 5 Sekunden gewartet, bevor die Relais geschaltet werden. Wenn der EVSE-Schreibvorgang fehlschlägt (Modbus-Timeout, Bus-Konflikt, evse_client is None), wird die Exception von SingleComponentUpdateContext stillschweigend geschluckt und die Relais werden unter Last geschaltet.

Folgen: Lichtbogenschäden an den Relaiskontakten (nur für stromloses Schalten ausgelegt), mögliches Verschweißen der Kontakte, im schlimmsten Fall Brandgefahr bei 32 A.
Ladeabruch da das Fahrzeug einen Fehler erkennt.

Lösung

  • reraise=True auf SingleComponentUpdateContext: Ein fehlgeschlagener set_current(0)-Aufruf wird nicht mehr geschluckt, sondern als Exception weitergegeben — die Relais werden nicht geschaltet.
  • Aktive Rücklesung statt blindem Sleep: EVSE-Register wird bis zu 20× im Abstand von 0,5 s abgefragt (max. 10 s). Bei jeder Iteration wird set_current(0) erneut gesendet.
  • Abbruch bei Timeout: Wenn die EVSE nach 10 s keinen Strom von 0 A bestätigt, wird die Phasenumschaltung mit log.error abgebrochen. Die Relais werden nicht betätigt.

Geänderte Datei

  • packages/modules/internal_chargepoint_handler/chargepoint_module.pyperform_phase_switch()

Test

  • Normalbetrieb: EVSE bestätigt 0 A nach 1–2 Abfragen → Phasenwechsel erfolgt wie bisher
  • Modbus-Fehler bei set_current(0): Exception wird geworfen → Relais bleiben unangetastet
  • EVSE antwortet, aber Strom bleibt > 0: Nach 10 s Timeout → Abbruch mit Fehlermeldung im Log

Ersetzt den blinden 5s-Sleep in perform_phase_switch durch eine aktive
Ruecklesung des EVSE-Registers (bis zu 20x alle 0,5s). Die Phasen-
umschaltung wird abgebrochen wenn die EVSE nach 10s keinen Strom von
0 A bestaetigt. reraise=True verhindert dass ein fehlgeschlagener
set_current(0) stillschweigend geschluckt wird.
@s0170071 s0170071 force-pushed the fix/phase-switch-evse-readback branch from 9843260 to c9ce41a Compare April 25, 2026 08:59
Comment on lines +156 to +158
log.error("CP%d: EVSE did not reach 0 A within 10s — aborting phase switch.",
self.local_charge_point_num)
return
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.

Suggested change
log.error("CP%d: EVSE did not reach 0 A within 10s — aborting phase switch.",
self.local_charge_point_num)
return
raise Exception("Ladung konnte nicht gestoppt werden - Phasenumschaltung abgebrochen.")

Mit einer Exception bekommt der Nutzer auch im UI eine Rückmeldung, warum die Umschaltung nicht geklappt hat.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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 hardens the internal chargepoint phase-switch procedure to avoid switching relays under load by actively verifying that the EVSE has accepted a 0 A setpoint and by ensuring write failures are not silently swallowed.

Changes:

  • Enable exception propagation (reraise=True) during EVSE current write before phase switching.
  • Replace fixed sleep with polling of EVSE state (up to 20 attempts) and abort phase switching if 0 A isn’t confirmed.

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

Comment on lines +149 to +153
for _ in range(20): # poll up to 10s (20 × 0.5s) for EVSE to confirm 0 A
_, _, evse_current = evse.get_plug_charge_state()
if evse_current == 0:
break
time.sleep(0.5)
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

The "poll up to 10s" timeout isn’t actually bounded to ~10s: each loop iteration also includes EVSE.get_plug_charge_state() (0.1s sleep) and evse.set_current() (0.1s sleep) in addition to the 0.5s sleep, so the worst-case runtime is noticeably >10s (plus Modbus latency). Consider implementing the timeout using a monotonic deadline (e.g., loop until time.monotonic() >= start+10) or adjusting the sleep/iteration count so the maximum wall time matches the intended 10s.

Suggested change
for _ in range(20): # poll up to 10s (20 × 0.5s) for EVSE to confirm 0 A
_, _, evse_current = evse.get_plug_charge_state()
if evse_current == 0:
break
time.sleep(0.5)
deadline = time.monotonic() + 10
while time.monotonic() < deadline: # poll up to 10s for EVSE to confirm 0 A
_, _, evse_current = evse.get_plug_charge_state()
if evse_current == 0:
break
remaining = deadline - time.monotonic()
if remaining <= 0:
break
time.sleep(min(0.5, remaining))

Copilot uses AI. Check for mistakes.
Comment thread packages/modules/internal_chargepoint_handler/chargepoint_module.py Outdated
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