Skip to content

Commit

Permalink
refactor bat_all
Browse files Browse the repository at this point in the history
  • Loading branch information
LKuemmel committed Jan 16, 2023
1 parent 2d712e6 commit 6c37508
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 110 deletions.
137 changes: 28 additions & 109 deletions packages/control/bat_all.py
Expand Up @@ -44,8 +44,6 @@ class Get:
daily_imported: float = 0
imported: float = 0
exported: float = 0
fault_state: int = 0
fault_str: str = ""
power: float = 0


Expand Down Expand Up @@ -154,12 +152,17 @@ def setup_bat(self):
except Exception:
log.exception("Fehler im Bat-Modul")

REACH_SWITCH_ON_SOC = ["freigegeben.", "nicht freigegeben, da Einschalt-SoC nicht erreicht."]
REACH_SWITCH_OFF_SOC = ["freigegeben.", "nicht freigegeben, da Ausschalt-SoC erreicht."]
REACH_ONLY_SWITCH_ON_SOC = ["freigegeben, da der Speicher komplett entladen werden darf.", "nicht freigegeben."]

def _get_charging_power_left(self):
""" ermittelt die Lade-Leistung des Speichers, die zum Laden der EV verwendet werden darf.
"""
try:
config = data.data.general_data.data.chargemode_config.pv_charging
if not config.bat_prio:
msg = None
# Laderegelung wurde noch nicht freigegeben
if not self.data.set.switch_on_soc_reached:
if config.switch_on_soc != 0:
Expand All @@ -168,12 +171,7 @@ def _get_charging_power_left(self):
self.data.set.charging_power_left = self.data.get.power
else:
self.data.set.charging_power_left = 0
if self.data.set.switch_on_soc_reached:
msg = "freigegeben."
else:
msg = "nicht freigegeben, da Einschalt-SoC nicht erreicht."
log.debug(f'Laderegelung wurde {msg} Verbleibene Speicher-Leistung: '
f'{self.data["set"]["charging_power_left"]}W')
msg = self.REACH_SWITCH_ON_SOC
else:
# Kein Einschalt-Soc; Nutzung, wenn Soc über Ausschalt-Soc liegt.
if config.switch_off_soc != 0:
Expand All @@ -183,82 +181,44 @@ def _get_charging_power_left(self):
else:
self.data.set.switch_on_soc_reached = False
self.data.set.charging_power_left = 0
log.debug(
"".join(
("Laderegelung wurde ", "freigegeben."
if self.data.set.switch_on_soc_reached else
"nicht freigegeben, da Ausschalt-SoC erreicht.",
" Verbleibene Speicher-Leistung: ", self.data.set.charging_power_left,
"W")))
msg = self.REACH_SWITCH_OFF_SOC
# Weder Einschalt- noch Ausschalt-Soc sind konfiguriert.
else:
self.data.set.charging_power_left = self.data.get.power
# Laderegelung wurde freigegeben.
elif self.data.set.switch_on_soc_reached:
if config.switch_off_soc != 0:
# Greift der Ausschalt-Soc?
if config.switch_off_soc < self.data.get.soc:
self.data.set.charging_power_left = self.data.get.power
else:
self.data.set.switch_on_soc_reached = False
self.data.set.charging_power_left = 0
log.debug(
"".join(
("Laderegelung wurde ", "freigegeben."
if self.data.set.switch_on_soc_reached else
"nicht freigegeben, da Ausschalt-SoC erreicht.",
" Verbleibene Speicher-Leistung: ", self.data.set.charging_power_left,
"W")))
# Wenn kein Ausschalt-Soc konfiguriert wurde, wird der Speicher komplett entladen.
if ((config.switch_off_soc != 0 and config.switch_off_soc < self.data.get.soc) or
(config.switch_off_soc == 0 and 0 < self.data.get.soc)):
self.data.set.charging_power_left = self.data.get.power
else:
if 0 < self.data.get.soc:
self.data.set.charging_power_left = self.data.get.power
else:
self.data.set.switch_on_soc_reached = False
self.data.set.charging_power_left = 0
log.debug(
"".join(
("Laderegelung wurde ", "freigegeben, da der Speicher komplett entladen werden darf."
if self.data.set.switch_on_soc_reached else "nicht freigegeben.",
" Verbleibene Speicher-Leistung: ", self.data.set.charging_power_left,
"W")))
self.data.set.switch_on_soc_reached = False
self.data.set.charging_power_left = 0
if config.switch_off_soc != 0:
msg = self.REACH_SWITCH_OFF_SOC
else:
msg = self.REACH_ONLY_SWITCH_ON_SOC
if msg is not None:
log.debug(f'Laderegelung wurde {msg[0] if self.data.set.switch_on_soc_reached else msg[1]}'
f' Verbleibende Speicher-Leistung: {self.data.set.charging_power_left}W')
# Ladeleistungs-Reserve
self.data.set.charging_power_left = self.data.set.charging_power_left - \
config.charging_power_reserve
log.debug(f'Ladeleistungs-Reserve subtrahieren: {self.data.set.charging_power_left} = '
f'{self.data.set.charging_power_left} - {config.charging_power_reserve}')
self.data.set.charging_power_left -= config.charging_power_reserve
log.debug(f'Ladeleistungs-Reserve ({config.charging_power_reserve}W) subtrahieren: '
f'{self.data.set.charging_power_left}')
# Wenn der Speicher Vorrang hat, darf die erlaubte Entlade-Leistung zum Laden der EV genutzt werden, wenn
# der Soc über dem minimalen Entlade-Soc liegt.
else:
if config.rundown_soc != 100:
if self.data.get.soc > config.rundown_soc:
self.data.set.charging_power_left = config.rundown_power
log.debug(f"Erlaubte Entlade-Leistung nutzen ({config.rundown_power}W)")
else:
# 50 W Überschuss übrig lassen, die sich der Speicher dann nehmen kann. Wenn der Speicher
# schneller regelt, als die LP, würde sonst der Speicher reduziert werden.
self.data.set.charging_power_left = -50
if self.data.get.soc > config.rundown_soc:
self.data.set.charging_power_left = config.rundown_power - data.data.cp_all_data.data.get.power
log.debug(f"Erlaubte Entlade-Leistung nutzen ({config.rundown_power}W, davon bisher ungeutzt "
f"{self.data.set.charging_power_left}W)")
else:
# 50 W Überschuss übrig lassen, die sich der Speicher dann nehmen kann. Wenn der Speicher
# schneller regelt, als die LP, würde sonst der Speicher reduziert werden.
self.data.set.charging_power_left = -50
except Exception:
log.exception("Fehler im Bat-Modul")

