Skip to content

Commit

Permalink
Merge pull request #1620 from LKuemmel/pv_start_with_3_phases
Browse files Browse the repository at this point in the history
pv phases automatic: directly start with max phases
  • Loading branch information
LKuemmel authored Jun 13, 2024
2 parents 9f9d237 + fc88cd4 commit d7649a9
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 21 deletions.
24 changes: 11 additions & 13 deletions packages/control/auto_phase_switch_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ def __init__(self,
phases_to_use: int,
required_current: float,
evu_surplus: int,
reserved_evu_overhang: int,
get_currents: List[float],
get_power: float,
state: ChargepointState,
Expand All @@ -50,7 +49,6 @@ def __init__(self,
self.phases_to_use = phases_to_use
self.required_current = required_current
self.available_power = evu_surplus
self.reserved_evu_overhang = reserved_evu_overhang
self.get_currents = get_currents
self.get_power = get_power
self.state = state
Expand All @@ -63,60 +61,60 @@ def __init__(self,

cases = [
Params("1to3, enough power, start timer", max_current_single_phase=16, timestamp_auto_phase_switch=None,
phases_to_use=1, required_current=6, evu_surplus=-800, reserved_evu_overhang=0, get_currents=[15.6, 0, 0],
phases_to_use=1, required_current=6, evu_surplus=800, get_currents=[15.6, 0, 0],
get_power=3450, state=ChargepointState.CHARGING_ALLOWED, expected_phases_to_use=1, expected_current=6,
expected_message=Ev.PHASE_SWITCH_DELAY_TEXT.format("Umschaltung von 1 auf 3", "7 Min."),
expected_timestamp_auto_phase_switch=1652683252.0,
expected_state=ChargepointState.PHASE_SWITCH_DELAY),
Params("1to3, not enough power, start timer", max_current_single_phase=16, timestamp_auto_phase_switch=None,
phases_to_use=1, required_current=6, evu_surplus=-300, reserved_evu_overhang=0, get_currents=[15.6, 0, 0],
phases_to_use=1, required_current=6, evu_surplus=300, get_currents=[15.6, 0, 0],
get_power=3450, state=ChargepointState.CHARGING_ALLOWED, expected_phases_to_use=1, expected_current=6,
expected_state=ChargepointState.CHARGING_ALLOWED),
Params("1to3, enough power, timer not expired", max_current_single_phase=16,
timestamp_auto_phase_switch=1652682952.0, phases_to_use=1, required_current=6,
evu_surplus=-1200, reserved_evu_overhang=460, get_currents=[15.6, 0, 0], get_power=3450,
evu_surplus=1460, get_currents=[15.6, 0, 0], get_power=3450,
state=ChargepointState.PHASE_SWITCH_DELAY, expected_phases_to_use=1, expected_current=6,
expected_message=Ev.PHASE_SWITCH_DELAY_TEXT.format("Umschaltung von 1 auf 3", "2 Min."),
expected_timestamp_auto_phase_switch=1652683252.0,
expected_state=ChargepointState.PHASE_SWITCH_DELAY),
Params("1to3, not enough power, timer not expired", max_current_single_phase=16,
timestamp_auto_phase_switch=1652682952.0, phases_to_use=1, required_current=6,
evu_surplus=0, reserved_evu_overhang=460, get_currents=[15.6, 0, 0], get_power=3450,
evu_surplus=460, get_currents=[15.6, 0, 0], get_power=3450,
state=ChargepointState.PHASE_SWITCH_DELAY, expected_phases_to_use=1, expected_current=6,
expected_message=f"Verzögerung für die Umschaltung von 1 auf 3 Phasen abgebrochen{Ev.NOT_ENOUGH_POWER}",
expected_timestamp_auto_phase_switch=1652683252.0,
expected_state=ChargepointState.CHARGING_ALLOWED),
Params("1to3, enough power, timer expired", max_current_single_phase=16,
timestamp_auto_phase_switch=1652682772.0, phases_to_use=1, required_current=6,
evu_surplus=-1200, reserved_evu_overhang=460, get_currents=[15.6, 0, 0], get_power=3450,
evu_surplus=1640, get_currents=[15.6, 0, 0], get_power=3450,
state=ChargepointState.PHASE_SWITCH_DELAY,
expected_phases_to_use=3, expected_current=6, expected_state=ChargepointState.PHASE_SWITCH_DELAY_EXPIRED),

Params("3to1, not enough power, start timer", max_current_single_phase=16, timestamp_auto_phase_switch=None,
phases_to_use=3, required_current=6, evu_surplus=0, reserved_evu_overhang=0,
phases_to_use=3, required_current=6, evu_surplus=0,
get_currents=[4.5, 4.4, 5.8], get_power=3381, state=ChargepointState.CHARGING_ALLOWED,
expected_phases_to_use=3, expected_current=6,
expected_message="Umschaltung von 3 auf 1 Phasen in 9 Min..",
expected_timestamp_auto_phase_switch=1652683252.0,
expected_state=ChargepointState.PHASE_SWITCH_DELAY),
Params("3to1, not enough power, timer not expired", max_current_single_phase=16,
timestamp_auto_phase_switch=1652682952.0,
phases_to_use=3, required_current=6, evu_surplus=0, reserved_evu_overhang=-460,
phases_to_use=3, required_current=6, evu_surplus=-460,
get_currents=[4.5, 4.4, 5.8], get_power=3381, state=ChargepointState.PHASE_SWITCH_DELAY,
expected_phases_to_use=3, expected_current=6,
expected_message="Umschaltung von 3 auf 1 Phasen in 4 Min..",
expected_timestamp_auto_phase_switch=1652683252.0,
expected_state=ChargepointState.PHASE_SWITCH_DELAY),
Params("3to1, enough power, timer not expired", max_current_single_phase=16,
timestamp_auto_phase_switch=1652682952.0, phases_to_use=3, required_current=6,
evu_surplus=-860, reserved_evu_overhang=0, get_currents=[4.5, 4.4, 5.8],
evu_surplus=860, get_currents=[4.5, 4.4, 5.8],
get_power=3381, state=ChargepointState.PHASE_SWITCH_DELAY, expected_phases_to_use=3, expected_current=6,
expected_message=f"Verzögerung für die Umschaltung von 3 auf 1 Phasen abgebrochen{Ev.ENOUGH_POWER}",
expected_timestamp_auto_phase_switch=1652683252.0,
expected_state=ChargepointState.CHARGING_ALLOWED),
Params("3to1, not enough power, timer expired", max_current_single_phase=16,
timestamp_auto_phase_switch=1652682592.0, phases_to_use=3, required_current=6,
evu_surplus=0, reserved_evu_overhang=-460, get_currents=[4.5, 4.4, 5.8],
evu_surplus=-460, get_currents=[4.5, 4.4, 5.8],
get_power=3381, state=ChargepointState.PHASE_SWITCH_DELAY, expected_phases_to_use=1, expected_current=16,
expected_state=ChargepointState.PHASE_SWITCH_DELAY_EXPIRED),
]
Expand All @@ -126,12 +124,12 @@ def __init__(self,
def test_auto_phase_switch(monkeypatch, vehicle: Ev, params: Params):
# setup
mock_evu = Mock(spec=Counter, data=Mock(spec=CounterData,
set=Mock(spec=Set, reserved_surplus=params.reserved_evu_overhang,
set=Mock(spec=Set, reserved_surplus=0,
released_surplus=0)))
mock_get_evu_counter = Mock(name="power_for_bat_charging", return_value=mock_evu)
monkeypatch.setattr(data.data.counter_all_data, "get_evu_counter", mock_get_evu_counter)
mock_evu_counter_surplus = Mock(return_value=params.available_power)
monkeypatch.setattr(mock_evu, "calc_surplus", mock_evu_counter_surplus)
monkeypatch.setattr(mock_evu, "get_usable_surplus", mock_evu_counter_surplus)

vehicle.ev_template.data.max_current_single_phase = params.max_current_single_phase
control_parameter = ControlParameter()
Expand Down
19 changes: 19 additions & 0 deletions packages/control/counter.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from typing import List, Tuple

from control import data
from control.chargemode import Chargemode
from control.ev import Ev
from control.chargepoint.chargepoint import Chargepoint
from control.chargepoint.chargepoint_state import ChargepointState
Expand Down Expand Up @@ -249,11 +250,17 @@ def _control_range_offset(self):
log.debug(f"Anpassen des Regelbereichs {range_offset}W")
return range_offset

def get_usable_surplus(self, feed_in_yield: float) -> float:
# verbleibender EVU-Überschuss unter Berücksichtigung der Einspeisegrenze und Speicherleistung
return (-self.calc_surplus() - self.data.set.released_surplus +
self.data.set.reserved_surplus - feed_in_yield)

SWITCH_ON_FALLEN_BELOW = "Einschaltschwelle während der Einschaltverzögerung unterschritten."
SWITCH_ON_WAITING = "Die Ladung wird gestartet, sobald in {} die Einschaltverzögerung abgelaufen ist."
SWITCH_ON_NOT_EXCEEDED = ("Die Ladung kann nicht gestartet werden, da die Einschaltschwelle nicht erreicht "
"wird.")
SWITCH_ON_EXPIRED = "Einschaltschwelle für die Dauer der Einschaltverzögerung überschritten."
SWITCH_ON_MAX_PHASES = "Der Überschuss ist ausreichend, um direkt mit {} Phasen zu laden."

def calc_switch_on_power(self, chargepoint: Chargepoint) -> Tuple[float, float]:
surplus = self.data.set.surplus_power_left - self.data.set.reserved_surplus
Expand Down Expand Up @@ -329,6 +336,18 @@ def switch_on_timer_expired(self, chargepoint: Chargepoint) -> None:
self.data.set.reserved_surplus -= pv_config.switch_on_threshold*control_parameter.phases
msg = self.SWITCH_ON_EXPIRED.format(pv_config.switch_on_threshold)
control_parameter.state = ChargepointState.CHARGING_ALLOWED

if chargepoint.data.set.charging_ev_data.charge_template.data.chargemode.pv_charging.feed_in_limit:
feed_in_yield = pv_config.feed_in_yield
else:
feed_in_yield = 0
ev_template = chargepoint.data.set.charging_ev_data.ev_template
max_phases_power = ev_template.data.min_current * ev_template.data.max_phases * 230
if (data.data.general_data.get_phases_chargemode(Chargemode.PV_CHARGING.value) == 0 and
chargepoint.cp_ev_support_phase_switch() and
self.get_usable_surplus(feed_in_yield) > max_phases_power):
control_parameter.phases = ev_template.data.max_phases
msg += self.SWITCH_ON_MAX_PHASES.format(ev_template.data.max_phases)
chargepoint.set_state_and_log(msg)
except Exception:
log.exception("Fehler im allgemeinen PV-Modul")
Expand Down
10 changes: 2 additions & 8 deletions packages/control/ev.py
Original file line number Diff line number Diff line change
Expand Up @@ -405,10 +405,7 @@ def _check_phase_switch_conditions(self,
feed_in_yield = pv_config.feed_in_yield
else:
feed_in_yield = 0
evu_counter = data.data.counter_all_data.get_evu_counter()
# verbleibender EVU-Überschuss unter Berücksichtigung der Einspeisegrenze und Speicherleistung
all_surplus = (-evu_counter.calc_surplus() - evu_counter.data.set.released_surplus +
evu_counter.data.set.reserved_surplus - feed_in_yield)
all_surplus = data.data.counter_all_data.get_evu_counter().get_usable_surplus(feed_in_yield)
condition_1_to_3 = (((max(get_currents) > max_current and
all_surplus > self.ev_template.data.min_current * max_phases_ev * 230
- get_power) or limit == LimitingValue.UNBALANCED_LOAD.value) and
Expand Down Expand Up @@ -446,10 +443,7 @@ def auto_phase_switch(self,
feed_in_yield = pv_config.feed_in_yield
else:
feed_in_yield = 0
evu_counter = data.data.counter_all_data.get_evu_counter()
# verbleibender EVU-Überschuss unter Berücksichtigung der Einspeisegrenze und Speicherleistung
all_surplus = (-evu_counter.calc_surplus() - evu_counter.data.set.released_surplus +
evu_counter.data.set.reserved_surplus - feed_in_yield)
all_surplus = data.data.counter_all_data.get_evu_counter().get_usable_surplus(feed_in_yield)
if phases_in_use == 1:
direction_str = f"Umschaltung von 1 auf {max_phases}"
delay = pv_config.phase_switch_delay * 60
Expand Down

0 comments on commit d7649a9

Please sign in to comment.