Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion packages/control/chargepoint/chargepoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@ def _process_charge_stop(self) -> None:
self.data.set.ocpp_transaction_id,
self.data.set.rfid)
self.data.set.ocpp_transaction_id = None
# muss vor dem Zurücksetzen der control parameter aufgerufen werden
self.data.set.charging_ev_data.reset_phase_switch(self.data.control_parameter)
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

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

In _process_charge_stop() you call reset_phase_switch() before resetting the control parameters, but Ev.reset_phase_switch() only releases reserved_surplus for PERFORMING_PHASE_SWITCH. If the EV is unplugged while control_parameter.state == PHASE_SWITCH_DELAY (1→multi-phase delay), the reserved power added in Ev.auto_phase_switch() will not be released, which can skew reserved_surplus as long as other EVs are still plugged in. Consider extending the reset to also handle PHASE_SWITCH_DELAY (or call reset_phase_switch_delay() here as well) and release exactly the amount that was reserved.

Suggested change
self.data.set.charging_ev_data.reset_phase_switch(self.data.control_parameter)
self.data.set.charging_ev_data.reset_phase_switch(self.data.control_parameter)
self.data.set.charging_ev_data.reset_phase_switch_delay(self.data.control_parameter)

Copilot uses AI. Check for mistakes.
self.reset_control_parameter_at_charge_stop()
Comment on lines +187 to 189
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

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

This change introduces new behavior on charge stop: releasing reserved phase-switch power via charging_ev_data.reset_phase_switch(control_parameter). There are already unit tests covering _process_charge_stop(), but none assert that reserved_surplus is correctly released when unplugging during PERFORMING_PHASE_SWITCH (and, after fixing, during PHASE_SWITCH_DELAY). Please add a focused test to prevent regressions in reserved-power accounting.

Copilot uses AI. Check for mistakes.
data.data.counter_all_data.get_evu_counter().reset_switch_on_off(self)
if self.data.get.plug_state is False and self.data.set.plug_state_prev is True:
Expand Down Expand Up @@ -665,7 +667,7 @@ def update(self, ev_list: Dict[str, Ev]) -> None:

if self.chargemode_changed or self.submode_changed:
data.data.counter_all_data.get_evu_counter().reset_switch_on_off(self)
charging_ev.reset_phase_switch(self.data.control_parameter)
charging_ev.reset_phase_switch_delay(self.data.control_parameter)
if self.chargemode_changed:
self.data.control_parameter.failed_phase_switches = 0
message = message_ev if message_ev else message
Expand Down
25 changes: 16 additions & 9 deletions packages/control/ev/ev.py
Original file line number Diff line number Diff line change
Expand Up @@ -429,21 +429,28 @@ def _remaining_phase_switch_time(self, control_parameter: ControlParameter,
control_parameter.timestamp_phase_switch_buffer_start = None
return True, None

def reset_phase_switch(self, control_parameter: ControlParameter):
def reset_phase_switch_delay(self, control_parameter: ControlParameter):
""" Zurücksetzen der Zeitstempel und reservierten Leistung.

Comment on lines 433 to 434
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

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

The docstring of reset_phase_switch_delay() says it resets timestamps ("Zurücksetzen der Zeitstempel"), but the method currently only adjusts reserved_surplus and does not touch timestamp_phase_switch_buffer_start / timestamp_last_phase_switch. Either update the docstring to reflect the actual behavior or reset the relevant timestamps/state here to avoid misleading documentation.

Suggested change
""" Zurücksetzen der Zeitstempel und reservierten Leistung.
""" Zurücksetzen der für die Phasenumschaltverzögerung reservierten Leistung.
Zeitstempel werden hier nicht zurückgesetzt.

Copilot uses AI. Check for mistakes.
Die Phasenumschaltung kann nicht abgebrochen werden!
"""
if control_parameter.state == ChargepointState.PHASE_SWITCH_DELAY:
if control_parameter.state == ChargepointState.PHASE_SWITCH_DELAY and control_parameter.phases == 1:
# Wenn der Timer läuft, ist den Control-Parametern die alte Phasenzahl hinterlegt.
if control_parameter.phases == 1:
reserved = control_parameter.required_current * \
3 * 230 - self.ev_template.data.max_current_single_phase * 230
data.data.counter_all_data.get_evu_counter().data.set.reserved_surplus -= reserved
log.debug(
"Zurücksetzen der reservierten Leistung für die Phasenumschaltung. reservierte Leistung: " +
str(data.data.counter_all_data.get_evu_counter().data.set.reserved_surplus))
# bei der Umschaltung 3p1p wird keine Leistung reserviert
evu_counter = data.data.counter_all_data.get_evu_counter()
reserved = control_parameter.required_current * \
3 * 230 - self.ev_template.data.max_current_single_phase * 230
evu_counter.data.set.reserved_surplus -= reserved
log.debug(f"Zurücksetzen von {reserved}W reservierter Leistung für die Phasenumschaltung. "
Comment on lines +437 to +444
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

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

reset_phase_switch_delay() recomputes the reserved power with control_parameter.required_current * 3 * 230 - max_current_single_phase * 230 and then subtracts it without clamping. This does not match the reservation logic in auto_phase_switch() (which reserves max(0, min_current * max_phases * 230 - max_current_single_phase * 230)), and it can even become negative (which would increase reserved_surplus when subtracting). Please compute/release the same value that was originally reserved (including max(0, …)), and avoid hard-coding 3 phases if 2-phase hardware is supported.

Copilot uses AI. Check for mistakes.
f"reservierte Leistung: {evu_counter.data.set.reserved_surplus} W")

def reset_phase_switch(self, control_parameter: ControlParameter):
if control_parameter.state == ChargepointState.PERFORMING_PHASE_SWITCH:
evu_counter = data.data.counter_all_data.get_evu_counter()
if control_parameter.phases == 1:
evu_counter.data.set.reserved_surplus -= self.ev_template.data.max_current_single_phase * 230
else:
evu_counter.data.set.reserved_surplus -= self.ev_template.data.max_current_single_phase * 3 * 230


def get_ev_to_rfid(rfid: Optional[str] = None, vehicle_id: Optional[str] = None) -> Optional[int]:
Expand Down
Loading