Skip to content
Merged
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
2 changes: 1 addition & 1 deletion packages/control/algorithm/algorithm.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def _check_auto_phase_switch_delay(self) -> None:
if cp.data.set.charging_ev != -1:
charging_ev = cp.data.set.charging_ev_data
control_parameter = cp.data.control_parameter
if cp.cp_ev_chargemode_support_phase_switch():
if cp.cp_state_hw_support_phase_switch() and control_parameter.template_phases == 0:
# Gibt die Stromstärke und Phasen zurück, mit denen nach der Umschaltung geladen werden
# soll. Falls keine Umschaltung erforderlich ist, werden Strom und Phasen, die übergeben
# wurden, wieder zurückgegeben.
Expand Down
10 changes: 7 additions & 3 deletions packages/control/algorithm/integration_test/pv_charging_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,9 +223,9 @@ def test_surplus(params: ParamsSurplus, all_cp_pv_charging_3p, all_cp_charging_3
data.data.counter_data["counter6"].data.set.raw_currents_left = params.raw_currents_left_counter6
mock_get_component_name_by_id = Mock(return_value="Garage")
monkeypatch.setattr(loadmanagement, "get_component_name_by_id", mock_get_component_name_by_id)
data.data.cp_data["cp3"].data.set.charge_template.data.chargemode.pv_charging.phases_to_use = 1
data.data.cp_data["cp4"].data.set.charge_template.data.chargemode.pv_charging.phases_to_use = 1
data.data.cp_data["cp5"].data.set.charge_template.data.chargemode.pv_charging.phases_to_use = 1
for i in range(3, 6):
data.data.cp_data[f"cp{i}"].data.set.charge_template.data.chargemode.pv_charging.phases_to_use = 1
data.data.cp_data[f"cp{i}"].data.control_parameter.template_phases = 1

# execution
Algorithm().calc_current()
Expand Down Expand Up @@ -276,6 +276,8 @@ def test_phase_switch(all_cp_pv_charging_3p, all_cp_charging_3p, monkeypatch):
"cp3"].data.control_parameter.state = ChargepointState.CHARGING_ALLOWED
data.data.cp_data[
"cp3"].data.control_parameter.timestamp_last_phase_switch = 1652682252
for i in range(3, 6):
data.data.cp_data[f"cp{i}"].data.control_parameter.template_phases = 0

# execution
Algorithm().calc_current()
Expand All @@ -298,6 +300,8 @@ def test_phase_switch_1p_3p(all_cp_pv_charging_1p, monkeypatch):
data.data.cp_data["cp3"].data.control_parameter.timestamp_last_phase_switch = 1652682252
data.data.cp_data["cp4"].data.get.currents = [0, 0, 0]
data.data.cp_data["cp5"].data.get.currents = [0, 0, 0]
for i in range(3, 6):
data.data.cp_data[f"cp{i}"].data.control_parameter.template_phases = 0

