Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Phasenumschaltung unter Beachtung der Schieflast #1121

Merged
merged 4 commits into from
Oct 17, 2023
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
1 change: 1 addition & 0 deletions packages/control/algorithm/additional_current.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ def set_additional_current(self, mode_range: List[int]) -> None:
cp = preferenced_chargepoints[0]
missing_currents, counts = common.get_missing_currents_left(preferenced_chargepoints)
available_currents, limit = Loadmanagement().get_available_currents(missing_currents, counter)
cp.data.control_parameter.limit = limit
available_for_cp = common.available_current_for_cp(cp, counts, available_currents, missing_currents)
current = common.get_current_to_set(
cp.data.set.current, available_for_cp, cp.data.set.target_current)
Expand Down
3 changes: 2 additions & 1 deletion packages/control/algorithm/algorithm.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ def _check_auto_phase_switch_delay(self) -> None:
cp.data.get.currents,
cp.data.get.power,
cp.template.data.max_current_single_phase,
cp.get_max_phase_hw())
cp.get_max_phase_hw(),
cp.data.control_parameter.limit)
if message is not None:
cp.data.get.state_str = message
# Nachdem im Automatikmodus die Anzahl Phasen bekannt ist, Einhaltung des Maximalstroms
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from control.chargemode import Chargemode
from control import data
from control.algorithm.algorithm import Algorithm
from control.loadmanagement import LimitingValue
from control.limiting_value import LimitingValue
from dataclass_utils.factories import currents_list_factory


Expand Down Expand Up @@ -88,7 +88,8 @@ class ParamsLimit(ParamsExpectedSetCurrent, ParamsExpectedCounterSet):
raw_power_left=21310,
raw_currents_left_counter0=[14, 30, 31],
raw_currents_left_counter6=[16, 12, 14],
expected_state_str=LimitingValue.CURRENT,
expected_state_str=(f"Es kann nicht mit der vorgegebenen Stromstärke geladen werden"
f"{LimitingValue.CURRENT.value.format('Garage')}"),
expected_current_cp3=14,
expected_current_cp4=12,
expected_current_cp5=14,
Expand All @@ -97,15 +98,16 @@ class ParamsLimit(ParamsExpectedSetCurrent, ParamsExpectedCounterSet):
expected_raw_currents_left_counter6=[16, 0, 0]),
ParamsLimit(name="limit by power",
raw_power_left=5520,
raw_currents_left_counter0=[14, 30, 31],
raw_currents_left_counter6=[16, 12, 14],
expected_state_str=LimitingValue.POWER,
expected_current_cp3=10.333333333333334,
expected_current_cp4=6.833333333333333,
expected_current_cp5=6.833333333333333,
raw_currents_left_counter0=[32]*3,
raw_currents_left_counter6=[16]*3,
expected_state_str=(f"Es kann nicht mit der vorgegebenen Stromstärke geladen werden"
f"{LimitingValue.POWER.value.format('Garage')}"),
expected_current_cp3=10.461538461538462,
expected_current_cp4=6.769230769230769,
expected_current_cp5=6.769230769230769,
expected_raw_power_left=0,
expected_raw_currents_left_counter0=[3.666666666666666, 23.166666666666668, 24.166666666666668],
expected_raw_currents_left_counter6=[16, 5.166666666666667, 7.166666666666667]),
expected_raw_currents_left_counter0=[21.53846153846154, 25.23076923076923, 25.23076923076923],
expected_raw_currents_left_counter6=[16, 9.23076923076923, 9.23076923076923]),
# limit by unbalanced load
]

Expand All @@ -125,8 +127,7 @@ def test_instant_charging_limit(params: ParamsLimit, all_cp_instant_charging_1p,
assert_expected_current(params)
for i in range(3, 6):
assert data.data.cp_data[
f"cp{i}"].data.get.state_str == (f"Es kann nicht mit der vorgegebenen Stromstärke geladen werden"
f"{params.expected_state_str.value.format('Garage')}")
f"cp{i}"].data.get.state_str.replace("\n", "") == params.expected_state_str.replace("\n", "")
assert_counter_set(params)


Expand Down
1 change: 1 addition & 0 deletions packages/control/algorithm/min_current.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ def set_min_current(self) -> None:
missing_currents, counts = common.get_min_current(cp)
if max(missing_currents) > 0:
available_currents, limit = Loadmanagement().get_available_currents(missing_currents, counter)
cp.data.control_parameter.limit = limit
available_for_cp = common.available_current_for_cp(
cp, counts, available_currents, missing_currents)
current = common.get_current_to_set(
Expand Down
1 change: 1 addition & 0 deletions packages/control/algorithm/surplus_controlled.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ def _set(self,
available_currents, limit = Loadmanagement().get_available_currents_surplus(missing_currents,
counter,
feed_in_yield)
cp.data.control_parameter.limit = limit
available_for_cp = common.available_current_for_cp(cp, counts, available_currents, missing_currents)
current = common.get_current_to_set(cp.data.set.current, available_for_cp, cp.data.set.target_current)
self._set_loadmangement_message(current, limit, cp, counter)
Expand Down
3 changes: 2 additions & 1 deletion packages/control/auto_phase_switch_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,8 @@ def test_auto_phase_switch(monkeypatch, vehicle: Ev, params: Params):
params.get_currents,
params.get_power,
32,
3)
3,
None)