def get_power(self):
""" gibt die Leistung zurück, die gerade am Speicher anliegt (Summe, wenn es mehrere Speicher gibt).
Return
------
int: Leistung am Speicher
"""
try:
if self.data.config.configured:
return self.data.get.power
else:
return 0
except Exception:
log.exception("Fehler im Bat-Modul")
return 0

def power_for_bat_charging(self):
""" gibt die Leistung zurück, die zum Laden verwendet werden kann.
Expand All @@ -274,44 +234,3 @@ def power_for_bat_charging(self):
except Exception:
log.exception("Fehler im Bat-Modul")
return 0

def allocate_bat_power(self, required_power):
""" subtrahieren der zugeteilten Leistung von der verfügbaren Speicher-Leistung
Parameter
---------
required_power: float
Leistung, mit der geladen werden soll
Return
------
True: Leistung konnte zugeteilt werden.
False: Leistung konnte nicht zugeteilt werden.
"""
try:
if self.data.config.configured:
self.data.set.charging_power_left -= required_power
if self.data.set.charging_power_left < 0:
log.error(
"Es wurde versucht, mehr Speicher-Leistung zuzuteilen, als geladen wird.")
too_much = self.data.set.charging_power_left
self.data.set.charging_power_left = 0
return too_much
return 0
except Exception:
log.exception("Fehler im Bat-Modul")
return required_power

def put_stats(self):
""" Publishen und Loggen der verbleibenden PV-Leistung und reservierten Leistung
"""
try:
Pub().pub("openWB/set/bat/config/configured",
self.data.config.configured)
if self.data.config.configured:
Pub().pub("openWB/set/bat/set/charging_power_left",
self.data.set.charging_power_left)
log.info(str(self.data.set.charging_power_left) +
"W Speicher-Leistung , die für die folgenden Ladepunkte übrig ist.")
except Exception:
log.exception("Fehler im Bat-Modul")
78 changes: 78 additions & 0 deletions packages/control/bat_all_test.py
@@ -0,0 +1,78 @@
from dataclasses import dataclass
from typing import Optional
from unittest.mock import Mock
import pytest

from control.bat_all import BatAll
from control import data
from control.chargepoint import AllChargepointData, AllChargepoints, AllGet
from control.general import General, PvCharging


@pytest.fixture
def data_fixture() -> None:
data.data_init(Mock())
data.data.general_data = General()
data.data.cp_all_data = Mock(spec=AllChargepoints, data=Mock(
spec=AllChargepointData, get=Mock(spec=AllGet, power=0)))


@dataclass
class Params:
name: str
config: PvCharging
soc: float
switch_on_soc_reached: bool
expected_charging_power_left: float
expected_msg: Optional[str]
expected_switch_on_soc_reached: bool


cases = [
Params("Laderegelung nicht freigegeben, Einschalt-SoC konfiguriert", PvCharging(bat_prio=False,
charging_power_reserve=0), 61, False, 500, f'Laderegelung wurde {BatAll.REACH_SWITCH_ON_SOC[0]}', True),
Params("Laderegelung nicht freigegeben, Einschalt-SoC konfiguriert", PvCharging(bat_prio=False,
charging_power_reserve=0), 60, False, 0, f'Laderegelung wurde {BatAll.REACH_SWITCH_ON_SOC[1]}', False),
Params("Laderegelung nicht freigegeben, nur Ausschalt-SoC konfiguriert",
PvCharging(bat_prio=False, charging_power_reserve=0, switch_on_soc=0),
41, False, 500, f'Laderegelung wurde {BatAll.REACH_SWITCH_OFF_SOC[0]}', True),
Params("Laderegelung nicht freigegeben, nur Ausschalt-SoC konfiguriert",
PvCharging(bat_prio=False, charging_power_reserve=0, switch_on_soc=0),
40, False, 0, f'Laderegelung wurde {BatAll.REACH_SWITCH_OFF_SOC[1]}', False),
Params("Laderegelung nicht freigegeben, kein Ein&Ausschalt-SoC konfiguriert", PvCharging(bat_prio=False,
charging_power_reserve=0, switch_on_soc=0, switch_off_soc=0), 40, False, 500, None, False),
Params("Laderegelung freigegeben, ", PvCharging(bat_prio=False, charging_power_reserve=0),
41, True, 500, f'Laderegelung wurde {BatAll.REACH_SWITCH_OFF_SOC[0]}', True),
Params("Laderegelung freigegeben, ", PvCharging(bat_prio=False, charging_power_reserve=0),
40, True, 0, f'Laderegelung wurde {BatAll.REACH_SWITCH_OFF_SOC[1]}', False),
Params("Laderegelung freigegeben, kein Ausschalt-Soc konfiguriert",
PvCharging(bat_prio=False, charging_power_reserve=0, switch_off_soc=0),
41, True, 500, f'Laderegelung wurde {BatAll.REACH_ONLY_SWITCH_ON_SOC[0]}', True),
Params("Laderegelung freigegeben, kein Ausschalt-Soc konfiguriert",
PvCharging(bat_prio=False, charging_power_reserve=0, switch_off_soc=0),
0, True, 0, f'Laderegelung wurde {BatAll.REACH_ONLY_SWITCH_ON_SOC[1]}', False),
Params("Laderegelung nicht freigegeben, Einschalt-SoC konfiguriert, Ladeleistungsreserve",
PvCharging(bat_prio=False),
61, False, 300, f'Laderegelung wurde {BatAll.REACH_SWITCH_ON_SOC[0]}', True),
Params("EV-Vorrang", PvCharging(bat_prio=True), 51, False, 1000,
"Erlaubte Entlade-Leistung nutzen (1000W, davon bisher ungeutzt 1000W)", False),
Params("EV-Vorrang", PvCharging(bat_prio=True), 50, False, -50, None, False),
]


@pytest.mark.parametrize("params", cases, ids=[c.name for c in cases])
def test_get_charging_power_left(params: Params, caplog, data_fixture):
# setup
b = BatAll()
b.data.set.switch_on_soc_reached = params.switch_on_soc_reached
b.data.get.power = 500
b.data.get.soc = params.soc
data.data.general_data.data.chargemode_config.pv_charging = params.config

# execution
b._get_charging_power_left()

# evaluation
assert b.data.set.charging_power_left == params.expected_charging_power_left
assert params.expected_msg is None or params.expected_msg in caplog.text
assert b.data.set.switch_on_soc_reached == params.expected_switch_on_soc_reached
2 changes: 1 addition & 1 deletion packages/control/counter.py
Expand Up @@ -353,7 +353,7 @@ def switch_off_check_threshold(self, chargepoint: Chargepoint) -> bool:
feed_in_yield = data.data.general_data.data.chargemode_config.pv_charging.feed_in_yield
else:
feed_in_yield = 0
switch_off_surplus = self.data.get.power
switch_off_surplus = self.data.get.power - data.data.bat_all_data.power_for_bat_charging()
log.debug(f'LP{chargepoint.num} Switch-Off-Threshold prüfen: EVU {switch_off_surplus}W, freigegebener '
f'Überschuss {self.data.set.released_surplus}W, Einspeisegrenze {feed_in_yield}W')
# Wenn automatische Phasenumschaltung aktiv, die Umschaltung abwarten, bevor die Abschaltschwelle
Expand Down

0 comments on commit 6c37508

Please sign in to comment.