# execution
Algorithm().calc_current()
Expand Down
6 changes: 4 additions & 2 deletions packages/control/algorithm/surplus_controlled.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,12 @@ def check_submode_pv_charging(self) -> None:
for cp in get_chargepoints_by_chargemodes(CONSIDERED_CHARGE_MODES_PV_ONLY):
try:
def phase_switch_necessary() -> bool:
return cp.cp_ev_chargemode_support_phase_switch() and cp.data.get.phases_in_use != 1
return (cp.cp_state_hw_support_phase_switch() and
cp.data.get.phases_in_use != 1 and
cp.data.control_parameter.template_phases == 0)
control_parameter = cp.data.control_parameter
if cp.chargemode_changed or cp.submode_changed:
if control_parameter.state == ChargepointState.CHARGING_ALLOWED:
if (control_parameter.state in CHARGING_STATES):
if cp.data.set.charging_ev_data.ev_template.data.prevent_charge_stop is False:
threshold = evu_counter.calc_switch_off_threshold(cp)[0]
if evu_counter.calc_raw_surplus() - cp.data.set.required_power < threshold:
Expand Down
42 changes: 12 additions & 30 deletions packages/control/chargepoint/chargepoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ def check_phase_switch_completed(self):
if self.data.control_parameter.state == ChargepointState.WAIT_FOR_USING_PHASES:
if check_timestamp(self.data.control_parameter.timestamp_charge_start,
charging_ev.ev_template.data.keep_charge_active_duration) is False:
if self.cp_ev_support_phase_switch() and self.failed_phase_switches_reached():
if self.hw_supports_phase_switch() and self.failed_phase_switches_reached():
if phase_switch.phase_switch_thread_alive(self.num) is False:
self.data.control_parameter.state = ChargepointState.PHASE_SWITCH_AWAITED
if self._is_phase_switch_required() is False:
Expand All @@ -467,7 +467,7 @@ def initiate_phase_switch(self):
Pub().pub("openWB/set/chargepoint/"+str(self.num)+"/set/phases_to_use",
self.data.control_parameter.phases)
self.data.set.phases_to_use = self.data.control_parameter.phases
if self.cp_ev_support_phase_switch():
if self.hw_supports_phase_switch():
if self._is_phase_switch_required():
# Wenn die Umschaltverzögerung aktiv ist, darf nicht umgeschaltet werden.
if (self.data.control_parameter.state != ChargepointState.PERFORMING_PHASE_SWITCH and
Expand Down Expand Up @@ -569,7 +569,7 @@ def hw_bidi_capable(self) -> BidiState:
else:
return BidiState.BIDI_CAPABLE

def set_phases(self, phases: int) -> int:
def set_phases(self, phases: int, template_phases: int) -> int:
charging_ev = self.data.set.charging_ev_data
phases = min(phases, self.get_max_phase_hw())

Expand All @@ -584,12 +584,13 @@ def set_phases(self, phases: int) -> int:
phases = self.data.get.phases_in_use
else:
phases = self.data.control_parameter.phases
elif self.cp_ev_support_phase_switch() is False:
elif self.hw_supports_phase_switch() is False:
# sonst passt die Phasenzahl nicht bei Autos, die eine Phase weg schalten.
log.info(f"Phasenumschaltung an Ladepunkt {self.num} wird durch die Hardware nicht unterstützt.")
phases = phases
if phases != self.data.control_parameter.phases:
self.data.control_parameter.phases = phases
self.data.control_parameter.template_phases = template_phases
return phases

def check_cp_max_current(self, required_current: float, phases: int) -> float:
Expand Down Expand Up @@ -698,18 +699,18 @@ def update(self, ev_list: Dict[str, Ev]) -> None:
if charging_possible:
try:
charging_ev = self._get_charging_ev(vehicle, ev_list)
state, message_ev, submode, required_current, phases = charging_ev.get_required_current(
state, message_ev, submode, required_current, template_phases = charging_ev.get_required_current(
self.data.set.charge_template,
self.data.control_parameter,
self.get_max_phase_hw(),
self.cp_ev_support_phase_switch(),
self.hw_supports_phase_switch(),
self.template.data.charging_type,
self.data.control_parameter.timestamp_chargemode_changed or create_timestamp(),
self.data.set.log.imported_since_plugged,
self.hw_bidi_capable(),
self.data.get.phases_in_use)
phases = self.get_phases_by_selected_chargemode(phases)
phases = self.set_phases(phases)
required_phases = self.get_phases_by_selected_chargemode(template_phases)
required_phases = self.set_phases(required_phases, template_phases)
self._pub_connected_vehicle(charging_ev)
required_current = self.chargepoint_module.add_conversion_loss_to_current(required_current)
self.set_chargemode_changed(submode)
Expand Down Expand Up @@ -900,40 +901,21 @@ def _pub_connected_vehicle(self, vehicle: Ev):
except Exception:
log.exception("Fehler im Prepare-Modul")

def cp_ev_chargemode_support_phase_switch(self) -> bool:
if (self.cp_ev_support_phase_switch() and
def cp_state_hw_support_phase_switch(self) -> bool:
if (self.hw_supports_phase_switch() and
self.data.get.charge_state and
self.chargemode_support_phase_switch() and
(self.data.control_parameter.state == ChargepointState.CHARGING_ALLOWED or
self.data.control_parameter.state == ChargepointState.PHASE_SWITCH_DELAY)):
return self.failed_phase_switches_reached()
else:
return False

def cp_ev_support_phase_switch(self) -> bool:
def hw_supports_phase_switch(self) -> bool:
return (self.data.config.auto_phase_switch_hw and
self.data.get.evse_signaling != EvseSignaling.HLC and
(self.data.set.charging_ev_data.ev_template.data.prevent_phase_switch is False or
self.data.set.log.imported_since_plugged == 0))

def chargemode_support_phase_switch(self) -> bool:
control_parameter = self.data.control_parameter
pv_auto_switch = ((control_parameter.chargemode == Chargemode.PV_CHARGING or
control_parameter.chargemode == Chargemode.ECO_CHARGING) and
control_parameter.submode == Chargemode.PV_CHARGING and
self.data.set.charge_template.data.chargemode.pv_charging.phases_to_use == 0)
for p in self.data.set.charge_template.data.chargemode.scheduled_charging.plans:
if p.id == self.data.control_parameter.current_plan:
phases_to_use_pv = p.phases_to_use_pv
break
else:
phases_to_use_pv = 1
scheduled_auto_switch = (
control_parameter.chargemode == Chargemode.SCHEDULED_CHARGING and
control_parameter.submode == Chargemode.PV_CHARGING and
phases_to_use_pv == 0)
return (pv_auto_switch or scheduled_auto_switch)

def failed_phase_switches_reached(self) -> bool:
if ((data.data.general_data.data.chargemode_config.retry_failed_phase_switches and
self.data.control_parameter.failed_phase_switches > self.MAX_FAILED_PHASE_SWITCHES) or
Expand Down
1 change: 1 addition & 0 deletions packages/control/chargepoint/control_parameter.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class ControlParameter:
state: ChargepointState = field(default=ChargepointState.NO_CHARGING_ALLOWED,
metadata={"topic": "control_parameter/state"})
submode: Chargemode_enum = field(default=Chargemode_enum.STOP, metadata={"topic": "control_parameter/submode"})
template_phases: int = field(default=None, metadata={"topic": "control_parameter/template_phases"})
timestamp_charge_start: Optional[float] = field(
default=None, metadata={"topic": "control_parameter/timestamp_charge_start"})
timestamp_chargemode_changed: Optional[float] = field(
Expand Down
4 changes: 2 additions & 2 deletions packages/control/chargepoint/get_phases_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,15 +160,15 @@ def __init__(self,
def test_set_phases(monkeypatch, cp: Chargepoint, params: SetPhasesParams):
# setup
mock_phase_switch_supported = Mock(name="phase_switch_supported", return_value=params.phase_switch_supported)
monkeypatch.setattr(Chargepoint, "cp_ev_support_phase_switch", mock_phase_switch_supported)
monkeypatch.setattr(Chargepoint, "hw_supports_phase_switch", mock_phase_switch_supported)
cp.data.get.phases_in_use = params.phases_in_use
cp.data.set.log.imported_since_plugged = params.imported_since_plugged
charging_ev_data = cp.data.set.charging_ev_data
charging_ev_data.ev_template.data.prevent_phase_switch = params.prevent_phase_switch
cp.data.control_parameter.phases = params.phases_in_use

# execution
phases = cp.set_phases(params.phases)
phases = cp.set_phases(params.phases, 3)

# evaluation
assert phases == params.expected_phases
2 changes: 1 addition & 1 deletion packages/control/counter.py
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ def switch_on_timer_expired(self, chargepoint: Chargepoint) -> None:
max_phases_power = ev_template.data.min_current * ev_template.data.max_phases * 230
if (control_parameter.submode == Chargemode.PV_CHARGING and
chargepoint.data.set.charge_template.data.chargemode.pv_charging.phases_to_use == 0 and
chargepoint.cp_ev_support_phase_switch() and
chargepoint.hw_supports_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)
Expand Down
3 changes: 2 additions & 1 deletion packages/helpermodules/setdata.py
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,8 @@ def process_chargepoint_topic(self, msg: mqtt.MQTTMessage):
self._validate_value(msg, float, [(0, 0), (6, 32), (0, 450)])
else:
self._validate_value(msg, float, [(6, 32), (0, 0)])
elif "/control_parameter/phases" in msg.topic:
elif ("/control_parameter/phases" in msg.topic or
"/control_parameter/template_phases" in msg.topic):
self._validate_value(msg, int, [(0, 3)])
elif "/control_parameter/failed_phase_switches" in msg.topic:
self._validate_value(msg, int, [(0, 4)])
Expand Down
1 change: 1 addition & 0 deletions packages/helpermodules/update_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ class UpdateConfig:
"^openWB/chargepoint/[0-9]+/control_parameter/required_currents$",
"^openWB/chargepoint/[0-9]+/control_parameter/state$",
"^openWB/chargepoint/[0-9]+/control_parameter/submode$",
"^openWB/chargepoint/[0-9]+/control_parameter/template_phases$",
"^openWB/chargepoint/[0-9]+/control_parameter/timestamp_charge_start$",
"^openWB/chargepoint/[0-9]+/control_parameter/timestamp_chargemode_changed$",
"^openWB/chargepoint/[0-9]+/control_parameter/timestamp_last_phase_switch$",
Expand Down