Skip to content

Commit

Permalink
fix calc costs
Browse files Browse the repository at this point in the history
  • Loading branch information
LKuemmel committed Nov 6, 2023
1 parent d5ed10b commit bd80107
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 39 deletions.
90 changes: 63 additions & 27 deletions packages/control/chargelog/chargelog.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import datetime
from enum import Enum
import json
import logging
import math
Expand Down Expand Up @@ -96,6 +97,7 @@ def save_data(chargepoint, charging_ev, immediately: bool = True, reset: bool =
power = 0
if duration > 0:
power = log_data.imported_since_mode_switch / duration
calculate_charge_cost(chargepoint, True)
costs = log_data.costs
new_entry = {
"chargepoint":
Expand Down Expand Up @@ -318,34 +320,68 @@ def truncate(number: Union[int, float], decimals: int = 0):
log.exception("Fehler im Ladelog-Modul")


def calculate_charge_cost(create_log_entry: bool = False):
def calculate_charge_cost(cp, create_log_entry: bool = False):
content = get_todays_daily_log()
for cp in data.data.cp_data.values():
try:
reference_time = _get_reference_time(cp, create_log_entry)
reference_entry = _get_reference_entry(content["entries"], reference_time)
energy_entry = process_entry(reference_entry, content["entries"][-1], CalculationType.ENERGY)
power_source_entry = analyse_percentage(energy_entry)
cp.data.set.log.costs += _calc(power_source_entry["power_source"],
# energy_imported in kWh
power_source_entry["cp"][f"cp{cp.num}"]["energy_imported"]*1000,
(data.data.optional_data.et_module is not None))
except Exception:
log.exception(f"Fehler beim Berechnen der Ladekosten für Ladepunkt {cp.num}")


def _get_reference_time(cp, create_log_entry: bool) -> float:
try:
reference = _get_reference_position(cp, create_log_entry)
reference_time = get_reference_time(cp, reference)
reference_entry = _get_reference_entry(content["entries"], reference_time)
energy_entry = process_entry(reference_entry, content["entries"][-1], CalculationType.ENERGY)
power_source_entry = analyse_percentage(energy_entry)
if reference == ReferenceTime.START:
charged_energy = cp.data.set.log.imported_since_mode_switch
elif reference == ReferenceTime.MIDDLE:
# energy_imported in kWh
charged_energy = (content["entries"][-1]["cp"][f"cp{cp.num}"]["imported"] -
power_source_entry["cp"][f"cp{cp.num}"]["energy_imported"]*1000)
elif reference == ReferenceTime.END:
reference_start_position = _get_reference_position(cp, False)
if reference_start_position == ReferenceTime.START:
charged_energy = cp.data.set.log.imported_since_mode_switch
else:
last_considered_entry = _get_reference_entry(
content["entries"], timecheck.create_unix_timestamp_current_full_hour())
charged_energy = cp.data.get.imported - \
last_considered_entry["cp"][f"cp{cp.num}"]["energy_imported"]*1000
else:
raise TypeError(f"Unbekannter Referenz-Zeitpunkt {reference}")
cp.data.set.log.costs += _calc(power_source_entry["power_source"],
charged_energy,
(data.data.optional_data.et_module is not None))
except Exception:
log.exception(f"Fehler beim Berechnen der Ladekosten für Ladepunkt {cp.num}")


class ReferenceTime(Enum):
START = 0
MIDDLE = 1
END = 2


def _get_reference_position(cp, create_log_entry: bool) -> ReferenceTime:
# Referenz-Zeitpunkt ermitteln (angesteckt oder letzte volle Stunde)
# Wurde innerhalb der letzten Stunde angesteckt?
if create_log_entry:
# Ladekosten für angefangene Stunde ermitteln
return timecheck.create_unix_timestamp_current_full_hour()
return ReferenceTime.END
else:
one_hour_back = (datetime.datetime.today()-datetime.timedelta(hours=1))
if timecheck.get_difference(cp.data.set.plug_time, one_hour_back.strftime("%m/%d/%Y, %H:%M:%S")) < 0:
return datetime.datetime.strptime(cp.data.set.plug_time, "%m/%d/%Y, %H:%M:%S").timestamp()
if (timecheck.get_difference(cp.data.set.log.timestamp_start_charging,
one_hour_back.strftime("%m/%d/%Y, %H:%M:%S")) < 0):
return ReferenceTime.START
else:
return one_hour_back.timestamp()
return ReferenceTime.MIDDLE


def get_reference_time(cp, reference_position):
if reference_position == ReferenceTime.START:
return datetime.datetime.strptime(cp.data.set.log.timestamp_start_charging, "%m/%d/%Y, %H:%M:%S").timestamp()
elif reference_position == ReferenceTime.MIDDLE:
return (datetime.datetime.today()-datetime.timedelta(hours=1)).timestamp()
elif reference_position == ReferenceTime.END:
return timecheck.create_unix_timestamp_current_full_hour()
else:
raise TypeError(f"Unbekannter Referenz-Zeitpunkt {reference_position}")


def _get_reference_entry(entries: List[Dict], reference_time: float) -> Dict:
Expand All @@ -371,24 +407,24 @@ def get_todays_daily_log():


def get_daily_log(day):
filepath = str(pathlib.Path(__file__).resolve().parents[2] / "data" / "daily_log" / f"{day}.json")
filepath = str(pathlib.Path(__file__).resolve().parents[3] / "data" / "daily_log" / f"{day}.json")
try:
with open(filepath, "r", encoding="utf-8") as json_file:
return json.load(json_file)
except FileNotFoundError:
return []


def _calc(power_source: Dict[str, float], charged_power_last_hour: float, et_active: bool) -> float:
def _calc(power_source: Dict[str, float], charged_energy_last_hour: float, et_active: bool) -> float:
prices = data.data.general_data.data.prices

bat_costs = prices.bat * charged_power_last_hour * power_source["bat"]
cp_costs = prices.cp * charged_power_last_hour * power_source["cp"]
bat_costs = prices.bat * charged_energy_last_hour * power_source["bat"]
cp_costs = prices.cp * charged_energy_last_hour * power_source["cp"]
if et_active:
grid_costs = data.data.optional_data.et_get_current_price() * charged_power_last_hour * power_source["grid"]
grid_costs = data.data.optional_data.et_get_current_price() * charged_energy_last_hour * power_source["grid"]
else:
grid_costs = prices.grid * charged_power_last_hour * power_source["grid"]
pv_costs = prices.pv * charged_power_last_hour * power_source["pv"]
grid_costs = prices.grid * charged_energy_last_hour * power_source["grid"]
pv_costs = prices.pv * charged_energy_last_hour * power_source["pv"]

log.debug(
f'Ladepreis für die letzte Stunde: {bat_costs}€ Speicher ({power_source["bat"]}%), {grid_costs}€ Netz '
Expand Down
44 changes: 33 additions & 11 deletions packages/control/chargelog/chargelog_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
import pytest
from control import data
from control.chargelog import chargelog
from control.chargelog.chargelog import _calc, _get_reference_entry, _get_reference_time, calculate_charge_cost
from control.chargelog.chargelog import (ReferenceTime, _calc, _get_reference_entry, _get_reference_position,
calculate_charge_cost, get_reference_time)
from control.chargepoint.chargepoint import Chargepoint
from control.general import General
from control.optional import Optional
Expand Down Expand Up @@ -60,20 +61,41 @@ def data_module() -> None:


@pytest.mark.parametrize(
"plug_time, create_log_entry, expected_timestamp",
(pytest.param("05/16/2022, 07:42:52", False, 1652679772, id="innerhalb der letzten Stunde angesteckt"),
pytest.param("05/16/2022, 06:40:52", False, 1652679652, id="vor mehr als einer Stunde angesteckt"),
pytest.param("05/16/2022, 06:40:52", True, 1652680800,
"start_charging, create_log_entry, expected_timestamp",
(pytest.param("05/16/2022, 07:42:52", False, ReferenceTime.START, id="innerhalb der letzten Stunde angesteckt"),
pytest.param("05/16/2022, 06:40:52", False, ReferenceTime.MIDDLE, id="vor mehr als einer Stunde angesteckt"),
pytest.param("05/16/2022, 06:40:52", True, ReferenceTime.END,
id="vor mehr als einer Stunde angesteckt, Ladevorgang beenden"),
)
)
def test_get_reference_time(plug_time: bool, create_log_entry: bool, expected_timestamp: float):
def test_get_reference_position(start_charging: str, create_log_entry: bool, expected_timestamp: float):
# setup
cp = Chargepoint(0, Mock())
cp.data.set.plug_time = plug_time
cp.data.set.log.timestamp_start_charging = start_charging

# execution
timestamp = _get_reference_time(cp, create_log_entry)
timestamp = _get_reference_position(cp, create_log_entry)

# evaluation
assert timestamp == expected_timestamp


@pytest.mark.parametrize(
"reference_position, start_charging, expected_timestamp",
(pytest.param(ReferenceTime.START, "05/16/2022, 07:42:52", 1652679772,
id="innerhalb der letzten Stunde angesteckt"),
pytest.param(ReferenceTime.MIDDLE, "05/16/2022, 06:40:52", 1652679652, id="vor mehr als einer Stunde angesteckt"),
pytest.param(ReferenceTime.END, "05/16/2022, 06:40:52", 1652680800,
id="vor mehr als einer Stunde angesteckt, Ladevorgang beenden"),
)
)
def test_get_reference_time(reference_position: ReferenceTime, start_charging: str, expected_timestamp: float):
# setup
cp = Chargepoint(0, Mock())
cp.data.set.log.timestamp_start_charging = start_charging

# execution
timestamp = get_reference_time(cp, reference_position)

# evaluation
assert timestamp == expected_timestamp
Expand Down Expand Up @@ -121,7 +143,7 @@ def test_calc(et_active, expected_costs, monkeypatch):
def test_calculate_charge_cost(monkeypatch):
# integration test
# setup
data.data.cp_data["cp3"].data.set.plug_time = "11/01/2023, 08:12:40"
data.data.cp_data["cp3"].data.set.log.timestamp_start_charging = "11/01/2023, 08:12:40"
# Mock today() to values in log-file
datetime_mock = MagicMock(wraps=datetime.datetime)
# Thu Nov 02 2023 07:00:51
Expand All @@ -135,7 +157,7 @@ def test_calculate_charge_cost(monkeypatch):
monkeypatch.setattr(chargelog, "get_todays_daily_log", Mock(return_value=content_today))

# execution
calculate_charge_cost()
calculate_charge_cost(data.data.cp_data["cp3"])

# evaluation
assert data.data.cp_data["cp3"].data.set.log.costs == 0.5441
assert data.data.cp_data["cp3"].data.set.log.costs == 6.7509
3 changes: 2 additions & 1 deletion packages/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,8 @@ def handler_random_nightly(self):
@exit_after(10)
def handler_hour(self):
try:
calculate_charge_cost()
for cp in data.data.cp_data.values():
calculate_charge_cost(cp)
except KeyboardInterrupt:
log.critical("Ausführung durch exit_after gestoppt: "+traceback.format_exc())
except Exception:
Expand Down

0 comments on commit bd80107

Please sign in to comment.