# evaluation
assert phases_to_use == params.expected_phases_to_use
Expand Down
5 changes: 4 additions & 1 deletion packages/control/chargepoint/chargepoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,10 @@ def __init__(self, index: int, event: Optional[threading.Event]):
def set_state_and_log(self, message: str) -> None:
if message:
log.info(f"LP {self.num}: {message}")
self.data.get.state_str = message
if self.data.get.state_str is None:
self.data.get.state_str = message
elif message not in self.data.get.state_str:
self.data.get.state_str += f" {message}"

def _is_grid_protection_inactive(self) -> Tuple[bool, Optional[str]]:
""" prüft, ob der Netzschutz inaktiv ist oder ob alle Ladepunkt gestoppt werden müssen.
Expand Down
4 changes: 4 additions & 0 deletions packages/control/chargepoint/control_parameter.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

from control.chargepoint.chargepoint_state import ChargepointState
from control.chargemode import Chargemode as Chargemode_enum
from control.limiting_value import LimitingValue
from dataclass_utils.factories import currents_list_factory


Expand All @@ -20,6 +21,9 @@ class ControlParameter:
imported_instant_charging: Optional[float] = field(
default=None,
metadata={"topic": "control_parameter/imported_instant_charging", "mutable_by_algorithm": True})
limit: Optional[LimitingValue] = field(
default=None,
metadata={"topic": "control_parameter/limit", "mutable_by_algorithm": True})
phases: int = field(
default=0,
metadata={"topic": "control_parameter/phases", "mutable_by_algorithm": True})
Expand Down
14 changes: 9 additions & 5 deletions packages/control/ev.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from control.bat_all import SwitchOnBatState
from control.chargepoint.chargepoint_state import ChargepointState, PHASE_SWITCH_STATES
from control.chargepoint.control_parameter import ControlParameter
from control.limiting_value import LimitingValue
from dataclass_utils.factories import empty_dict_factory, empty_list_factory
from helpermodules.abstract_plans import Limit, limit_factory, ScheduledChargingPlan, TimeChargingPlan
from helpermodules import timecheck
Expand Down Expand Up @@ -365,7 +366,8 @@ def _check_phase_switch_conditions(self,
control_parameter: ControlParameter,
get_currents: List[float],
get_power: float,
max_current_cp: int) -> Tuple[bool, Optional[str]]:
max_current_cp: int,
limit: LimitingValue) -> Tuple[bool, Optional[str]]:
# Manche EV laden mit 6.1A bei 6A Sollstrom
min_current = self.ev_template.data.min_current + self.ev_template.data.nominal_difference
max_current = (min(self.ev_template.data.max_current_single_phase, max_current_cp)
Expand All @@ -381,9 +383,9 @@ def _check_phase_switch_conditions(self,
# 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)
condition_1_to_3 = (max(get_currents) > max_current and
condition_1_to_3 = (((max(get_currents) > max_current and
all_surplus > self.ev_template.data.min_current * max_phases_ev * 230
- get_power and
- get_power) or limit == LimitingValue.UNBALANCED_LOAD.value) and
phases_in_use == 1)
condition_3_to_1 = max(get_currents) < min_current and all_surplus <= 0 and phases_in_use > 1
if condition_1_to_3 or condition_3_to_1:
Expand All @@ -404,7 +406,8 @@ def auto_phase_switch(self,
get_currents: List[float],
get_power: float,
max_current_cp: int,
max_phases: int) -> Tuple[int, float, Optional[str]]:
max_phases: int,
limit: LimitingValue) -> Tuple[int, float, Optional[str]]:
message = None
current = control_parameter.required_current
timestamp_auto_phase_switch = control_parameter.timestamp_auto_phase_switch
Expand Down Expand Up @@ -442,7 +445,8 @@ def auto_phase_switch(self,
condition, condition_msg = self._check_phase_switch_conditions(control_parameter,
get_currents,
get_power,
max_current_cp)
max_current_cp,
limit)
if control_parameter.state not in PHASE_SWITCH_STATES:
if condition:
# Umschaltverzögerung starten
Expand Down
7 changes: 7 additions & 0 deletions packages/control/limiting_value.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from enum import Enum


class LimitingValue(Enum):
CURRENT = ", da der Maximal-Strom an Zähler {} erreicht ist."
POWER = ", da die maximale Leistung an Zähler {} erreicht ist."
UNBALANCED_LOAD = ", da die maximale Schieflast an Zähler {} erreicht ist."
8 changes: 1 addition & 7 deletions packages/control/loadmanagement.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,15 @@
from enum import Enum
import logging
import operator
from typing import List, Optional, Tuple

from control import data
from control.counter import Counter
from control.limiting_value import LimitingValue


log = logging.getLogger(__name__)


class LimitingValue(Enum):
CURRENT = ", da der Maximal-Strom an Zähler {} erreicht ist."
POWER = ", da die maximale Leistung an Zähler {} erreicht ist."
UNBALANCED_LOAD = ", da die maximale Schieflast an Zähler {} erreicht ist."


class Loadmanagement:
def get_available_currents(self,
missing_currents: List[float],
Expand Down
1 change: 1 addition & 0 deletions packages/helpermodules/setdata.py
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,7 @@ def process_chargepoint_topic(self, msg: mqtt.MQTTMessage):
elif "/control_parameter/phases" in msg.topic:
self._validate_value(msg, int, [(0, 3)])
elif ("/control_parameter/submode" in msg.topic or
"/control_parameter/limit" in msg.topic or
"/control_parameter/chargemode" in msg.topic):
self._validate_value(msg, str)
elif "/control_parameter/prio" in msg.topic:
Expand Down